From a26f6f242b47d38aeb8038375f652aaea284d1bd Mon Sep 17 00:00:00 2001 From: Arron Wang Date: Mon, 21 Oct 2013 11:11:55 +0800 Subject: [PATCH 1/2] Imported Upstream version 3.9.0 --- COPYING | 502 + ChangeLog | 336 + Makefile.am | 22 + Makefile.in | 874 ++ aclocal.m4 | 1287 ++ build-aux/ar-lib | 270 + build-aux/compile | 343 + build-aux/config.guess | 1530 +++ build-aux/config.sub | 1773 +++ build-aux/depcomp | 708 ++ build-aux/install-sh | 527 + build-aux/ltmain.sh | 9655 +++++++++++++++ build-aux/missing | 331 + configure | 15398 ++++++++++++++++++++++++ configure.ac | 176 + etc/classid | 45 + etc/pktloc | 76 + include/Makefile.am | 135 + include/Makefile.in | 640 + include/linux/can/netlink.h | 122 + include/linux/fib_rules.h | 69 + include/linux/gen_stats.h | 67 + include/linux/genetlink.h | 83 + include/linux/if.h | 146 + include/linux/if_addr.h | 55 + include/linux/if_arp.h | 156 + include/linux/if_bridge.h | 185 + include/linux/if_ether.h | 125 + include/linux/if_link.h | 446 + include/linux/if_vlan.h | 62 + include/linux/inetdevice.h | 36 + include/linux/ip_mp_alg.h | 22 + include/linux/ipv6.h | 146 + include/linux/neighbour.h | 155 + include/linux/netfilter.h | 57 + include/linux/netfilter/nf_conntrack_common.h | 117 + include/linux/netfilter/nfnetlink.h | 56 + include/linux/netfilter/nfnetlink_compat.h | 63 + include/linux/netfilter/nfnetlink_conntrack.h | 248 + include/linux/netfilter/nfnetlink_log.h | 101 + include/linux/netfilter/nfnetlink_queue.h | 105 + include/linux/netlink.h | 149 + include/linux/pkt_cls.h | 467 + include/linux/pkt_sched.h | 627 + include/linux/rtnetlink.h | 605 + include/linux/snmp.h | 270 + include/linux/tc_ematch/tc_em_meta.h | 89 + include/netlink-private/cache-api.h | 270 + include/netlink-private/genl.h | 22 + include/netlink-private/netlink.h | 262 + include/netlink-private/object-api.h | 376 + include/netlink-private/route/link/api.h | 153 + include/netlink-private/route/tc-api.h | 134 + include/netlink-private/tc.h | 55 + include/netlink-private/types.h | 912 ++ include/netlink/addr.h | 66 + include/netlink/attr.h | 285 + include/netlink/cache-api.h | 20 + include/netlink/cache.h | 168 + include/netlink/cli/addr.h | 32 + include/netlink/cli/class.h | 21 + include/netlink/cli/cls.h | 24 + include/netlink/cli/ct.h | 34 + include/netlink/cli/exp.h | 42 + include/netlink/cli/link.h | 30 + include/netlink/cli/neigh.h | 27 + include/netlink/cli/qdisc.h | 23 + include/netlink/cli/route.h | 34 + include/netlink/cli/rule.h | 21 + include/netlink/cli/tc.h | 41 + include/netlink/cli/utils.h | 82 + include/netlink/data.h | 41 + include/netlink/errno.h | 64 + include/netlink/fib_lookup/lookup.h | 42 + include/netlink/fib_lookup/request.h | 51 + include/netlink/genl/ctrl.h | 40 + include/netlink/genl/family.h | 47 + include/netlink/genl/genl.h | 52 + include/netlink/genl/mngt.h | 176 + include/netlink/handlers.h | 146 + include/netlink/hash.h | 69 + include/netlink/hashtable.h | 52 + include/netlink/list.h | 93 + include/netlink/msg.h | 147 + include/netlink/netfilter/ct.h | 126 + include/netlink/netfilter/exp.h | 129 + include/netlink/netfilter/log.h | 109 + include/netlink/netfilter/log_msg.h | 98 + include/netlink/netfilter/netfilter.h | 31 + include/netlink/netfilter/nfnl.h | 44 + include/netlink/netfilter/queue.h | 90 + include/netlink/netfilter/queue_msg.h | 104 + include/netlink/netlink-compat.h | 50 + include/netlink/netlink-kernel.h | 293 + include/netlink/netlink.h | 97 + include/netlink/object-api.h | 19 + include/netlink/object.h | 80 + include/netlink/route/addr.h | 98 + include/netlink/route/class.h | 66 + include/netlink/route/classifier.h | 51 + include/netlink/route/cls/basic.h | 33 + include/netlink/route/cls/cgroup.h | 32 + include/netlink/route/cls/ematch.h | 95 + include/netlink/route/cls/ematch/cmp.h | 32 + include/netlink/route/cls/ematch/meta.h | 41 + include/netlink/route/cls/ematch/nbyte.h | 36 + include/netlink/route/cls/ematch/text.h | 42 + include/netlink/route/cls/fw.h | 31 + include/netlink/route/cls/police.h | 29 + include/netlink/route/cls/u32.h | 49 + include/netlink/route/link.h | 235 + include/netlink/route/link/api.h | 20 + include/netlink/route/link/bonding.h | 39 + include/netlink/route/link/bridge.h | 56 + include/netlink/route/link/can.h | 60 + include/netlink/route/link/inet.h | 33 + include/netlink/route/link/info-api.h | 20 + include/netlink/route/link/vlan.h | 59 + include/netlink/route/neighbour.h | 81 + include/netlink/route/neightbl.h | 65 + include/netlink/route/nexthop.h | 65 + include/netlink/route/pktloc.h | 49 + include/netlink/route/qdisc.h | 73 + include/netlink/route/qdisc/cbq.h | 30 + include/netlink/route/qdisc/dsmark.h | 43 + include/netlink/route/qdisc/fifo.h | 29 + include/netlink/route/qdisc/htb.h | 49 + include/netlink/route/qdisc/netem.h | 76 + include/netlink/route/qdisc/plug.h | 31 + include/netlink/route/qdisc/prio.h | 54 + include/netlink/route/qdisc/red.h | 17 + include/netlink/route/qdisc/sfq.h | 37 + include/netlink/route/qdisc/tbf.h | 41 + include/netlink/route/route.h | 128 + include/netlink/route/rtnl.h | 69 + include/netlink/route/rule.h | 75 + include/netlink/route/tc-api.h | 21 + include/netlink/route/tc.h | 114 + include/netlink/socket.h | 71 + include/netlink/types.h | 110 + include/netlink/utils.h | 86 + include/netlink/version.h | 37 + include/netlink/version.h.in | 37 + lib/Makefile.am | 118 + lib/Makefile.in | 1370 +++ lib/addr.c | 1067 ++ lib/attr.c | 907 ++ lib/cache.c | 1220 ++ lib/cache_mngr.c | 523 + lib/cache_mngt.c | 439 + lib/cli/cls/basic.c | 93 + lib/cli/cls/cgroup.c | 75 + lib/cli/qdisc/bfifo.c | 83 + lib/cli/qdisc/blackhole.c | 64 + lib/cli/qdisc/htb.c | 203 + lib/cli/qdisc/pfifo.c | 77 + lib/cli/qdisc/plug.c | 113 + lib/data.c | 195 + lib/defs.h.in | 86 + lib/error.c | 116 + lib/fib_lookup/lookup.c | 349 + lib/fib_lookup/request.c | 185 + lib/genl/ctrl.c | 547 + lib/genl/family.c | 402 + lib/genl/genl.c | 391 + lib/genl/mngt.c | 399 + lib/handlers.c | 391 + lib/hash.c | 482 + lib/hashtable.c | 197 + lib/msg.c | 996 ++ lib/netfilter/ct.c | 628 + lib/netfilter/ct_obj.c | 796 ++ lib/netfilter/exp.c | 621 + lib/netfilter/exp_obj.c | 888 ++ lib/netfilter/log.c | 251 + lib/netfilter/log_msg.c | 210 + lib/netfilter/log_msg_obj.c | 461 + lib/netfilter/log_obj.c | 287 + lib/netfilter/netfilter.c | 53 + lib/netfilter/nfnl.c | 245 + lib/netfilter/queue.c | 251 + lib/netfilter/queue_msg.c | 285 + lib/netfilter/queue_msg_obj.c | 495 + lib/netfilter/queue_obj.c | 215 + lib/nl.c | 1124 ++ lib/object.c | 538 + lib/route/addr.c | 1120 ++ lib/route/class.c | 473 + lib/route/classid.c | 456 + lib/route/cls.c | 441 + lib/route/cls/basic.c | 229 + lib/route/cls/cgroup.c | 189 + lib/route/cls/ematch.c | 701 ++ lib/route/cls/ematch/cmp.c | 93 + lib/route/cls/ematch/container.c | 47 + lib/route/cls/ematch/meta.c | 334 + lib/route/cls/ematch/nbyte.c | 139 + lib/route/cls/ematch/text.c | 183 + lib/route/cls/ematch_grammar.l | 162 + lib/route/cls/ematch_syntax.y | 501 + lib/route/cls/fw.c | 219 + lib/route/cls/police.c | 66 + lib/route/cls/u32.c | 636 + lib/route/link.c | 2644 ++++ lib/route/link/api.c | 397 + lib/route/link/bonding.c | 227 + lib/route/link/bridge.c | 474 + lib/route/link/can.c | 784 ++ lib/route/link/dummy.c | 40 + lib/route/link/inet.c | 280 + lib/route/link/inet6.c | 377 + lib/route/link/vlan.c | 587 + lib/route/neigh.c | 962 ++ lib/route/neightbl.c | 827 ++ lib/route/nexthop.c | 297 + lib/route/pktloc.c | 260 + lib/route/pktloc_grammar.l | 51 + lib/route/pktloc_syntax.y | 103 + lib/route/qdisc.c | 575 + lib/route/qdisc/blackhole.c | 37 + lib/route/qdisc/cbq.c | 204 + lib/route/qdisc/dsmark.c | 413 + lib/route/qdisc/fifo.c | 169 + lib/route/qdisc/htb.c | 643 + lib/route/qdisc/netem.c | 908 ++ lib/route/qdisc/plug.c | 177 + lib/route/qdisc/prio.c | 294 + lib/route/qdisc/red.c | 190 + lib/route/qdisc/sfq.c | 256 + lib/route/qdisc/tbf.c | 460 + lib/route/route.c | 206 + lib/route/route_obj.c | 1315 ++ lib/route/route_utils.c | 171 + lib/route/rtnl.c | 124 + lib/route/rule.c | 757 ++ lib/route/tc.c | 1072 ++ lib/socket.c | 696 ++ lib/utils.c | 1106 ++ lib/version.c | 36 + libnl-3.0.pc.in | 10 + libnl-3.9.0.tar.gz | Bin 0 -> 1074117 bytes libnl-cli-3.0.pc.in | 11 + libnl-genl-3.0.pc.in | 11 + libnl-nf-3.0.pc.in | 11 + libnl-route-3.0.pc.in | 11 + m4/libtool.m4 | 7986 ++++++++++++ m4/ltoptions.m4 | 384 + m4/ltsugar.m4 | 123 + m4/ltversion.m4 | 23 + m4/lt~obsolete.m4 | 98 + man/Makefile.am | 7 + man/Makefile.in | 502 + man/genl-ctrl-list.8 | 104 + man/nl-classid-lookup.8 | 51 + man/nl-pktloc-lookup.8 | 48 + man/nl-qdisc-add.8 | 118 + man/nl-qdisc-delete.8 | 1 + man/nl-qdisc-list.8 | 1 + python/Makefile.am | 3 + python/Makefile.in | 607 + python/README | 12 + python/netlink/Makefile.am | 10 + python/netlink/Makefile.in | 611 + python/netlink/__init__.py | 0 python/netlink/capi.i | 454 + python/netlink/core.py | 744 ++ python/netlink/fixes.h | 1 + python/netlink/route/Makefile.am | 14 + python/netlink/route/Makefile.in | 417 + python/netlink/route/__init__.py | 0 python/netlink/route/address.py | 367 + python/netlink/route/capi.i | 396 + python/netlink/route/link.py | 539 + python/netlink/route/links/__init__.py | 0 python/netlink/route/links/dummy.py | 26 + python/netlink/route/links/inet.py | 158 + python/netlink/route/links/vlan.py | 71 + python/netlink/route/qdisc/__init__.py | 0 python/netlink/route/qdisc/htb.py | 145 + python/netlink/route/tc.py | 595 + python/netlink/util.py | 174 + python/setup.py.in | 30 + src/Makefile.am | 100 + src/Makefile.in | 1374 +++ src/genl-ctrl-list.c | 71 + src/lib/Makefile.am | 43 + src/lib/Makefile.in | 643 + src/lib/addr.c | 135 + src/lib/class.c | 45 + src/lib/cls.c | 71 + src/lib/ct.c | 162 + src/lib/exp.c | 165 + src/lib/link.c | 101 + src/lib/neigh.c | 88 + src/lib/qdisc.c | 32 + src/lib/route.c | 278 + src/lib/rule.c | 55 + src/lib/tc.c | 165 + src/lib/utils.c | 196 + src/nf-ct-list.c | 136 + src/nf-exp-add.c | 187 + src/nf-exp-delete.c | 165 + src/nf-exp-list.c | 137 + src/nf-log.c | 147 + src/nf-monitor.c | 105 + src/nf-queue.c | 149 + src/nl-addr-add.c | 120 + src/nl-addr-delete.c | 140 + src/nl-addr-list.c | 196 + src/nl-class-add.c | 155 + src/nl-class-delete.c | 128 + src/nl-class-list.c | 117 + src/nl-classid-lookup.c | 87 + src/nl-cls-add.c | 163 + src/nl-cls-delete.c | 155 + src/nl-cls-list.c | 129 + src/nl-fib-lookup.c | 109 + src/nl-link-enslave.c | 50 + src/nl-link-ifindex2name.c | 44 + src/nl-link-list.c | 98 + src/nl-link-name2ifindex.c | 41 + src/nl-link-release.c | 45 + src/nl-link-set.c | 128 + src/nl-link-stats.c | 119 + src/nl-list-caches.c | 117 + src/nl-list-sockets.c | 49 + src/nl-monitor.c | 115 + src/nl-neigh-add.c | 110 + src/nl-neigh-delete.c | 122 + src/nl-neigh-list.c | 89 + src/nl-neightbl-list.c | 66 + src/nl-pktloc-lookup.c | 154 + src/nl-qdisc-add.c | 146 + src/nl-qdisc-delete.c | 144 + src/nl-qdisc-list.c | 183 + src/nl-route-add.c | 132 + src/nl-route-delete.c | 168 + src/nl-route-get.c | 85 + src/nl-route-list.c | 129 + src/nl-rule-list.c | 77 + src/nl-tctree-list.c | 165 + src/nl-util-addr.c | 34 + tests/Makefile.am | 54 + tests/Makefile.in | 814 ++ tests/check-addr.c | 212 + tests/check-all.c | 44 + tests/check-attr.c | 88 + tests/test-cache-mngr.c | 66 + tests/test-complex-HTB-with-hash-filters.c | 761 ++ tests/test-create-bond.c | 29 + tests/test-create-vlan.c | 43 + tests/test-delete-link.c | 28 + tests/test-genl.c | 118 + tests/test-nf-cache-mngr.c | 57 + tests/test-socket-creation.c | 28 + tests/util.h | 5 + 356 files changed, 116150 insertions(+) create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 Makefile.am create mode 100644 Makefile.in create mode 100644 aclocal.m4 create mode 100755 build-aux/ar-lib create mode 100755 build-aux/compile create mode 100755 build-aux/config.guess create mode 100755 build-aux/config.sub create mode 100755 build-aux/depcomp create mode 100755 build-aux/install-sh create mode 100644 build-aux/ltmain.sh create mode 100755 build-aux/missing create mode 100755 configure create mode 100644 configure.ac create mode 100644 etc/classid create mode 100644 etc/pktloc create mode 100644 include/Makefile.am create mode 100644 include/Makefile.in create mode 100644 include/linux/can/netlink.h create mode 100644 include/linux/fib_rules.h create mode 100644 include/linux/gen_stats.h create mode 100644 include/linux/genetlink.h create mode 100644 include/linux/if.h create mode 100644 include/linux/if_addr.h create mode 100644 include/linux/if_arp.h create mode 100644 include/linux/if_bridge.h create mode 100644 include/linux/if_ether.h create mode 100644 include/linux/if_link.h create mode 100644 include/linux/if_vlan.h create mode 100644 include/linux/inetdevice.h create mode 100644 include/linux/ip_mp_alg.h create mode 100644 include/linux/ipv6.h create mode 100644 include/linux/neighbour.h create mode 100644 include/linux/netfilter.h create mode 100644 include/linux/netfilter/nf_conntrack_common.h create mode 100644 include/linux/netfilter/nfnetlink.h create mode 100644 include/linux/netfilter/nfnetlink_compat.h create mode 100644 include/linux/netfilter/nfnetlink_conntrack.h create mode 100644 include/linux/netfilter/nfnetlink_log.h create mode 100644 include/linux/netfilter/nfnetlink_queue.h create mode 100644 include/linux/netlink.h create mode 100644 include/linux/pkt_cls.h create mode 100644 include/linux/pkt_sched.h create mode 100644 include/linux/rtnetlink.h create mode 100644 include/linux/snmp.h create mode 100644 include/linux/tc_ematch/tc_em_meta.h create mode 100644 include/netlink-private/cache-api.h create mode 100644 include/netlink-private/genl.h create mode 100644 include/netlink-private/netlink.h create mode 100644 include/netlink-private/object-api.h create mode 100644 include/netlink-private/route/link/api.h create mode 100644 include/netlink-private/route/tc-api.h create mode 100644 include/netlink-private/tc.h create mode 100644 include/netlink-private/types.h create mode 100644 include/netlink/addr.h create mode 100644 include/netlink/attr.h create mode 100644 include/netlink/cache-api.h create mode 100644 include/netlink/cache.h create mode 100644 include/netlink/cli/addr.h create mode 100644 include/netlink/cli/class.h create mode 100644 include/netlink/cli/cls.h create mode 100644 include/netlink/cli/ct.h create mode 100644 include/netlink/cli/exp.h create mode 100644 include/netlink/cli/link.h create mode 100644 include/netlink/cli/neigh.h create mode 100644 include/netlink/cli/qdisc.h create mode 100644 include/netlink/cli/route.h create mode 100644 include/netlink/cli/rule.h create mode 100644 include/netlink/cli/tc.h create mode 100644 include/netlink/cli/utils.h create mode 100644 include/netlink/data.h create mode 100644 include/netlink/errno.h create mode 100644 include/netlink/fib_lookup/lookup.h create mode 100644 include/netlink/fib_lookup/request.h create mode 100644 include/netlink/genl/ctrl.h create mode 100644 include/netlink/genl/family.h create mode 100644 include/netlink/genl/genl.h create mode 100644 include/netlink/genl/mngt.h create mode 100644 include/netlink/handlers.h create mode 100644 include/netlink/hash.h create mode 100644 include/netlink/hashtable.h create mode 100644 include/netlink/list.h create mode 100644 include/netlink/msg.h create mode 100644 include/netlink/netfilter/ct.h create mode 100644 include/netlink/netfilter/exp.h create mode 100644 include/netlink/netfilter/log.h create mode 100644 include/netlink/netfilter/log_msg.h create mode 100644 include/netlink/netfilter/netfilter.h create mode 100644 include/netlink/netfilter/nfnl.h create mode 100644 include/netlink/netfilter/queue.h create mode 100644 include/netlink/netfilter/queue_msg.h create mode 100644 include/netlink/netlink-compat.h create mode 100644 include/netlink/netlink-kernel.h create mode 100644 include/netlink/netlink.h create mode 100644 include/netlink/object-api.h create mode 100644 include/netlink/object.h create mode 100644 include/netlink/route/addr.h create mode 100644 include/netlink/route/class.h create mode 100644 include/netlink/route/classifier.h create mode 100644 include/netlink/route/cls/basic.h create mode 100644 include/netlink/route/cls/cgroup.h create mode 100644 include/netlink/route/cls/ematch.h create mode 100644 include/netlink/route/cls/ematch/cmp.h create mode 100644 include/netlink/route/cls/ematch/meta.h create mode 100644 include/netlink/route/cls/ematch/nbyte.h create mode 100644 include/netlink/route/cls/ematch/text.h create mode 100644 include/netlink/route/cls/fw.h create mode 100644 include/netlink/route/cls/police.h create mode 100644 include/netlink/route/cls/u32.h create mode 100644 include/netlink/route/link.h create mode 100644 include/netlink/route/link/api.h create mode 100644 include/netlink/route/link/bonding.h create mode 100644 include/netlink/route/link/bridge.h create mode 100644 include/netlink/route/link/can.h create mode 100644 include/netlink/route/link/inet.h create mode 100644 include/netlink/route/link/info-api.h create mode 100644 include/netlink/route/link/vlan.h create mode 100644 include/netlink/route/neighbour.h create mode 100644 include/netlink/route/neightbl.h create mode 100644 include/netlink/route/nexthop.h create mode 100644 include/netlink/route/pktloc.h create mode 100644 include/netlink/route/qdisc.h create mode 100644 include/netlink/route/qdisc/cbq.h create mode 100644 include/netlink/route/qdisc/dsmark.h create mode 100644 include/netlink/route/qdisc/fifo.h create mode 100644 include/netlink/route/qdisc/htb.h create mode 100644 include/netlink/route/qdisc/netem.h create mode 100644 include/netlink/route/qdisc/plug.h create mode 100644 include/netlink/route/qdisc/prio.h create mode 100644 include/netlink/route/qdisc/red.h create mode 100644 include/netlink/route/qdisc/sfq.h create mode 100644 include/netlink/route/qdisc/tbf.h create mode 100644 include/netlink/route/route.h create mode 100644 include/netlink/route/rtnl.h create mode 100644 include/netlink/route/rule.h create mode 100644 include/netlink/route/tc-api.h create mode 100644 include/netlink/route/tc.h create mode 100644 include/netlink/socket.h create mode 100644 include/netlink/types.h create mode 100644 include/netlink/utils.h create mode 100644 include/netlink/version.h create mode 100644 include/netlink/version.h.in create mode 100644 lib/Makefile.am create mode 100644 lib/Makefile.in create mode 100644 lib/addr.c create mode 100644 lib/attr.c create mode 100644 lib/cache.c create mode 100644 lib/cache_mngr.c create mode 100644 lib/cache_mngt.c create mode 100644 lib/cli/cls/basic.c create mode 100644 lib/cli/cls/cgroup.c create mode 100644 lib/cli/qdisc/bfifo.c create mode 100644 lib/cli/qdisc/blackhole.c create mode 100644 lib/cli/qdisc/htb.c create mode 100644 lib/cli/qdisc/pfifo.c create mode 100644 lib/cli/qdisc/plug.c create mode 100644 lib/data.c create mode 100644 lib/defs.h.in create mode 100644 lib/error.c create mode 100644 lib/fib_lookup/lookup.c create mode 100644 lib/fib_lookup/request.c create mode 100644 lib/genl/ctrl.c create mode 100644 lib/genl/family.c create mode 100644 lib/genl/genl.c create mode 100644 lib/genl/mngt.c create mode 100644 lib/handlers.c create mode 100644 lib/hash.c create mode 100644 lib/hashtable.c create mode 100644 lib/msg.c create mode 100644 lib/netfilter/ct.c create mode 100644 lib/netfilter/ct_obj.c create mode 100644 lib/netfilter/exp.c create mode 100644 lib/netfilter/exp_obj.c create mode 100644 lib/netfilter/log.c create mode 100644 lib/netfilter/log_msg.c create mode 100644 lib/netfilter/log_msg_obj.c create mode 100644 lib/netfilter/log_obj.c create mode 100644 lib/netfilter/netfilter.c create mode 100644 lib/netfilter/nfnl.c create mode 100644 lib/netfilter/queue.c create mode 100644 lib/netfilter/queue_msg.c create mode 100644 lib/netfilter/queue_msg_obj.c create mode 100644 lib/netfilter/queue_obj.c create mode 100644 lib/nl.c create mode 100644 lib/object.c create mode 100644 lib/route/addr.c create mode 100644 lib/route/class.c create mode 100644 lib/route/classid.c create mode 100644 lib/route/cls.c create mode 100644 lib/route/cls/basic.c create mode 100644 lib/route/cls/cgroup.c create mode 100644 lib/route/cls/ematch.c create mode 100644 lib/route/cls/ematch/cmp.c create mode 100644 lib/route/cls/ematch/container.c create mode 100644 lib/route/cls/ematch/meta.c create mode 100644 lib/route/cls/ematch/nbyte.c create mode 100644 lib/route/cls/ematch/text.c create mode 100644 lib/route/cls/ematch_grammar.l create mode 100644 lib/route/cls/ematch_syntax.y create mode 100644 lib/route/cls/fw.c create mode 100644 lib/route/cls/police.c create mode 100644 lib/route/cls/u32.c create mode 100644 lib/route/link.c create mode 100644 lib/route/link/api.c create mode 100644 lib/route/link/bonding.c create mode 100644 lib/route/link/bridge.c create mode 100644 lib/route/link/can.c create mode 100644 lib/route/link/dummy.c create mode 100644 lib/route/link/inet.c create mode 100644 lib/route/link/inet6.c create mode 100644 lib/route/link/vlan.c create mode 100644 lib/route/neigh.c create mode 100644 lib/route/neightbl.c create mode 100644 lib/route/nexthop.c create mode 100644 lib/route/pktloc.c create mode 100644 lib/route/pktloc_grammar.l create mode 100644 lib/route/pktloc_syntax.y create mode 100644 lib/route/qdisc.c create mode 100644 lib/route/qdisc/blackhole.c create mode 100644 lib/route/qdisc/cbq.c create mode 100644 lib/route/qdisc/dsmark.c create mode 100644 lib/route/qdisc/fifo.c create mode 100644 lib/route/qdisc/htb.c create mode 100644 lib/route/qdisc/netem.c create mode 100644 lib/route/qdisc/plug.c create mode 100644 lib/route/qdisc/prio.c create mode 100644 lib/route/qdisc/red.c create mode 100644 lib/route/qdisc/sfq.c create mode 100644 lib/route/qdisc/tbf.c create mode 100644 lib/route/route.c create mode 100644 lib/route/route_obj.c create mode 100644 lib/route/route_utils.c create mode 100644 lib/route/rtnl.c create mode 100644 lib/route/rule.c create mode 100644 lib/route/tc.c create mode 100644 lib/socket.c create mode 100644 lib/utils.c create mode 100644 lib/version.c create mode 100644 libnl-3.0.pc.in create mode 100644 libnl-3.9.0.tar.gz create mode 100644 libnl-cli-3.0.pc.in create mode 100644 libnl-genl-3.0.pc.in create mode 100644 libnl-nf-3.0.pc.in create mode 100644 libnl-route-3.0.pc.in create mode 100644 m4/libtool.m4 create mode 100644 m4/ltoptions.m4 create mode 100644 m4/ltsugar.m4 create mode 100644 m4/ltversion.m4 create mode 100644 m4/lt~obsolete.m4 create mode 100644 man/Makefile.am create mode 100644 man/Makefile.in create mode 100644 man/genl-ctrl-list.8 create mode 100644 man/nl-classid-lookup.8 create mode 100644 man/nl-pktloc-lookup.8 create mode 100644 man/nl-qdisc-add.8 create mode 100644 man/nl-qdisc-delete.8 create mode 100644 man/nl-qdisc-list.8 create mode 100644 python/Makefile.am create mode 100644 python/Makefile.in create mode 100644 python/README create mode 100644 python/netlink/Makefile.am create mode 100644 python/netlink/Makefile.in create mode 100644 python/netlink/__init__.py create mode 100644 python/netlink/capi.i create mode 100644 python/netlink/core.py create mode 100644 python/netlink/fixes.h create mode 100644 python/netlink/route/Makefile.am create mode 100644 python/netlink/route/Makefile.in create mode 100644 python/netlink/route/__init__.py create mode 100644 python/netlink/route/address.py create mode 100644 python/netlink/route/capi.i create mode 100644 python/netlink/route/link.py create mode 100644 python/netlink/route/links/__init__.py create mode 100644 python/netlink/route/links/dummy.py create mode 100644 python/netlink/route/links/inet.py create mode 100644 python/netlink/route/links/vlan.py create mode 100644 python/netlink/route/qdisc/__init__.py create mode 100644 python/netlink/route/qdisc/htb.py create mode 100644 python/netlink/route/tc.py create mode 100644 python/netlink/util.py create mode 100644 python/setup.py.in create mode 100644 src/Makefile.am create mode 100644 src/Makefile.in create mode 100644 src/genl-ctrl-list.c create mode 100644 src/lib/Makefile.am create mode 100644 src/lib/Makefile.in create mode 100644 src/lib/addr.c create mode 100644 src/lib/class.c create mode 100644 src/lib/cls.c create mode 100644 src/lib/ct.c create mode 100644 src/lib/exp.c create mode 100644 src/lib/link.c create mode 100644 src/lib/neigh.c create mode 100644 src/lib/qdisc.c create mode 100644 src/lib/route.c create mode 100644 src/lib/rule.c create mode 100644 src/lib/tc.c create mode 100644 src/lib/utils.c create mode 100644 src/nf-ct-list.c create mode 100644 src/nf-exp-add.c create mode 100644 src/nf-exp-delete.c create mode 100644 src/nf-exp-list.c create mode 100644 src/nf-log.c create mode 100644 src/nf-monitor.c create mode 100644 src/nf-queue.c create mode 100644 src/nl-addr-add.c create mode 100644 src/nl-addr-delete.c create mode 100644 src/nl-addr-list.c create mode 100644 src/nl-class-add.c create mode 100644 src/nl-class-delete.c create mode 100644 src/nl-class-list.c create mode 100644 src/nl-classid-lookup.c create mode 100644 src/nl-cls-add.c create mode 100644 src/nl-cls-delete.c create mode 100644 src/nl-cls-list.c create mode 100644 src/nl-fib-lookup.c create mode 100644 src/nl-link-enslave.c create mode 100644 src/nl-link-ifindex2name.c create mode 100644 src/nl-link-list.c create mode 100644 src/nl-link-name2ifindex.c create mode 100644 src/nl-link-release.c create mode 100644 src/nl-link-set.c create mode 100644 src/nl-link-stats.c create mode 100644 src/nl-list-caches.c create mode 100644 src/nl-list-sockets.c create mode 100644 src/nl-monitor.c create mode 100644 src/nl-neigh-add.c create mode 100644 src/nl-neigh-delete.c create mode 100644 src/nl-neigh-list.c create mode 100644 src/nl-neightbl-list.c create mode 100644 src/nl-pktloc-lookup.c create mode 100644 src/nl-qdisc-add.c create mode 100644 src/nl-qdisc-delete.c create mode 100644 src/nl-qdisc-list.c create mode 100644 src/nl-route-add.c create mode 100644 src/nl-route-delete.c create mode 100644 src/nl-route-get.c create mode 100644 src/nl-route-list.c create mode 100644 src/nl-rule-list.c create mode 100644 src/nl-tctree-list.c create mode 100644 src/nl-util-addr.c create mode 100644 tests/Makefile.am create mode 100644 tests/Makefile.in create mode 100644 tests/check-addr.c create mode 100644 tests/check-all.c create mode 100644 tests/check-attr.c create mode 100644 tests/test-cache-mngr.c create mode 100644 tests/test-complex-HTB-with-hash-filters.c create mode 100644 tests/test-create-bond.c create mode 100644 tests/test-create-vlan.c create mode 100644 tests/test-delete-link.c create mode 100644 tests/test-genl.c create mode 100644 tests/test-nf-cache-mngr.c create mode 100644 tests/test-socket-creation.c create mode 100644 tests/util.h diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..4362b49 --- /dev/null +++ b/COPYING @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..cdd78a8 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,336 @@ +ChangeLog discontinued, git history can be found here: +http://git.infradead.org/users/tgr/libnl.git + +Summary of Changes from 1.0-pre6 to 1.0-pre7 +================================================ + Thomas Graf + o Generic netlink support + o Route Addition/Deletion + o Added nl_cache_subset() + o Have nl_object_clone() make real clones without + sharing any data. + o Remove old nl_object_alloc() not based on a object + operations to avoid bugs due to missing init. + o Added nl-list-caches utility + o Removed nlmsg_build_no_hdr(), duplicate + o Reworked message interface + o Fixed nlmsg_put() and genlmsg_put() to correctly reserve + tail room for user specific headers. + o Added nl_cache_move() + o Renamed nl_cache_delete() to nl_cache_remove() (no API break) + o Fixed reference counting while objects stay in caches. + o Object marking + o Moved attribute mask for objects into generic structure + o nl-list-caches: List available dump procedures + o Use PAGE_SIZE as initial buffer size when reading from + netlink socket + o Double buffer size when recv() returns MSG_TRUNC + o Replaced filter object operation with new compare operation + capable of listing differences between two objects + o Added nl_object_identical() to check if two objects are + identical from a uniqueness point of view + o Added nl_object_diff() returning a bitmask of differences in + attributes + o Added nl_object_attr_list() generating a list of attribute + name the object has assigned + o Cache updates based on event notifications, code based on + Patrick McHardy's patches + o Cache Manager + o Added NL_AUTO_PID, NL_AUTO_SEQ for convenience + o Disable MSG_PEEK by default and provide nl_socket_enable_msg_peek() + o Fixed nl_recvmsgs() to return 0 when interrupted via NL_STOP or + NL_SKIP + o Fixed nl_recvmsgs() to stop reading after parsing if not in the + middle of a multipart message. + o Fixed nl_recvmsgs() to not stop after receving an ACK + o Fixed nl_recvmsgs() to not blindly discard remaining messages + if a NLMSG_DONE message is received. + + Petr Gotthard + Siemens AG Oesterreich + o Fix u32 to properly handle multiple keys + o rtnl_htb_set_(r|c)buffer() + o Fixed MTU handling in HTB class, problem pointed out + by Edouard Thuleau + + Zilvinas Valinskas + o Fix wrong msg_namelen in nl_recv() + o Fix memory leak in flnl_request_put() + + Helmut Schaa + o Fix for using libnl from within C++ + + Patrick McHardy + o *_alloc_cache(): Only refill cache if handle is provided + + James Oakley + o Fix rtnl_link_set_arptype() typo + + Philip Craig + o Change address family type from char to int + o Fix the error handling when the build fails. + o add nl_cache_mngr_get_fd() + o add netfilter support + o add netfilter conntrack support + o add netfilter log support + +Summary of Changes from 1.0-pre5 to 1.0-pre6 +================================================ + Christopher Aillon + o Use $(libdir) instead of $(prefix)/lib for 64bit awesomeness. + + Thomas Graf + o Extend nl_msg to include source address, destination address + and the protocol being used. + o Make nl_send*() take a nl_msg instead of a nlmsghdr (API BREAK) + o Change callbacks to take a nl_msg instead of source address + and nlmsghdr (API BREAK) + o caches must specify the protocol they're hooked up from now on + if they intend to be associated with message types. + o cache_mngt_associate now takes the protocol besides the message + type to allow for multiple protocols to be supported (API BREAK) + o overwrite destination address in nl_send() when specified in the + message itself, allows for unbound addressing. + o Support for netlink based fib_lookup() + o Documentation fixes + o Fix double nlmsg_free() in nl_recvmsgs() while receiving + a multipart message and the read was interrupted. + o Change cache operations to store names for message types. + o Provide interface to convert message type to character string. + o Add dp_dump_msgtype to prefix each dumped element with a + pretty printed message type. + o netlink fib lookup support + o nl_recvmsgs() debugging + o use nl_cachemngt_type2name() when pretty printing netlink header + o Routing protocol translations. + o Routing metric translations. + o Revised route dumping + o Nexthop flag translations. + o Add support for IFF_DORMANT + + Petr Gotthard + Siemens AG Oesterreich + o Fix access to obj after freeing it + o Fix u32 selector access after realloc() + o Fix missing out-of-memory error handling in various places + o Enhance nl-monitor to have group selection selectable and + demonstrate usage of select() + o Don't ignore IFF_RUNNING any longer + o fw classifier support + + Patrick McHardy + o Fix conflicting types for __u64 + o Fix printf format string warnings + o Fix object cloning + o Deal with structure padding in nl_object_clone + o Fix nl_addr leak + o Set ce_msgtype in all parsed objects + o Fix addr flag filter + o Fix RTNLGRP definitions (was based on broken kernel version) + o Export nl_get_errno() + o Add function to get/set peer pid + o Add IFF_LOWER_UP + o Add/export some missing accessor functions + o print /0 prefix in nl_addr2str() + o Fix invalid free in nl_addr_parse for AF_UNSPEC addresses + o Use __str2flags instead of __str2type in rtnl_link_str2flags() + o Make sure object and filter types match in nl_object_match() + o Add support for credential passing over netlink sockets (API BREAK) + o Add support for custom dump callbacks + o Add NL_DUMP_ENV format + + Michael Biebl + "Alex V. Myltsev" + o Makefile fixes + + +Summary of Changes from 1.0-pre4 to 1.0-pre5 +================================================ + Thomas Graf + o Use minimized local copies for , , + and to avoid compile troubles with + applications including + Reported by Christopher Aillon. + +Summary of Changes from 1.0-pre3 to 1.0-pre4 +================================================ + Thomas Graf + o Fix wrong rtnl_addr_set_prefixlen() external declaration, + reported by Dan Williams. + o Fix nl_addr_parse() to not change the original string + for prefixes. + o Do not build documentation per default, but have the user + issue 'make gendoc' + o Assume neighbours to be permanent, set NUD_PERMANENT if not + specified otherwise. + +Summary of Changes from 1.0-pre2 to 1.0-pre3 +================================================ + Thomas Graf + o Fix SFQ parser to allocate qdisc options. + o Fix rule statistics dumping to not call itself. + o Complete Netem qdisc interface. + o Add rtnl_*_put() and rtnl_*_free() to increase readability. + o Cleanup of nl-* tools + o Fix inclusion guards of route/neightbl.h + o Fix nl_connect() to only modify rx/tx socket buffers if not + already modified by the user. + o Fix wrong nl_handle_alloc() prototype. + o Fix typo in route/addr.c causing label to be marked as + local address. + o Use ~0UL as default prefix length instead of 0. + o Fix neighbour message parser to correctly store core. + attributes and provide them again. + o Fix neighbour message parser to correctly guess address family. + to make it compatible with nl_addr_parse() and ether llc + addresses. + o Add rtnl_route_table2str(), rtnl_route_str2table(). + o Add nl_cache_nitems_filter() to find out if a filter produces + any matches. + o Remove rtnl_rule_set_(dst|src)_str() (obsolete). + o Remove scope and protocol field of routing rule. + o Complete routing rules module. + o Move realms translations from route to rtnl module. + +Summary of Changes from 1.0-pre1 to 1.0-pre2 +================================================ + Thomas Graf + o More API documentation + o Added flags argument to rtnl_addr_(add|build_add_request)(). + o Added rtnl_addr_(set|get)_multicast(). + o Moved scope translations routines from route/route.c to + route/rtnl.c, required by other modules as well. + o Removed old rtattr bits from rtnetlink-kernel.h + o Customized libnl.css for doxygen documentation + o Removed non-reentrant translation routines, only bloating + the code and too risky. + o Fixed wrong version number from 1.0-pre1. + o Reenabled unfinished policer module. + o Reworked TBF module, automatic caluclation of transmit times, + limit setable via latency, automatic cell size calculation, + options TLV generation. (untested) + o Renamed nl_xmittime() to rtnl_tc_calc_txtime(). + o Renamde nl_build_rtable() to rtnl_tc_build_rate_table() + + Petr Gotthard , + Siemens AG Oesterreich + o Fix symlinks to libnl library files to be moveable + o Fix extern struct prototypes meant to be static. + o Add empty install target to src/Makefile + + Simon Stelling + o Use LIBDIR instead of $(prefix)/lib for users to alllow librariers + into $(prefix)/lib64. + +Summary of Changes from 0.5.0 to 1.0-pre1 +================================================ + Thomas Graf + o Uncountable number of changes, rewrite of certain modules, + several major API breakages + + Petr Gotthard , + Siemens AG Oesterreich + o added class_build, rtnl_class_build_add_request, rtnl_class_add + o added HTB (Hierachical Token Bucket) class support + o added nl_xmittime, nl_build_rtable + o added nl_data_append to realloc a nl_data structure + o added rtnl_rcopy_ratespec as reverse to rtnl_copy_ratespec + o fixed byte order conversion of rtnl_filter.protocol + o SuSE and Fedora Linux compile fixes + o fixed u32 classifier support + o added rtnl_u32_set_handle, rtnl_u32_set_classid, rtnl_u32_set_flags + and several rtnl_u32_add_key_... operations to u32 classifier + +Summary of Changes from 0.4.4 to 0.5.0 +================================================ + Thomas Graf + o API documentation + o nl_cache_filter to manually filter on a object + o partial routing support + o routing rules support + o Propely set address family when setting addresses + o debug flag and some rare messages, more to come + o make error mesage verboseness configureable + o tc fixes to wait for ack + o cleanup and adaption of address code to latest internal API + o various cleanups + o dozens of API breakages (better now than later) + + Daniel Hottinger + o arch 64bit printf length modifier fixes + + Baruch Even , + Mediatrix Telecom, inc. + o address support + +Summary of changes from 0.4.3 to 0.4.4 +================================================ + Thomas Graf : + o overall cleanups for better code quality + o replace dump_(brief|full|with_stats) ops with + dump[NL_DUMP_MAX] array to allow further additions without + breaking the ABI. + o add of send_ack callback, called whenever when oppenent + asks for an ACK. + o make nl_parse_rtattr initialize the tb buffer like in the + kernel, caller must no longer take care of it. + o remove nl_addrnattr (obsolete) + o fixed nl_msg_append_raw to correctly calculate length + for raw data not aligned to NLMSG_ALIGN + o fix memory leak in nl_recv in case of errors + o correctly check sequence numbers if more than one message + was sent out before the answer is being received. + o add workaround for buggy netlink applications not properly + setting NLM_F_MULTI. + +Summary of changes from 0.4.2 to 0.4.3 +================================================ + + Thomas Graf : + o use parser_param in nl_cache_parse + o EGP: dump nfilters attribute + o allow retrieving of filters attached to classes via + FILTER_CACHE_PARENT(C) cache argument + o filter message building API + +Summary of changes from 0.4.1 to 0.4.2 +================================================ + + Baruch Even : + o memory leak fix in nl_parse_rtattr + o reset padding to 0 when appending raw data to a nl_msg + o avoid overwriting nlmsg ptr when buffer extending fails + o typo fixes + o create symlinks libnl.so.0 and libnl.so + + Thomas Graf : + o EGP classifier support + o avoid null pointer in printf call + o added nl_cache_parse to put nl_msg's into a cache + o added rtnl_filter_build to build a nl_msg filter message + o correctly install header files + o nl_msg_payload/nl_msg_payloadlen to access nl_msg payload + o nl_parse_nested macro to simplify nested TLV parsing + o NL_ERROR_ASSERT compile flag to assert(0) on errors + o rta alignment fix in nl_msg_append_tlv + o added nl_msg_parse_rtattr as shortcut for nl_parse_rtattr + for nl_msg API + o added nl_parse_nested for nested TLVs + o added RTA_ARRAY_ELEMS macro to calculate array length + for array TLVs + o added nl_wait_for_ack to wait for the next ack + o added rtnl_link_build_change_request(...) + o added rtnl_neigh_build_*_request + o converted neighbour code to use nl_wait_for_ack + o cb_recvmsgs_ow callback to overwrite internal calls to + nl_recvmsgs_def + o cb_seq_check callback to overwrite default sequence checking + o added nl_parser_param as argument for message parsers including + a callback to be called upon successful parsing of a message. + Removes the requirement of having all parsed messages to be added + to a cache. + o added cb_recv_ow and nl_send_ow callbacks to overwrite internal + calls to nl_recv and nl_send. + + Jamal Hadi Salim + o Linux 2.4 compile fixes diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..bc4266d --- /dev/null +++ b/Makefile.am @@ -0,0 +1,22 @@ +# -*- Makefile -*- + +ACLOCAL_AMFLAGS = -I m4 + +SUBDIRS = include lib man python tests + +pkgconfig_DATA = libnl-3.0.pc \ + libnl-route-3.0.pc \ + libnl-genl-3.0.pc \ + libnl-nf-3.0.pc + +if ENABLE_CLI +SUBDIRS += src +pkgconfig_DATA += libnl-cli-3.0.pc +endif + + +pkgsysconfdir = ${sysconfdir}/libnl +pkgsysconf_DATA = etc/pktloc etc/classid + +EXTRA_DIST = \ + $(pkgsysconf_DATA) diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..03c8d14 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,874 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# -*- Makefile -*- + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@ENABLE_CLI_TRUE@am__append_1 = src +@ENABLE_CLI_TRUE@am__append_2 = libnl-cli-3.0.pc +subdir = . +DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/libnl-3.0.pc.in \ + $(srcdir)/libnl-cli-3.0.pc.in $(srcdir)/libnl-genl-3.0.pc.in \ + $(srcdir)/libnl-nf-3.0.pc.in $(srcdir)/libnl-route-3.0.pc.in \ + $(top_srcdir)/configure \ + $(top_srcdir)/include/netlink/version.h.in COPYING ChangeLog \ + build-aux/ar-lib build-aux/compile build-aux/config.guess \ + build-aux/config.sub build-aux/depcomp build-aux/install-sh \ + build-aux/ltmain.sh build-aux/missing +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/lib/defs.h +CONFIG_CLEAN_FILES = libnl-3.0.pc libnl-route-3.0.pc libnl-genl-3.0.pc \ + libnl-nf-3.0.pc libnl-cli-3.0.pc include/netlink/version.h +CONFIG_CLEAN_VPATH_FILES = +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkgconfigdir)" \ + "$(DESTDIR)$(pkgsysconfdir)" +DATA = $(pkgconfig_DATA) $(pkgsysconf_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir dist dist-all distcheck +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = include lib man python tests src +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_CFLAGS = @CHECK_CFLAGS@ +CHECK_LIBS = @CHECK_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FLEX = @FLEX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBNL_VERSION = @LIBNL_VERSION@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_CURRENT = @LT_CURRENT@ +LT_REVISION = @LT_REVISION@ +MAJ_VERSION = @MAJ_VERSION@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIC_VERSION = @MIC_VERSION@ +MIN_VERSION = @MIN_VERSION@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgconfigdir = @pkgconfigdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I m4 +SUBDIRS = include lib man python tests $(am__append_1) +pkgconfig_DATA = libnl-3.0.pc libnl-route-3.0.pc libnl-genl-3.0.pc \ + libnl-nf-3.0.pc $(am__append_2) +pkgsysconfdir = ${sysconfdir}/libnl +pkgsysconf_DATA = etc/pktloc etc/classid +EXTRA_DIST = \ + $(pkgsysconf_DATA) + +all: all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): +libnl-3.0.pc: $(top_builddir)/config.status $(srcdir)/libnl-3.0.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +libnl-route-3.0.pc: $(top_builddir)/config.status $(srcdir)/libnl-route-3.0.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +libnl-genl-3.0.pc: $(top_builddir)/config.status $(srcdir)/libnl-genl-3.0.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +libnl-nf-3.0.pc: $(top_builddir)/config.status $(srcdir)/libnl-nf-3.0.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +libnl-cli-3.0.pc: $(top_builddir)/config.status $(srcdir)/libnl-cli-3.0.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +include/netlink/version.h: $(top_builddir)/config.status $(top_srcdir)/include/netlink/version.h.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) +install-pkgsysconfDATA: $(pkgsysconf_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgsysconf_DATA)'; test -n "$(pkgsysconfdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgsysconfdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgsysconfdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgsysconfdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgsysconfdir)" || exit $$?; \ + done + +uninstall-pkgsysconfDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgsysconf_DATA)'; test -n "$(pkgsysconfdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgsysconfdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__remove_distdir) + +dist-lzma: distdir + tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma + $(am__remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lzma*) \ + lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod u+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(pkgsysconfdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-libtool \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-pkgconfigDATA install-pkgsysconfDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-pkgconfigDATA uninstall-pkgsysconfDATA + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am am--refresh check check-am clean clean-generic \ + clean-libtool ctags ctags-recursive dist dist-all dist-bzip2 \ + dist-gzip dist-lzip dist-lzma dist-shar dist-tarZ dist-xz \ + dist-zip distcheck distclean distclean-generic \ + distclean-libtool distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkgconfigDATA \ + install-pkgsysconfDATA install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-recursive uninstall uninstall-am \ + uninstall-pkgconfigDATA uninstall-pkgsysconfDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..af98b20 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,1287 @@ +# generated automatically by aclocal 1.11.6 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, +# Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],, +[m4_warning([this file was generated for autoconf 2.68. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically `autoreconf'.])]) + +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# serial 1 (pkg-config-0.24) +# +# Copyright © 2004 Scott James Remnant . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# PKG_PROG_PKG_CONFIG([MIN-VERSION]) +# ---------------------------------- +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])# PKG_PROG_PKG_CONFIG + +# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# +# Check to see whether a particular set of modules exists. Similar +# to PKG_CHECK_MODULES(), but does not set variables or print errors. +# +# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +# only at the first occurence in configure.ac, so if the first place +# it's called might be skipped (such as if it is within an "if", you +# have to call PKG_CHECK_EXISTS manually +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +# --------------------------------------------- +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])# _PKG_CONFIG + +# _PKG_SHORT_ERRORS_SUPPORTED +# ----------------------------- +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])# _PKG_SHORT_ERRORS_SUPPORTED + + +# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# +# +# Note that if there is a possibility the first call to +# PKG_CHECK_MODULES might not happen, you should be sure to include an +# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +# +# +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT]) + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .]) + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])# PKG_CHECK_MODULES + +# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008, 2011 Free Software +# Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.11' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.11.6], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.11.6])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# Copyright (C) 2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_PROG_AR([ACT-IF-FAIL]) +# ------------------------- +# Try to determine the archiver interface, and trigger the ar-lib wrapper +# if it is needed. If the detection of archiver interface fails, run +# ACT-IF-FAIL (default is to abort configure with a proper error message). +AC_DEFUN([AM_PROG_AR], +[AC_BEFORE([$0], [LT_INIT])dnl +AC_BEFORE([$0], [AC_PROG_LIBTOOL])dnl +AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([ar-lib])dnl +AC_CHECK_TOOLS([AR], [ar lib "link -lib"], [false]) +: ${AR=ar} + +AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface], + [am_cv_ar_interface=ar + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int some_variable = 0;]])], + [am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([am_ar_try]) + if test "$ac_status" -eq 0; then + am_cv_ar_interface=ar + else + am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([am_ar_try]) + if test "$ac_status" -eq 0; then + am_cv_ar_interface=lib + else + am_cv_ar_interface=unknown + fi + fi + rm -f conftest.lib libconftest.a + ]) + ]) + +case $am_cv_ar_interface in +ar) + ;; +lib) + # Microsoft lib, so override with the ar-lib wrapper script. + # FIXME: It is wrong to rewrite AR. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__AR in this case, + # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something + # similar. + AR="$am_aux_dir/ar-lib $AR" + ;; +unknown) + m4_default([$1], + [AC_MSG_ERROR([could not determine $AR interface])]) + ;; +esac +AC_SUBST([AR])dnl +]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 9 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ(2.52)dnl + ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009, +# 2010, 2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 12 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], UPC, [depcc="$UPC" am_compiler_list=], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +#serial 5 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2008, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 16 + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.62])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES(OBJC)], + [define([AC_PROG_OBJC], + defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl +]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The `parallel-tests' driver may need to know about EXEEXT, so add the +dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl +]) + +dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001, 2003, 2005, 2008, 2011 Free Software Foundation, +# Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST(install_sh)]) + +# Copyright (C) 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 4 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 6 + +# AM_PROG_CC_C_O +# -------------- +# Like AC_PROG_CC_C_O, but changed for automake. +AC_DEFUN([AM_PROG_CC_C_O], +[AC_REQUIRE([AC_PROG_CC_C_O])dnl +AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +# FIXME: we rely on the cache variable name because +# there is no other way. +set dummy $CC +am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` +eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o +if test "$am_t" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +dnl Make sure AC_PROG_CC is never called again, or it will override our +dnl setting of CC. +m4_define([AC_PROG_CC], + [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 6 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# Copyright (C) 2003, 2004, 2005, 2006, 2011 Free Software Foundation, +# Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_PROG_MKDIR_P +# --------------- +# Check for `mkdir -p'. +AC_DEFUN([AM_PROG_MKDIR_P], +[AC_PREREQ([2.60])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, +dnl while keeping a definition of mkdir_p for backward compatibility. +dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. +dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of +dnl Makefile.ins that do not define MKDIR_P, so we do our own +dnl adjustment using top_builddir (which is defined more often than +dnl MKDIR_P). +AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +case $mkdir_p in + [[\\/$]]* | ?:[[\\/]]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2008, 2010 Free Software +# Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# Copyright (C) 2009, 2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# (`yes' being less verbose, `no' or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], +[ --enable-silent-rules less verbose build output (undo: `make V=1') + --disable-silent-rules verbose build output (undo: `make V=0')]) +case $enable_silent_rules in +yes) AM_DEFAULT_VERBOSITY=0;; +no) AM_DEFAULT_VERBOSITY=1;; +*) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few `make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using `$V' instead of `$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006, 2008, 2010 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 3 + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004, 2005, 2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of `v7', `ustar', or `pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of `-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([m4/libtool.m4]) +m4_include([m4/ltoptions.m4]) +m4_include([m4/ltsugar.m4]) +m4_include([m4/ltversion.m4]) +m4_include([m4/lt~obsolete.m4]) diff --git a/build-aux/ar-lib b/build-aux/ar-lib new file mode 100755 index 0000000..0f62c6f --- /dev/null +++ b/build-aux/ar-lib @@ -0,0 +1,270 @@ +#! /bin/sh +# Wrapper for Microsoft lib.exe + +me=ar-lib +scriptversion=2012-03-01.08; # UTC + +# Copyright (C) 2010, 2012 Free Software Foundation, Inc. +# Written by Peter Rosin . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + + +# func_error message +func_error () +{ + echo "$me: $1" 1>&2 + exit 1 +} + +file_conv= + +# func_file_conv build_file +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv in + mingw) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_at_file at_file operation archive +# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE +# for each of them. +# When interpreting the content of the @FILE, do NOT use func_file_conv, +# since the user would need to supply preconverted file names to +# binutils ar, at least for MinGW. +func_at_file () +{ + operation=$2 + archive=$3 + at_file_contents=`cat "$1"` + eval set x "$at_file_contents" + shift + + for member + do + $AR -NOLOGO $operation:"$member" "$archive" || exit $? + done +} + +case $1 in + '') + func_error "no command. Try '$0 --help' for more information." + ;; + -h | --h*) + cat <. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/config.guess b/build-aux/config.guess new file mode 100755 index 0000000..d622a44 --- /dev/null +++ b/build-aux/config.guess @@ -0,0 +1,1530 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-02-10' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/build-aux/config.sub b/build-aux/config.sub new file mode 100755 index 0000000..c894da4 --- /dev/null +++ b/build-aux/config.sub @@ -0,0 +1,1773 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-02-10' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | open8 \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i386-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/build-aux/depcomp b/build-aux/depcomp new file mode 100755 index 0000000..25a39e6 --- /dev/null +++ b/build-aux/depcomp @@ -0,0 +1,708 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2012-03-27.16; # UTC + +# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' "$nl" < "$tmpdepfile" | +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependent.h'. + # Do two passes, one to just change these to + # '$object: dependent.h' and one to simply 'dependent.h:'. + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'. + # However on + # $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\': + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + # tcc 0.9.26 (FIXME still under development at the moment of writing) + # will emit a similar output, but also prepend the continuation lines + # with horizontal tabulation characters. + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form 'foo.o: dependent.h', + # or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'. + # Do two passes, one to just change these to + # '$object: dependent.h' and one to simply 'dependent.h:'. + sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \ + < "$tmpdepfile" > "$depfile" + sed ' + s/[ '"$tab"'][ '"$tab"']*/ /g + s/^ *// + s/ *\\*$// + s/^[^:]*: *// + /^$/d + /:$/d + s/$/ :/ + ' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mechanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test "$stat" = 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' "$nl" < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/install-sh b/build-aux/install-sh new file mode 100755 index 0000000..a9244eb --- /dev/null +++ b/build-aux/install-sh @@ -0,0 +1,527 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2011-01-19.21; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + # Protect names problematic for `test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for `test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for `test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/ltmain.sh b/build-aux/ltmain.sh new file mode 100644 index 0000000..63ae69d --- /dev/null +++ b/build-aux/ltmain.sh @@ -0,0 +1,9655 @@ + +# libtool (GNU libtool) 2.4.2 +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, +# 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, +# or obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Usage: $progname [OPTION]... [MODE-ARG]... +# +# Provide generalized library-building support services. +# +# --config show all configuration variables +# --debug enable verbose shell tracing +# -n, --dry-run display commands without modifying any files +# --features display basic configuration information and exit +# --mode=MODE use operation mode MODE +# --preserve-dup-deps don't remove duplicate dependency libraries +# --quiet, --silent don't print informational messages +# --no-quiet, --no-silent +# print informational messages (default) +# --no-warn don't display warning messages +# --tag=TAG use configuration variables from tag TAG +# -v, --verbose print more informational messages than default +# --no-verbose don't print the extra informational messages +# --version print version information +# -h, --help, --help-all print short, long, or detailed help message +# +# MODE must be one of the following: +# +# clean remove files from the build directory +# compile compile a source file into a libtool object +# execute automatically set library path, then run a program +# finish complete the installation of libtool libraries +# install install libraries or executables +# link create a library or an executable +# uninstall remove libraries from an installed directory +# +# MODE-ARGS vary depending on the MODE. When passed as first option, +# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. +# Try `$progname --help --mode=MODE' for a more detailed description of MODE. +# +# When reporting a bug, please describe a test case to reproduce it and +# include the following information: +# +# host-triplet: $host +# shell: $SHELL +# compiler: $LTCC +# compiler flags: $LTCFLAGS +# linker: $LD (gnu? $with_gnu_ld) +# $progname: (GNU libtool) 2.4.2 +# automake: $automake_version +# autoconf: $autoconf_version +# +# Report bugs to . +# GNU libtool home page: . +# General help using GNU software: . + +PROGRAM=libtool +PACKAGE=libtool +VERSION=2.4.2 +TIMESTAMP="" +package_revision=1.3337 + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# NLS nuisances: We save the old values to restore during execute mode. +lt_user_locale= +lt_safe_locale= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test \"\${$lt_var+set}\" = set; then + save_$lt_var=\$$lt_var + $lt_var=C + export $lt_var + lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" + lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + fi" +done +LC_ALL=C +LANGUAGE=C +export LANGUAGE LC_ALL + +$lt_unset CDPATH + + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + + + +: ${CP="cp -f"} +test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} +: ${Xsed="$SED -e 1s/^X//"} + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +exit_status=$EXIT_SUCCESS + +# Make sure IFS has a sensible default +lt_nl=' +' +IFS=" $lt_nl" + +dirname="s,/[^/]*$,," +basename="s,^.*/,," + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} # func_dirname may be replaced by extended shell implementation + + +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "${1}" | $SED "$basename"` +} # func_basename may be replaced by extended shell implementation + + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi + func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` +} # func_dirname_and_basename may be replaced by extended shell implementation + + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname may be replaced by extended shell implementation + + +# These SED scripts presuppose an absolute path with a trailing slash. +pathcar='s,^/\([^/]*\).*$,\1,' +pathcdr='s,^/[^/]*,,' +removedotparts=':dotsl + s@/\./@/@g + t dotsl + s,/\.$,/,' +collapseslashes='s@/\{1,\}@/@g' +finalslash='s,/*$,/,' + +# func_normal_abspath PATH +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +# value returned in "$func_normal_abspath_result" +func_normal_abspath () +{ + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` + while :; do + # Processed it all yet? + if test "$func_normal_abspath_tpath" = / ; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result" ; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + +# func_relative_path SRCDIR DSTDIR +# generates a relative path from SRCDIR to DSTDIR, with a trailing +# slash if non-empty, suitable for immediately appending a filename +# without needing to append a separator. +# value returned in "$func_relative_path_result" +func_relative_path () +{ + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=${func_dirname_result} + if test "x$func_relative_path_tlibdir" = x ; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test "x$func_stripname_result" != x ; then + func_relative_path_result=${func_relative_path_result}/${func_stripname_result} + fi + + # Normalisation. If bindir is libdir, return empty string, + # else relative path ending with a slash; either way, target + # file name can be directly appended. + if test ! -z "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result/" + func_relative_path_result=$func_stripname_result + fi +} + +# The name of this program: +func_dirname_and_basename "$progpath" +progname=$func_basename_result + +# Make sure we have an absolute path for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=$func_dirname_result + progdir=`cd "$progdir" && pwd` + progpath="$progdir/$progname" + ;; + *) + save_IFS="$IFS" + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS="$save_IFS" + test -x "$progdir/$progname" && break + done + IFS="$save_IFS" + test -n "$progdir" || progdir=`pwd` + progpath="$progdir/$progname" + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed="${SED}"' -e 1s/^X//' +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' + +# Sed substitution that converts a w32 file name or path +# which contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-`\' parameter expansions in output of double_quote_subst that were +# `\'-ed in input to the same. If an odd number of `\' preceded a '$' +# in input to double_quote_subst, that '$' was protected from expansion. +# Since each input `\' is now two `\'s, look for any number of runs of +# four `\'s followed by two `\'s and then a '$'. `\' that '$'. +bs='\\' +bs2='\\\\' +bs4='\\\\\\\\' +dollar='\$' +sed_double_backslash="\ + s/$bs4/&\\ +/g + s/^$bs2$dollar/$bs&/ + s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g + s/\n//g" + +# Standard options: +opt_dry_run=false +opt_help=false +opt_quiet=false +opt_verbose=false +opt_warning=: + +# func_echo arg... +# Echo program name prefixed message, along with the current mode +# name if it has been set yet. +func_echo () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }$*" +} + +# func_verbose arg... +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $opt_verbose && func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +# func_error arg... +# Echo program name prefixed message to standard error. +func_error () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 +} + +# func_warning arg... +# Echo program name prefixed warning message to standard error. +func_warning () +{ + $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 + + # bash bug again: + : +} + +# func_fatal_error arg... +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + +# func_fatal_help arg... +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + func_error ${1+"$@"} + func_fatal_error "$help" +} +help="Try \`$progname --help' for more information." ## default + + +# func_grep expression filename +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_mkdir_p directory-path +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + my_directory_path="$1" + my_dir_list= + + if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then + + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$my_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + my_dir_list="$my_directory_path:$my_dir_list" + + # If the last portion added has no slash in it, the list is done + case $my_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` + done + my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` + + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$my_dir" 2>/dev/null || : + done + IFS="$save_mkdir_p_IFS" + + # Bail out if we (or some other process) failed to create a directory. + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" + fi +} + + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$opt_dry_run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || \ + func_fatal_error "cannot create temporary directory \`$my_tmpdir'" + fi + + $ECHO "$my_tmpdir" +} + + +# func_quote_for_eval arg +# Aesthetically quote ARG to be evaled later. +# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT +# is double-quoted, suitable for a subsequent eval, whereas +# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters +# which are still active within double quotes backslashified. +func_quote_for_eval () +{ + case $1 in + *[\\\`\"\$]*) + func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; + *) + func_quote_for_eval_unquoted_result="$1" ;; + esac + + case $func_quote_for_eval_unquoted_result in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and and variable + # expansion for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" + ;; + *) + func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" + esac +} + + +# func_quote_for_expand arg +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + case $1 in + *[\\\`\"]*) + my_arg=`$ECHO "$1" | $SED \ + -e "$double_quote_subst" -e "$sed_double_backslash"` ;; + *) + my_arg="$1" ;; + esac + + case $my_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + my_arg="\"$my_arg\"" + ;; + esac + + func_quote_for_expand_result="$my_arg" +} + + +# func_show_eval cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$my_cmd" + my_status=$? + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + +# func_show_eval_locale cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$lt_user_locale + $my_cmd" + my_status=$? + eval "$lt_safe_locale" + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + +# func_tr_sh +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_version +# Echo version message to standard output and exit. +func_version () +{ + $opt_debug + + $SED -n '/(C)/!b go + :more + /\./!{ + N + s/\n# / / + b more + } + :go + /^# '$PROGRAM' (GNU /,/# warranty; / { + s/^# // + s/^# *$// + s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ + p + }' < "$progpath" + exit $? +} + +# func_usage +# Echo short help message to standard output and exit. +func_usage () +{ + $opt_debug + + $SED -n '/^# Usage:/,/^# *.*--help/ { + s/^# // + s/^# *$// + s/\$progname/'$progname'/ + p + }' < "$progpath" + echo + $ECHO "run \`$progname --help | more' for full usage" + exit $? +} + +# func_help [NOEXIT] +# Echo long help message to standard output and exit, +# unless 'noexit' is passed as argument. +func_help () +{ + $opt_debug + + $SED -n '/^# Usage:/,/# Report bugs to/ { + :print + s/^# // + s/^# *$// + s*\$progname*'$progname'* + s*\$host*'"$host"'* + s*\$SHELL*'"$SHELL"'* + s*\$LTCC*'"$LTCC"'* + s*\$LTCFLAGS*'"$LTCFLAGS"'* + s*\$LD*'"$LD"'* + s/\$with_gnu_ld/'"$with_gnu_ld"'/ + s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ + s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ + p + d + } + /^# .* home page:/b print + /^# General help using/b print + ' < "$progpath" + ret=$? + if test -z "$1"; then + exit $ret + fi +} + +# func_missing_arg argname +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $opt_debug + + func_error "missing argument for $1." + exit_cmd=exit +} + + +# func_split_short_opt shortopt +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +func_split_short_opt () +{ + my_sed_short_opt='1s/^\(..\).*$/\1/;q' + my_sed_short_rest='1s/^..\(.*\)$/\1/;q' + + func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` + func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` +} # func_split_short_opt may be replaced by extended shell implementation + + +# func_split_long_opt longopt +# Set func_split_long_opt_name and func_split_long_opt_arg shell +# variables after splitting LONGOPT at the `=' sign. +func_split_long_opt () +{ + my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' + my_sed_long_arg='1s/^--[^=]*=//' + + func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` + func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` +} # func_split_long_opt may be replaced by extended shell implementation + +exit_cmd=: + + + + + +magic="%%%MAGIC variable%%%" +magic_exe="%%%MAGIC EXE variable%%%" + +# Global variables. +nonopt= +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "${1}=\$${1}\${2}" +} # func_append may be replaced by extended shell implementation + +# func_append_quoted var value +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +func_append_quoted () +{ + func_quote_for_eval "${2}" + eval "${1}=\$${1}\\ \$func_quote_for_eval_result" +} # func_append_quoted may be replaced by extended shell implementation + + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=`expr "${@}"` +} # func_arith may be replaced by extended shell implementation + + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` +} # func_len may be replaced by extended shell implementation + + +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` +} # func_lo2o may be replaced by extended shell implementation + + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` +} # func_xform may be replaced by extended shell implementation + + +# func_fatal_configuration arg... +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func_error ${1+"$@"} + func_error "See the $PACKAGE documentation for more information." + func_fatal_error "Fatal configuration error." +} + + +# func_config +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + +# func_features +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test "$build_libtool_libs" = yes; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + +# func_enable_tag tagname +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname="$1" + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf="/$re_begincf/,/$re_endcf/p" + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + +# func_check_version_match +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# Shorthand for --mode=foo, only valid as the first argument +case $1 in +clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; +compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; +execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; +finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; +install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; +link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; +uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; +esac + + + +# Option defaults: +opt_debug=: +opt_dry_run=false +opt_config=false +opt_preserve_dup_deps=false +opt_features=false +opt_finish=false +opt_help=false +opt_help_all=false +opt_silent=: +opt_warning=: +opt_verbose=: +opt_silent=false +opt_verbose=false + + +# Parse options once, thoroughly. This comes as soon as possible in the +# script to make things like `--version' happen as quickly as we can. +{ + # this just eases exit handling + while test $# -gt 0; do + opt="$1" + shift + case $opt in + --debug|-x) opt_debug='set -x' + func_echo "enabling shell trace mode" + $opt_debug + ;; + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + --config) + opt_config=: +func_config + ;; + --dlopen|-dlopen) + optarg="$1" + opt_dlopen="${opt_dlopen+$opt_dlopen +}$optarg" + shift + ;; + --preserve-dup-deps) + opt_preserve_dup_deps=: + ;; + --features) + opt_features=: +func_features + ;; + --finish) + opt_finish=: +set dummy --mode finish ${1+"$@"}; shift + ;; + --help) + opt_help=: + ;; + --help-all) + opt_help_all=: +opt_help=': help-all' + ;; + --mode) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_mode="$optarg" +case $optarg in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $opt" + exit_cmd=exit + break + ;; +esac + shift + ;; + --no-silent|--no-quiet) + opt_silent=false +func_append preserve_args " $opt" + ;; + --no-warning|--no-warn) + opt_warning=false +func_append preserve_args " $opt" + ;; + --no-verbose) + opt_verbose=false +func_append preserve_args " $opt" + ;; + --silent|--quiet) + opt_silent=: +func_append preserve_args " $opt" + opt_verbose=false + ;; + --verbose|-v) + opt_verbose=: +func_append preserve_args " $opt" +opt_silent=false + ;; + --tag) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_tag="$optarg" +func_append preserve_args " $opt $optarg" +func_enable_tag "$optarg" + shift + ;; + + -\?|-h) func_usage ;; + --help) func_help ;; + --version) func_version ;; + + # Separate optargs to long options: + --*=*) + func_split_long_opt "$opt" + set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-n*|-v*) + func_split_short_opt "$opt" + set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognized option \`$opt'" ;; + *) set dummy "$opt" ${1+"$@"}; shift; break ;; + esac + done + + # Validate options: + + # save first non-option argument + if test "$#" -gt 0; then + nonopt="$opt" + shift + fi + + # preserve --debug + test "$opt_debug" = : || func_append preserve_args " --debug" + + case $host in + *cygwin* | *mingw* | *pw32* | *cegcc*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + func_fatal_configuration "not configured to build any kind of library" + fi + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test "$opt_mode" != execute; then + func_error "unrecognized option \`-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$progname --help --mode=$opt_mode' for more information." + } + + + # Bail if the options were screwed + $exit_cmd $EXIT_FAILURE +} + + + + +## ----------- ## +## Main. ## +## ----------- ## + +# func_lalib_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null \ + | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if `file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case "$lalib_p_line" in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test "$lalib_p" = yes +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + func_lalib_p "$1" +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $opt_debug + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$save_ifs + eval cmd=\"$cmd\" + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# `FILE.' does not work on cygwin managed mounts. +func_source () +{ + $opt_debug + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case "$lt_sysroot:$1" in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result="=$func_stripname_result" + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $opt_debug + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with \`--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=${1} + if test "$build_libtool_libs" = yes; then + write_lobj=\'${2}\' + else + write_lobj=none + fi + + if test "$build_old_libs" = yes; then + write_oldobj=\'${3}\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$lt_sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $opt_debug + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result="" + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result" ; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $opt_debug + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $opt_debug + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $opt_debug + if test -z "$2" && test -n "$1" ; then + func_error "Could not determine host file name corresponding to" + func_error " \`$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result="$1" + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $opt_debug + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " \`$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result="$3" + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $opt_debug + case $4 in + $1 ) func_to_host_path_result="$3$func_to_host_path_result" + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via `$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $opt_debug + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $opt_debug + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result="$1" +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result="$func_convert_core_msys_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via `$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $opt_debug + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd="func_convert_path_${func_stripname_result}" + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $opt_debug + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result="$1" +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_msys_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result="$func_cygpath_result" + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result="$func_cygpath_result" + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_mode_compile arg... +func_mode_compile () +{ + $opt_debug + # Get the compilation command and the source file. + base_compile= + srcfile="$nonopt" # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg="$arg" + arg_mode=normal + ;; + + target ) + libobj="$arg" + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify \`-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + func_append_quoted lastarg "$arg" + done + IFS="$save_ifs" + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg="$srcfile" + srcfile="$arg" + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with \`-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj="$func_basename_result" + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from \`$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name \`$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname="$func_basename_result" + xdir="$func_dirname_result" + lobj=${xdir}$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test "$suppress_opt" = yes; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test "$compiler_c_o" = yes; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test "$opt_mode" = compile && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a \`.o' file suitable for static linking + -static only build a \`.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode \`$opt_mode'" + ;; + esac + + echo + $ECHO "Try \`$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test "$opt_help" = :; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | sed -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + sed '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $opt_debug + # The first argument is the command name. + cmd="$nonopt" + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "\`$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "\`$file' was not linked with \`-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir="$func_dirname_result" + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir="$func_dirname_result" + ;; + + *) + func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file="$progdir/$program" + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if test "X$opt_dry_run" = Xfalse; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + fi +} + +test "$opt_mode" = execute && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $opt_debug + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "\`$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument \`$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and \`=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_silent && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test "$opt_mode" = finish && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $opt_debug + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac; then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test "x$prev" = x-m && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the \`$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir="$func_dirname_result" + destname="$func_basename_result" + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "\`$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "\`$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir="$func_dirname_result" + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking \`$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname="$1" + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme="$stripme" + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme="" + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name="$func_basename_result" + instname="$dir/$name"i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to \`$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script \`$wrapper'" + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "\`$lib' has not been installed in \`$libdir'" + finalize=no + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + $opt_dry_run || { + if test "$finalize" = yes; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file="$func_basename_result" + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_silent || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink \`$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file="$outputname" + else + func_warning "cannot relink \`$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name="$func_basename_result" + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run \`$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test "$opt_mode" = install && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $opt_debug + my_outputname="$1" + my_originator="$2" + my_pic_p="${3-no}" + my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms="${my_outputname}S.c" + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${my_outputname}.nm" + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + func_verbose "generating symbol list for \`$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $opt_dry_run || { + $RM $export_symbols + eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from \`$dlprefile'" + func_basename "$dlprefile" + name="$func_basename_result" + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename="" + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname" ; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename="$func_basename_result" + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename" ; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[]; +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{\ + { \"$my_originator\", (void *) 0 }," + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + if test "X$my_pic_p" != Xno; then + pic_flag_for_symtable=" $pic_flag" + fi + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' + + # Transform the symbol file into the correct name. + symfileobj="$output_objdir/${my_outputname}S.$objext" + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for \`$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $opt_debug + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s,.*,import, + p + q + } + }'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $opt_debug + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $opt_debug + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive which possess that section. Heuristic: eliminate + # all those which have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $opt_debug + if func_cygming_gnu_implib_p "$1" ; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1" ; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result="" + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $opt_debug + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + if test "$lock_old_archive_extraction" = yes; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test "$lock_old_archive_extraction" = yes; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $opt_debug + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib="$func_basename_result" + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir="$my_gentop/$my_xlib_u" + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`basename "$darwin_archive"` + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result="$my_oldobjs" +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory in which it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ which is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options which match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +/* declarations of non-ANSI functions */ +#if defined(__MINGW32__) +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined(__CYGWIN__) +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined (other platforms) ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined(_MSC_VER) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +# ifndef _INTPTR_T_DEFINED +# define _INTPTR_T_DEFINED +# define intptr_t int +# endif +#elif defined(__MINGW32__) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined(__CYGWIN__) +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined (other platforms) ... */ +#endif + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +#if defined(LT_DEBUGWRAPPER) +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp (str, pat) == 0) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + int len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + int orig_value_len = strlen (orig_value); + int add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + int len = strlen (new_value); + while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[len-1] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $opt_debug + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $opt_debug + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module="${wl}-single_module" + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir="$arg" + prev= + continue + ;; + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + test -f "$arg" \ + || func_fatal_error "symbol file \`$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file \`$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "\`-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between \`-L' and \`$1'" + else + func_fatal_error "need path for \`-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of \`$dir'" + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module="${wl}-multi_module" + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "\`-no-install' is ignored for $host" + func_warning "assuming \`-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-flto*|-fwhopr*|-fuse-linker-plugin) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the \`$prevarg' option requires an argument" + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname="$func_basename_result" + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + func_dirname "$output" "/" "" + output_objdir="$func_dirname_result$objdir" + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps ; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test "$linkmode,$pass" = "lib,link"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs="$tmp_deplibs" + fi + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test "$linkmode,$pass" = "lib,dlpreopen"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs="$dlprefiles" + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + func_warning "\`-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test "$linkmode" = lib; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + *.ltframework) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "\`-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + else + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + ;; + esac + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + + if test "$found" = yes || test -f "$lib"; then : + else + func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" + fi + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "\`$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + elif test "$linkmode" != prog && test "$linkmode" != lib; then + func_fatal_error "\`$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test "$prefer_static_libs" = yes || + test "$prefer_static_libs,$installed" = "built,no"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib="$l" + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + func_fatal_error "cannot -dlopen a convenience library: \`$lib'" + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of \`$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir="$ladir" + fi + ;; + esac + func_basename "$lib" + laname="$func_basename_result" + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library \`$lib' was moved." + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$lt_sysroot$libdir" + absdir="$lt_sysroot$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir" && test "$linkmode" = prog; then + func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" + fi + case "$host" in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { { test "$prefer_static_libs" = no || + test "$prefer_static_libs,$installed" = "built,yes"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath:" in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test "$installed" = no; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule="" + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule="$dlpremoduletest" + break + fi + done + if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then + echo + if test "$linkmode" = prog; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname="$1" + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc*) + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + func_basename "$soroot" + soname="$func_basename_result" + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from \`$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for \`$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$opt_mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we can not + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null ; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + elif test -n "$old_library"; then + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$absdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && + test "$hardcode_minus_L" != yes && + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$opt_mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system can not link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path="$deplib" ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of \`$dir'" + absdir="$dir" + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl" ; then + depdepl="$absdir/$objdir/$depdepl" + darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" + func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" + path= + fi + fi + ;; + *) + path="-L$absdir/$objdir" + ;; + esac + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "\`$deplib' seems to be moved" + + path="-L$absdir" + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test "$pass" = link; then + if test "$linkmode" = "prog"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + fi + if test "$linkmode" = prog || test "$linkmode" = lib; then + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "\`-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "\`-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test "$module" = no && \ + func_fatal_help "libtool library \`$output' must begin with \`lib'" + + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test "$dlself" != no && \ + func_warning "\`-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test "$#" -gt 1 && \ + func_warning "ignoring multiple \`-rpath's for a libtool library" + + install_libdir="$1" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "\`-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + shift + IFS="$save_ifs" + + test -n "$7" && \ + func_fatal_help "too many parameters to \`-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$1" + number_minor="$2" + number_revision="$3" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|qnx|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_minor" + lt_irix_increment=no + ;; + esac + ;; + no) + current="$1" + revision="$2" + age="$3" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT \`$current' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION \`$revision' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE \`$age' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE \`$age' is greater than the current interface number \`$current'" + func_fatal_error "\`$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current" + ;; + + irix | nonstopux) + if test "X$lt_irix_increment" = "Xno"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + func_append verstring ":${current}.0" + ;; + + qnx) + major=".$current" + versuffix=".$current" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + + *) + func_fatal_configuration "unknown library version type \`$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + func_warning "undefined symbols not allowed in $host shared libraries" + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + fi + + func_generate_dlsyms "$libname" "$libname" "yes" + func_append libobjs " $symfileobj" + test "X$libobjs" = "X " && libobjs= + + if test "$opt_mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test "X$deplibs_check_method" = "Xnone"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs="$new_libs" + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + # Remove ${wl} instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$opt_mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname="$1" + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols="$output_objdir/$libname.uexp" + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + if test "x`$SED 1q $export_symbols`" != xEXPORTS; then + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols="$export_symbols" + export_symbols= + always_export_symbols=yes + fi + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd1 in $cmds; do + IFS="$save_ifs" + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test "$try_normal_branch" = yes \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=${output_objdir}/${output_la}.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test "$compiler_needs_object" = yes && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$opt_mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then + output=${output_objdir}/${output_la}.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then + output=${output_objdir}/${output_la}.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test "$compiler_needs_object" = yes; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-${k}.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test "X$objlist" = X || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-${k}.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\${concat_cmds}$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + if ${skipped_export-false}; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + fi + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + if ${skipped_export-false}; then + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + fi + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "\`-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object \`$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec and hope we can get by with + # turning comma into space.. + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + else + gentop="$output_objdir/${obj}x" + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "\`-release' is ignored for programs" + + test "$preload" = yes \ + && test "$dlopen_support" = unknown \ + && test "$dlopen_self" = unknown \ + && test "$dlopen_self_static" = unknown && \ + func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test "$tagname" = CXX ; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " ${wl}-bind_at_load" + func_append finalize_command " ${wl}-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" "no" + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=yes + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=no + ;; + *cygwin* | *mingw* ) + if test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + *) + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + esac + if test "$wrappers_required" = no; then + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.${objext}"; then + func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' + fi + + exit $exit_status + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "\`$output' will be relinked during installation" + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host" ; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save $symfileobj" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + if test "$preload" = yes && test -f "$symfileobj"; then + func_append oldobjs " $symfileobj" + fi + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase="$func_basename_result" + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name="$func_basename_result" + func_resolve_sysroot "$deplib" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles="$newdlprefiles" + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test "x$bindir" != x ; + then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +{ test "$opt_mode" = link || test "$opt_mode" = relink; } && + func_mode_link ${1+"$@"} + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $opt_debug + RM="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=yes ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir="$func_dirname_result" + if test "X$dir" = X.; then + odir="$objdir" + else + odir="$dir/$objdir" + fi + func_basename "$file" + name="$func_basename_result" + test "$opt_mode" = uninstall && odir="$dir" + + # Remember odir for removal later, being careful to avoid duplicates + if test "$opt_mode" = clean; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case "$opt_mode" in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && + test "$pic_object" != none; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && + test "$non_pic_object" != none; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$opt_mode" = clean ; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + func_append rmfiles " $odir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && + func_mode_uninstall ${1+"$@"} + +test -z "$opt_mode" && { + help="$generic_help" + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode \`$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: +# vi:sw=2 + diff --git a/build-aux/missing b/build-aux/missing new file mode 100755 index 0000000..86a8fc3 --- /dev/null +++ b/build-aux/missing @@ -0,0 +1,331 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2012-01-06.13; # UTC + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, +# 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: +sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' +sed_minuso='s/.* -o \([^ ]*\).*/\1/p' + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case $1 in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + autom4te touch the output file, or create a stub one + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and +\`g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# normalize program name to check for. +program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). This is about non-GNU programs, so use $1 not +# $program. +case $1 in + lex*|yacc*) + # Not GNU programs, they don't have --version. + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case $program in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case $f in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te*) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison*|yacc*) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if test $# -ne 1; then + eval LASTARG=\${$#} + case $LASTARG in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if test ! -f y.tab.h; then + echo >y.tab.h + fi + if test ! -f y.tab.c; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex*|flex*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if test $# -ne 1; then + eval LASTARG=\${$#} + case $LASTARG in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if test ! -f lex.yy.c; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit $? + fi + ;; + + makeinfo*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n ' + /^@setfilename/{ + s/.* \([^ ]*\) *$/\1/ + p + q + }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/configure b/configure new file mode 100755 index 0000000..701bd27 --- /dev/null +++ b/configure @@ -0,0 +1,15398 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.68 for libnl 3.2.22. +# +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software +# Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + # Preserve -v and -x to the replacement shell. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; + esac + exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='libnl' +PACKAGE_TARNAME='libnl' +PACKAGE_VERSION='3.2.22' +PACKAGE_STRING='libnl 3.2.22' +PACKAGE_BUGREPORT='' +PACKAGE_URL='http://www.infradead.org/~tgr/libnl/' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +enable_option_checking=no +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +subdirs +ENABLE_DEBUG_FALSE +ENABLE_DEBUG_TRUE +DISABLE_PTHREADS_FALSE +DISABLE_PTHREADS_TRUE +ENABLE_CLI_FALSE +ENABLE_CLI_TRUE +pkgconfigdir +ENABLE_UNIT_TESTS_FALSE +ENABLE_UNIT_TESTS_TRUE +CHECK_LIBS +CHECK_CFLAGS +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG +YACC +FLEX +CPP +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +RANLIB +DLLTOOL +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +EGREP +GREP +SED +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +LIBTOOL +LT_AGE +LT_REVISION +LT_CURRENT +LIBNL_VERSION +MIC_VERSION +MIN_VERSION +MAJ_VERSION +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +ac_ct_AR +AR +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_silent_rules +enable_dependency_tracking +enable_shared +enable_static +with_pic +enable_fast_install +with_gnu_ld +with_sysroot +enable_libtool_lock +with_pkgconfigdir +enable_cli +enable_pthreads +enable_debug +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +CHECK_CFLAGS +CHECK_LIBS' +ac_subdirs_all='doc' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used" >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures libnl 3.2.22 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/libnl] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of libnl 3.2.22:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: `make V=1') + --disable-silent-rules verbose build output (undo: `make V=0') + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --disable-cli Do not build command line interface utils + --disable-pthreads Disable pthreads support + --disable-debug Do not include debugging statements + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + both] + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot=DIR Search for dependent libraries within DIR + (or the compiler's sysroot if not specified). + --with-pkgconfigdir=PATH + Path to the pkgconfig directory [[LIBDIR/pkgconfig]] + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + CHECK_CFLAGS + C compiler flags for CHECK, overriding pkg-config + CHECK_LIBS linker flags for CHECK, overriding pkg-config + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +libnl home page: . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +libnl configure 3.2.22 +generated by GNU Autoconf 2.68 + +Copyright (C) 2010 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by libnl $as_me 3.2.22, which was +generated by GNU Autoconf 2.68. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_config_headers="$ac_config_headers lib/defs.h" + +ac_aux_dir= +for ac_dir in build-aux "$srcdir"/build-aux; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in build-aux \"$srcdir\"/build-aux" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + +am__api_version='1.11' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken +alias in your environment" "$LINENO" 5 + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +mkdir_p="$MKDIR_P" +case $mkdir_p in + [\\/$]* | ?:[\\/]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='libnl' + VERSION='3.2.22' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in +yes) AM_DEFAULT_VERBOSITY=0;; +no) AM_DEFAULT_VERBOSITY=1;; +*) AM_DEFAULT_VERBOSITY=0;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar lib "link -lib" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar lib "link -lib" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5 +$as_echo_n "checking the archiver ($AR) interface... " >&6; } +if ${am_cv_ar_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + am_cv_ar_interface=ar + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int some_variable = 0; +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 + (eval $am_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + am_cv_ar_interface=ar + else + am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 + (eval $am_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + am_cv_ar_interface=lib + else + am_cv_ar_interface=unknown + fi + fi + rm -f conftest.lib libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5 +$as_echo "$am_cv_ar_interface" >&6; } + +case $am_cv_ar_interface in +ar) + ;; +lib) + # Microsoft lib, so override with the ar-lib wrapper script. + # FIXME: It is wrong to rewrite AR. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__AR in this case, + # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something + # similar. + AR="$am_aux_dir/ar-lib $AR" + ;; +unknown) + as_fn_error $? "could not determine $AR interface" "$LINENO" 5 + ;; +esac + + +MAJ_VERSION=3 + +MIN_VERSION=2 + +MIC_VERSION=22 + +LIBNL_VERSION=3.2.22 + + +LT_CURRENT=217 + +LT_REVISION=0 + +LT_AGE=17 + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + +if test "x$CC" != xcc; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 +$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 +$as_echo_n "checking whether cc understands -c and -o together... " >&6; } +fi +set dummy $CC; ac_cc=`$as_echo "$2" | + sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` +if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +# Make sure it works both with $CC and with simple cc. +# We do the test twice because some compilers refuse to overwrite an +# existing .o file with -o, though they will create one. +ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' +rm -f conftest2.* +if { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && + test -f conftest2.$ac_objext && { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; +then + eval ac_cv_prog_cc_${ac_cc}_c_o=yes + if test "x$CC" != xcc; then + # Test first that cc exists at all. + if { ac_try='cc -c conftest.$ac_ext >&5' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' + rm -f conftest2.* + if { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && + test -f conftest2.$ac_objext && { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; + then + # cc works too. + : + else + # cc exists but doesn't like -o. + eval ac_cv_prog_cc_${ac_cc}_c_o=no + fi + fi + fi +else + eval ac_cv_prog_cc_${ac_cc}_c_o=no +fi +rm -f core conftest* + +fi +if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h + +fi + +# FIXME: we rely on the cache variable name because +# there is no other way. +set dummy $CC +am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` +eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o +if test "$am_t" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi + + + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.2' +macro_revision='1.3337' + + + + + + + + + + + + + +ltmain="$ac_aux_dir/ltmain.sh" + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case "$ECHO" in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 +$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 +$as_echo "$xsi_shell" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 +$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } +lt_shell_append=no +( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 +$as_echo "$lt_shell_append" >&6; } + + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test "$GCC" != yes; then + reload_cmds=false + fi + ;; + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. + if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 +$as_echo "${with_sysroot}" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD="${LD-ld}_sol2" + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test $_lt_result -eq 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[012]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + +# Set options + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + # Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=yes +fi + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for lt_pkg in $withval; do + IFS="$lt_save_ifs" + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + pic_mode=default +fi + + +test -z "$pic_mode" && pic_mode=default + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC="$CC" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test "$GCC" = yes; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test x"$lt_cv_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test x"$lt_cv_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='${wl}--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + export_dynamic_flag_spec='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test x"$lt_cv_prog_compiler__b" = xyes; then + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test "$lt_cv_irix_exported_symbol" = yes; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='${wl}-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test "$ld_shlibs" = no && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([A-Za-z]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" + + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test "$hardcode_action" = relink || + test "$inherit_rpath" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report which library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + +for ac_prog in 'flex' +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_FLEX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$FLEX"; then + ac_cv_prog_FLEX="$FLEX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_FLEX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +FLEX=$ac_cv_prog_FLEX +if test -n "$FLEX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FLEX" >&5 +$as_echo "$FLEX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$FLEX" && break +done + +for ac_prog in 'bison -y' +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_YACC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$YACC"; then + ac_cv_prog_YACC="$YACC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_YACC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +YACC=$ac_cv_prog_YACC +if test -n "$YACC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5 +$as_echo "$YACC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$YACC" && break +done + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if ${ac_cv_c_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset cs; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_const=yes +else + ac_cv_c_const=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +$as_echo "#define const /**/" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if ${ac_cv_c_inline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_inline=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +$as_echo "$ac_cv_c_inline" >&6; } + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CHECK" >&5 +$as_echo_n "checking for CHECK... " >&6; } + +if test -n "$CHECK_CFLAGS"; then + pkg_cv_CHECK_CFLAGS="$CHECK_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"check >= 0.9.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "check >= 0.9.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_CHECK_CFLAGS=`$PKG_CONFIG --cflags "check >= 0.9.0" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$CHECK_LIBS"; then + pkg_cv_CHECK_LIBS="$CHECK_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"check >= 0.9.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "check >= 0.9.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_CHECK_LIBS=`$PKG_CONFIG --libs "check >= 0.9.0" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + CHECK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "check >= 0.9.0" 2>&1` + else + CHECK_PKG_ERRORS=`$PKG_CONFIG --print-errors "check >= 0.9.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$CHECK_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Disabling building of unit tests" >&5 +$as_echo "$as_me: WARNING: *** Disabling building of unit tests" >&2;} + enable_unit_tests="no" +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Disabling building of unit tests" >&5 +$as_echo "$as_me: WARNING: *** Disabling building of unit tests" >&2;} + enable_unit_tests="no" +else + CHECK_CFLAGS=$pkg_cv_CHECK_CFLAGS + CHECK_LIBS=$pkg_cv_CHECK_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + enable_unit_tests="yes" +fi + + if test "$enable_unit_tests" = "yes"; then + ENABLE_UNIT_TESTS_TRUE= + ENABLE_UNIT_TESTS_FALSE='#' +else + ENABLE_UNIT_TESTS_TRUE='#' + ENABLE_UNIT_TESTS_FALSE= +fi + + + +# Check whether --with-pkgconfigdir was given. +if test "${with_pkgconfigdir+set}" = set; then : + withval=$with_pkgconfigdir; pkgconfigdir="$withval" +else + pkgconfigdir='${libdir}/pkgconfig' +fi + + + +# Check whether --enable-cli was given. +if test "${enable_cli+set}" = set; then : + enableval=$enable_cli; enable_cli="$enableval" +else + enable_cli="yes" +fi + + if test "$enable_cli" = "yes"; then + ENABLE_CLI_TRUE= + ENABLE_CLI_FALSE='#' +else + ENABLE_CLI_TRUE='#' + ENABLE_CLI_FALSE= +fi + + +# Check whether --enable-pthreads was given. +if test "${enable_pthreads+set}" = set; then : + enableval=$enable_pthreads; enable_pthreads="$enableval" +else + enable_pthreads="yes" +fi + + if test "$enable_pthreads" = "no"; then + DISABLE_PTHREADS_TRUE= + DISABLE_PTHREADS_FALSE='#' +else + DISABLE_PTHREADS_TRUE='#' + DISABLE_PTHREADS_FALSE= +fi + + +# Check whether --enable-debug was given. +if test "${enable_debug+set}" = set; then : + enableval=$enable_debug; enable_debug="$enableval" +else + enable_debug="yes" +fi + + if test "$enable_debug" = "no" ; then + ENABLE_DEBUG_TRUE= + ENABLE_DEBUG_FALSE='#' +else + ENABLE_DEBUG_TRUE='#' + ENABLE_DEBUG_FALSE= +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pow in -lm" >&5 +$as_echo_n "checking for pow in -lm... " >&6; } +if ${ac_cv_lib_m_pow+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pow (); +int +main () +{ +return pow (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_pow=yes +else + ac_cv_lib_m_pow=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_pow" >&5 +$as_echo "$ac_cv_lib_m_pow" >&6; } +if test "x$ac_cv_lib_m_pow" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBM 1 +_ACEOF + + LIBS="-lm $LIBS" + +else + as_fn_error $? "libm is required" "$LINENO" 5 +fi + + +if test "x$enable_pthreads" = "xno"; then + +$as_echo "#define DISABLE_PTHREADS 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_lock in -lpthread" >&5 +$as_echo_n "checking for pthread_mutex_lock in -lpthread... " >&6; } +if ${ac_cv_lib_pthread_pthread_mutex_lock+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_mutex_lock (); +int +main () +{ +return pthread_mutex_lock (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthread_pthread_mutex_lock=yes +else + ac_cv_lib_pthread_pthread_mutex_lock=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_lock" >&5 +$as_echo "$ac_cv_lib_pthread_pthread_mutex_lock" >&6; } +if test "x$ac_cv_lib_pthread_pthread_mutex_lock" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPTHREAD 1 +_ACEOF + + LIBS="-lpthread $LIBS" + +else + as_fn_error $? "libpthread is required" "$LINENO" 5 +fi + +fi + +if test "x$enable_debug" = "xyes"; then + +$as_echo "#define NL_DEBUG 1" >>confdefs.h + +fi + + + +subdirs="$subdirs doc" + + +ac_config_files="$ac_config_files Makefile libnl-3.0.pc libnl-route-3.0.pc libnl-genl-3.0.pc libnl-nf-3.0.pc libnl-cli-3.0.pc lib/Makefile include/Makefile src/Makefile src/lib/Makefile tests/Makefile man/Makefile python/Makefile python/setup.py python/netlink/Makefile python/netlink/route/Makefile include/netlink/version.h" + + +ac_errcount=0 +if test -z "$YACC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: bison not found. Please install before continuing." >&5 +$as_echo "$as_me: WARNING: bison not found. Please install before continuing." >&2;} + ac_errcount=$((ac_errcount + 1)) +fi +if test -z "$FLEX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: flex not found. Please install before continuing." >&5 +$as_echo "$as_me: WARNING: flex not found. Please install before continuing." >&2;} + ac_errcount=$((ac_errcount + 1)) +fi +if test $ac_errcount -gt 0; then + as_fn_error $? "Required packages are missing. Please install them and rerun ./configure" "$LINENO" 5 +fi + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_UNIT_TESTS_TRUE}" && test -z "${ENABLE_UNIT_TESTS_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_UNIT_TESTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_CLI_TRUE}" && test -z "${ENABLE_CLI_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_CLI\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DISABLE_PTHREADS_TRUE}" && test -z "${DISABLE_PTHREADS_FALSE}"; then + as_fn_error $? "conditional \"DISABLE_PTHREADS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_DEBUG_TRUE}" && test -z "${ENABLE_DEBUG_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_DEBUG\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by libnl $as_me 3.2.22, which was +generated by GNU Autoconf 2.68. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to the package provider. +libnl home page: ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +libnl config.status 3.2.22 +configured by $0, generated by GNU Autoconf 2.68, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2010 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +nm_file_list_spec \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +sys_lib_dlsearch_path_spec; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' +xsi_shell='$xsi_shell' +lt_shell_append='$lt_shell_append' + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile' + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "lib/defs.h") CONFIG_HEADERS="$CONFIG_HEADERS lib/defs.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "libnl-3.0.pc") CONFIG_FILES="$CONFIG_FILES libnl-3.0.pc" ;; + "libnl-route-3.0.pc") CONFIG_FILES="$CONFIG_FILES libnl-route-3.0.pc" ;; + "libnl-genl-3.0.pc") CONFIG_FILES="$CONFIG_FILES libnl-genl-3.0.pc" ;; + "libnl-nf-3.0.pc") CONFIG_FILES="$CONFIG_FILES libnl-nf-3.0.pc" ;; + "libnl-cli-3.0.pc") CONFIG_FILES="$CONFIG_FILES libnl-cli-3.0.pc" ;; + "lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;; + "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "src/lib/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib/Makefile" ;; + "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; + "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; + "python/Makefile") CONFIG_FILES="$CONFIG_FILES python/Makefile" ;; + "python/setup.py") CONFIG_FILES="$CONFIG_FILES python/setup.py" ;; + "python/netlink/Makefile") CONFIG_FILES="$CONFIG_FILES python/netlink/Makefile" ;; + "python/netlink/route/Makefile") CONFIG_FILES="$CONFIG_FILES python/netlink/route/Makefile" ;; + "include/netlink/version.h") CONFIG_FILES="$CONFIG_FILES include/netlink/version.h" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +# The names of the tagged configurations supported by this script. +available_tags="" + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and in which our libraries should be installed. +lt_sysroot=$lt_sysroot + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain="$ac_aux_dir/ltmain.sh" + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + if test x"$xsi_shell" = xyes; then + sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ +func_dirname ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_basename ()$/,/^} # func_basename /c\ +func_basename ()\ +{\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ +func_dirname_and_basename ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ +func_stripname ()\ +{\ +\ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ +\ # positional parameters, so assign one to ordinary parameter first.\ +\ func_stripname_result=${3}\ +\ func_stripname_result=${func_stripname_result#"${1}"}\ +\ func_stripname_result=${func_stripname_result%"${2}"}\ +} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ +func_split_long_opt ()\ +{\ +\ func_split_long_opt_name=${1%%=*}\ +\ func_split_long_opt_arg=${1#*=}\ +} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ +func_split_short_opt ()\ +{\ +\ func_split_short_opt_arg=${1#??}\ +\ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ +} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ +func_lo2o ()\ +{\ +\ case ${1} in\ +\ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ +\ *) func_lo2o_result=${1} ;;\ +\ esac\ +} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_xform ()$/,/^} # func_xform /c\ +func_xform ()\ +{\ + func_xform_result=${1%.*}.lo\ +} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_arith ()$/,/^} # func_arith /c\ +func_arith ()\ +{\ + func_arith_result=$(( $* ))\ +} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_len ()$/,/^} # func_len /c\ +func_len ()\ +{\ + func_len_result=${#1}\ +} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + +fi + +if test x"$lt_shell_append" = xyes; then + sed -e '/^func_append ()$/,/^} # func_append /c\ +func_append ()\ +{\ + eval "${1}+=\\${2}"\ +} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ +func_append_quoted ()\ +{\ +\ func_quote_for_eval "${2}"\ +\ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ +} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 +$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} +fi + + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi + +# +# CONFIG_SUBDIRS section. +# +if test "$no_recursion" != yes; then + + # Remove --cache-file, --srcdir, and --disable-option-checking arguments + # so they do not pile up. + ac_sub_configure_args= + ac_prev= + eval "set x $ac_configure_args" + shift + for ac_arg + do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case $ac_arg in + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \ + | --c=*) + ;; + --config-cache | -C) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + ;; + --disable-option-checking) + ;; + *) + case $ac_arg in + *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append ac_sub_configure_args " '$ac_arg'" ;; + esac + done + + # Always prepend --prefix to ensure using the same prefix + # in subdir configurations. + ac_arg="--prefix=$prefix" + case $ac_arg in + *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args" + + # Pass --silent + if test "$silent" = yes; then + ac_sub_configure_args="--silent $ac_sub_configure_args" + fi + + # Always prepend --disable-option-checking to silence warnings, since + # different subdirs can have different --enable and --with options. + ac_sub_configure_args="--disable-option-checking $ac_sub_configure_args" + + ac_popdir=`pwd` + for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + test -d "$srcdir/$ac_dir" || continue + + ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)" + $as_echo "$as_me:${as_lineno-$LINENO}: $ac_msg" >&5 + $as_echo "$ac_msg" >&6 + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + cd "$ac_dir" + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f "$ac_srcdir/configure.gnu"; then + ac_sub_configure=$ac_srcdir/configure.gnu + elif test -f "$ac_srcdir/configure"; then + ac_sub_configure=$ac_srcdir/configure + elif test -f "$ac_srcdir/configure.in"; then + # This should be Cygnus configure. + ac_sub_configure=$ac_aux_dir/configure + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in $ac_dir" >&5 +$as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} + ac_sub_configure= + fi + + # The recursion is here. + if test -n "$ac_sub_configure"; then + # Make the cache file name correct relative to the subdirectory. + case $cache_file in + [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;; + *) # Relative name. + ac_sub_cache_file=$ac_top_build_prefix$cache_file ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 +$as_echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} + # The eval makes quoting arguments work. + eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \ + --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" || + as_fn_error $? "$ac_sub_configure failed for $ac_dir" "$LINENO" 5 + fi + + cd "$ac_popdir" + done +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + +echo "-------------------------------------------------------------------------------" +echo " NOTE" +echo "" +echo " There have been some changes starting with 3.2 regarding where and how libnl" +echo " is being installed on the system in order to allow multiple libnl versions" +echo " to be installed in parallel:" +echo "" +echo " - Headers will be installed in ${includedir}/libnl${MAJ_VERSION}, therefore" +echo " you will need to add \"-I/usr/include/libnl${MAJ_VERSION}\" to CFLAGS" +echo "" +echo " - The library basename was renamed to libnl-${MAJ_VERSION}, i.e. the SO names become" +echo " libnl-${MAJ_VERSION}.so., libnl-route-${MAJ_VERSION}.so, etc." +echo "" +echo " - libtool versioning was assumed, to ease detection of compatible library" +echo " versions." +echo "" +echo " If you are using pkg-config for detecting and linking against the library " +echo " things will continue magically as if nothing every happened. If you are " +echo " linking manually you need to adapt your Makefiles or switch to using " +echo " pkg-config files." +echo "" +echo "-------------------------------------------------------------------------------" + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..34e8c9f --- /dev/null +++ b/configure.ac @@ -0,0 +1,176 @@ +# +# configure.in +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation version 2.1 +# of the License. +# +# Copyright (c) 2003-2013 Thomas Graf +# + + +# copied from glib +m4_define([libnl_major_version], [3]) +m4_define([libnl_minor_version], [2]) +m4_define([libnl_micro_version], [22]) + + +# The following explanation may help to understand the above rules a bit +# better: consider that there are three possible kinds of reactions from +# users of your library to changes in a shared library: +# +# 1. Programs using the previous version may use the new version as drop-in +# replacement, and programs using the new version can also work with the +# previous one. In other words, no recompiling nor relinking is needed. +# In this case, bump revision only, don't touch current nor age. +# +# 2. Programs using the previous version may use the new version as drop-in +# replacement, but programs using the new version may use APIs not +# present in the previous one. In other words, a program linking against +# the new version may fail with “unresolved symbols” if linking against +# the old version at runtime: set revision to 0, bump current and age. +# +# 3. Programs may need to be changed, recompiled, relinked in order to use +# the new version. Bump current, set revision and age to 0. + +m4_define([libnl_lt_current], [217]) +m4_define([libnl_lt_revision], [0]) +m4_define([libnl_lt_age], [17]) + +m4_define([libnl_version], + [libnl_major_version.libnl_minor_version.libnl_micro_version]) + +AC_INIT(libnl, [libnl_version], [], [], [http://www.infradead.org/~tgr/libnl/]) +AC_CONFIG_HEADERS([lib/defs.h]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_MACRO_DIR([m4]) +AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)], []) +m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) + +MAJ_VERSION=libnl_major_version +AC_SUBST(MAJ_VERSION) +MIN_VERSION=libnl_minor_version +AC_SUBST(MIN_VERSION) +MIC_VERSION=libnl_micro_version +AC_SUBST(MIC_VERSION) +LIBNL_VERSION=libnl_version +AC_SUBST(LIBNL_VERSION) + +LT_CURRENT=libnl_lt_current +AC_SUBST(LT_CURRENT) +LT_REVISION=libnl_lt_revision +AC_SUBST(LT_REVISION) +LT_AGE=libnl_lt_age +AC_SUBST(LT_AGE) + +AC_PROG_CC +AM_PROG_CC_C_O +AC_PROG_INSTALL +AM_PROG_LIBTOOL +AC_CHECK_PROGS(FLEX, 'flex') +AC_CHECK_PROGS(YACC, 'bison -y') + +AC_C_CONST +AC_C_INLINE + +PKG_CHECK_MODULES([CHECK], [check >= 0.9.0], + [enable_unit_tests="yes"], + [AC_MSG_WARN([*** Disabling building of unit tests]) + enable_unit_tests="no"]) + +AM_CONDITIONAL([ENABLE_UNIT_TESTS], [test "$enable_unit_tests" = "yes"]) + +AC_ARG_WITH([pkgconfigdir], AS_HELP_STRING([--with-pkgconfigdir=PATH], + [Path to the pkgconfig directory [[LIBDIR/pkgconfig]]]), + [pkgconfigdir="$withval"], [pkgconfigdir='${libdir}/pkgconfig']) +AC_SUBST([pkgconfigdir]) + +AC_ARG_ENABLE([cli], + AS_HELP_STRING([--disable-cli], [Do not build command line interface utils]), + [enable_cli="$enableval"], [enable_cli="yes"]) +AM_CONDITIONAL([ENABLE_CLI], [test "$enable_cli" = "yes"]) + +AC_ARG_ENABLE([pthreads], + AS_HELP_STRING([--disable-pthreads], [Disable pthreads support]), + [enable_pthreads="$enableval"], [enable_pthreads="yes"]) +AM_CONDITIONAL([DISABLE_PTHREADS], [test "$enable_pthreads" = "no"]) + +AC_ARG_ENABLE([debug], + AS_HELP_STRING([--disable-debug], [Do not include debugging statements]), + [enable_debug="$enableval"], [enable_debug="yes"]) +AM_CONDITIONAL([ENABLE_DEBUG], [test "$enable_debug" = "no" ]) + +AC_CHECK_LIB([m], [pow], [], AC_MSG_ERROR([libm is required])) + +if test "x$enable_pthreads" = "xno"; then + AC_DEFINE([DISABLE_PTHREADS], [1], [Define to 1 to disable pthreads]) +else + AC_CHECK_LIB([pthread], [pthread_mutex_lock], [], AC_MSG_ERROR([libpthread is required])) +fi + +if test "x$enable_debug" = "xyes"; then + AC_DEFINE([NL_DEBUG], [1], [Define to 1 to enable debugging]) +fi + +AC_CONFIG_SUBDIRS([doc]) + +AC_CONFIG_FILES([ +Makefile +libnl-3.0.pc +libnl-route-3.0.pc +libnl-genl-3.0.pc +libnl-nf-3.0.pc +libnl-cli-3.0.pc +lib/Makefile +include/Makefile +src/Makefile +src/lib/Makefile +tests/Makefile +man/Makefile +python/Makefile +python/setup.py +python/netlink/Makefile +python/netlink/route/Makefile +include/netlink/version.h +]) + +ac_errcount=0 +if test -z "$YACC"; then + AC_MSG_WARN(bison not found. Please install before continuing.) + ac_errcount=$((ac_errcount + 1)) +fi +if test -z "$FLEX"; then + AC_MSG_WARN(flex not found. Please install before continuing.) + ac_errcount=$((ac_errcount + 1)) +fi +if test $ac_errcount -gt 0; then + AC_MSG_ERROR(Required packages are missing. Please install them and rerun ./configure) +fi + +AC_OUTPUT + +echo "-------------------------------------------------------------------------------" +echo " NOTE" +echo "" +echo " There have been some changes starting with 3.2 regarding where and how libnl" +echo " is being installed on the system in order to allow multiple libnl versions" +echo " to be installed in parallel:" +echo "" +echo " - Headers will be installed in ${includedir}/libnl${MAJ_VERSION}, therefore" +echo " you will need to add \"-I/usr/include/libnl${MAJ_VERSION}\" to CFLAGS" +echo "" +echo " - The library basename was renamed to libnl-${MAJ_VERSION}, i.e. the SO names become" +echo " libnl-${MAJ_VERSION}.so., libnl-route-${MAJ_VERSION}.so, etc." +echo "" +echo " - libtool versioning was assumed, to ease detection of compatible library" +echo " versions." +echo "" +echo " If you are using pkg-config for detecting and linking against the library " +echo " things will continue magically as if nothing every happened. If you are " +echo " linking manually you need to adapt your Makefiles or switch to using " +echo " pkg-config files." +echo "" +echo "-------------------------------------------------------------------------------" + diff --git a/etc/classid b/etc/classid new file mode 100644 index 0000000..2203243 --- /dev/null +++ b/etc/classid @@ -0,0 +1,45 @@ +############################################################################### +# +# ClassID <-> Name Translation Table +# +# This file can be used to assign names to classids for easier reference +# in all libnl tools. +# +# Format: +# # qdisc definition +# # class deifnition +# # class definition referencing an +# existing qdisc definition. +# +# Example: +# 1: top # top -> 1:0 +# top:1 interactive # interactive -> 1:1 +# top:2 www # www -> 1:2 +# top:3 bulk # bulk -> 1:3 +# 2:1 test_class # test_class -> 2:1 +# +# Illegal Example: +# 30:1 classD +# classD:2 invalidClass # classD refers to a class, not a qdisc +# +############################################################################### + +# + +# Reserved default classids +0:0 none +ffff:ffff root +ffff:fff1 ingress + +# +# List your classid definitions here: +# + + + +############################################################################### +# List of auto-generated classids +# +# DO NOT ADD CLASSID DEFINITIONS BELOW THIS LINE +# +# diff --git a/etc/pktloc b/etc/pktloc new file mode 100644 index 0000000..505c44e --- /dev/null +++ b/etc/pktloc @@ -0,0 +1,76 @@ +# +# Location definitions for packet matching +# + +# name alignment offset mask shift +ip.version u8 net+0 0xF0 4 +ip.hdrlen u8 net+0 0x0F +ip.diffserv u8 net+1 +ip.length u16 net+2 +ip.id u16 net+4 +ip.flag.res u8 net+6 0xff 7 +ip.df u8 net+6 0x40 6 +ip.mf u8 net+6 0x20 5 +ip.offset u16 net+6 0x1FFF +ip.ttl u8 net+8 +ip.proto u8 net+9 +ip.chksum u16 net+10 +ip.src u32 net+12 +ip.dst u32 net+16 + +# if ip.ihl > 5 +ip.opts u32 net+20 + + +# +# IP version 6 +# +# name alignment offset mask shift +ip6.version u8 net+0 0xF0 4 +ip6.tc u16 net+0 0xFF0 4 +ip6.flowlabel u32 net+0 0xFFFFF +ip6.length u16 net+4 +ip6.nexthdr u8 net+6 +ip6.hoplimit u8 net+7 +ip6.src 16 net+8 +ip6.dst 16 net+24 + +# +# Transmission Control Protocol (TCP) +# +# name alignment offset mask shift +tcp.sport u16 tcp+0 +tcp.dport u16 tcp+2 +tcp.seq u32 tcp+4 +tcp.ack u32 tcp+8 + +# Data offset (4 bits) +tcp.off u8 tcp+12 0xF0 4 + +# Reserved [0 0 0] (3 bits) +tcp.reserved u8 tcp+12 0x04 1 + +# ECN [N C E] (3 bits) +tcp.ecn u16 tcp+12 0x01C00 6 + +# Individual TCP flags (0|1) (6 bits in total) +tcp.flag.urg u8 tcp+13 0x20 5 +tcp.flag.ack u8 tcp+13 0x10 4 +tcp.flag.psh u8 tcp+13 0x08 3 +tcp.flag.rst u8 tcp+13 0x04 2 +tpc.flag.syn u8 tcp+13 0x02 1 +tcp.flag.fin u8 tcp+13 0x01 + +tcp.win u16 tcp+14 +tcp.csum u16 tcp+16 +tcp.urg u16 tcp+18 +tcp.opts u32 tcp+20 + +# +# User Datagram Protocol (UDP) +# +# name alignment offset mask shift +udp.sport u16 tcp+0 +udp.dport u16 tcp+2 +udp.length u16 tcp+4 +udp.csum u16 tcp+6 diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 0000000..3488c52 --- /dev/null +++ b/include/Makefile.am @@ -0,0 +1,135 @@ +# -*- Makefile -*- + +libnlincludedir = $(includedir)/libnl@MAJ_VERSION@ + +nobase_libnlinclude_HEADERS = \ + netlink/fib_lookup/lookup.h \ + netlink/fib_lookup/request.h \ + netlink/genl/ctrl.h \ + netlink/genl/family.h \ + netlink/genl/genl.h \ + netlink/genl/mngt.h \ + netlink/netfilter/ct.h \ + netlink/netfilter/exp.h \ + netlink/netfilter/log.h \ + netlink/netfilter/log_msg.h \ + netlink/netfilter/netfilter.h \ + netlink/netfilter/nfnl.h \ + netlink/netfilter/queue.h \ + netlink/netfilter/queue_msg.h \ + netlink/addr.h \ + netlink/attr.h \ + netlink/cache.h \ + netlink/data.h \ + netlink/errno.h \ + netlink/handlers.h \ + netlink/hash.h \ + netlink/hashtable.h \ + netlink/list.h \ + netlink/msg.h \ + netlink/netlink-compat.h \ + netlink/netlink-kernel.h \ + netlink/netlink.h \ + netlink/object.h \ + netlink/route/cls/ematch/cmp.h \ + netlink/route/cls/ematch/meta.h \ + netlink/route/cls/ematch/nbyte.h \ + netlink/route/cls/ematch/text.h \ + netlink/route/cls/basic.h \ + netlink/route/cls/cgroup.h \ + netlink/route/cls/ematch.h \ + netlink/route/cls/fw.h \ + netlink/route/cls/police.h \ + netlink/route/cls/u32.h \ + netlink/route/link/bonding.h \ + netlink/route/link/bridge.h \ + netlink/route/link/can.h \ + netlink/route/link/inet.h \ + netlink/route/link/vlan.h \ + netlink/route/qdisc/cbq.h \ + netlink/route/qdisc/dsmark.h \ + netlink/route/qdisc/fifo.h \ + netlink/route/qdisc/htb.h \ + netlink/route/qdisc/netem.h \ + netlink/route/qdisc/prio.h \ + netlink/route/qdisc/red.h \ + netlink/route/qdisc/sfq.h \ + netlink/route/qdisc/tbf.h \ + netlink/route/qdisc/plug.h \ + netlink/route/addr.h \ + netlink/route/class.h \ + netlink/route/classifier.h \ + netlink/route/link.h \ + netlink/route/neighbour.h \ + netlink/route/neightbl.h \ + netlink/route/nexthop.h \ + netlink/route/pktloc.h \ + netlink/route/qdisc.h \ + netlink/route/route.h \ + netlink/route/rtnl.h \ + netlink/route/rule.h \ + netlink/route/tc.h \ + netlink/socket.h \ + netlink/types.h \ + netlink/utils.h \ + netlink/version.h \ + netlink/cache-api.h \ + netlink/object-api.h \ + netlink/route/link/api.h \ + netlink/route/link/info-api.h \ + netlink/route/tc-api.h + + +if ENABLE_CLI +nobase_libnlinclude_HEADERS += \ + netlink/cli/addr.h \ + netlink/cli/class.h \ + netlink/cli/cls.h \ + netlink/cli/ct.h \ + netlink/cli/exp.h \ + netlink/cli/link.h \ + netlink/cli/neigh.h \ + netlink/cli/qdisc.h \ + netlink/cli/route.h \ + netlink/cli/rule.h \ + netlink/cli/tc.h \ + netlink/cli/utils.h +endif + +noinst_HEADERS = \ + linux/fib_rules.h \ + linux/genetlink.h \ + linux/gen_stats.h \ + linux/if_addr.h \ + linux/if_arp.h \ + linux/if_ether.h \ + linux/if.h \ + linux/if_bridge.h \ + linux/if_link.h \ + linux/if_vlan.h \ + linux/inetdevice.h \ + linux/ip_mp_alg.h \ + linux/ipv6.h \ + linux/can/netlink.h \ + linux/neighbour.h \ + linux/netfilter.h \ + linux/netfilter/nf_conntrack_common.h \ + linux/netfilter/nfnetlink_compat.h \ + linux/netfilter/nfnetlink_conntrack.h \ + linux/netfilter/nfnetlink.h \ + linux/netfilter/nfnetlink_log.h \ + linux/netfilter/nfnetlink_queue.h \ + linux/netlink.h \ + linux/pkt_cls.h \ + linux/pkt_sched.h \ + linux/rtnetlink.h \ + linux/snmp.h \ + linux/tc_ematch/tc_em_meta.h \ + netlink-private/genl.h \ + netlink-private/netlink.h \ + netlink-private/tc.h \ + netlink-private/types.h \ + netlink-private/cache-api.h \ + netlink-private/object-api.h \ + netlink-private/route/link/api.h \ + netlink-private/route/tc-api.h diff --git a/include/Makefile.in b/include/Makefile.in new file mode 100644 index 0000000..142c716 --- /dev/null +++ b/include/Makefile.in @@ -0,0 +1,640 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# -*- Makefile -*- + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@ENABLE_CLI_TRUE@am__append_1 = \ +@ENABLE_CLI_TRUE@ netlink/cli/addr.h \ +@ENABLE_CLI_TRUE@ netlink/cli/class.h \ +@ENABLE_CLI_TRUE@ netlink/cli/cls.h \ +@ENABLE_CLI_TRUE@ netlink/cli/ct.h \ +@ENABLE_CLI_TRUE@ netlink/cli/exp.h \ +@ENABLE_CLI_TRUE@ netlink/cli/link.h \ +@ENABLE_CLI_TRUE@ netlink/cli/neigh.h \ +@ENABLE_CLI_TRUE@ netlink/cli/qdisc.h \ +@ENABLE_CLI_TRUE@ netlink/cli/route.h \ +@ENABLE_CLI_TRUE@ netlink/cli/rule.h \ +@ENABLE_CLI_TRUE@ netlink/cli/tc.h \ +@ENABLE_CLI_TRUE@ netlink/cli/utils.h + +subdir = include +DIST_COMMON = $(am__nobase_libnlinclude_HEADERS_DIST) \ + $(noinst_HEADERS) $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/lib/defs.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__nobase_libnlinclude_HEADERS_DIST = netlink/fib_lookup/lookup.h \ + netlink/fib_lookup/request.h netlink/genl/ctrl.h \ + netlink/genl/family.h netlink/genl/genl.h netlink/genl/mngt.h \ + netlink/netfilter/ct.h netlink/netfilter/exp.h \ + netlink/netfilter/log.h netlink/netfilter/log_msg.h \ + netlink/netfilter/netfilter.h netlink/netfilter/nfnl.h \ + netlink/netfilter/queue.h netlink/netfilter/queue_msg.h \ + netlink/addr.h netlink/attr.h netlink/cache.h netlink/data.h \ + netlink/errno.h netlink/handlers.h netlink/hash.h \ + netlink/hashtable.h netlink/list.h netlink/msg.h \ + netlink/netlink-compat.h netlink/netlink-kernel.h \ + netlink/netlink.h netlink/object.h \ + netlink/route/cls/ematch/cmp.h netlink/route/cls/ematch/meta.h \ + netlink/route/cls/ematch/nbyte.h \ + netlink/route/cls/ematch/text.h netlink/route/cls/basic.h \ + netlink/route/cls/cgroup.h netlink/route/cls/ematch.h \ + netlink/route/cls/fw.h netlink/route/cls/police.h \ + netlink/route/cls/u32.h netlink/route/link/bonding.h \ + netlink/route/link/bridge.h netlink/route/link/can.h \ + netlink/route/link/inet.h netlink/route/link/vlan.h \ + netlink/route/qdisc/cbq.h netlink/route/qdisc/dsmark.h \ + netlink/route/qdisc/fifo.h netlink/route/qdisc/htb.h \ + netlink/route/qdisc/netem.h netlink/route/qdisc/prio.h \ + netlink/route/qdisc/red.h netlink/route/qdisc/sfq.h \ + netlink/route/qdisc/tbf.h netlink/route/qdisc/plug.h \ + netlink/route/addr.h netlink/route/class.h \ + netlink/route/classifier.h netlink/route/link.h \ + netlink/route/neighbour.h netlink/route/neightbl.h \ + netlink/route/nexthop.h netlink/route/pktloc.h \ + netlink/route/qdisc.h netlink/route/route.h \ + netlink/route/rtnl.h netlink/route/rule.h netlink/route/tc.h \ + netlink/socket.h netlink/types.h netlink/utils.h \ + netlink/version.h netlink/cache-api.h netlink/object-api.h \ + netlink/route/link/api.h netlink/route/link/info-api.h \ + netlink/route/tc-api.h netlink/cli/addr.h netlink/cli/class.h \ + netlink/cli/cls.h netlink/cli/ct.h netlink/cli/exp.h \ + netlink/cli/link.h netlink/cli/neigh.h netlink/cli/qdisc.h \ + netlink/cli/route.h netlink/cli/rule.h netlink/cli/tc.h \ + netlink/cli/utils.h +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libnlincludedir)" +HEADERS = $(nobase_libnlinclude_HEADERS) $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_CFLAGS = @CHECK_CFLAGS@ +CHECK_LIBS = @CHECK_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FLEX = @FLEX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBNL_VERSION = @LIBNL_VERSION@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_CURRENT = @LT_CURRENT@ +LT_REVISION = @LT_REVISION@ +MAJ_VERSION = @MAJ_VERSION@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIC_VERSION = @MIC_VERSION@ +MIN_VERSION = @MIN_VERSION@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgconfigdir = @pkgconfigdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +libnlincludedir = $(includedir)/libnl@MAJ_VERSION@ +nobase_libnlinclude_HEADERS = netlink/fib_lookup/lookup.h \ + netlink/fib_lookup/request.h netlink/genl/ctrl.h \ + netlink/genl/family.h netlink/genl/genl.h netlink/genl/mngt.h \ + netlink/netfilter/ct.h netlink/netfilter/exp.h \ + netlink/netfilter/log.h netlink/netfilter/log_msg.h \ + netlink/netfilter/netfilter.h netlink/netfilter/nfnl.h \ + netlink/netfilter/queue.h netlink/netfilter/queue_msg.h \ + netlink/addr.h netlink/attr.h netlink/cache.h netlink/data.h \ + netlink/errno.h netlink/handlers.h netlink/hash.h \ + netlink/hashtable.h netlink/list.h netlink/msg.h \ + netlink/netlink-compat.h netlink/netlink-kernel.h \ + netlink/netlink.h netlink/object.h \ + netlink/route/cls/ematch/cmp.h netlink/route/cls/ematch/meta.h \ + netlink/route/cls/ematch/nbyte.h \ + netlink/route/cls/ematch/text.h netlink/route/cls/basic.h \ + netlink/route/cls/cgroup.h netlink/route/cls/ematch.h \ + netlink/route/cls/fw.h netlink/route/cls/police.h \ + netlink/route/cls/u32.h netlink/route/link/bonding.h \ + netlink/route/link/bridge.h netlink/route/link/can.h \ + netlink/route/link/inet.h netlink/route/link/vlan.h \ + netlink/route/qdisc/cbq.h netlink/route/qdisc/dsmark.h \ + netlink/route/qdisc/fifo.h netlink/route/qdisc/htb.h \ + netlink/route/qdisc/netem.h netlink/route/qdisc/prio.h \ + netlink/route/qdisc/red.h netlink/route/qdisc/sfq.h \ + netlink/route/qdisc/tbf.h netlink/route/qdisc/plug.h \ + netlink/route/addr.h netlink/route/class.h \ + netlink/route/classifier.h netlink/route/link.h \ + netlink/route/neighbour.h netlink/route/neightbl.h \ + netlink/route/nexthop.h netlink/route/pktloc.h \ + netlink/route/qdisc.h netlink/route/route.h \ + netlink/route/rtnl.h netlink/route/rule.h netlink/route/tc.h \ + netlink/socket.h netlink/types.h netlink/utils.h \ + netlink/version.h netlink/cache-api.h netlink/object-api.h \ + netlink/route/link/api.h netlink/route/link/info-api.h \ + netlink/route/tc-api.h $(am__append_1) +noinst_HEADERS = \ + linux/fib_rules.h \ + linux/genetlink.h \ + linux/gen_stats.h \ + linux/if_addr.h \ + linux/if_arp.h \ + linux/if_ether.h \ + linux/if.h \ + linux/if_bridge.h \ + linux/if_link.h \ + linux/if_vlan.h \ + linux/inetdevice.h \ + linux/ip_mp_alg.h \ + linux/ipv6.h \ + linux/can/netlink.h \ + linux/neighbour.h \ + linux/netfilter.h \ + linux/netfilter/nf_conntrack_common.h \ + linux/netfilter/nfnetlink_compat.h \ + linux/netfilter/nfnetlink_conntrack.h \ + linux/netfilter/nfnetlink.h \ + linux/netfilter/nfnetlink_log.h \ + linux/netfilter/nfnetlink_queue.h \ + linux/netlink.h \ + linux/pkt_cls.h \ + linux/pkt_sched.h \ + linux/rtnetlink.h \ + linux/snmp.h \ + linux/tc_ematch/tc_em_meta.h \ + netlink-private/genl.h \ + netlink-private/netlink.h \ + netlink-private/tc.h \ + netlink-private/types.h \ + netlink-private/cache-api.h \ + netlink-private/object-api.h \ + netlink-private/route/link/api.h \ + netlink-private/route/tc-api.h + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign include/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-nobase_libnlincludeHEADERS: $(nobase_libnlinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nobase_libnlinclude_HEADERS)'; test -n "$(libnlincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libnlincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libnlincludedir)" || exit 1; \ + fi; \ + $(am__nobase_list) | while read dir files; do \ + xfiles=; for file in $$files; do \ + if test -f "$$file"; then xfiles="$$xfiles $$file"; \ + else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ + test -z "$$xfiles" || { \ + test "x$$dir" = x. || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libnlincludedir)/$$dir'"; \ + $(MKDIR_P) "$(DESTDIR)$(libnlincludedir)/$$dir"; }; \ + echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(libnlincludedir)/$$dir'"; \ + $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(libnlincludedir)/$$dir" || exit $$?; }; \ + done + +uninstall-nobase_libnlincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nobase_libnlinclude_HEADERS)'; test -n "$(libnlincludedir)" || list=; \ + $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ + dir='$(DESTDIR)$(libnlincludedir)'; $(am__uninstall_files_from_dir) + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libnlincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-nobase_libnlincludeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-nobase_libnlincludeHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool ctags distclean distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-nobase_libnlincludeHEADERS \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am \ + uninstall-nobase_libnlincludeHEADERS + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/include/linux/can/netlink.h b/include/linux/can/netlink.h new file mode 100644 index 0000000..14966dd --- /dev/null +++ b/include/linux/can/netlink.h @@ -0,0 +1,122 @@ +/* + * linux/can/netlink.h + * + * Definitions for the CAN netlink interface + * + * Copyright (c) 2009 Wolfgang Grandegger + * + */ + +#ifndef CAN_NETLINK_H +#define CAN_NETLINK_H + +#include + +/* + * CAN bit-timing parameters + * + * For further information, please read chapter "8 BIT TIMING + * REQUIREMENTS" of the "Bosch CAN Specification version 2.0" + * at http://www.semiconductors.bosch.de/pdf/can2spec.pdf. + */ +struct can_bittiming { + __u32 bitrate; /* Bit-rate in bits/second */ + __u32 sample_point; /* Sample point in one-tenth of a percent */ + __u32 tq; /* Time quanta (TQ) in nanoseconds */ + __u32 prop_seg; /* Propagation segment in TQs */ + __u32 phase_seg1; /* Phase buffer segment 1 in TQs */ + __u32 phase_seg2; /* Phase buffer segment 2 in TQs */ + __u32 sjw; /* Synchronisation jump width in TQs */ + __u32 brp; /* Bit-rate prescaler */ +}; + +/* + * CAN harware-dependent bit-timing constant + * + * Used for calculating and checking bit-timing parameters + */ +struct can_bittiming_const { + char name[16]; /* Name of the CAN controller hardware */ + __u32 tseg1_min; /* Time segement 1 = prop_seg + phase_seg1 */ + __u32 tseg1_max; + __u32 tseg2_min; /* Time segement 2 = phase_seg2 */ + __u32 tseg2_max; + __u32 sjw_max; /* Synchronisation jump width */ + __u32 brp_min; /* Bit-rate prescaler */ + __u32 brp_max; + __u32 brp_inc; +}; + +/* + * CAN clock parameters + */ +struct can_clock { + __u32 freq; /* CAN system clock frequency in Hz */ +}; + +/* + * CAN operational and error states + */ +enum can_state { + CAN_STATE_ERROR_ACTIVE = 0, /* RX/TX error count < 96 */ + CAN_STATE_ERROR_WARNING, /* RX/TX error count < 128 */ + CAN_STATE_ERROR_PASSIVE, /* RX/TX error count < 256 */ + CAN_STATE_BUS_OFF, /* RX/TX error count >= 256 */ + CAN_STATE_STOPPED, /* Device is stopped */ + CAN_STATE_SLEEPING, /* Device is sleeping */ + CAN_STATE_MAX +}; + +/* + * CAN bus error counters + */ +struct can_berr_counter { + __u16 txerr; + __u16 rxerr; +}; + +/* + * CAN controller mode + */ +struct can_ctrlmode { + __u32 mask; + __u32 flags; +}; + +#define CAN_CTRLMODE_LOOPBACK 0x01 /* Loopback mode */ +#define CAN_CTRLMODE_LISTENONLY 0x02 /* Listen-only mode */ +#define CAN_CTRLMODE_3_SAMPLES 0x04 /* Triple sampling mode */ +#define CAN_CTRLMODE_ONE_SHOT 0x08 /* One-Shot mode */ +#define CAN_CTRLMODE_BERR_REPORTING 0x10 /* Bus-error reporting */ + +/* + * CAN device statistics + */ +struct can_device_stats { + __u32 bus_error; /* Bus errors */ + __u32 error_warning; /* Changes to error warning state */ + __u32 error_passive; /* Changes to error passive state */ + __u32 bus_off; /* Changes to bus off state */ + __u32 arbitration_lost; /* Arbitration lost errors */ + __u32 restarts; /* CAN controller re-starts */ +}; + +/* + * CAN netlink interface + */ +enum { + IFLA_CAN_UNSPEC, + IFLA_CAN_BITTIMING, + IFLA_CAN_BITTIMING_CONST, + IFLA_CAN_CLOCK, + IFLA_CAN_STATE, + IFLA_CAN_CTRLMODE, + IFLA_CAN_RESTART_MS, + IFLA_CAN_RESTART, + IFLA_CAN_BERR_COUNTER, + __IFLA_CAN_MAX +}; + +#define IFLA_CAN_MAX (__IFLA_CAN_MAX - 1) + +#endif /* CAN_NETLINK_H */ diff --git a/include/linux/fib_rules.h b/include/linux/fib_rules.h new file mode 100644 index 0000000..ed4504a --- /dev/null +++ b/include/linux/fib_rules.h @@ -0,0 +1,69 @@ +#ifndef __LINUX_FIB_RULES_H +#define __LINUX_FIB_RULES_H + +/* rule is permanent, and cannot be deleted */ +#define FIB_RULE_PERMANENT 0x00000001 +#define FIB_RULE_INVERT 0x00000002 +#define FIB_RULE_UNRESOLVED 0x00000004 +#define FIB_RULE_IIF_DETACHED 0x00000008 +#define FIB_RULE_DEV_DETACHED FIB_RULE_IIF_DETACHED +#define FIB_RULE_OIF_DETACHED 0x00000010 + +/* try to find source address in routing lookups */ +#define FIB_RULE_FIND_SADDR 0x00010000 + +struct fib_rule_hdr { + __u8 family; + __u8 dst_len; + __u8 src_len; + __u8 tos; + + __u8 table; + __u8 res1; /* reserved */ + __u8 res2; /* reserved */ + __u8 action; + + __u32 flags; +}; + +enum { + FRA_UNSPEC, + FRA_DST, /* destination address */ + FRA_SRC, /* source address */ + FRA_IIFNAME, /* interface name */ +#define FRA_IFNAME FRA_IIFNAME + FRA_GOTO, /* target to jump to (FR_ACT_GOTO) */ + FRA_UNUSED2, + FRA_PRIORITY, /* priority/preference */ + FRA_UNUSED3, + FRA_UNUSED4, + FRA_UNUSED5, + FRA_FWMARK, /* mark */ + FRA_FLOW, /* flow/class id */ + FRA_UNUSED6, + FRA_UNUSED7, + FRA_UNUSED8, + FRA_TABLE, /* Extended table id */ + FRA_FWMASK, /* mask for netfilter mark */ + FRA_OIFNAME, + __FRA_MAX +}; + +#define FRA_MAX (__FRA_MAX - 1) + +enum { + FR_ACT_UNSPEC, + FR_ACT_TO_TBL, /* Pass to fixed table */ + FR_ACT_GOTO, /* Jump to another rule */ + FR_ACT_NOP, /* No operation */ + FR_ACT_RES3, + FR_ACT_RES4, + FR_ACT_BLACKHOLE, /* Drop without notification */ + FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */ + FR_ACT_PROHIBIT, /* Drop with EACCES */ + __FR_ACT_MAX, +}; + +#define FR_ACT_MAX (__FR_ACT_MAX - 1) + +#endif diff --git a/include/linux/gen_stats.h b/include/linux/gen_stats.h new file mode 100644 index 0000000..552c8a0 --- /dev/null +++ b/include/linux/gen_stats.h @@ -0,0 +1,67 @@ +#ifndef __LINUX_GEN_STATS_H +#define __LINUX_GEN_STATS_H + +#include + +enum { + TCA_STATS_UNSPEC, + TCA_STATS_BASIC, + TCA_STATS_RATE_EST, + TCA_STATS_QUEUE, + TCA_STATS_APP, + __TCA_STATS_MAX, +}; +#define TCA_STATS_MAX (__TCA_STATS_MAX - 1) + +/** + * struct gnet_stats_basic - byte/packet throughput statistics + * @bytes: number of seen bytes + * @packets: number of seen packets + */ +struct gnet_stats_basic { + __u64 bytes; + __u32 packets; +}; +struct gnet_stats_basic_packed { + __u64 bytes; + __u32 packets; +} __attribute__ ((packed)); + +/** + * struct gnet_stats_rate_est - rate estimator + * @bps: current byte rate + * @pps: current packet rate + */ +struct gnet_stats_rate_est { + __u32 bps; + __u32 pps; +}; + +/** + * struct gnet_stats_queue - queuing statistics + * @qlen: queue length + * @backlog: backlog size of queue + * @drops: number of dropped packets + * @requeues: number of requeues + * @overlimits: number of enqueues over the limit + */ +struct gnet_stats_queue { + __u32 qlen; + __u32 backlog; + __u32 drops; + __u32 requeues; + __u32 overlimits; +}; + +/** + * struct gnet_estimator - rate estimator configuration + * @interval: sampling period + * @ewma_log: the log of measurement window weight + */ +struct gnet_estimator { + signed char interval; + unsigned char ewma_log; +}; + + +#endif /* __LINUX_GEN_STATS_H */ diff --git a/include/linux/genetlink.h b/include/linux/genetlink.h new file mode 100644 index 0000000..b834ef6 --- /dev/null +++ b/include/linux/genetlink.h @@ -0,0 +1,83 @@ +#ifndef __LINUX_GENERIC_NETLINK_H +#define __LINUX_GENERIC_NETLINK_H + +#include +#include + +#define GENL_NAMSIZ 16 /* length of family name */ + +#define GENL_MIN_ID NLMSG_MIN_TYPE +#define GENL_MAX_ID 1023 + +struct genlmsghdr { + __u8 cmd; + __u8 version; + __u16 reserved; +}; + +#define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr)) + +#define GENL_ADMIN_PERM 0x01 +#define GENL_CMD_CAP_DO 0x02 +#define GENL_CMD_CAP_DUMP 0x04 +#define GENL_CMD_CAP_HASPOL 0x08 + +/* + * List of reserved static generic netlink identifiers: + */ +#define GENL_ID_GENERATE 0 +#define GENL_ID_CTRL NLMSG_MIN_TYPE + +/************************************************************************** + * Controller + **************************************************************************/ + +enum { + CTRL_CMD_UNSPEC, + CTRL_CMD_NEWFAMILY, + CTRL_CMD_DELFAMILY, + CTRL_CMD_GETFAMILY, + CTRL_CMD_NEWOPS, + CTRL_CMD_DELOPS, + CTRL_CMD_GETOPS, + CTRL_CMD_NEWMCAST_GRP, + CTRL_CMD_DELMCAST_GRP, + CTRL_CMD_GETMCAST_GRP, /* unused */ + __CTRL_CMD_MAX, +}; + +#define CTRL_CMD_MAX (__CTRL_CMD_MAX - 1) + +enum { + CTRL_ATTR_UNSPEC, + CTRL_ATTR_FAMILY_ID, + CTRL_ATTR_FAMILY_NAME, + CTRL_ATTR_VERSION, + CTRL_ATTR_HDRSIZE, + CTRL_ATTR_MAXATTR, + CTRL_ATTR_OPS, + CTRL_ATTR_MCAST_GROUPS, + __CTRL_ATTR_MAX, +}; + +#define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1) + +enum { + CTRL_ATTR_OP_UNSPEC, + CTRL_ATTR_OP_ID, + CTRL_ATTR_OP_FLAGS, + __CTRL_ATTR_OP_MAX, +}; + +#define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1) + +enum { + CTRL_ATTR_MCAST_GRP_UNSPEC, + CTRL_ATTR_MCAST_GRP_NAME, + CTRL_ATTR_MCAST_GRP_ID, + __CTRL_ATTR_MCAST_GRP_MAX, +}; + +#define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1) + +#endif /* __LINUX_GENERIC_NETLINK_H */ diff --git a/include/linux/if.h b/include/linux/if.h new file mode 100644 index 0000000..238cf43 --- /dev/null +++ b/include/linux/if.h @@ -0,0 +1,146 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Global definitions for the INET interface module. + * + * Version: @(#)if.h 1.0.2 04/18/93 + * + * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988 + * Ross Biro + * Fred N. van Kempen, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _LINUX_IF_H +#define _LINUX_IF_H + +#define IFNAMSIZ 16 +#define IFALIASZ 256 + +/* Standard interface flags (netdevice->flags). */ +#define IFF_UP 0x1 /* interface is up */ +#define IFF_BROADCAST 0x2 /* broadcast address valid */ +#define IFF_DEBUG 0x4 /* turn on debugging */ +#define IFF_LOOPBACK 0x8 /* is a loopback net */ +#define IFF_POINTOPOINT 0x10 /* interface is has p-p link */ +#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */ +#define IFF_RUNNING 0x40 /* interface RFC2863 OPER_UP */ +#define IFF_NOARP 0x80 /* no ARP protocol */ +#define IFF_PROMISC 0x100 /* receive all packets */ +#define IFF_ALLMULTI 0x200 /* receive all multicast packets*/ + +#define IFF_MASTER 0x400 /* master of a load balancer */ +#define IFF_SLAVE 0x800 /* slave of a load balancer */ + +#define IFF_MULTICAST 0x1000 /* Supports multicast */ + +#define IFF_PORTSEL 0x2000 /* can set media type */ +#define IFF_AUTOMEDIA 0x4000 /* auto media select active */ +#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/ + +#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ +#define IFF_DORMANT 0x20000 /* driver signals dormant */ + +#define IFF_ECHO 0x40000 /* echo sent packets */ + +#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\ + IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT) + +/* Private (from user) interface flags (netdevice->priv_flags). */ +#define IFF_802_1Q_VLAN 0x1 /* 802.1Q VLAN device. */ +#define IFF_EBRIDGE 0x2 /* Ethernet bridging device. */ +#define IFF_SLAVE_INACTIVE 0x4 /* bonding slave not the curr. active */ +#define IFF_MASTER_8023AD 0x8 /* bonding master, 802.3ad. */ +#define IFF_MASTER_ALB 0x10 /* bonding master, balance-alb. */ +#define IFF_BONDING 0x20 /* bonding master or slave */ +#define IFF_SLAVE_NEEDARP 0x40 /* need ARPs for validation */ +#define IFF_ISATAP 0x80 /* ISATAP interface (RFC4214) */ +#define IFF_MASTER_ARPMON 0x100 /* bonding master, ARP mon in use */ +#define IFF_WAN_HDLC 0x200 /* WAN HDLC device */ +#define IFF_XMIT_DST_RELEASE 0x400 /* dev_hard_start_xmit() is allowed to + * release skb->dst + */ +#define IFF_DONT_BRIDGE 0x800 /* disallow bridging this ether dev */ +#define IFF_IN_NETPOLL 0x1000 /* whether we are processing netpoll */ +#define IFF_DISABLE_NETPOLL 0x2000 /* disable netpoll at run-time */ +#define IFF_MACVLAN_PORT 0x4000 /* device used as macvlan port */ +#define IFF_BRIDGE_PORT 0x8000 /* device used as bridge port */ +#define IFF_OVS_DATAPATH 0x10000 /* device used as Open vSwitch + * datapath port */ + +#define IF_GET_IFACE 0x0001 /* for querying only */ +#define IF_GET_PROTO 0x0002 + +/* For definitions see hdlc.h */ +#define IF_IFACE_V35 0x1000 /* V.35 serial interface */ +#define IF_IFACE_V24 0x1001 /* V.24 serial interface */ +#define IF_IFACE_X21 0x1002 /* X.21 serial interface */ +#define IF_IFACE_T1 0x1003 /* T1 telco serial interface */ +#define IF_IFACE_E1 0x1004 /* E1 telco serial interface */ +#define IF_IFACE_SYNC_SERIAL 0x1005 /* can't be set by software */ +#define IF_IFACE_X21D 0x1006 /* X.21 Dual Clocking (FarSite) */ + +/* For definitions see hdlc.h */ +#define IF_PROTO_HDLC 0x2000 /* raw HDLC protocol */ +#define IF_PROTO_PPP 0x2001 /* PPP protocol */ +#define IF_PROTO_CISCO 0x2002 /* Cisco HDLC protocol */ +#define IF_PROTO_FR 0x2003 /* Frame Relay protocol */ +#define IF_PROTO_FR_ADD_PVC 0x2004 /* Create FR PVC */ +#define IF_PROTO_FR_DEL_PVC 0x2005 /* Delete FR PVC */ +#define IF_PROTO_X25 0x2006 /* X.25 */ +#define IF_PROTO_HDLC_ETH 0x2007 /* raw HDLC, Ethernet emulation */ +#define IF_PROTO_FR_ADD_ETH_PVC 0x2008 /* Create FR Ethernet-bridged PVC */ +#define IF_PROTO_FR_DEL_ETH_PVC 0x2009 /* Delete FR Ethernet-bridged PVC */ +#define IF_PROTO_FR_PVC 0x200A /* for reading PVC status */ +#define IF_PROTO_FR_ETH_PVC 0x200B +#define IF_PROTO_RAW 0x200C /* RAW Socket */ + +/* RFC 2863 operational status */ +enum { + IF_OPER_UNKNOWN, + IF_OPER_NOTPRESENT, + IF_OPER_DOWN, + IF_OPER_LOWERLAYERDOWN, + IF_OPER_TESTING, + IF_OPER_DORMANT, + IF_OPER_UP, +}; + +/* link modes */ +enum { + IF_LINK_MODE_DEFAULT, + IF_LINK_MODE_DORMANT, /* limit upward transition to dormant */ +}; + +/* carrier state */ +enum { + IF_CARRIER_DOWN, + IF_CARRIER_UP +}; + +/* + * Device mapping structure. I'd just gone off and designed a + * beautiful scheme using only loadable modules with arguments + * for driver options and along come the PCMCIA people 8) + * + * Ah well. The get() side of this is good for WDSETUP, and it'll + * be handy for debugging things. The set side is fine for now and + * being very small might be worth keeping for clean configuration. + */ + +struct ifmap { + unsigned long mem_start; + unsigned long mem_end; + unsigned short base_addr; + unsigned char irq; + unsigned char dma; + unsigned char port; + /* 3 bytes spare */ +}; + +#endif /* _LINUX_IF_H */ diff --git a/include/linux/if_addr.h b/include/linux/if_addr.h new file mode 100644 index 0000000..c355522 --- /dev/null +++ b/include/linux/if_addr.h @@ -0,0 +1,55 @@ +#ifndef __LINUX_IF_ADDR_H +#define __LINUX_IF_ADDR_H + +#include +#include + +struct ifaddrmsg { + __u8 ifa_family; + __u8 ifa_prefixlen; /* The prefix length */ + __u8 ifa_flags; /* Flags */ + __u8 ifa_scope; /* Address scope */ + __u32 ifa_index; /* Link index */ +}; + +/* + * Important comment: + * IFA_ADDRESS is prefix address, rather than local interface address. + * It makes no difference for normally configured broadcast interfaces, + * but for point-to-point IFA_ADDRESS is DESTINATION address, + * local address is supplied in IFA_LOCAL attribute. + */ +enum { + IFA_UNSPEC, + IFA_ADDRESS, + IFA_LOCAL, + IFA_LABEL, + IFA_BROADCAST, + IFA_ANYCAST, + IFA_CACHEINFO, + IFA_MULTICAST, + __IFA_MAX, +}; + +#define IFA_MAX (__IFA_MAX - 1) + +/* ifa_flags */ +#define IFA_F_SECONDARY 0x01 +#define IFA_F_TEMPORARY IFA_F_SECONDARY + +#define IFA_F_NODAD 0x02 +#define IFA_F_OPTIMISTIC 0x04 +#define IFA_F_DADFAILED 0x08 +#define IFA_F_HOMEADDRESS 0x10 +#define IFA_F_DEPRECATED 0x20 +#define IFA_F_TENTATIVE 0x40 +#define IFA_F_PERMANENT 0x80 + +struct ifa_cacheinfo { + __u32 ifa_prefered; + __u32 ifa_valid; + __u32 cstamp; /* created timestamp, hundredths of seconds */ + __u32 tstamp; /* updated timestamp, hundredths of seconds */ +}; + +#endif diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h new file mode 100644 index 0000000..e04cd2c --- /dev/null +++ b/include/linux/if_arp.h @@ -0,0 +1,156 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Global definitions for the ARP (RFC 826) protocol. + * + * Version: @(#)if_arp.h 1.0.1 04/16/93 + * + * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988 + * Portions taken from the KA9Q/NOS (v2.00m PA0GRI) source. + * Ross Biro + * Fred N. van Kempen, + * Florian La Roche, + * Jonathan Layes + * Arnaldo Carvalho de Melo ARPHRD_HWX25 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _LINUX_IF_ARP_H +#define _LINUX_IF_ARP_H + +#include + +/* ARP protocol HARDWARE identifiers. */ +#define ARPHRD_NETROM 0 /* from KA9Q: NET/ROM pseudo */ +#define ARPHRD_ETHER 1 /* Ethernet 10Mbps */ +#define ARPHRD_EETHER 2 /* Experimental Ethernet */ +#define ARPHRD_AX25 3 /* AX.25 Level 2 */ +#define ARPHRD_PRONET 4 /* PROnet token ring */ +#define ARPHRD_CHAOS 5 /* Chaosnet */ +#define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB */ +#define ARPHRD_ARCNET 7 /* ARCnet */ +#define ARPHRD_APPLETLK 8 /* APPLEtalk */ +#define ARPHRD_DLCI 15 /* Frame Relay DLCI */ +#define ARPHRD_ATM 19 /* ATM */ +#define ARPHRD_METRICOM 23 /* Metricom STRIP (new IANA id) */ +#define ARPHRD_IEEE1394 24 /* IEEE 1394 IPv4 - RFC 2734 */ +#define ARPHRD_EUI64 27 /* EUI-64 */ +#define ARPHRD_INFINIBAND 32 /* InfiniBand */ + +/* Dummy types for non ARP hardware */ +#define ARPHRD_SLIP 256 +#define ARPHRD_CSLIP 257 +#define ARPHRD_SLIP6 258 +#define ARPHRD_CSLIP6 259 +#define ARPHRD_RSRVD 260 /* Notional KISS type */ +#define ARPHRD_ADAPT 264 +#define ARPHRD_ROSE 270 +#define ARPHRD_X25 271 /* CCITT X.25 */ +#define ARPHRD_HWX25 272 /* Boards with X.25 in firmware */ +#define ARPHRD_CAN 280 /* Controller Area Network */ +#define ARPHRD_PPP 512 +#define ARPHRD_CISCO 513 /* Cisco HDLC */ +#define ARPHRD_HDLC ARPHRD_CISCO +#define ARPHRD_LAPB 516 /* LAPB */ +#define ARPHRD_DDCMP 517 /* Digital's DDCMP protocol */ +#define ARPHRD_RAWHDLC 518 /* Raw HDLC */ + +#define ARPHRD_TUNNEL 768 /* IPIP tunnel */ +#define ARPHRD_TUNNEL6 769 /* IP6IP6 tunnel */ +#define ARPHRD_FRAD 770 /* Frame Relay Access Device */ +#define ARPHRD_SKIP 771 /* SKIP vif */ +#define ARPHRD_LOOPBACK 772 /* Loopback device */ +#define ARPHRD_LOCALTLK 773 /* Localtalk device */ +#define ARPHRD_FDDI 774 /* Fiber Distributed Data Interface */ +#define ARPHRD_BIF 775 /* AP1000 BIF */ +#define ARPHRD_SIT 776 /* sit0 device - IPv6-in-IPv4 */ +#define ARPHRD_IPDDP 777 /* IP over DDP tunneller */ +#define ARPHRD_IPGRE 778 /* GRE over IP */ +#define ARPHRD_PIMREG 779 /* PIMSM register interface */ +#define ARPHRD_HIPPI 780 /* High Performance Parallel Interface */ +#define ARPHRD_ASH 781 /* Nexus 64Mbps Ash */ +#define ARPHRD_ECONET 782 /* Acorn Econet */ +#define ARPHRD_IRDA 783 /* Linux-IrDA */ +/* ARP works differently on different FC media .. so */ +#define ARPHRD_FCPP 784 /* Point to point fibrechannel */ +#define ARPHRD_FCAL 785 /* Fibrechannel arbitrated loop */ +#define ARPHRD_FCPL 786 /* Fibrechannel public loop */ +#define ARPHRD_FCFABRIC 787 /* Fibrechannel fabric */ + /* 787->799 reserved for fibrechannel media types */ +#define ARPHRD_IEEE802_TR 800 /* Magic type ident for TR */ +#define ARPHRD_IEEE80211 801 /* IEEE 802.11 */ +#define ARPHRD_IEEE80211_PRISM 802 /* IEEE 802.11 + Prism2 header */ +#define ARPHRD_IEEE80211_RADIOTAP 803 /* IEEE 802.11 + radiotap header */ +#define ARPHRD_IEEE802154 804 + +#define ARPHRD_PHONET 820 /* PhoNet media type */ +#define ARPHRD_PHONET_PIPE 821 /* PhoNet pipe header */ +#define ARPHRD_CAIF 822 /* CAIF media type */ + +#define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */ +#define ARPHRD_NONE 0xFFFE /* zero header length */ + +/* ARP protocol opcodes. */ +#define ARPOP_REQUEST 1 /* ARP request */ +#define ARPOP_REPLY 2 /* ARP reply */ +#define ARPOP_RREQUEST 3 /* RARP request */ +#define ARPOP_RREPLY 4 /* RARP reply */ +#define ARPOP_InREQUEST 8 /* InARP request */ +#define ARPOP_InREPLY 9 /* InARP reply */ +#define ARPOP_NAK 10 /* (ATM)ARP NAK */ + + +/* ARP ioctl request. */ +struct arpreq { + struct sockaddr arp_pa; /* protocol address */ + struct sockaddr arp_ha; /* hardware address */ + int arp_flags; /* flags */ + struct sockaddr arp_netmask; /* netmask (only for proxy arps) */ + char arp_dev[16]; +}; + +struct arpreq_old { + struct sockaddr arp_pa; /* protocol address */ + struct sockaddr arp_ha; /* hardware address */ + int arp_flags; /* flags */ + struct sockaddr arp_netmask; /* netmask (only for proxy arps) */ +}; + +/* ARP Flag values. */ +#define ATF_COM 0x02 /* completed entry (ha valid) */ +#define ATF_PERM 0x04 /* permanent entry */ +#define ATF_PUBL 0x08 /* publish entry */ +#define ATF_USETRAILERS 0x10 /* has requested trailers */ +#define ATF_NETMASK 0x20 /* want to use a netmask (only + for proxy entries) */ +#define ATF_DONTPUB 0x40 /* don't answer this addresses */ + +/* + * This structure defines an ethernet arp header. + */ + +struct arphdr { + __be16 ar_hrd; /* format of hardware address */ + __be16 ar_pro; /* format of protocol address */ + unsigned char ar_hln; /* length of hardware address */ + unsigned char ar_pln; /* length of protocol address */ + __be16 ar_op; /* ARP opcode (command) */ + +#if 0 + /* + * Ethernet looks like this : This bit is variable sized however... + */ + unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */ + unsigned char ar_sip[4]; /* sender IP address */ + unsigned char ar_tha[ETH_ALEN]; /* target hardware address */ + unsigned char ar_tip[4]; /* target IP address */ +#endif + +}; + +#endif /* _LINUX_IF_ARP_H */ diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h new file mode 100644 index 0000000..5db2975 --- /dev/null +++ b/include/linux/if_bridge.h @@ -0,0 +1,185 @@ +/* + * Linux ethernet bridge + * + * Authors: + * Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _UAPI_LINUX_IF_BRIDGE_H +#define _UAPI_LINUX_IF_BRIDGE_H + +#include + +#define SYSFS_BRIDGE_ATTR "bridge" +#define SYSFS_BRIDGE_FDB "brforward" +#define SYSFS_BRIDGE_PORT_SUBDIR "brif" +#define SYSFS_BRIDGE_PORT_ATTR "brport" +#define SYSFS_BRIDGE_PORT_LINK "bridge" + +#define BRCTL_VERSION 1 + +#define BRCTL_GET_VERSION 0 +#define BRCTL_GET_BRIDGES 1 +#define BRCTL_ADD_BRIDGE 2 +#define BRCTL_DEL_BRIDGE 3 +#define BRCTL_ADD_IF 4 +#define BRCTL_DEL_IF 5 +#define BRCTL_GET_BRIDGE_INFO 6 +#define BRCTL_GET_PORT_LIST 7 +#define BRCTL_SET_BRIDGE_FORWARD_DELAY 8 +#define BRCTL_SET_BRIDGE_HELLO_TIME 9 +#define BRCTL_SET_BRIDGE_MAX_AGE 10 +#define BRCTL_SET_AGEING_TIME 11 +#define BRCTL_SET_GC_INTERVAL 12 +#define BRCTL_GET_PORT_INFO 13 +#define BRCTL_SET_BRIDGE_STP_STATE 14 +#define BRCTL_SET_BRIDGE_PRIORITY 15 +#define BRCTL_SET_PORT_PRIORITY 16 +#define BRCTL_SET_PATH_COST 17 +#define BRCTL_GET_FDB_ENTRIES 18 + +#define BR_STATE_DISABLED 0 +#define BR_STATE_LISTENING 1 +#define BR_STATE_LEARNING 2 +#define BR_STATE_FORWARDING 3 +#define BR_STATE_BLOCKING 4 + +struct __bridge_info { + __u64 designated_root; + __u64 bridge_id; + __u32 root_path_cost; + __u32 max_age; + __u32 hello_time; + __u32 forward_delay; + __u32 bridge_max_age; + __u32 bridge_hello_time; + __u32 bridge_forward_delay; + __u8 topology_change; + __u8 topology_change_detected; + __u8 root_port; + __u8 stp_enabled; + __u32 ageing_time; + __u32 gc_interval; + __u32 hello_timer_value; + __u32 tcn_timer_value; + __u32 topology_change_timer_value; + __u32 gc_timer_value; +}; + +struct __port_info { + __u64 designated_root; + __u64 designated_bridge; + __u16 port_id; + __u16 designated_port; + __u32 path_cost; + __u32 designated_cost; + __u8 state; + __u8 top_change_ack; + __u8 config_pending; + __u8 unused0; + __u32 message_age_timer_value; + __u32 forward_delay_timer_value; + __u32 hold_timer_value; +}; + +struct __fdb_entry { + __u8 mac_addr[6]; + __u8 port_no; + __u8 is_local; + __u32 ageing_timer_value; + __u8 port_hi; + __u8 pad0; + __u16 unused; +}; + +/* Bridge Flags */ +#define BRIDGE_FLAGS_MASTER 1 /* Bridge command to/from master */ +#define BRIDGE_FLAGS_SELF 2 /* Bridge command to/from lowerdev */ + +#define BRIDGE_MODE_VEB 0 /* Default loopback mode */ +#define BRIDGE_MODE_VEPA 1 /* 802.1Qbg defined VEPA mode */ + +/* Bridge management nested attributes + * [IFLA_AF_SPEC] = { + * [IFLA_BRIDGE_FLAGS] + * [IFLA_BRIDGE_MODE] + * } + */ +enum { + IFLA_BRIDGE_FLAGS, + IFLA_BRIDGE_MODE, + __IFLA_BRIDGE_MAX, +}; +#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1) + +/* Bridge multicast database attributes + * [MDBA_MDB] = { + * [MDBA_MDB_ENTRY] = { + * [MDBA_MDB_ENTRY_INFO] + * } + * } + * [MDBA_ROUTER] = { + * [MDBA_ROUTER_PORT] + * } + */ +enum { + MDBA_UNSPEC, + MDBA_MDB, + MDBA_ROUTER, + __MDBA_MAX, +}; +#define MDBA_MAX (__MDBA_MAX - 1) + +enum { + MDBA_MDB_UNSPEC, + MDBA_MDB_ENTRY, + __MDBA_MDB_MAX, +}; +#define MDBA_MDB_MAX (__MDBA_MDB_MAX - 1) + +enum { + MDBA_MDB_ENTRY_UNSPEC, + MDBA_MDB_ENTRY_INFO, + __MDBA_MDB_ENTRY_MAX, +}; +#define MDBA_MDB_ENTRY_MAX (__MDBA_MDB_ENTRY_MAX - 1) + +enum { + MDBA_ROUTER_UNSPEC, + MDBA_ROUTER_PORT, + __MDBA_ROUTER_MAX, +}; +#define MDBA_ROUTER_MAX (__MDBA_ROUTER_MAX - 1) + +struct br_port_msg { + __u8 family; + __u32 ifindex; +}; + +struct br_mdb_entry { + __u32 ifindex; +#define MDB_TEMPORARY 0 +#define MDB_PERMANENT 1 + __u8 state; + struct { + union { + __be32 ip4; + struct in6_addr ip6; + } u; + __be16 proto; + } addr; +}; + +enum { + MDBA_SET_ENTRY_UNSPEC, + MDBA_SET_ENTRY, + __MDBA_SET_ENTRY_MAX, +}; +#define MDBA_SET_ENTRY_MAX (__MDBA_SET_ENTRY_MAX - 1) + +#endif /* _UAPI_LINUX_IF_BRIDGE_H */ diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h new file mode 100644 index 0000000..a6af32d --- /dev/null +++ b/include/linux/if_ether.h @@ -0,0 +1,125 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Global definitions for the Ethernet IEEE 802.3 interface. + * + * Version: @(#)if_ether.h 1.0.1a 02/08/94 + * + * Author: Fred N. van Kempen, + * Donald Becker, + * Alan Cox, + * Steve Whitehouse, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _LINUX_IF_ETHER_H +#define _LINUX_IF_ETHER_H + +#include + +/* + * IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble + * and FCS/CRC (frame check sequence). + */ + +#define ETH_ALEN 6 /* Octets in one ethernet addr */ +#define ETH_HLEN 14 /* Total octets in header. */ +#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ +#define ETH_DATA_LEN 1500 /* Max. octets in payload */ +#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */ +#define ETH_FCS_LEN 4 /* Octets in the FCS */ + +/* + * These are the defined Ethernet Protocol ID's. + */ + +#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */ +#define ETH_P_PUP 0x0200 /* Xerox PUP packet */ +#define ETH_P_PUPAT 0x0201 /* Xerox PUP Addr Trans packet */ +#define ETH_P_IP 0x0800 /* Internet Protocol packet */ +#define ETH_P_X25 0x0805 /* CCITT X.25 */ +#define ETH_P_ARP 0x0806 /* Address Resolution packet */ +#define ETH_P_BPQ 0x08FF /* G8BPQ AX.25 Ethernet Packet [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_IEEEPUP 0x0a00 /* Xerox IEEE802.3 PUP packet */ +#define ETH_P_IEEEPUPAT 0x0a01 /* Xerox IEEE802.3 PUP Addr Trans packet */ +#define ETH_P_DEC 0x6000 /* DEC Assigned proto */ +#define ETH_P_DNA_DL 0x6001 /* DEC DNA Dump/Load */ +#define ETH_P_DNA_RC 0x6002 /* DEC DNA Remote Console */ +#define ETH_P_DNA_RT 0x6003 /* DEC DNA Routing */ +#define ETH_P_LAT 0x6004 /* DEC LAT */ +#define ETH_P_DIAG 0x6005 /* DEC Diagnostics */ +#define ETH_P_CUST 0x6006 /* DEC Customer use */ +#define ETH_P_SCA 0x6007 /* DEC Systems Comms Arch */ +#define ETH_P_TEB 0x6558 /* Trans Ether Bridging */ +#define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */ +#define ETH_P_ATALK 0x809B /* Appletalk DDP */ +#define ETH_P_AARP 0x80F3 /* Appletalk AARP */ +#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */ +#define ETH_P_IPX 0x8137 /* IPX over DIX */ +#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ +#define ETH_P_PAUSE 0x8808 /* IEEE Pause frames. See 802.3 31B */ +#define ETH_P_SLOW 0x8809 /* Slow Protocol. See 802.3ad 43B */ +#define ETH_P_WCCP 0x883E /* Web-cache coordination protocol + * defined in draft-wilson-wrec-wccp-v2-00.txt */ +#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ +#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */ +#define ETH_P_MPLS_UC 0x8847 /* MPLS Unicast traffic */ +#define ETH_P_MPLS_MC 0x8848 /* MPLS Multicast traffic */ +#define ETH_P_ATMMPOA 0x884c /* MultiProtocol Over ATM */ +#define ETH_P_LINK_CTL 0x886c /* HPNA, wlan link local tunnel */ +#define ETH_P_ATMFATE 0x8884 /* Frame-based ATM Transport + * over Ethernet + */ +#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ +#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */ +#define ETH_P_TIPC 0x88CA /* TIPC */ +#define ETH_P_1588 0x88F7 /* IEEE 1588 Timesync */ +#define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */ +#define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */ +#define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ + +/* + * Non DIX types. Won't clash for 1500 types. + */ + +#define ETH_P_802_3 0x0001 /* Dummy type for 802.3 frames */ +#define ETH_P_AX25 0x0002 /* Dummy protocol id for AX.25 */ +#define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */ +#define ETH_P_802_2 0x0004 /* 802.2 frames */ +#define ETH_P_SNAP 0x0005 /* Internal only */ +#define ETH_P_DDCMP 0x0006 /* DEC DDCMP: Internal only */ +#define ETH_P_WAN_PPP 0x0007 /* Dummy type for WAN PPP frames*/ +#define ETH_P_PPP_MP 0x0008 /* Dummy type for PPP MP frames */ +#define ETH_P_LOCALTALK 0x0009 /* Localtalk pseudo type */ +#define ETH_P_CAN 0x000C /* Controller Area Network */ +#define ETH_P_PPPTALK 0x0010 /* Dummy type for Atalk over PPP*/ +#define ETH_P_TR_802_2 0x0011 /* 802.2 frames */ +#define ETH_P_MOBITEX 0x0015 /* Mobitex (kaz@cafe.net) */ +#define ETH_P_CONTROL 0x0016 /* Card specific control frames */ +#define ETH_P_IRDA 0x0017 /* Linux-IrDA */ +#define ETH_P_ECONET 0x0018 /* Acorn Econet */ +#define ETH_P_HDLC 0x0019 /* HDLC frames */ +#define ETH_P_ARCNET 0x001A /* 1A for ArcNet :-) */ +#define ETH_P_DSA 0x001B /* Distributed Switch Arch. */ +#define ETH_P_TRAILER 0x001C /* Trailer switch tagging */ +#define ETH_P_PHONET 0x00F5 /* Nokia Phonet frames */ +#define ETH_P_IEEE802154 0x00F6 /* IEEE802.15.4 frame */ +#define ETH_P_CAIF 0x00F7 /* ST-Ericsson CAIF protocol */ + +/* + * This is an Ethernet frame header. + */ + +struct ethhdr { + unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ + unsigned char h_source[ETH_ALEN]; /* source ether addr */ + __be16 h_proto; /* packet type ID field */ +} __attribute__((packed)); + +#endif /* _LINUX_IF_ETHER_H */ diff --git a/include/linux/if_link.h b/include/linux/if_link.h new file mode 100644 index 0000000..73ee05c --- /dev/null +++ b/include/linux/if_link.h @@ -0,0 +1,446 @@ +#ifndef _UAPI_LINUX_IF_LINK_H +#define _UAPI_LINUX_IF_LINK_H + +#include +#include + +/* This struct should be in sync with struct rtnl_link_stats64 */ +struct rtnl_link_stats { + __u32 rx_packets; /* total packets received */ + __u32 tx_packets; /* total packets transmitted */ + __u32 rx_bytes; /* total bytes received */ + __u32 tx_bytes; /* total bytes transmitted */ + __u32 rx_errors; /* bad packets received */ + __u32 tx_errors; /* packet transmit problems */ + __u32 rx_dropped; /* no space in linux buffers */ + __u32 tx_dropped; /* no space available in linux */ + __u32 multicast; /* multicast packets received */ + __u32 collisions; + + /* detailed rx_errors: */ + __u32 rx_length_errors; + __u32 rx_over_errors; /* receiver ring buff overflow */ + __u32 rx_crc_errors; /* recved pkt with crc error */ + __u32 rx_frame_errors; /* recv'd frame alignment error */ + __u32 rx_fifo_errors; /* recv'r fifo overrun */ + __u32 rx_missed_errors; /* receiver missed packet */ + + /* detailed tx_errors */ + __u32 tx_aborted_errors; + __u32 tx_carrier_errors; + __u32 tx_fifo_errors; + __u32 tx_heartbeat_errors; + __u32 tx_window_errors; + + /* for cslip etc */ + __u32 rx_compressed; + __u32 tx_compressed; +}; + +/* The main device statistics structure */ +struct rtnl_link_stats64 { + __u64 rx_packets; /* total packets received */ + __u64 tx_packets; /* total packets transmitted */ + __u64 rx_bytes; /* total bytes received */ + __u64 tx_bytes; /* total bytes transmitted */ + __u64 rx_errors; /* bad packets received */ + __u64 tx_errors; /* packet transmit problems */ + __u64 rx_dropped; /* no space in linux buffers */ + __u64 tx_dropped; /* no space available in linux */ + __u64 multicast; /* multicast packets received */ + __u64 collisions; + + /* detailed rx_errors: */ + __u64 rx_length_errors; + __u64 rx_over_errors; /* receiver ring buff overflow */ + __u64 rx_crc_errors; /* recved pkt with crc error */ + __u64 rx_frame_errors; /* recv'd frame alignment error */ + __u64 rx_fifo_errors; /* recv'r fifo overrun */ + __u64 rx_missed_errors; /* receiver missed packet */ + + /* detailed tx_errors */ + __u64 tx_aborted_errors; + __u64 tx_carrier_errors; + __u64 tx_fifo_errors; + __u64 tx_heartbeat_errors; + __u64 tx_window_errors; + + /* for cslip etc */ + __u64 rx_compressed; + __u64 tx_compressed; +}; + +/* The struct should be in sync with struct ifmap */ +struct rtnl_link_ifmap { + __u64 mem_start; + __u64 mem_end; + __u64 base_addr; + __u16 irq; + __u8 dma; + __u8 port; +}; + +/* + * IFLA_AF_SPEC + * Contains nested attributes for address family specific attributes. + * Each address family may create a attribute with the address family + * number as type and create its own attribute structure in it. + * + * Example: + * [IFLA_AF_SPEC] = { + * [AF_INET] = { + * [IFLA_INET_CONF] = ..., + * }, + * [AF_INET6] = { + * [IFLA_INET6_FLAGS] = ..., + * [IFLA_INET6_CONF] = ..., + * } + * } + */ + +enum { + IFLA_UNSPEC, + IFLA_ADDRESS, + IFLA_BROADCAST, + IFLA_IFNAME, + IFLA_MTU, + IFLA_LINK, + IFLA_QDISC, + IFLA_STATS, + IFLA_COST, +#define IFLA_COST IFLA_COST + IFLA_PRIORITY, +#define IFLA_PRIORITY IFLA_PRIORITY + IFLA_MASTER, +#define IFLA_MASTER IFLA_MASTER + IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */ +#define IFLA_WIRELESS IFLA_WIRELESS + IFLA_PROTINFO, /* Protocol specific information for a link */ +#define IFLA_PROTINFO IFLA_PROTINFO + IFLA_TXQLEN, +#define IFLA_TXQLEN IFLA_TXQLEN + IFLA_MAP, +#define IFLA_MAP IFLA_MAP + IFLA_WEIGHT, +#define IFLA_WEIGHT IFLA_WEIGHT + IFLA_OPERSTATE, + IFLA_LINKMODE, + IFLA_LINKINFO, +#define IFLA_LINKINFO IFLA_LINKINFO + IFLA_NET_NS_PID, + IFLA_IFALIAS, + IFLA_NUM_VF, /* Number of VFs if device is SR-IOV PF */ + IFLA_VFINFO_LIST, + IFLA_STATS64, + IFLA_VF_PORTS, + IFLA_PORT_SELF, + IFLA_AF_SPEC, + IFLA_GROUP, /* Group the device belongs to */ + IFLA_NET_NS_FD, + IFLA_EXT_MASK, /* Extended info mask, VFs, etc */ + IFLA_PROMISCUITY, /* Promiscuity count: > 0 means acts PROMISC */ +#define IFLA_PROMISCUITY IFLA_PROMISCUITY + IFLA_NUM_TX_QUEUES, + IFLA_NUM_RX_QUEUES, + IFLA_CARRIER, + __IFLA_MAX +}; + + +#define IFLA_MAX (__IFLA_MAX - 1) + +enum { + IFLA_INET_UNSPEC, + IFLA_INET_CONF, + __IFLA_INET_MAX, +}; + +#define IFLA_INET_MAX (__IFLA_INET_MAX - 1) + +/* ifi_flags. + + IFF_* flags. + + The only change is: + IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are + more not changeable by user. They describe link media + characteristics and set by device driver. + + Comments: + - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid + - If neither of these three flags are set; + the interface is NBMA. + + - IFF_MULTICAST does not mean anything special: + multicasts can be used on all not-NBMA links. + IFF_MULTICAST means that this media uses special encapsulation + for multicast frames. Apparently, all IFF_POINTOPOINT and + IFF_BROADCAST devices are able to use multicasts too. + */ + +/* IFLA_LINK. + For usual devices it is equal ifi_index. + If it is a "virtual interface" (f.e. tunnel), ifi_link + can point to real physical interface (f.e. for bandwidth calculations), + or maybe 0, what means, that real media is unknown (usual + for IPIP tunnels, when route to endpoint is allowed to change) + */ + +/* Subtype attributes for IFLA_PROTINFO */ +enum { + IFLA_INET6_UNSPEC, + IFLA_INET6_FLAGS, /* link flags */ + IFLA_INET6_CONF, /* sysctl parameters */ + IFLA_INET6_STATS, /* statistics */ + IFLA_INET6_MCAST, /* MC things. What of them? */ + IFLA_INET6_CACHEINFO, /* time values and max reasm size */ + IFLA_INET6_ICMP6STATS, /* statistics (icmpv6) */ + __IFLA_INET6_MAX +}; + +#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) + +enum { + BRIDGE_MODE_UNSPEC, + BRIDGE_MODE_HAIRPIN, +}; + +enum { + IFLA_BRPORT_UNSPEC, + IFLA_BRPORT_STATE, /* Spanning tree state */ + IFLA_BRPORT_PRIORITY, /* " priority */ + IFLA_BRPORT_COST, /* " cost */ + IFLA_BRPORT_MODE, /* mode (hairpin) */ + IFLA_BRPORT_GUARD, /* bpdu guard */ + IFLA_BRPORT_PROTECT, /* root port protection */ + IFLA_BRPORT_FAST_LEAVE, /* multicast fast leave */ + __IFLA_BRPORT_MAX +}; +#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) + +struct ifla_cacheinfo { + __u32 max_reasm_len; + __u32 tstamp; /* ipv6InterfaceTable updated timestamp */ + __u32 reachable_time; + __u32 retrans_time; +}; + +enum { + IFLA_INFO_UNSPEC, + IFLA_INFO_KIND, + IFLA_INFO_DATA, + IFLA_INFO_XSTATS, + __IFLA_INFO_MAX, +}; + +#define IFLA_INFO_MAX (__IFLA_INFO_MAX - 1) + +/* VLAN section */ + +enum { + IFLA_VLAN_UNSPEC, + IFLA_VLAN_ID, + IFLA_VLAN_FLAGS, + IFLA_VLAN_EGRESS_QOS, + IFLA_VLAN_INGRESS_QOS, + __IFLA_VLAN_MAX, +}; + +#define IFLA_VLAN_MAX (__IFLA_VLAN_MAX - 1) + +struct ifla_vlan_flags { + __u32 flags; + __u32 mask; +}; + +enum { + IFLA_VLAN_QOS_UNSPEC, + IFLA_VLAN_QOS_MAPPING, + __IFLA_VLAN_QOS_MAX +}; + +#define IFLA_VLAN_QOS_MAX (__IFLA_VLAN_QOS_MAX - 1) + +struct ifla_vlan_qos_mapping { + __u32 from; + __u32 to; +}; + +/* MACVLAN section */ +enum { + IFLA_MACVLAN_UNSPEC, + IFLA_MACVLAN_MODE, + IFLA_MACVLAN_FLAGS, + __IFLA_MACVLAN_MAX, +}; + +#define IFLA_MACVLAN_MAX (__IFLA_MACVLAN_MAX - 1) + +enum macvlan_mode { + MACVLAN_MODE_PRIVATE = 1, /* don't talk to other macvlans */ + MACVLAN_MODE_VEPA = 2, /* talk to other ports through ext bridge */ + MACVLAN_MODE_BRIDGE = 4, /* talk to bridge ports directly */ + MACVLAN_MODE_PASSTHRU = 8,/* take over the underlying device */ +}; + +#define MACVLAN_FLAG_NOPROMISC 1 + +/* VXLAN section */ +enum { + IFLA_VXLAN_UNSPEC, + IFLA_VXLAN_ID, + IFLA_VXLAN_GROUP, + IFLA_VXLAN_LINK, + IFLA_VXLAN_LOCAL, + IFLA_VXLAN_TTL, + IFLA_VXLAN_TOS, + IFLA_VXLAN_LEARNING, + IFLA_VXLAN_AGEING, + IFLA_VXLAN_LIMIT, + IFLA_VXLAN_PORT_RANGE, + IFLA_VXLAN_PROXY, + IFLA_VXLAN_RSC, + IFLA_VXLAN_L2MISS, + IFLA_VXLAN_L3MISS, + __IFLA_VXLAN_MAX +}; +#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) + +struct ifla_vxlan_port_range { + __be16 low; + __be16 high; +}; + +/* SR-IOV virtual function management section */ + +enum { + IFLA_VF_INFO_UNSPEC, + IFLA_VF_INFO, + __IFLA_VF_INFO_MAX, +}; + +#define IFLA_VF_INFO_MAX (__IFLA_VF_INFO_MAX - 1) + +enum { + IFLA_VF_UNSPEC, + IFLA_VF_MAC, /* Hardware queue specific attributes */ + IFLA_VF_VLAN, + IFLA_VF_TX_RATE, /* TX Bandwidth Allocation */ + IFLA_VF_SPOOFCHK, /* Spoof Checking on/off switch */ + __IFLA_VF_MAX, +}; + +#define IFLA_VF_MAX (__IFLA_VF_MAX - 1) + +struct ifla_vf_mac { + __u32 vf; + __u8 mac[32]; /* MAX_ADDR_LEN */ +}; + +struct ifla_vf_vlan { + __u32 vf; + __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */ + __u32 qos; +}; + +struct ifla_vf_tx_rate { + __u32 vf; + __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */ +}; + +struct ifla_vf_spoofchk { + __u32 vf; + __u32 setting; +}; + +/* VF ports management section + * + * Nested layout of set/get msg is: + * + * [IFLA_NUM_VF] + * [IFLA_VF_PORTS] + * [IFLA_VF_PORT] + * [IFLA_PORT_*], ... + * [IFLA_VF_PORT] + * [IFLA_PORT_*], ... + * ... + * [IFLA_PORT_SELF] + * [IFLA_PORT_*], ... + */ + +enum { + IFLA_VF_PORT_UNSPEC, + IFLA_VF_PORT, /* nest */ + __IFLA_VF_PORT_MAX, +}; + +#define IFLA_VF_PORT_MAX (__IFLA_VF_PORT_MAX - 1) + +enum { + IFLA_PORT_UNSPEC, + IFLA_PORT_VF, /* __u32 */ + IFLA_PORT_PROFILE, /* string */ + IFLA_PORT_VSI_TYPE, /* 802.1Qbg (pre-)standard VDP */ + IFLA_PORT_INSTANCE_UUID, /* binary UUID */ + IFLA_PORT_HOST_UUID, /* binary UUID */ + IFLA_PORT_REQUEST, /* __u8 */ + IFLA_PORT_RESPONSE, /* __u16, output only */ + __IFLA_PORT_MAX, +}; + +#define IFLA_PORT_MAX (__IFLA_PORT_MAX - 1) + +#define PORT_PROFILE_MAX 40 +#define PORT_UUID_MAX 16 +#define PORT_SELF_VF -1 + +enum { + PORT_REQUEST_PREASSOCIATE = 0, + PORT_REQUEST_PREASSOCIATE_RR, + PORT_REQUEST_ASSOCIATE, + PORT_REQUEST_DISASSOCIATE, +}; + +enum { + PORT_VDP_RESPONSE_SUCCESS = 0, + PORT_VDP_RESPONSE_INVALID_FORMAT, + PORT_VDP_RESPONSE_INSUFFICIENT_RESOURCES, + PORT_VDP_RESPONSE_UNUSED_VTID, + PORT_VDP_RESPONSE_VTID_VIOLATION, + PORT_VDP_RESPONSE_VTID_VERSION_VIOALTION, + PORT_VDP_RESPONSE_OUT_OF_SYNC, + /* 0x08-0xFF reserved for future VDP use */ + PORT_PROFILE_RESPONSE_SUCCESS = 0x100, + PORT_PROFILE_RESPONSE_INPROGRESS, + PORT_PROFILE_RESPONSE_INVALID, + PORT_PROFILE_RESPONSE_BADSTATE, + PORT_PROFILE_RESPONSE_INSUFFICIENT_RESOURCES, + PORT_PROFILE_RESPONSE_ERROR, +}; + +struct ifla_port_vsi { + __u8 vsi_mgr_id; + __u8 vsi_type_id[3]; + __u8 vsi_type_version; + __u8 pad[3]; +}; + + +/* IPoIB section */ + +enum { + IFLA_IPOIB_UNSPEC, + IFLA_IPOIB_PKEY, + IFLA_IPOIB_MODE, + IFLA_IPOIB_UMCAST, + __IFLA_IPOIB_MAX +}; + +enum { + IPOIB_MODE_DATAGRAM = 0, /* using unreliable datagram QPs */ + IPOIB_MODE_CONNECTED = 1, /* using connected QPs */ +}; + +#define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1) + +#endif /* _UAPI_LINUX_IF_LINK_H */ diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h new file mode 100644 index 0000000..67affd1 --- /dev/null +++ b/include/linux/if_vlan.h @@ -0,0 +1,62 @@ +/* + * VLAN An implementation of 802.1Q VLAN tagging. + * + * Authors: Ben Greear + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#ifndef _LINUX_IF_VLAN_H_ +#define _LINUX_IF_VLAN_H_ + +/* VLAN IOCTLs are found in sockios.h */ + +/* Passed in vlan_ioctl_args structure to determine behaviour. */ +enum vlan_ioctl_cmds { + ADD_VLAN_CMD, + DEL_VLAN_CMD, + SET_VLAN_INGRESS_PRIORITY_CMD, + SET_VLAN_EGRESS_PRIORITY_CMD, + GET_VLAN_INGRESS_PRIORITY_CMD, + GET_VLAN_EGRESS_PRIORITY_CMD, + SET_VLAN_NAME_TYPE_CMD, + SET_VLAN_FLAG_CMD, + GET_VLAN_REALDEV_NAME_CMD, /* If this works, you know it's a VLAN device, btw */ + GET_VLAN_VID_CMD /* Get the VID of this VLAN (specified by name) */ +}; + +enum vlan_flags { + VLAN_FLAG_REORDER_HDR = 0x1, + VLAN_FLAG_GVRP = 0x2, + VLAN_FLAG_LOOSE_BINDING = 0x4, +}; + +enum vlan_name_types { + VLAN_NAME_TYPE_PLUS_VID, /* Name will look like: vlan0005 */ + VLAN_NAME_TYPE_RAW_PLUS_VID, /* name will look like: eth1.0005 */ + VLAN_NAME_TYPE_PLUS_VID_NO_PAD, /* Name will look like: vlan5 */ + VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD, /* Name will look like: eth0.5 */ + VLAN_NAME_TYPE_HIGHEST +}; + +struct vlan_ioctl_args { + int cmd; /* Should be one of the vlan_ioctl_cmds enum above. */ + char device1[24]; + + union { + char device2[24]; + int VID; + unsigned int skb_priority; + unsigned int name_type; + unsigned int bind_type; + unsigned int flag; /* Matches vlan_dev_info flags */ + } u; + + short vlan_qos; +}; + +#endif /* !(_LINUX_IF_VLAN_H_) */ diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h new file mode 100644 index 0000000..fd4d2df --- /dev/null +++ b/include/linux/inetdevice.h @@ -0,0 +1,36 @@ +#ifndef _LINUX_INETDEVICE_H +#define _LINUX_INETDEVICE_H + +enum +{ + IPV4_DEVCONF_FORWARDING=1, + IPV4_DEVCONF_MC_FORWARDING, + IPV4_DEVCONF_PROXY_ARP, + IPV4_DEVCONF_ACCEPT_REDIRECTS, + IPV4_DEVCONF_SECURE_REDIRECTS, + IPV4_DEVCONF_SEND_REDIRECTS, + IPV4_DEVCONF_SHARED_MEDIA, + IPV4_DEVCONF_RP_FILTER, + IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE, + IPV4_DEVCONF_BOOTP_RELAY, + IPV4_DEVCONF_LOG_MARTIANS, + IPV4_DEVCONF_TAG, + IPV4_DEVCONF_ARPFILTER, + IPV4_DEVCONF_MEDIUM_ID, + IPV4_DEVCONF_NOXFRM, + IPV4_DEVCONF_NOPOLICY, + IPV4_DEVCONF_FORCE_IGMP_VERSION, + IPV4_DEVCONF_ARP_ANNOUNCE, + IPV4_DEVCONF_ARP_IGNORE, + IPV4_DEVCONF_PROMOTE_SECONDARIES, + IPV4_DEVCONF_ARP_ACCEPT, + IPV4_DEVCONF_ARP_NOTIFY, + IPV4_DEVCONF_ACCEPT_LOCAL, + IPV4_DEVCONF_SRC_VMARK, + IPV4_DEVCONF_PROXY_ARP_PVLAN, + __IPV4_DEVCONF_MAX +}; + +#define IPV4_DEVCONF_MAX (__IPV4_DEVCONF_MAX - 1) + +#endif /* _LINUX_INETDEVICE_H */ diff --git a/include/linux/ip_mp_alg.h b/include/linux/ip_mp_alg.h new file mode 100644 index 0000000..e234e20 --- /dev/null +++ b/include/linux/ip_mp_alg.h @@ -0,0 +1,22 @@ +/* ip_mp_alg.h: IPV4 multipath algorithm support, user-visible values. + * + * Copyright (C) 2004, 2005 Einar Lueck + * Copyright (C) 2005 David S. Miller + */ + +#ifndef _LINUX_IP_MP_ALG_H +#define _LINUX_IP_MP_ALG_H + +enum ip_mp_alg { + IP_MP_ALG_NONE, + IP_MP_ALG_RR, + IP_MP_ALG_DRR, + IP_MP_ALG_RANDOM, + IP_MP_ALG_WRANDOM, + __IP_MP_ALG_MAX +}; + +#define IP_MP_ALG_MAX (__IP_MP_ALG_MAX - 1) + +#endif /* _LINUX_IP_MP_ALG_H */ + diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h new file mode 100644 index 0000000..f16349d --- /dev/null +++ b/include/linux/ipv6.h @@ -0,0 +1,146 @@ +#ifndef _IPV6_H +#define _IPV6_H + +#include + +/* The latest drafts declared increase in minimal mtu up to 1280. */ + +#define IPV6_MIN_MTU 1280 + +/* + * Advanced API + * source interface/address selection, source routing, etc... + * *under construction* + */ + + +#define IPV6_SRCRT_STRICT 0x01 /* Deprecated; will be removed */ +#define IPV6_SRCRT_TYPE_0 0 /* Deprecated; will be removed */ +#define IPV6_SRCRT_TYPE_2 2 /* IPv6 type 2 Routing Header */ + +/* + * routing header + */ +struct ipv6_rt_hdr { + __u8 nexthdr; + __u8 hdrlen; + __u8 type; + __u8 segments_left; + + /* + * type specific data + * variable length field + */ +}; + + +struct ipv6_opt_hdr { + __u8 nexthdr; + __u8 hdrlen; + /* + * TLV encoded option data follows. + */ +} __attribute__((packed)); /* required for some archs */ + +#define ipv6_destopt_hdr ipv6_opt_hdr +#define ipv6_hopopt_hdr ipv6_opt_hdr + + +/* + * routing header type 0 (used in cmsghdr struct) + */ + +struct rt0_hdr { + struct ipv6_rt_hdr rt_hdr; + __u32 reserved; + struct in6_addr addr[0]; + +#define rt0_type rt_hdr.type +}; + +/* + * routing header type 2 + */ + +struct rt2_hdr { + struct ipv6_rt_hdr rt_hdr; + __u32 reserved; + struct in6_addr addr; + +#define rt2_type rt_hdr.type +}; + +/* + * home address option in destination options header + */ + +struct ipv6_destopt_hao { + __u8 type; + __u8 length; + struct in6_addr addr; +} __attribute__((packed)); + +/* + * IPv6 fixed header + * + * BEWARE, it is incorrect. The first 4 bits of flow_lbl + * are glued to priority now, forming "class". + */ + +struct ipv6hdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 priority:4, + version:4; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u8 version:4, + priority:4; +#else +#error "Please fix " +#endif + __u8 flow_lbl[3]; + + __be16 payload_len; + __u8 nexthdr; + __u8 hop_limit; + + struct in6_addr saddr; + struct in6_addr daddr; +}; + + +/* index values for the variables in ipv6_devconf */ +enum { + DEVCONF_FORWARDING = 0, + DEVCONF_HOPLIMIT, + DEVCONF_MTU6, + DEVCONF_ACCEPT_RA, + DEVCONF_ACCEPT_REDIRECTS, + DEVCONF_AUTOCONF, + DEVCONF_DAD_TRANSMITS, + DEVCONF_RTR_SOLICITS, + DEVCONF_RTR_SOLICIT_INTERVAL, + DEVCONF_RTR_SOLICIT_DELAY, + DEVCONF_USE_TEMPADDR, + DEVCONF_TEMP_VALID_LFT, + DEVCONF_TEMP_PREFERED_LFT, + DEVCONF_REGEN_MAX_RETRY, + DEVCONF_MAX_DESYNC_FACTOR, + DEVCONF_MAX_ADDRESSES, + DEVCONF_FORCE_MLD_VERSION, + DEVCONF_ACCEPT_RA_DEFRTR, + DEVCONF_ACCEPT_RA_PINFO, + DEVCONF_ACCEPT_RA_RTR_PREF, + DEVCONF_RTR_PROBE_INTERVAL, + DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN, + DEVCONF_PROXY_NDP, + DEVCONF_OPTIMISTIC_DAD, + DEVCONF_ACCEPT_SOURCE_ROUTE, + DEVCONF_MC_FORWARDING, + DEVCONF_DISABLE_IPV6, + DEVCONF_ACCEPT_DAD, + DEVCONF_FORCE_TLLAO, + DEVCONF_MAX +}; + + +#endif /* _IPV6_H */ diff --git a/include/linux/neighbour.h b/include/linux/neighbour.h new file mode 100644 index 0000000..a7003b7 --- /dev/null +++ b/include/linux/neighbour.h @@ -0,0 +1,155 @@ +#ifndef __LINUX_NEIGHBOUR_H +#define __LINUX_NEIGHBOUR_H + +#include +#include + +struct ndmsg { + __u8 ndm_family; + __u8 ndm_pad1; + __u16 ndm_pad2; + __s32 ndm_ifindex; + __u16 ndm_state; + __u8 ndm_flags; + __u8 ndm_type; +}; + +enum { + NDA_UNSPEC, + NDA_DST, + NDA_LLADDR, + NDA_CACHEINFO, + NDA_PROBES, + __NDA_MAX +}; + +#define NDA_MAX (__NDA_MAX - 1) + +/* + * Neighbor Cache Entry Flags + */ + +#define NTF_USE 0x01 +#define NTF_PROXY 0x08 /* == ATF_PUBL */ +#define NTF_ROUTER 0x80 + +/* + * Neighbor Cache Entry States. + */ + +#define NUD_INCOMPLETE 0x01 +#define NUD_REACHABLE 0x02 +#define NUD_STALE 0x04 +#define NUD_DELAY 0x08 +#define NUD_PROBE 0x10 +#define NUD_FAILED 0x20 + +/* Dummy states */ +#define NUD_NOARP 0x40 +#define NUD_PERMANENT 0x80 +#define NUD_NONE 0x00 + +/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change + and make no address resolution or NUD. + NUD_PERMANENT is also cannot be deleted by garbage collectors. + */ + +struct nda_cacheinfo { + __u32 ndm_confirmed; + __u32 ndm_used; + __u32 ndm_updated; + __u32 ndm_refcnt; +}; + +/***************************************************************** + * Neighbour tables specific messages. + * + * To retrieve the neighbour tables send RTM_GETNEIGHTBL with the + * NLM_F_DUMP flag set. Every neighbour table configuration is + * spread over multiple messages to avoid running into message + * size limits on systems with many interfaces. The first message + * in the sequence transports all not device specific data such as + * statistics, configuration, and the default parameter set. + * This message is followed by 0..n messages carrying device + * specific parameter sets. + * Although the ordering should be sufficient, NDTA_NAME can be + * used to identify sequences. The initial message can be identified + * by checking for NDTA_CONFIG. The device specific messages do + * not contain this TLV but have NDTPA_IFINDEX set to the + * corresponding interface index. + * + * To change neighbour table attributes, send RTM_SETNEIGHTBL + * with NDTA_NAME set. Changeable attribute include NDTA_THRESH[1-3], + * NDTA_GC_INTERVAL, and all TLVs in NDTA_PARMS unless marked + * otherwise. Device specific parameter sets can be changed by + * setting NDTPA_IFINDEX to the interface index of the corresponding + * device. + ****/ + +struct ndt_stats { + __u64 ndts_allocs; + __u64 ndts_destroys; + __u64 ndts_hash_grows; + __u64 ndts_res_failed; + __u64 ndts_lookups; + __u64 ndts_hits; + __u64 ndts_rcv_probes_mcast; + __u64 ndts_rcv_probes_ucast; + __u64 ndts_periodic_gc_runs; + __u64 ndts_forced_gc_runs; +}; + +enum { + NDTPA_UNSPEC, + NDTPA_IFINDEX, /* u32, unchangeable */ + NDTPA_REFCNT, /* u32, read-only */ + NDTPA_REACHABLE_TIME, /* u64, read-only, msecs */ + NDTPA_BASE_REACHABLE_TIME, /* u64, msecs */ + NDTPA_RETRANS_TIME, /* u64, msecs */ + NDTPA_GC_STALETIME, /* u64, msecs */ + NDTPA_DELAY_PROBE_TIME, /* u64, msecs */ + NDTPA_QUEUE_LEN, /* u32 */ + NDTPA_APP_PROBES, /* u32 */ + NDTPA_UCAST_PROBES, /* u32 */ + NDTPA_MCAST_PROBES, /* u32 */ + NDTPA_ANYCAST_DELAY, /* u64, msecs */ + NDTPA_PROXY_DELAY, /* u64, msecs */ + NDTPA_PROXY_QLEN, /* u32 */ + NDTPA_LOCKTIME, /* u64, msecs */ + __NDTPA_MAX +}; +#define NDTPA_MAX (__NDTPA_MAX - 1) + +struct ndtmsg { + __u8 ndtm_family; + __u8 ndtm_pad1; + __u16 ndtm_pad2; +}; + +struct ndt_config { + __u16 ndtc_key_len; + __u16 ndtc_entry_size; + __u32 ndtc_entries; + __u32 ndtc_last_flush; /* delta to now in msecs */ + __u32 ndtc_last_rand; /* delta to now in msecs */ + __u32 ndtc_hash_rnd; + __u32 ndtc_hash_mask; + __u32 ndtc_hash_chain_gc; + __u32 ndtc_proxy_qlen; +}; + +enum { + NDTA_UNSPEC, + NDTA_NAME, /* char *, unchangeable */ + NDTA_THRESH1, /* u32 */ + NDTA_THRESH2, /* u32 */ + NDTA_THRESH3, /* u32 */ + NDTA_CONFIG, /* struct ndt_config, read-only */ + NDTA_PARMS, /* nested TLV NDTPA_* */ + NDTA_STATS, /* struct ndt_stats, read-only */ + NDTA_GC_INTERVAL, /* u64, msecs */ + __NDTA_MAX +}; +#define NDTA_MAX (__NDTA_MAX - 1) + +#endif diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h new file mode 100644 index 0000000..7999885 --- /dev/null +++ b/include/linux/netfilter.h @@ -0,0 +1,57 @@ +#ifndef __LINUX_NETFILTER_H +#define __LINUX_NETFILTER_H + +#include + +/* Responses from hook functions. */ +#define NF_DROP 0 +#define NF_ACCEPT 1 +#define NF_STOLEN 2 +#define NF_QUEUE 3 +#define NF_REPEAT 4 +#define NF_STOP 5 +#define NF_MAX_VERDICT NF_STOP + +/* we overload the higher bits for encoding auxiliary data such as the queue + * number. Not nice, but better than additional function arguments. */ +#define NF_VERDICT_MASK 0x0000ffff +#define NF_VERDICT_BITS 16 + +#define NF_VERDICT_QMASK 0xffff0000 +#define NF_VERDICT_QBITS 16 + +#define NF_QUEUE_NR(x) ((((x) << NF_VERDICT_BITS) & NF_VERDICT_QMASK) | NF_QUEUE) + +/* Generic cache responses from hook functions. + <= 0x2000 is used for protocol-flags. */ +#define NFC_UNKNOWN 0x4000 +#define NFC_ALTERED 0x8000 + +enum nf_inet_hooks { + NF_INET_PRE_ROUTING, + NF_INET_LOCAL_IN, + NF_INET_FORWARD, + NF_INET_LOCAL_OUT, + NF_INET_POST_ROUTING, + NF_INET_NUMHOOKS +}; + +enum { + NFPROTO_UNSPEC = 0, + NFPROTO_IPV4 = 2, + NFPROTO_ARP = 3, + NFPROTO_BRIDGE = 7, + NFPROTO_IPV6 = 10, + NFPROTO_DECNET = 12, + NFPROTO_NUMPROTO, +}; + +union nf_inet_addr { + __u32 all[4]; + __be32 ip; + __be32 ip6[4]; + struct in_addr in; + struct in6_addr in6; +}; + +#endif /*__LINUX_NETFILTER_H*/ diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h new file mode 100644 index 0000000..1644cdd --- /dev/null +++ b/include/linux/netfilter/nf_conntrack_common.h @@ -0,0 +1,117 @@ +#ifndef _UAPI_NF_CONNTRACK_COMMON_H +#define _UAPI_NF_CONNTRACK_COMMON_H +/* Connection state tracking for netfilter. This is separated from, + but required by, the NAT layer; it can also be used by an iptables + extension. */ +enum ip_conntrack_info { + /* Part of an established connection (either direction). */ + IP_CT_ESTABLISHED, + + /* Like NEW, but related to an existing connection, or ICMP error + (in either direction). */ + IP_CT_RELATED, + + /* Started a new connection to track (only + IP_CT_DIR_ORIGINAL); may be a retransmission. */ + IP_CT_NEW, + + /* >= this indicates reply direction */ + IP_CT_IS_REPLY, + + IP_CT_ESTABLISHED_REPLY = IP_CT_ESTABLISHED + IP_CT_IS_REPLY, + IP_CT_RELATED_REPLY = IP_CT_RELATED + IP_CT_IS_REPLY, + IP_CT_NEW_REPLY = IP_CT_NEW + IP_CT_IS_REPLY, + /* Number of distinct IP_CT types (no NEW in reply dirn). */ + IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1 +}; + +/* Bitset representing status of connection. */ +enum ip_conntrack_status { + /* It's an expected connection: bit 0 set. This bit never changed */ + IPS_EXPECTED_BIT = 0, + IPS_EXPECTED = (1 << IPS_EXPECTED_BIT), + + /* We've seen packets both ways: bit 1 set. Can be set, not unset. */ + IPS_SEEN_REPLY_BIT = 1, + IPS_SEEN_REPLY = (1 << IPS_SEEN_REPLY_BIT), + + /* Conntrack should never be early-expired. */ + IPS_ASSURED_BIT = 2, + IPS_ASSURED = (1 << IPS_ASSURED_BIT), + + /* Connection is confirmed: originating packet has left box */ + IPS_CONFIRMED_BIT = 3, + IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT), + + /* Connection needs src nat in orig dir. This bit never changed. */ + IPS_SRC_NAT_BIT = 4, + IPS_SRC_NAT = (1 << IPS_SRC_NAT_BIT), + + /* Connection needs dst nat in orig dir. This bit never changed. */ + IPS_DST_NAT_BIT = 5, + IPS_DST_NAT = (1 << IPS_DST_NAT_BIT), + + /* Both together. */ + IPS_NAT_MASK = (IPS_DST_NAT | IPS_SRC_NAT), + + /* Connection needs TCP sequence adjusted. */ + IPS_SEQ_ADJUST_BIT = 6, + IPS_SEQ_ADJUST = (1 << IPS_SEQ_ADJUST_BIT), + + /* NAT initialization bits. */ + IPS_SRC_NAT_DONE_BIT = 7, + IPS_SRC_NAT_DONE = (1 << IPS_SRC_NAT_DONE_BIT), + + IPS_DST_NAT_DONE_BIT = 8, + IPS_DST_NAT_DONE = (1 << IPS_DST_NAT_DONE_BIT), + + /* Both together */ + IPS_NAT_DONE_MASK = (IPS_DST_NAT_DONE | IPS_SRC_NAT_DONE), + + /* Connection is dying (removed from lists), can not be unset. */ + IPS_DYING_BIT = 9, + IPS_DYING = (1 << IPS_DYING_BIT), + + /* Connection has fixed timeout. */ + IPS_FIXED_TIMEOUT_BIT = 10, + IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT), + + /* Conntrack is a template */ + IPS_TEMPLATE_BIT = 11, + IPS_TEMPLATE = (1 << IPS_TEMPLATE_BIT), + + /* Conntrack is a fake untracked entry */ + IPS_UNTRACKED_BIT = 12, + IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT), + + /* Conntrack got a helper explicitly attached via CT target. */ + IPS_HELPER_BIT = 13, + IPS_HELPER = (1 << IPS_HELPER_BIT), +}; + +/* Connection tracking event types */ +enum ip_conntrack_events { + IPCT_NEW, /* new conntrack */ + IPCT_RELATED, /* related conntrack */ + IPCT_DESTROY, /* destroyed conntrack */ + IPCT_REPLY, /* connection has seen two-way traffic */ + IPCT_ASSURED, /* connection status has changed to assured */ + IPCT_PROTOINFO, /* protocol information has changed */ + IPCT_HELPER, /* new helper has been set */ + IPCT_MARK, /* new mark has been set */ + IPCT_NATSEQADJ, /* NAT is doing sequence adjustment */ + IPCT_SECMARK, /* new security mark has been set */ +}; + +enum ip_conntrack_expect_events { + IPEXP_NEW, /* new expectation */ + IPEXP_DESTROY, /* destroyed expectation */ +}; + +/* expectation flags */ +#define NF_CT_EXPECT_PERMANENT 0x1 +#define NF_CT_EXPECT_INACTIVE 0x2 +#define NF_CT_EXPECT_USERSPACE 0x4 + + +#endif /* _UAPI_NF_CONNTRACK_COMMON_H */ diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h new file mode 100644 index 0000000..4a4efaf --- /dev/null +++ b/include/linux/netfilter/nfnetlink.h @@ -0,0 +1,56 @@ +#ifndef _UAPI_NFNETLINK_H +#define _UAPI_NFNETLINK_H +#include +#include + +enum nfnetlink_groups { + NFNLGRP_NONE, +#define NFNLGRP_NONE NFNLGRP_NONE + NFNLGRP_CONNTRACK_NEW, +#define NFNLGRP_CONNTRACK_NEW NFNLGRP_CONNTRACK_NEW + NFNLGRP_CONNTRACK_UPDATE, +#define NFNLGRP_CONNTRACK_UPDATE NFNLGRP_CONNTRACK_UPDATE + NFNLGRP_CONNTRACK_DESTROY, +#define NFNLGRP_CONNTRACK_DESTROY NFNLGRP_CONNTRACK_DESTROY + NFNLGRP_CONNTRACK_EXP_NEW, +#define NFNLGRP_CONNTRACK_EXP_NEW NFNLGRP_CONNTRACK_EXP_NEW + NFNLGRP_CONNTRACK_EXP_UPDATE, +#define NFNLGRP_CONNTRACK_EXP_UPDATE NFNLGRP_CONNTRACK_EXP_UPDATE + NFNLGRP_CONNTRACK_EXP_DESTROY, +#define NFNLGRP_CONNTRACK_EXP_DESTROY NFNLGRP_CONNTRACK_EXP_DESTROY + __NFNLGRP_MAX, +}; +#define NFNLGRP_MAX (__NFNLGRP_MAX - 1) + +/* General form of address family dependent message. + */ +struct nfgenmsg { + __u8 nfgen_family; /* AF_xxx */ + __u8 version; /* nfnetlink version */ + __be16 res_id; /* resource id */ +}; + +#define NFNETLINK_V0 0 + +/* netfilter netlink message types are split in two pieces: + * 8 bit subsystem, 8bit operation. + */ + +#define NFNL_SUBSYS_ID(x) ((x & 0xff00) >> 8) +#define NFNL_MSG_TYPE(x) (x & 0x00ff) + +/* No enum here, otherwise __stringify() trick of MODULE_ALIAS_NFNL_SUBSYS() + * won't work anymore */ +#define NFNL_SUBSYS_NONE 0 +#define NFNL_SUBSYS_CTNETLINK 1 +#define NFNL_SUBSYS_CTNETLINK_EXP 2 +#define NFNL_SUBSYS_QUEUE 3 +#define NFNL_SUBSYS_ULOG 4 +#define NFNL_SUBSYS_OSF 5 +#define NFNL_SUBSYS_IPSET 6 +#define NFNL_SUBSYS_ACCT 7 +#define NFNL_SUBSYS_CTNETLINK_TIMEOUT 8 +#define NFNL_SUBSYS_CTHELPER 9 +#define NFNL_SUBSYS_COUNT 10 + +#endif /* _UAPI_NFNETLINK_H */ diff --git a/include/linux/netfilter/nfnetlink_compat.h b/include/linux/netfilter/nfnetlink_compat.h new file mode 100644 index 0000000..ffb9503 --- /dev/null +++ b/include/linux/netfilter/nfnetlink_compat.h @@ -0,0 +1,63 @@ +#ifndef _NFNETLINK_COMPAT_H +#define _NFNETLINK_COMPAT_H + +#include + +#ifndef __KERNEL__ +/* Old nfnetlink macros for userspace */ + +/* nfnetlink groups: Up to 32 maximum */ +#define NF_NETLINK_CONNTRACK_NEW 0x00000001 +#define NF_NETLINK_CONNTRACK_UPDATE 0x00000002 +#define NF_NETLINK_CONNTRACK_DESTROY 0x00000004 +#define NF_NETLINK_CONNTRACK_EXP_NEW 0x00000008 +#define NF_NETLINK_CONNTRACK_EXP_UPDATE 0x00000010 +#define NF_NETLINK_CONNTRACK_EXP_DESTROY 0x00000020 + +/* Generic structure for encapsulation optional netfilter information. + * It is reminiscent of sockaddr, but with sa_family replaced + * with attribute type. + * ! This should someday be put somewhere generic as now rtnetlink and + * ! nfnetlink use the same attributes methods. - J. Schulist. + */ + +struct nfattr { + __u16 nfa_len; + __u16 nfa_type; /* we use 15 bits for the type, and the highest + * bit to indicate whether the payload is nested */ +}; + +/* FIXME: Apart from NFNL_NFA_NESTED shamelessly copy and pasted from + * rtnetlink.h, it's time to put this in a generic file */ + +#define NFNL_NFA_NEST 0x8000 +#define NFA_TYPE(attr) ((attr)->nfa_type & 0x7fff) + +#define NFA_ALIGNTO 4 +#define NFA_ALIGN(len) (((len) + NFA_ALIGNTO - 1) & ~(NFA_ALIGNTO - 1)) +#define NFA_OK(nfa,len) ((len) > 0 && (nfa)->nfa_len >= sizeof(struct nfattr) \ + && (nfa)->nfa_len <= (len)) +#define NFA_NEXT(nfa,attrlen) ((attrlen) -= NFA_ALIGN((nfa)->nfa_len), \ + (struct nfattr *)(((char *)(nfa)) + NFA_ALIGN((nfa)->nfa_len))) +#define NFA_LENGTH(len) (NFA_ALIGN(sizeof(struct nfattr)) + (len)) +#define NFA_SPACE(len) NFA_ALIGN(NFA_LENGTH(len)) +#define NFA_DATA(nfa) ((void *)(((char *)(nfa)) + NFA_LENGTH(0))) +#define NFA_PAYLOAD(nfa) ((int)((nfa)->nfa_len) - NFA_LENGTH(0)) +#define NFA_NEST(skb, type) \ +({ struct nfattr *__start = (struct nfattr *)skb_tail_pointer(skb); \ + NFA_PUT(skb, (NFNL_NFA_NEST | type), 0, NULL); \ + __start; }) +#define NFA_NEST_END(skb, start) \ +({ (start)->nfa_len = skb_tail_pointer(skb) - (unsigned char *)(start); \ + (skb)->len; }) +#define NFA_NEST_CANCEL(skb, start) \ +({ if (start) \ + skb_trim(skb, (unsigned char *) (start) - (skb)->data); \ + -1; }) + +#define NFM_NFA(n) ((struct nfattr *)(((char *)(n)) \ + + NLMSG_ALIGN(sizeof(struct nfgenmsg)))) +#define NFM_PAYLOAD(n) NLMSG_PAYLOAD(n, sizeof(struct nfgenmsg)) + +#endif /* ! __KERNEL__ */ +#endif /* _NFNETLINK_COMPAT_H */ diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h new file mode 100644 index 0000000..43bfe3e --- /dev/null +++ b/include/linux/netfilter/nfnetlink_conntrack.h @@ -0,0 +1,248 @@ +#ifndef _IPCONNTRACK_NETLINK_H +#define _IPCONNTRACK_NETLINK_H +#include + +enum cntl_msg_types { + IPCTNL_MSG_CT_NEW, + IPCTNL_MSG_CT_GET, + IPCTNL_MSG_CT_DELETE, + IPCTNL_MSG_CT_GET_CTRZERO, + IPCTNL_MSG_CT_GET_STATS_CPU, + IPCTNL_MSG_CT_GET_STATS, + + IPCTNL_MSG_MAX +}; + +enum ctnl_exp_msg_types { + IPCTNL_MSG_EXP_NEW, + IPCTNL_MSG_EXP_GET, + IPCTNL_MSG_EXP_DELETE, + IPCTNL_MSG_EXP_GET_STATS_CPU, + + IPCTNL_MSG_EXP_MAX +}; + + +enum ctattr_type { + CTA_UNSPEC, + CTA_TUPLE_ORIG, + CTA_TUPLE_REPLY, + CTA_STATUS, + CTA_PROTOINFO, + CTA_HELP, + CTA_NAT_SRC, +#define CTA_NAT CTA_NAT_SRC /* backwards compatibility */ + CTA_TIMEOUT, + CTA_MARK, + CTA_COUNTERS_ORIG, + CTA_COUNTERS_REPLY, + CTA_USE, + CTA_ID, + CTA_NAT_DST, + CTA_TUPLE_MASTER, + CTA_NAT_SEQ_ADJ_ORIG, + CTA_NAT_SEQ_ADJ_REPLY, + CTA_SECMARK, /* obsolete */ + CTA_ZONE, + CTA_SECCTX, + CTA_TIMESTAMP, + CTA_MARK_MASK, + __CTA_MAX +}; +#define CTA_MAX (__CTA_MAX - 1) + +enum ctattr_tuple { + CTA_TUPLE_UNSPEC, + CTA_TUPLE_IP, + CTA_TUPLE_PROTO, + __CTA_TUPLE_MAX +}; +#define CTA_TUPLE_MAX (__CTA_TUPLE_MAX - 1) + +enum ctattr_ip { + CTA_IP_UNSPEC, + CTA_IP_V4_SRC, + CTA_IP_V4_DST, + CTA_IP_V6_SRC, + CTA_IP_V6_DST, + __CTA_IP_MAX +}; +#define CTA_IP_MAX (__CTA_IP_MAX - 1) + +enum ctattr_l4proto { + CTA_PROTO_UNSPEC, + CTA_PROTO_NUM, + CTA_PROTO_SRC_PORT, + CTA_PROTO_DST_PORT, + CTA_PROTO_ICMP_ID, + CTA_PROTO_ICMP_TYPE, + CTA_PROTO_ICMP_CODE, + CTA_PROTO_ICMPV6_ID, + CTA_PROTO_ICMPV6_TYPE, + CTA_PROTO_ICMPV6_CODE, + __CTA_PROTO_MAX +}; +#define CTA_PROTO_MAX (__CTA_PROTO_MAX - 1) + +enum ctattr_protoinfo { + CTA_PROTOINFO_UNSPEC, + CTA_PROTOINFO_TCP, + CTA_PROTOINFO_DCCP, + CTA_PROTOINFO_SCTP, + __CTA_PROTOINFO_MAX +}; +#define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1) + +enum ctattr_protoinfo_tcp { + CTA_PROTOINFO_TCP_UNSPEC, + CTA_PROTOINFO_TCP_STATE, + CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, + CTA_PROTOINFO_TCP_WSCALE_REPLY, + CTA_PROTOINFO_TCP_FLAGS_ORIGINAL, + CTA_PROTOINFO_TCP_FLAGS_REPLY, + __CTA_PROTOINFO_TCP_MAX +}; +#define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1) + +enum ctattr_protoinfo_dccp { + CTA_PROTOINFO_DCCP_UNSPEC, + CTA_PROTOINFO_DCCP_STATE, + CTA_PROTOINFO_DCCP_ROLE, + CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ, + __CTA_PROTOINFO_DCCP_MAX, +}; +#define CTA_PROTOINFO_DCCP_MAX (__CTA_PROTOINFO_DCCP_MAX - 1) + +enum ctattr_protoinfo_sctp { + CTA_PROTOINFO_SCTP_UNSPEC, + CTA_PROTOINFO_SCTP_STATE, + CTA_PROTOINFO_SCTP_VTAG_ORIGINAL, + CTA_PROTOINFO_SCTP_VTAG_REPLY, + __CTA_PROTOINFO_SCTP_MAX +}; +#define CTA_PROTOINFO_SCTP_MAX (__CTA_PROTOINFO_SCTP_MAX - 1) + +enum ctattr_counters { + CTA_COUNTERS_UNSPEC, + CTA_COUNTERS_PACKETS, /* 64bit counters */ + CTA_COUNTERS_BYTES, /* 64bit counters */ + CTA_COUNTERS32_PACKETS, /* old 32bit counters, unused */ + CTA_COUNTERS32_BYTES, /* old 32bit counters, unused */ + __CTA_COUNTERS_MAX +}; +#define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1) + +enum ctattr_tstamp { + CTA_TIMESTAMP_UNSPEC, + CTA_TIMESTAMP_START, + CTA_TIMESTAMP_STOP, + __CTA_TIMESTAMP_MAX +}; +#define CTA_TIMESTAMP_MAX (__CTA_TIMESTAMP_MAX - 1) + +enum ctattr_nat { + CTA_NAT_UNSPEC, + CTA_NAT_V4_MINIP, +#define CTA_NAT_MINIP CTA_NAT_V4_MINIP + CTA_NAT_V4_MAXIP, +#define CTA_NAT_MAXIP CTA_NAT_V4_MAXIP + CTA_NAT_PROTO, + CTA_NAT_V6_MINIP, + CTA_NAT_V6_MAXIP, + __CTA_NAT_MAX +}; +#define CTA_NAT_MAX (__CTA_NAT_MAX - 1) + +enum ctattr_protonat { + CTA_PROTONAT_UNSPEC, + CTA_PROTONAT_PORT_MIN, + CTA_PROTONAT_PORT_MAX, + __CTA_PROTONAT_MAX +}; +#define CTA_PROTONAT_MAX (__CTA_PROTONAT_MAX - 1) + +enum ctattr_natseq { + CTA_NAT_SEQ_UNSPEC, + CTA_NAT_SEQ_CORRECTION_POS, + CTA_NAT_SEQ_OFFSET_BEFORE, + CTA_NAT_SEQ_OFFSET_AFTER, + __CTA_NAT_SEQ_MAX +}; +#define CTA_NAT_SEQ_MAX (__CTA_NAT_SEQ_MAX - 1) + +enum ctattr_expect { + CTA_EXPECT_UNSPEC, + CTA_EXPECT_MASTER, + CTA_EXPECT_TUPLE, + CTA_EXPECT_MASK, + CTA_EXPECT_TIMEOUT, + CTA_EXPECT_ID, + CTA_EXPECT_HELP_NAME, + CTA_EXPECT_ZONE, + CTA_EXPECT_FLAGS, + CTA_EXPECT_CLASS, + CTA_EXPECT_NAT, + CTA_EXPECT_FN, + __CTA_EXPECT_MAX +}; +#define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1) + +enum ctattr_expect_nat { + CTA_EXPECT_NAT_UNSPEC, + CTA_EXPECT_NAT_DIR, + CTA_EXPECT_NAT_TUPLE, + __CTA_EXPECT_NAT_MAX +}; +#define CTA_EXPECT_NAT_MAX (__CTA_EXPECT_NAT_MAX - 1) + +enum ctattr_help { + CTA_HELP_UNSPEC, + CTA_HELP_NAME, + CTA_HELP_INFO, + __CTA_HELP_MAX +}; +#define CTA_HELP_MAX (__CTA_HELP_MAX - 1) + +enum ctattr_secctx { + CTA_SECCTX_UNSPEC, + CTA_SECCTX_NAME, + __CTA_SECCTX_MAX +}; +#define CTA_SECCTX_MAX (__CTA_SECCTX_MAX - 1) + +enum ctattr_stats_cpu { + CTA_STATS_UNSPEC, + CTA_STATS_SEARCHED, + CTA_STATS_FOUND, + CTA_STATS_NEW, + CTA_STATS_INVALID, + CTA_STATS_IGNORE, + CTA_STATS_DELETE, + CTA_STATS_DELETE_LIST, + CTA_STATS_INSERT, + CTA_STATS_INSERT_FAILED, + CTA_STATS_DROP, + CTA_STATS_EARLY_DROP, + CTA_STATS_ERROR, + CTA_STATS_SEARCH_RESTART, + __CTA_STATS_MAX, +}; +#define CTA_STATS_MAX (__CTA_STATS_MAX - 1) + +enum ctattr_stats_global { + CTA_STATS_GLOBAL_UNSPEC, + CTA_STATS_GLOBAL_ENTRIES, + __CTA_STATS_GLOBAL_MAX, +}; +#define CTA_STATS_GLOBAL_MAX (__CTA_STATS_GLOBAL_MAX - 1) + +enum ctattr_expect_stats { + CTA_STATS_EXP_UNSPEC, + CTA_STATS_EXP_NEW, + CTA_STATS_EXP_CREATE, + CTA_STATS_EXP_DELETE, + __CTA_STATS_EXP_MAX, +}; +#define CTA_STATS_EXP_MAX (__CTA_STATS_EXP_MAX - 1) + +#endif /* _IPCONNTRACK_NETLINK_H */ diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h new file mode 100644 index 0000000..2cfbf13 --- /dev/null +++ b/include/linux/netfilter/nfnetlink_log.h @@ -0,0 +1,101 @@ +#ifndef _NFNETLINK_LOG_H +#define _NFNETLINK_LOG_H + +/* This file describes the netlink messages (i.e. 'protocol packets'), + * and not any kind of function definitions. It is shared between kernel and + * userspace. Don't put kernel specific stuff in here */ + +#ifndef __aligned_be64 +#define __aligned_be64 u_int64_t __attribute__((aligned(8))) +#endif + +#include +#include + +enum nfulnl_msg_types { + NFULNL_MSG_PACKET, /* packet from kernel to userspace */ + NFULNL_MSG_CONFIG, /* connect to a particular queue */ + + NFULNL_MSG_MAX +}; + +struct nfulnl_msg_packet_hdr { + __be16 hw_protocol; /* hw protocol (network order) */ + __u8 hook; /* netfilter hook */ + __u8 _pad; +}; + +struct nfulnl_msg_packet_hw { + __be16 hw_addrlen; + __u16 _pad; + __u8 hw_addr[8]; +}; + +struct nfulnl_msg_packet_timestamp { + __aligned_be64 sec; + __aligned_be64 usec; +}; + +enum nfulnl_attr_type { + NFULA_UNSPEC, + NFULA_PACKET_HDR, + NFULA_MARK, /* __u32 nfmark */ + NFULA_TIMESTAMP, /* nfulnl_msg_packet_timestamp */ + NFULA_IFINDEX_INDEV, /* __u32 ifindex */ + NFULA_IFINDEX_OUTDEV, /* __u32 ifindex */ + NFULA_IFINDEX_PHYSINDEV, /* __u32 ifindex */ + NFULA_IFINDEX_PHYSOUTDEV, /* __u32 ifindex */ + NFULA_HWADDR, /* nfulnl_msg_packet_hw */ + NFULA_PAYLOAD, /* opaque data payload */ + NFULA_PREFIX, /* string prefix */ + NFULA_UID, /* user id of socket */ + NFULA_SEQ, /* instance-local sequence number */ + NFULA_SEQ_GLOBAL, /* global sequence number */ + NFULA_GID, /* group id of socket */ + NFULA_HWTYPE, /* hardware type */ + NFULA_HWHEADER, /* hardware header */ + NFULA_HWLEN, /* hardware header length */ + + __NFULA_MAX +}; +#define NFULA_MAX (__NFULA_MAX - 1) + +enum nfulnl_msg_config_cmds { + NFULNL_CFG_CMD_NONE, + NFULNL_CFG_CMD_BIND, + NFULNL_CFG_CMD_UNBIND, + NFULNL_CFG_CMD_PF_BIND, + NFULNL_CFG_CMD_PF_UNBIND, +}; + +struct nfulnl_msg_config_cmd { + __u8 command; /* nfulnl_msg_config_cmds */ +} __attribute__ ((packed)); + +struct nfulnl_msg_config_mode { + __be32 copy_range; + __u8 copy_mode; + __u8 _pad; +} __attribute__ ((packed)); + +enum nfulnl_attr_config { + NFULA_CFG_UNSPEC, + NFULA_CFG_CMD, /* nfulnl_msg_config_cmd */ + NFULA_CFG_MODE, /* nfulnl_msg_config_mode */ + NFULA_CFG_NLBUFSIZ, /* __u32 buffer size */ + NFULA_CFG_TIMEOUT, /* __u32 in 1/100 s */ + NFULA_CFG_QTHRESH, /* __u32 */ + NFULA_CFG_FLAGS, /* __u16 */ + __NFULA_CFG_MAX +}; +#define NFULA_CFG_MAX (__NFULA_CFG_MAX -1) + +#define NFULNL_COPY_NONE 0x00 +#define NFULNL_COPY_META 0x01 +#define NFULNL_COPY_PACKET 0x02 +/* 0xff is reserved, don't use it for new copy modes. */ + +#define NFULNL_CFG_F_SEQ 0x0001 +#define NFULNL_CFG_F_SEQ_GLOBAL 0x0002 + +#endif /* _NFNETLINK_LOG_H */ diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h new file mode 100644 index 0000000..95af967 --- /dev/null +++ b/include/linux/netfilter/nfnetlink_queue.h @@ -0,0 +1,105 @@ +#ifndef _NFNETLINK_QUEUE_H +#define _NFNETLINK_QUEUE_H + +#include +#include + +#ifndef __aligned_be64 +#define __aligned_be64 u_int64_t __attribute__((aligned(8))) +#endif + +enum nfqnl_msg_types { + NFQNL_MSG_PACKET, /* packet from kernel to userspace */ + NFQNL_MSG_VERDICT, /* verdict from userspace to kernel */ + NFQNL_MSG_CONFIG, /* connect to a particular queue */ + NFQNL_MSG_VERDICT_BATCH, /* batchv from userspace to kernel */ + + NFQNL_MSG_MAX +}; + +struct nfqnl_msg_packet_hdr { + __be32 packet_id; /* unique ID of packet in queue */ + __be16 hw_protocol; /* hw protocol (network order) */ + __u8 hook; /* netfilter hook */ +} __attribute__ ((packed)); + +struct nfqnl_msg_packet_hw { + __be16 hw_addrlen; + __u16 _pad; + __u8 hw_addr[8]; +}; + +struct nfqnl_msg_packet_timestamp { + __aligned_be64 sec; + __aligned_be64 usec; +}; + +enum nfqnl_attr_type { + NFQA_UNSPEC, + NFQA_PACKET_HDR, + NFQA_VERDICT_HDR, /* nfqnl_msg_verdict_hrd */ + NFQA_MARK, /* __u32 nfmark */ + NFQA_TIMESTAMP, /* nfqnl_msg_packet_timestamp */ + NFQA_IFINDEX_INDEV, /* __u32 ifindex */ + NFQA_IFINDEX_OUTDEV, /* __u32 ifindex */ + NFQA_IFINDEX_PHYSINDEV, /* __u32 ifindex */ + NFQA_IFINDEX_PHYSOUTDEV, /* __u32 ifindex */ + NFQA_HWADDR, /* nfqnl_msg_packet_hw */ + NFQA_PAYLOAD, /* opaque data payload */ + NFQA_CT, /* nf_conntrack_netlink.h */ + NFQA_CT_INFO, /* enum ip_conntrack_info */ + NFQA_CAP_LEN, /* __u32 length of captured packet */ + + __NFQA_MAX +}; +#define NFQA_MAX (__NFQA_MAX - 1) + +struct nfqnl_msg_verdict_hdr { + __be32 verdict; + __be32 id; +}; + + +enum nfqnl_msg_config_cmds { + NFQNL_CFG_CMD_NONE, + NFQNL_CFG_CMD_BIND, + NFQNL_CFG_CMD_UNBIND, + NFQNL_CFG_CMD_PF_BIND, + NFQNL_CFG_CMD_PF_UNBIND, +}; + +struct nfqnl_msg_config_cmd { + __u8 command; /* nfqnl_msg_config_cmds */ + __u8 _pad; + __be16 pf; /* AF_xxx for PF_[UN]BIND */ +}; + +enum nfqnl_config_mode { + NFQNL_COPY_NONE, + NFQNL_COPY_META, + NFQNL_COPY_PACKET, +}; + +struct nfqnl_msg_config_params { + __be32 copy_range; + __u8 copy_mode; /* enum nfqnl_config_mode */ +} __attribute__ ((packed)); + + +enum nfqnl_attr_config { + NFQA_CFG_UNSPEC, + NFQA_CFG_CMD, /* nfqnl_msg_config_cmd */ + NFQA_CFG_PARAMS, /* nfqnl_msg_config_params */ + NFQA_CFG_QUEUE_MAXLEN, /* __u32 */ + NFQA_CFG_MASK, /* identify which flags to change */ + NFQA_CFG_FLAGS, /* value of these flags (__u32) */ + __NFQA_CFG_MAX +}; +#define NFQA_CFG_MAX (__NFQA_CFG_MAX-1) + +/* Flags for NFQA_CFG_FLAGS */ +#define NFQA_CFG_F_FAIL_OPEN (1 << 0) +#define NFQA_CFG_F_CONNTRACK (1 << 1) +#define NFQA_CFG_F_MAX (1 << 2) + +#endif /* _NFNETLINK_QUEUE_H */ diff --git a/include/linux/netlink.h b/include/linux/netlink.h new file mode 100644 index 0000000..3925254 --- /dev/null +++ b/include/linux/netlink.h @@ -0,0 +1,149 @@ +#ifndef __LINUX_NETLINK_H +#define __LINUX_NETLINK_H + +#include /* for sa_family_t */ +#include + +#define NETLINK_ROUTE 0 /* Routing/device hook */ +#define NETLINK_UNUSED 1 /* Unused number */ +#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */ +#define NETLINK_FIREWALL 3 /* Firewalling hook */ +#define NETLINK_INET_DIAG 4 /* INET socket monitoring */ +#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */ +#define NETLINK_XFRM 6 /* ipsec */ +#define NETLINK_SELINUX 7 /* SELinux event notifications */ +#define NETLINK_ISCSI 8 /* Open-iSCSI */ +#define NETLINK_AUDIT 9 /* auditing */ +#define NETLINK_FIB_LOOKUP 10 +#define NETLINK_CONNECTOR 11 +#define NETLINK_NETFILTER 12 /* netfilter subsystem */ +#define NETLINK_IP6_FW 13 +#define NETLINK_DNRTMSG 14 /* DECnet routing messages */ +#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */ +#define NETLINK_GENERIC 16 +/* leave room for NETLINK_DM (DM Events) */ +#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */ +#define NETLINK_ECRYPTFS 19 +#define NETLINK_RDMA 20 + +#define MAX_LINKS 32 + +struct sockaddr_nl { + sa_family_t nl_family; /* AF_NETLINK */ + unsigned short nl_pad; /* zero */ + __u32 nl_pid; /* port ID */ + __u32 nl_groups; /* multicast groups mask */ +}; + +struct nlmsghdr { + __u32 nlmsg_len; /* Length of message including header */ + __u16 nlmsg_type; /* Message content */ + __u16 nlmsg_flags; /* Additional flags */ + __u32 nlmsg_seq; /* Sequence number */ + __u32 nlmsg_pid; /* Sending process port ID */ +}; + +/* Flags values */ + +#define NLM_F_REQUEST 1 /* It is request message. */ +#define NLM_F_MULTI 2 /* Multipart message, terminated by NLMSG_DONE */ +#define NLM_F_ACK 4 /* Reply with ack, with zero or error code */ +#define NLM_F_ECHO 8 /* Echo this request */ +#define NLM_F_DUMP_INTR 16 /* Dump was inconsistent due to sequence change */ + +/* Modifiers to GET request */ +#define NLM_F_ROOT 0x100 /* specify tree root */ +#define NLM_F_MATCH 0x200 /* return all matching */ +#define NLM_F_ATOMIC 0x400 /* atomic GET */ +#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH) + +/* Modifiers to NEW request */ +#define NLM_F_REPLACE 0x100 /* Override existing */ +#define NLM_F_EXCL 0x200 /* Do not touch, if it exists */ +#define NLM_F_CREATE 0x400 /* Create, if it does not exist */ +#define NLM_F_APPEND 0x800 /* Add to end of list */ + +/* + 4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL + 4.4BSD CHANGE NLM_F_REPLACE + + True CHANGE NLM_F_CREATE|NLM_F_REPLACE + Append NLM_F_CREATE + Check NLM_F_EXCL + */ + +#define NLMSG_ALIGNTO 4U +#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) ) +#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr))) +#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN)) +#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len)) +#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0))) +#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \ + (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len))) +#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \ + (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \ + (nlh)->nlmsg_len <= (len)) +#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len))) + +#define NLMSG_NOOP 0x1 /* Nothing. */ +#define NLMSG_ERROR 0x2 /* Error */ +#define NLMSG_DONE 0x3 /* End of a dump */ +#define NLMSG_OVERRUN 0x4 /* Data lost */ + +#define NLMSG_MIN_TYPE 0x10 /* < 0x10: reserved control messages */ + +struct nlmsgerr { + int error; + struct nlmsghdr msg; +}; + +#define NETLINK_ADD_MEMBERSHIP 1 +#define NETLINK_DROP_MEMBERSHIP 2 +#define NETLINK_PKTINFO 3 +#define NETLINK_BROADCAST_ERROR 4 +#define NETLINK_NO_ENOBUFS 5 + +struct nl_pktinfo { + __u32 group; +}; + +#define NET_MAJOR 36 /* Major 36 is reserved for networking */ + +enum { + NETLINK_UNCONNECTED = 0, + NETLINK_CONNECTED, +}; + +/* + * <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)--> + * +---------------------+- - -+- - - - - - - - - -+- - -+ + * | Header | Pad | Payload | Pad | + * | (struct nlattr) | ing | | ing | + * +---------------------+- - -+- - - - - - - - - -+- - -+ + * <-------------- nlattr->nla_len --------------> + */ + +struct nlattr { + __u16 nla_len; + __u16 nla_type; +}; + +/* + * nla_type (16 bits) + * +---+---+-------------------------------+ + * | N | O | Attribute Type | + * +---+---+-------------------------------+ + * N := Carries nested attributes + * O := Payload stored in network byte order + * + * Note: The N and O flag are mutually exclusive. + */ +#define NLA_F_NESTED (1 << 15) +#define NLA_F_NET_BYTEORDER (1 << 14) +#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER) + +#define NLA_ALIGNTO 4 +#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1)) +#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr))) + +#endif /* __LINUX_NETLINK_H */ diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h new file mode 100644 index 0000000..defbde2 --- /dev/null +++ b/include/linux/pkt_cls.h @@ -0,0 +1,467 @@ +#ifndef __LINUX_PKT_CLS_H +#define __LINUX_PKT_CLS_H + +#include +#include + +/* I think i could have done better macros ; for now this is stolen from + * some arch/mips code - jhs +*/ +#define _TC_MAKE32(x) ((x)) + +#define _TC_MAKEMASK1(n) (_TC_MAKE32(1) << _TC_MAKE32(n)) +#define _TC_MAKEMASK(v,n) (_TC_MAKE32((_TC_MAKE32(1)<<(v))-1) << _TC_MAKE32(n)) +#define _TC_MAKEVALUE(v,n) (_TC_MAKE32(v) << _TC_MAKE32(n)) +#define _TC_GETVALUE(v,n,m) ((_TC_MAKE32(v) & _TC_MAKE32(m)) >> _TC_MAKE32(n)) + +/* verdict bit breakdown + * +bit 0: when set -> this packet has been munged already + +bit 1: when set -> It is ok to munge this packet + +bit 2,3,4,5: Reclassify counter - sort of reverse TTL - if exceeded +assume loop + +bit 6,7: Where this packet was last seen +0: Above the transmit example at the socket level +1: on the Ingress +2: on the Egress + +bit 8: when set --> Request not to classify on ingress. + +bits 9,10,11: redirect counter - redirect TTL. Loop avoidance + + * + * */ + +#define TC_MUNGED _TC_MAKEMASK1(0) +#define SET_TC_MUNGED(v) ( TC_MUNGED | (v & ~TC_MUNGED)) +#define CLR_TC_MUNGED(v) ( v & ~TC_MUNGED) + +#define TC_OK2MUNGE _TC_MAKEMASK1(1) +#define SET_TC_OK2MUNGE(v) ( TC_OK2MUNGE | (v & ~TC_OK2MUNGE)) +#define CLR_TC_OK2MUNGE(v) ( v & ~TC_OK2MUNGE) + +#define S_TC_VERD _TC_MAKE32(2) +#define M_TC_VERD _TC_MAKEMASK(4,S_TC_VERD) +#define G_TC_VERD(x) _TC_GETVALUE(x,S_TC_VERD,M_TC_VERD) +#define V_TC_VERD(x) _TC_MAKEVALUE(x,S_TC_VERD) +#define SET_TC_VERD(v,n) ((V_TC_VERD(n)) | (v & ~M_TC_VERD)) + +#define S_TC_FROM _TC_MAKE32(6) +#define M_TC_FROM _TC_MAKEMASK(2,S_TC_FROM) +#define G_TC_FROM(x) _TC_GETVALUE(x,S_TC_FROM,M_TC_FROM) +#define V_TC_FROM(x) _TC_MAKEVALUE(x,S_TC_FROM) +#define SET_TC_FROM(v,n) ((V_TC_FROM(n)) | (v & ~M_TC_FROM)) +#define AT_STACK 0x0 +#define AT_INGRESS 0x1 +#define AT_EGRESS 0x2 + +#define TC_NCLS _TC_MAKEMASK1(8) +#define SET_TC_NCLS(v) ( TC_NCLS | (v & ~TC_NCLS)) +#define CLR_TC_NCLS(v) ( v & ~TC_NCLS) + +#define S_TC_RTTL _TC_MAKE32(9) +#define M_TC_RTTL _TC_MAKEMASK(3,S_TC_RTTL) +#define G_TC_RTTL(x) _TC_GETVALUE(x,S_TC_RTTL,M_TC_RTTL) +#define V_TC_RTTL(x) _TC_MAKEVALUE(x,S_TC_RTTL) +#define SET_TC_RTTL(v,n) ((V_TC_RTTL(n)) | (v & ~M_TC_RTTL)) + +#define S_TC_AT _TC_MAKE32(12) +#define M_TC_AT _TC_MAKEMASK(2,S_TC_AT) +#define G_TC_AT(x) _TC_GETVALUE(x,S_TC_AT,M_TC_AT) +#define V_TC_AT(x) _TC_MAKEVALUE(x,S_TC_AT) +#define SET_TC_AT(v,n) ((V_TC_AT(n)) | (v & ~M_TC_AT)) + +/* Action attributes */ +enum { + TCA_ACT_UNSPEC, + TCA_ACT_KIND, + TCA_ACT_OPTIONS, + TCA_ACT_INDEX, + TCA_ACT_STATS, + __TCA_ACT_MAX +}; + +#define TCA_ACT_MAX __TCA_ACT_MAX +#define TCA_OLD_COMPAT (TCA_ACT_MAX+1) +#define TCA_ACT_MAX_PRIO 32 +#define TCA_ACT_BIND 1 +#define TCA_ACT_NOBIND 0 +#define TCA_ACT_UNBIND 1 +#define TCA_ACT_NOUNBIND 0 +#define TCA_ACT_REPLACE 1 +#define TCA_ACT_NOREPLACE 0 +#define MAX_REC_LOOP 4 +#define MAX_RED_LOOP 4 + +#define TC_ACT_UNSPEC (-1) +#define TC_ACT_OK 0 +#define TC_ACT_RECLASSIFY 1 +#define TC_ACT_SHOT 2 +#define TC_ACT_PIPE 3 +#define TC_ACT_STOLEN 4 +#define TC_ACT_QUEUED 5 +#define TC_ACT_REPEAT 6 +#define TC_ACT_JUMP 0x10000000 + +/* Action type identifiers*/ +enum { + TCA_ID_UNSPEC=0, + TCA_ID_POLICE=1, + /* other actions go here */ + __TCA_ID_MAX=255 +}; + +#define TCA_ID_MAX __TCA_ID_MAX + +struct tc_police { + __u32 index; + int action; +#define TC_POLICE_UNSPEC TC_ACT_UNSPEC +#define TC_POLICE_OK TC_ACT_OK +#define TC_POLICE_RECLASSIFY TC_ACT_RECLASSIFY +#define TC_POLICE_SHOT TC_ACT_SHOT +#define TC_POLICE_PIPE TC_ACT_PIPE + + __u32 limit; + __u32 burst; + __u32 mtu; + struct tc_ratespec rate; + struct tc_ratespec peakrate; + int refcnt; + int bindcnt; + __u32 capab; +}; + +struct tcf_t { + __u64 install; + __u64 lastuse; + __u64 expires; +}; + +struct tc_cnt { + int refcnt; + int bindcnt; +}; + +#define tc_gen \ + __u32 index; \ + __u32 capab; \ + int action; \ + int refcnt; \ + int bindcnt + +enum { + TCA_POLICE_UNSPEC, + TCA_POLICE_TBF, + TCA_POLICE_RATE, + TCA_POLICE_PEAKRATE, + TCA_POLICE_AVRATE, + TCA_POLICE_RESULT, + __TCA_POLICE_MAX +#define TCA_POLICE_RESULT TCA_POLICE_RESULT +}; + +#define TCA_POLICE_MAX (__TCA_POLICE_MAX - 1) + +/* U32 filters */ + +#define TC_U32_HTID(h) ((h)&0xFFF00000) +#define TC_U32_USERHTID(h) (TC_U32_HTID(h)>>20) +#define TC_U32_HASH(h) (((h)>>12)&0xFF) +#define TC_U32_NODE(h) ((h)&0xFFF) +#define TC_U32_KEY(h) ((h)&0xFFFFF) +#define TC_U32_UNSPEC 0 +#define TC_U32_ROOT (0xFFF00000) + +enum { + TCA_U32_UNSPEC, + TCA_U32_CLASSID, + TCA_U32_HASH, + TCA_U32_LINK, + TCA_U32_DIVISOR, + TCA_U32_SEL, + TCA_U32_POLICE, + TCA_U32_ACT, + TCA_U32_INDEV, + TCA_U32_PCNT, + TCA_U32_MARK, + __TCA_U32_MAX +}; + +#define TCA_U32_MAX (__TCA_U32_MAX - 1) + +struct tc_u32_key { + __be32 mask; + __be32 val; + int off; + int offmask; +}; + +struct tc_u32_sel { + unsigned char flags; + unsigned char offshift; + unsigned char nkeys; + + __be16 offmask; + __u16 off; + short offoff; + + short hoff; + __be32 hmask; + struct tc_u32_key keys[0]; +}; + +struct tc_u32_mark { + __u32 val; + __u32 mask; + __u32 success; +}; + +struct tc_u32_pcnt { + __u64 rcnt; + __u64 rhit; + __u64 kcnts[0]; +}; + +/* Flags */ + +#define TC_U32_TERMINAL 1 +#define TC_U32_OFFSET 2 +#define TC_U32_VAROFFSET 4 +#define TC_U32_EAT 8 + +#define TC_U32_MAXDEPTH 8 + + +/* RSVP filter */ + +enum { + TCA_RSVP_UNSPEC, + TCA_RSVP_CLASSID, + TCA_RSVP_DST, + TCA_RSVP_SRC, + TCA_RSVP_PINFO, + TCA_RSVP_POLICE, + TCA_RSVP_ACT, + __TCA_RSVP_MAX +}; + +#define TCA_RSVP_MAX (__TCA_RSVP_MAX - 1 ) + +struct tc_rsvp_gpi { + __u32 key; + __u32 mask; + int offset; +}; + +struct tc_rsvp_pinfo { + struct tc_rsvp_gpi dpi; + struct tc_rsvp_gpi spi; + __u8 protocol; + __u8 tunnelid; + __u8 tunnelhdr; + __u8 pad; +}; + +/* ROUTE filter */ + +enum { + TCA_ROUTE4_UNSPEC, + TCA_ROUTE4_CLASSID, + TCA_ROUTE4_TO, + TCA_ROUTE4_FROM, + TCA_ROUTE4_IIF, + TCA_ROUTE4_POLICE, + TCA_ROUTE4_ACT, + __TCA_ROUTE4_MAX +}; + +#define TCA_ROUTE4_MAX (__TCA_ROUTE4_MAX - 1) + + +/* FW filter */ + +enum { + TCA_FW_UNSPEC, + TCA_FW_CLASSID, + TCA_FW_POLICE, + TCA_FW_INDEV, /* used by CONFIG_NET_CLS_IND */ + TCA_FW_ACT, /* used by CONFIG_NET_CLS_ACT */ + TCA_FW_MASK, + __TCA_FW_MAX +}; + +#define TCA_FW_MAX (__TCA_FW_MAX - 1) + +/* TC index filter */ + +enum { + TCA_TCINDEX_UNSPEC, + TCA_TCINDEX_HASH, + TCA_TCINDEX_MASK, + TCA_TCINDEX_SHIFT, + TCA_TCINDEX_FALL_THROUGH, + TCA_TCINDEX_CLASSID, + TCA_TCINDEX_POLICE, + TCA_TCINDEX_ACT, + __TCA_TCINDEX_MAX +}; + +#define TCA_TCINDEX_MAX (__TCA_TCINDEX_MAX - 1) + +/* Flow filter */ + +enum { + FLOW_KEY_SRC, + FLOW_KEY_DST, + FLOW_KEY_PROTO, + FLOW_KEY_PROTO_SRC, + FLOW_KEY_PROTO_DST, + FLOW_KEY_IIF, + FLOW_KEY_PRIORITY, + FLOW_KEY_MARK, + FLOW_KEY_NFCT, + FLOW_KEY_NFCT_SRC, + FLOW_KEY_NFCT_DST, + FLOW_KEY_NFCT_PROTO_SRC, + FLOW_KEY_NFCT_PROTO_DST, + FLOW_KEY_RTCLASSID, + FLOW_KEY_SKUID, + FLOW_KEY_SKGID, + FLOW_KEY_VLAN_TAG, + FLOW_KEY_RXHASH, + __FLOW_KEY_MAX, +}; + +#define FLOW_KEY_MAX (__FLOW_KEY_MAX - 1) + +enum { + FLOW_MODE_MAP, + FLOW_MODE_HASH, +}; + +enum { + TCA_FLOW_UNSPEC, + TCA_FLOW_KEYS, + TCA_FLOW_MODE, + TCA_FLOW_BASECLASS, + TCA_FLOW_RSHIFT, + TCA_FLOW_ADDEND, + TCA_FLOW_MASK, + TCA_FLOW_XOR, + TCA_FLOW_DIVISOR, + TCA_FLOW_ACT, + TCA_FLOW_POLICE, + TCA_FLOW_EMATCHES, + TCA_FLOW_PERTURB, + __TCA_FLOW_MAX +}; + +#define TCA_FLOW_MAX (__TCA_FLOW_MAX - 1) + +/* Basic filter */ + +enum { + TCA_BASIC_UNSPEC, + TCA_BASIC_CLASSID, + TCA_BASIC_EMATCHES, + TCA_BASIC_ACT, + TCA_BASIC_POLICE, + __TCA_BASIC_MAX +}; + +#define TCA_BASIC_MAX (__TCA_BASIC_MAX - 1) + + +/* Cgroup classifier */ + +enum { + TCA_CGROUP_UNSPEC, + TCA_CGROUP_ACT, + TCA_CGROUP_POLICE, + TCA_CGROUP_EMATCHES, + __TCA_CGROUP_MAX, +}; + +#define TCA_CGROUP_MAX (__TCA_CGROUP_MAX - 1) + +/* Extended Matches */ + +struct tcf_ematch_tree_hdr { + __u16 nmatches; + __u16 progid; +}; + +enum { + TCA_EMATCH_TREE_UNSPEC, + TCA_EMATCH_TREE_HDR, + TCA_EMATCH_TREE_LIST, + __TCA_EMATCH_TREE_MAX +}; +#define TCA_EMATCH_TREE_MAX (__TCA_EMATCH_TREE_MAX - 1) + +struct tcf_ematch_hdr { + __u16 matchid; + __u16 kind; + __u16 flags; + __u16 pad; /* currently unused */ +}; + +/* 0 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +-----------------------+-+-+---+ + * | Unused |S|I| R | + * +-----------------------+-+-+---+ + * + * R(2) ::= relation to next ematch + * where: 0 0 END (last ematch) + * 0 1 AND + * 1 0 OR + * 1 1 Unused (invalid) + * I(1) ::= invert result + * S(1) ::= simple payload + */ +#define TCF_EM_REL_END 0 +#define TCF_EM_REL_AND (1<<0) +#define TCF_EM_REL_OR (1<<1) +#define TCF_EM_INVERT (1<<2) +#define TCF_EM_SIMPLE (1<<3) + +#define TCF_EM_REL_MASK 3 +#define TCF_EM_REL_VALID(v) (((v) & TCF_EM_REL_MASK) != TCF_EM_REL_MASK) + +enum { + TCF_LAYER_LINK, + TCF_LAYER_NETWORK, + TCF_LAYER_TRANSPORT, + __TCF_LAYER_MAX +}; +#define TCF_LAYER_MAX (__TCF_LAYER_MAX - 1) + +/* Ematch type assignments + * 1..32767 Reserved for ematches inside kernel tree + * 32768..65535 Free to use, not reliable + */ +#define TCF_EM_CONTAINER 0 +#define TCF_EM_CMP 1 +#define TCF_EM_NBYTE 2 +#define TCF_EM_U32 3 +#define TCF_EM_META 4 +#define TCF_EM_TEXT 5 +#define TCF_EM_VLAN 6 +#define TCF_EM_MAX 6 + +enum { + TCF_EM_PROG_TC +}; + +enum { + TCF_EM_OPND_EQ, + TCF_EM_OPND_GT, + TCF_EM_OPND_LT +}; + +#endif diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h new file mode 100644 index 0000000..7ccc1fd --- /dev/null +++ b/include/linux/pkt_sched.h @@ -0,0 +1,627 @@ +#ifndef __LINUX_PKT_SCHED_H +#define __LINUX_PKT_SCHED_H + +#include + +/* Logical priority bands not depending on specific packet scheduler. + Every scheduler will map them to real traffic classes, if it has + no more precise mechanism to classify packets. + + These numbers have no special meaning, though their coincidence + with obsolete IPv6 values is not occasional :-). New IPv6 drafts + preferred full anarchy inspired by diffserv group. + + Note: TC_PRIO_BESTEFFORT does not mean that it is the most unhappy + class, actually, as rule it will be handled with more care than + filler or even bulk. + */ + +#define TC_PRIO_BESTEFFORT 0 +#define TC_PRIO_FILLER 1 +#define TC_PRIO_BULK 2 +#define TC_PRIO_INTERACTIVE_BULK 4 +#define TC_PRIO_INTERACTIVE 6 +#define TC_PRIO_CONTROL 7 + +#define TC_PRIO_MAX 15 + +/* Generic queue statistics, available for all the elements. + Particular schedulers may have also their private records. + */ + +struct tc_stats { + __u64 bytes; /* NUmber of enqueues bytes */ + __u32 packets; /* Number of enqueued packets */ + __u32 drops; /* Packets dropped because of lack of resources */ + __u32 overlimits; /* Number of throttle events when this + * flow goes out of allocated bandwidth */ + __u32 bps; /* Current flow byte rate */ + __u32 pps; /* Current flow packet rate */ + __u32 qlen; + __u32 backlog; +}; + +struct tc_estimator { + signed char interval; + unsigned char ewma_log; +}; + +/* "Handles" + --------- + + All the traffic control objects have 32bit identifiers, or "handles". + + They can be considered as opaque numbers from user API viewpoint, + but actually they always consist of two fields: major and + minor numbers, which are interpreted by kernel specially, + that may be used by applications, though not recommended. + + F.e. qdisc handles always have minor number equal to zero, + classes (or flows) have major equal to parent qdisc major, and + minor uniquely identifying class inside qdisc. + + Macros to manipulate handles: + */ + +#define TC_H_MAJ_MASK (0xFFFF0000U) +#define TC_H_MIN_MASK (0x0000FFFFU) +#define TC_H_MAJ(h) ((h)&TC_H_MAJ_MASK) +#define TC_H_MIN(h) ((h)&TC_H_MIN_MASK) +#define TC_H_MAKE(maj,min) (((maj)&TC_H_MAJ_MASK)|((min)&TC_H_MIN_MASK)) + +#define TC_H_UNSPEC (0U) +#define TC_H_ROOT (0xFFFFFFFFU) +#define TC_H_INGRESS (0xFFFFFFF1U) + +struct tc_ratespec { + unsigned char cell_log; + unsigned char __reserved; + unsigned short overhead; + short cell_align; + unsigned short mpu; + __u32 rate; +}; + +#define TC_RTAB_SIZE 1024 + +struct tc_sizespec { + unsigned char cell_log; + unsigned char size_log; + short cell_align; + int overhead; + unsigned int linklayer; + unsigned int mpu; + unsigned int mtu; + unsigned int tsize; +}; + +enum { + TCA_STAB_UNSPEC, + TCA_STAB_BASE, + TCA_STAB_DATA, + __TCA_STAB_MAX +}; + +#define TCA_STAB_MAX (__TCA_STAB_MAX - 1) + +/* FIFO section */ + +struct tc_fifo_qopt { + __u32 limit; /* Queue length: bytes for bfifo, packets for pfifo */ +}; + +/* PRIO section */ + +#define TCQ_PRIO_BANDS 16 +#define TCQ_MIN_PRIO_BANDS 2 + +struct tc_prio_qopt { + int bands; /* Number of bands */ + __u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */ +}; + +/* MULTIQ section */ + +struct tc_multiq_qopt { + __u16 bands; /* Number of bands */ + __u16 max_bands; /* Maximum number of queues */ +}; + +/* PLUG section */ + +#define TCQ_PLUG_BUFFER 0 +#define TCQ_PLUG_RELEASE_ONE 1 +#define TCQ_PLUG_RELEASE_INDEFINITE 2 +#define TCQ_PLUG_LIMIT 3 + +struct tc_plug_qopt { + /* TCQ_PLUG_BUFFER: Inset a plug into the queue and + * buffer any incoming packets + * TCQ_PLUG_RELEASE_ONE: Dequeue packets from queue head + * to beginning of the next plug. + * TCQ_PLUG_RELEASE_INDEFINITE: Dequeue all packets from queue. + * Stop buffering packets until the next TCQ_PLUG_BUFFER + * command is received (just act as a pass-thru queue). + * TCQ_PLUG_LIMIT: Increase/decrease queue size + */ + int action; + __u32 limit; +}; + +/* TBF section */ + +struct tc_tbf_qopt { + struct tc_ratespec rate; + struct tc_ratespec peakrate; + __u32 limit; + __u32 buffer; + __u32 mtu; +}; + +enum { + TCA_TBF_UNSPEC, + TCA_TBF_PARMS, + TCA_TBF_RTAB, + TCA_TBF_PTAB, + __TCA_TBF_MAX, +}; + +#define TCA_TBF_MAX (__TCA_TBF_MAX - 1) + + +/* TEQL section */ + +/* TEQL does not require any parameters */ + +/* SFQ section */ + +struct tc_sfq_qopt { + unsigned quantum; /* Bytes per round allocated to flow */ + int perturb_period; /* Period of hash perturbation */ + __u32 limit; /* Maximal packets in queue */ + unsigned divisor; /* Hash divisor */ + unsigned flows; /* Maximal number of flows */ +}; + +struct tc_sfq_xstats { + __s32 allot; +}; + +/* + * NOTE: limit, divisor and flows are hardwired to code at the moment. + * + * limit=flows=128, divisor=1024; + * + * The only reason for this is efficiency, it is possible + * to change these parameters in compile time. + */ + +/* RED section */ + +enum { + TCA_RED_UNSPEC, + TCA_RED_PARMS, + TCA_RED_STAB, + __TCA_RED_MAX, +}; + +#define TCA_RED_MAX (__TCA_RED_MAX - 1) + +struct tc_red_qopt { + __u32 limit; /* HARD maximal queue length (bytes) */ + __u32 qth_min; /* Min average length threshold (bytes) */ + __u32 qth_max; /* Max average length threshold (bytes) */ + unsigned char Wlog; /* log(W) */ + unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ + unsigned char Scell_log; /* cell size for idle damping */ + unsigned char flags; +#define TC_RED_ECN 1 +#define TC_RED_HARDDROP 2 +}; + +struct tc_red_xstats { + __u32 early; /* Early drops */ + __u32 pdrop; /* Drops due to queue limits */ + __u32 other; /* Drops due to drop() calls */ + __u32 marked; /* Marked packets */ +}; + +/* GRED section */ + +#define MAX_DPs 16 + +enum { + TCA_GRED_UNSPEC, + TCA_GRED_PARMS, + TCA_GRED_STAB, + TCA_GRED_DPS, + __TCA_GRED_MAX, +}; + +#define TCA_GRED_MAX (__TCA_GRED_MAX - 1) + +struct tc_gred_qopt { + __u32 limit; /* HARD maximal queue length (bytes) */ + __u32 qth_min; /* Min average length threshold (bytes) */ + __u32 qth_max; /* Max average length threshold (bytes) */ + __u32 DP; /* up to 2^32 DPs */ + __u32 backlog; + __u32 qave; + __u32 forced; + __u32 early; + __u32 other; + __u32 pdrop; + __u8 Wlog; /* log(W) */ + __u8 Plog; /* log(P_max/(qth_max-qth_min)) */ + __u8 Scell_log; /* cell size for idle damping */ + __u8 prio; /* prio of this VQ */ + __u32 packets; + __u32 bytesin; +}; + +/* gred setup */ +struct tc_gred_sopt { + __u32 DPs; + __u32 def_DP; + __u8 grio; + __u8 flags; + __u16 pad1; +}; + +/* CHOKe section */ + +enum { + TCA_CHOKE_UNSPEC, + TCA_CHOKE_PARMS, + TCA_CHOKE_STAB, + __TCA_CHOKE_MAX, +}; + +#define TCA_CHOKE_MAX (__TCA_CHOKE_MAX - 1) + +struct tc_choke_qopt { + __u32 limit; /* Hard queue length (packets) */ + __u32 qth_min; /* Min average threshold (packets) */ + __u32 qth_max; /* Max average threshold (packets) */ + unsigned char Wlog; /* log(W) */ + unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ + unsigned char Scell_log; /* cell size for idle damping */ + unsigned char flags; /* see RED flags */ +}; + +struct tc_choke_xstats { + __u32 early; /* Early drops */ + __u32 pdrop; /* Drops due to queue limits */ + __u32 other; /* Drops due to drop() calls */ + __u32 marked; /* Marked packets */ + __u32 matched; /* Drops due to flow match */ +}; + +/* HTB section */ +#define TC_HTB_NUMPRIO 8 +#define TC_HTB_MAXDEPTH 8 +#define TC_HTB_PROTOVER 3 /* the same as HTB and TC's major */ + +struct tc_htb_opt { + struct tc_ratespec rate; + struct tc_ratespec ceil; + __u32 buffer; + __u32 cbuffer; + __u32 quantum; + __u32 level; /* out only */ + __u32 prio; +}; +struct tc_htb_glob { + __u32 version; /* to match HTB/TC */ + __u32 rate2quantum; /* bps->quantum divisor */ + __u32 defcls; /* default class number */ + __u32 debug; /* debug flags */ + + /* stats */ + __u32 direct_pkts; /* count of non shapped packets */ +}; +enum { + TCA_HTB_UNSPEC, + TCA_HTB_PARMS, + TCA_HTB_INIT, + TCA_HTB_CTAB, + TCA_HTB_RTAB, + __TCA_HTB_MAX, +}; + +#define TCA_HTB_MAX (__TCA_HTB_MAX - 1) + +struct tc_htb_xstats { + __u32 lends; + __u32 borrows; + __u32 giants; /* too big packets (rate will not be accurate) */ + __u32 tokens; + __u32 ctokens; +}; + +/* HFSC section */ + +struct tc_hfsc_qopt { + __u16 defcls; /* default class */ +}; + +struct tc_service_curve { + __u32 m1; /* slope of the first segment in bps */ + __u32 d; /* x-projection of the first segment in us */ + __u32 m2; /* slope of the second segment in bps */ +}; + +struct tc_hfsc_stats { + __u64 work; /* total work done */ + __u64 rtwork; /* work done by real-time criteria */ + __u32 period; /* current period */ + __u32 level; /* class level in hierarchy */ +}; + +enum { + TCA_HFSC_UNSPEC, + TCA_HFSC_RSC, + TCA_HFSC_FSC, + TCA_HFSC_USC, + __TCA_HFSC_MAX, +}; + +#define TCA_HFSC_MAX (__TCA_HFSC_MAX - 1) + + +/* CBQ section */ + +#define TC_CBQ_MAXPRIO 8 +#define TC_CBQ_MAXLEVEL 8 +#define TC_CBQ_DEF_EWMA 5 + +struct tc_cbq_lssopt { + unsigned char change; + unsigned char flags; +#define TCF_CBQ_LSS_BOUNDED 1 +#define TCF_CBQ_LSS_ISOLATED 2 + unsigned char ewma_log; + unsigned char level; +#define TCF_CBQ_LSS_FLAGS 1 +#define TCF_CBQ_LSS_EWMA 2 +#define TCF_CBQ_LSS_MAXIDLE 4 +#define TCF_CBQ_LSS_MINIDLE 8 +#define TCF_CBQ_LSS_OFFTIME 0x10 +#define TCF_CBQ_LSS_AVPKT 0x20 + __u32 maxidle; + __u32 minidle; + __u32 offtime; + __u32 avpkt; +}; + +struct tc_cbq_wrropt { + unsigned char flags; + unsigned char priority; + unsigned char cpriority; + unsigned char __reserved; + __u32 allot; + __u32 weight; +}; + +struct tc_cbq_ovl { + unsigned char strategy; +#define TC_CBQ_OVL_CLASSIC 0 +#define TC_CBQ_OVL_DELAY 1 +#define TC_CBQ_OVL_LOWPRIO 2 +#define TC_CBQ_OVL_DROP 3 +#define TC_CBQ_OVL_RCLASSIC 4 + unsigned char priority2; + __u16 pad; + __u32 penalty; +}; + +struct tc_cbq_police { + unsigned char police; + unsigned char __res1; + unsigned short __res2; +}; + +struct tc_cbq_fopt { + __u32 split; + __u32 defmap; + __u32 defchange; +}; + +struct tc_cbq_xstats { + __u32 borrows; + __u32 overactions; + __s32 avgidle; + __s32 undertime; +}; + +enum { + TCA_CBQ_UNSPEC, + TCA_CBQ_LSSOPT, + TCA_CBQ_WRROPT, + TCA_CBQ_FOPT, + TCA_CBQ_OVL_STRATEGY, + TCA_CBQ_RATE, + TCA_CBQ_RTAB, + TCA_CBQ_POLICE, + __TCA_CBQ_MAX, +}; + +#define TCA_CBQ_MAX (__TCA_CBQ_MAX - 1) + +/* dsmark section */ + +enum { + TCA_DSMARK_UNSPEC, + TCA_DSMARK_INDICES, + TCA_DSMARK_DEFAULT_INDEX, + TCA_DSMARK_SET_TC_INDEX, + TCA_DSMARK_MASK, + TCA_DSMARK_VALUE, + __TCA_DSMARK_MAX, +}; + +#define TCA_DSMARK_MAX (__TCA_DSMARK_MAX - 1) + +/* ATM section */ + +enum { + TCA_ATM_UNSPEC, + TCA_ATM_FD, /* file/socket descriptor */ + TCA_ATM_PTR, /* pointer to descriptor - later */ + TCA_ATM_HDR, /* LL header */ + TCA_ATM_EXCESS, /* excess traffic class (0 for CLP) */ + TCA_ATM_ADDR, /* PVC address (for output only) */ + TCA_ATM_STATE, /* VC state (ATM_VS_*; for output only) */ + __TCA_ATM_MAX, +}; + +#define TCA_ATM_MAX (__TCA_ATM_MAX - 1) + +/* Network emulator */ + +enum { + TCA_NETEM_UNSPEC, + TCA_NETEM_CORR, + TCA_NETEM_DELAY_DIST, + TCA_NETEM_REORDER, + TCA_NETEM_CORRUPT, + TCA_NETEM_LOSS, + __TCA_NETEM_MAX, +}; + +#define TCA_NETEM_MAX (__TCA_NETEM_MAX - 1) + +struct tc_netem_qopt { + __u32 latency; /* added delay (us) */ + __u32 limit; /* fifo limit (packets) */ + __u32 loss; /* random packet loss (0=none ~0=100%) */ + __u32 gap; /* re-ordering gap (0 for none) */ + __u32 duplicate; /* random packet dup (0=none ~0=100%) */ + __u32 jitter; /* random jitter in latency (us) */ +}; + +struct tc_netem_corr { + __u32 delay_corr; /* delay correlation */ + __u32 loss_corr; /* packet loss correlation */ + __u32 dup_corr; /* duplicate correlation */ +}; + +struct tc_netem_reorder { + __u32 probability; + __u32 correlation; +}; + +struct tc_netem_corrupt { + __u32 probability; + __u32 correlation; +}; + +enum { + NETEM_LOSS_UNSPEC, + NETEM_LOSS_GI, /* General Intuitive - 4 state model */ + NETEM_LOSS_GE, /* Gilbert Elliot models */ + __NETEM_LOSS_MAX +}; +#define NETEM_LOSS_MAX (__NETEM_LOSS_MAX - 1) + +/* State transition probablities for 4 state model */ +struct tc_netem_gimodel { + __u32 p13; + __u32 p31; + __u32 p32; + __u32 p14; + __u32 p23; +}; + +/* Gilbert-Elliot models */ +struct tc_netem_gemodel { + __u32 p; + __u32 r; + __u32 h; + __u32 k1; +}; + +#define NETEM_DIST_SCALE 8192 +#define NETEM_DIST_MAX 16384 + +/* DRR */ + +enum { + TCA_DRR_UNSPEC, + TCA_DRR_QUANTUM, + __TCA_DRR_MAX +}; + +#define TCA_DRR_MAX (__TCA_DRR_MAX - 1) + +struct tc_drr_stats { + __u32 deficit; +}; + +/* MQPRIO */ +#define TC_QOPT_BITMASK 15 +#define TC_QOPT_MAX_QUEUE 16 + +struct tc_mqprio_qopt { + __u8 num_tc; + __u8 prio_tc_map[TC_QOPT_BITMASK + 1]; + __u8 hw; + __u16 count[TC_QOPT_MAX_QUEUE]; + __u16 offset[TC_QOPT_MAX_QUEUE]; +}; + +/* SFB */ + +enum { + TCA_SFB_UNSPEC, + TCA_SFB_PARMS, + __TCA_SFB_MAX, +}; + +#define TCA_SFB_MAX (__TCA_SFB_MAX - 1) + +/* + * Note: increment, decrement are Q0.16 fixed-point values. + */ +struct tc_sfb_qopt { + __u32 rehash_interval; /* delay between hash move, in ms */ + __u32 warmup_time; /* double buffering warmup time in ms (warmup_time < rehash_interval) */ + __u32 max; /* max len of qlen_min */ + __u32 bin_size; /* maximum queue length per bin */ + __u32 increment; /* probability increment, (d1 in Blue) */ + __u32 decrement; /* probability decrement, (d2 in Blue) */ + __u32 limit; /* max SFB queue length */ + __u32 penalty_rate; /* inelastic flows are rate limited to 'rate' pps */ + __u32 penalty_burst; +}; + +struct tc_sfb_xstats { + __u32 earlydrop; + __u32 penaltydrop; + __u32 bucketdrop; + __u32 queuedrop; + __u32 childdrop; /* drops in child qdisc */ + __u32 marked; + __u32 maxqlen; + __u32 maxprob; + __u32 avgprob; +}; + +#define SFB_MAX_PROB 0xFFFF + +/* QFQ */ +enum { + TCA_QFQ_UNSPEC, + TCA_QFQ_WEIGHT, + TCA_QFQ_LMAX, + __TCA_QFQ_MAX +}; + +#define TCA_QFQ_MAX (__TCA_QFQ_MAX - 1) + +struct tc_qfq_stats { + __u32 weight; + __u32 lmax; +}; + +#endif diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h new file mode 100644 index 0000000..2363c18 --- /dev/null +++ b/include/linux/rtnetlink.h @@ -0,0 +1,605 @@ +#ifndef __LINUX_RTNETLINK_H +#define __LINUX_RTNETLINK_H + +#include +#include +#include +#include +#include + +/* rtnetlink families. Values up to 127 are reserved for real address + * families, values above 128 may be used arbitrarily. + */ +#define RTNL_FAMILY_IPMR 128 +#define RTNL_FAMILY_IP6MR 129 +#define RTNL_FAMILY_MAX 129 + +/**** + * Routing/neighbour discovery messages. + ****/ + +/* Types of messages */ + +enum { + RTM_BASE = 16, +#define RTM_BASE RTM_BASE + + RTM_NEWLINK = 16, +#define RTM_NEWLINK RTM_NEWLINK + RTM_DELLINK, +#define RTM_DELLINK RTM_DELLINK + RTM_GETLINK, +#define RTM_GETLINK RTM_GETLINK + RTM_SETLINK, +#define RTM_SETLINK RTM_SETLINK + + RTM_NEWADDR = 20, +#define RTM_NEWADDR RTM_NEWADDR + RTM_DELADDR, +#define RTM_DELADDR RTM_DELADDR + RTM_GETADDR, +#define RTM_GETADDR RTM_GETADDR + + RTM_NEWROUTE = 24, +#define RTM_NEWROUTE RTM_NEWROUTE + RTM_DELROUTE, +#define RTM_DELROUTE RTM_DELROUTE + RTM_GETROUTE, +#define RTM_GETROUTE RTM_GETROUTE + + RTM_NEWNEIGH = 28, +#define RTM_NEWNEIGH RTM_NEWNEIGH + RTM_DELNEIGH, +#define RTM_DELNEIGH RTM_DELNEIGH + RTM_GETNEIGH, +#define RTM_GETNEIGH RTM_GETNEIGH + + RTM_NEWRULE = 32, +#define RTM_NEWRULE RTM_NEWRULE + RTM_DELRULE, +#define RTM_DELRULE RTM_DELRULE + RTM_GETRULE, +#define RTM_GETRULE RTM_GETRULE + + RTM_NEWQDISC = 36, +#define RTM_NEWQDISC RTM_NEWQDISC + RTM_DELQDISC, +#define RTM_DELQDISC RTM_DELQDISC + RTM_GETQDISC, +#define RTM_GETQDISC RTM_GETQDISC + + RTM_NEWTCLASS = 40, +#define RTM_NEWTCLASS RTM_NEWTCLASS + RTM_DELTCLASS, +#define RTM_DELTCLASS RTM_DELTCLASS + RTM_GETTCLASS, +#define RTM_GETTCLASS RTM_GETTCLASS + + RTM_NEWTFILTER = 44, +#define RTM_NEWTFILTER RTM_NEWTFILTER + RTM_DELTFILTER, +#define RTM_DELTFILTER RTM_DELTFILTER + RTM_GETTFILTER, +#define RTM_GETTFILTER RTM_GETTFILTER + + RTM_NEWACTION = 48, +#define RTM_NEWACTION RTM_NEWACTION + RTM_DELACTION, +#define RTM_DELACTION RTM_DELACTION + RTM_GETACTION, +#define RTM_GETACTION RTM_GETACTION + + RTM_NEWPREFIX = 52, +#define RTM_NEWPREFIX RTM_NEWPREFIX + + RTM_GETMULTICAST = 58, +#define RTM_GETMULTICAST RTM_GETMULTICAST + + RTM_GETANYCAST = 62, +#define RTM_GETANYCAST RTM_GETANYCAST + + RTM_NEWNEIGHTBL = 64, +#define RTM_NEWNEIGHTBL RTM_NEWNEIGHTBL + RTM_GETNEIGHTBL = 66, +#define RTM_GETNEIGHTBL RTM_GETNEIGHTBL + RTM_SETNEIGHTBL, +#define RTM_SETNEIGHTBL RTM_SETNEIGHTBL + + RTM_NEWNDUSEROPT = 68, +#define RTM_NEWNDUSEROPT RTM_NEWNDUSEROPT + + RTM_NEWADDRLABEL = 72, +#define RTM_NEWADDRLABEL RTM_NEWADDRLABEL + RTM_DELADDRLABEL, +#define RTM_DELADDRLABEL RTM_DELADDRLABEL + RTM_GETADDRLABEL, +#define RTM_GETADDRLABEL RTM_GETADDRLABEL + + RTM_GETDCB = 78, +#define RTM_GETDCB RTM_GETDCB + RTM_SETDCB, +#define RTM_SETDCB RTM_SETDCB + + __RTM_MAX, +#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1) +}; + +#define RTM_NR_MSGTYPES (RTM_MAX + 1 - RTM_BASE) +#define RTM_NR_FAMILIES (RTM_NR_MSGTYPES >> 2) +#define RTM_FAM(cmd) (((cmd) - RTM_BASE) >> 2) + +/* + Generic structure for encapsulation of optional route information. + It is reminiscent of sockaddr, but with sa_family replaced + with attribute type. + */ + +struct rtattr { + unsigned short rta_len; + unsigned short rta_type; +}; + +/* Macros to handle rtattributes */ + +#define RTA_ALIGNTO 4 +#define RTA_ALIGN(len) ( ((len)+RTA_ALIGNTO-1) & ~(RTA_ALIGNTO-1) ) +#define RTA_OK(rta,len) ((len) >= (int)sizeof(struct rtattr) && \ + (rta)->rta_len >= sizeof(struct rtattr) && \ + (rta)->rta_len <= (len)) +#define RTA_NEXT(rta,attrlen) ((attrlen) -= RTA_ALIGN((rta)->rta_len), \ + (struct rtattr*)(((char*)(rta)) + RTA_ALIGN((rta)->rta_len))) +#define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len)) +#define RTA_SPACE(len) RTA_ALIGN(RTA_LENGTH(len)) +#define RTA_DATA(rta) ((void*)(((char*)(rta)) + RTA_LENGTH(0))) +#define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0)) + + + + +/****************************************************************************** + * Definitions used in routing table administration. + ****/ + +struct rtmsg { + unsigned char rtm_family; + unsigned char rtm_dst_len; + unsigned char rtm_src_len; + unsigned char rtm_tos; + + unsigned char rtm_table; /* Routing table id */ + unsigned char rtm_protocol; /* Routing protocol; see below */ + unsigned char rtm_scope; /* See below */ + unsigned char rtm_type; /* See below */ + + unsigned rtm_flags; +}; + +/* rtm_type */ + +enum { + RTN_UNSPEC, + RTN_UNICAST, /* Gateway or direct route */ + RTN_LOCAL, /* Accept locally */ + RTN_BROADCAST, /* Accept locally as broadcast, + send as broadcast */ + RTN_ANYCAST, /* Accept locally as broadcast, + but send as unicast */ + RTN_MULTICAST, /* Multicast route */ + RTN_BLACKHOLE, /* Drop */ + RTN_UNREACHABLE, /* Destination is unreachable */ + RTN_PROHIBIT, /* Administratively prohibited */ + RTN_THROW, /* Not in this table */ + RTN_NAT, /* Translate this address */ + RTN_XRESOLVE, /* Use external resolver */ + __RTN_MAX +}; + +#define RTN_MAX (__RTN_MAX - 1) + + +/* rtm_protocol */ + +#define RTPROT_UNSPEC 0 +#define RTPROT_REDIRECT 1 /* Route installed by ICMP redirects; + not used by current IPv4 */ +#define RTPROT_KERNEL 2 /* Route installed by kernel */ +#define RTPROT_BOOT 3 /* Route installed during boot */ +#define RTPROT_STATIC 4 /* Route installed by administrator */ + +/* Values of protocol >= RTPROT_STATIC are not interpreted by kernel; + they are just passed from user and back as is. + It will be used by hypothetical multiple routing daemons. + Note that protocol values should be standardized in order to + avoid conflicts. + */ + +#define RTPROT_GATED 8 /* Apparently, GateD */ +#define RTPROT_RA 9 /* RDISC/ND router advertisements */ +#define RTPROT_MRT 10 /* Merit MRT */ +#define RTPROT_ZEBRA 11 /* Zebra */ +#define RTPROT_BIRD 12 /* BIRD */ +#define RTPROT_DNROUTED 13 /* DECnet routing daemon */ +#define RTPROT_XORP 14 /* XORP */ +#define RTPROT_NTK 15 /* Netsukuku */ +#define RTPROT_DHCP 16 /* DHCP client */ + +/* rtm_scope + + Really it is not scope, but sort of distance to the destination. + NOWHERE are reserved for not existing destinations, HOST is our + local addresses, LINK are destinations, located on directly attached + link and UNIVERSE is everywhere in the Universe. + + Intermediate values are also possible f.e. interior routes + could be assigned a value between UNIVERSE and LINK. +*/ + +enum rt_scope_t { + RT_SCOPE_UNIVERSE=0, +/* User defined values */ + RT_SCOPE_SITE=200, + RT_SCOPE_LINK=253, + RT_SCOPE_HOST=254, + RT_SCOPE_NOWHERE=255 +}; + +/* rtm_flags */ + +#define RTM_F_NOTIFY 0x100 /* Notify user of route change */ +#define RTM_F_CLONED 0x200 /* This route is cloned */ +#define RTM_F_EQUALIZE 0x400 /* Multipath equalizer: NI */ +#define RTM_F_PREFIX 0x800 /* Prefix addresses */ + +/* Reserved table identifiers */ + +enum rt_class_t { + RT_TABLE_UNSPEC=0, +/* User defined values */ + RT_TABLE_COMPAT=252, + RT_TABLE_DEFAULT=253, + RT_TABLE_MAIN=254, + RT_TABLE_LOCAL=255, + RT_TABLE_MAX=0xFFFFFFFF +}; + + +/* Routing message attributes */ + +enum rtattr_type_t { + RTA_UNSPEC, + RTA_DST, + RTA_SRC, + RTA_IIF, + RTA_OIF, + RTA_GATEWAY, + RTA_PRIORITY, + RTA_PREFSRC, + RTA_METRICS, + RTA_MULTIPATH, + RTA_PROTOINFO, /* no longer used */ + RTA_FLOW, + RTA_CACHEINFO, + RTA_SESSION, /* no longer used */ + RTA_MP_ALGO, /* no longer used */ + RTA_TABLE, + RTA_MARK, + __RTA_MAX +}; + +#define RTA_MAX (__RTA_MAX - 1) + +#define RTM_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtmsg)))) +#define RTM_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct rtmsg)) + +/* RTM_MULTIPATH --- array of struct rtnexthop. + * + * "struct rtnexthop" describes all necessary nexthop information, + * i.e. parameters of path to a destination via this nexthop. + * + * At the moment it is impossible to set different prefsrc, mtu, window + * and rtt for different paths from multipath. + */ + +struct rtnexthop { + unsigned short rtnh_len; + unsigned char rtnh_flags; + unsigned char rtnh_hops; + int rtnh_ifindex; +}; + +/* rtnh_flags */ + +#define RTNH_F_DEAD 1 /* Nexthop is dead (used by multipath) */ +#define RTNH_F_PERVASIVE 2 /* Do recursive gateway lookup */ +#define RTNH_F_ONLINK 4 /* Gateway is forced on link */ + +/* Macros to handle hexthops */ + +#define RTNH_ALIGNTO 4 +#define RTNH_ALIGN(len) ( ((len)+RTNH_ALIGNTO-1) & ~(RTNH_ALIGNTO-1) ) +#define RTNH_OK(rtnh,len) ((rtnh)->rtnh_len >= sizeof(struct rtnexthop) && \ + ((int)(rtnh)->rtnh_len) <= (len)) +#define RTNH_NEXT(rtnh) ((struct rtnexthop*)(((char*)(rtnh)) + RTNH_ALIGN((rtnh)->rtnh_len))) +#define RTNH_LENGTH(len) (RTNH_ALIGN(sizeof(struct rtnexthop)) + (len)) +#define RTNH_SPACE(len) RTNH_ALIGN(RTNH_LENGTH(len)) +#define RTNH_DATA(rtnh) ((struct rtattr*)(((char*)(rtnh)) + RTNH_LENGTH(0))) + +/* RTM_CACHEINFO */ + +struct rta_cacheinfo { + __u32 rta_clntref; + __u32 rta_lastuse; + __s32 rta_expires; + __u32 rta_error; + __u32 rta_used; + +#define RTNETLINK_HAVE_PEERINFO 1 + __u32 rta_id; + __u32 rta_ts; + __u32 rta_tsage; +}; + +/* RTM_METRICS --- array of struct rtattr with types of RTAX_* */ + +enum { + RTAX_UNSPEC, +#define RTAX_UNSPEC RTAX_UNSPEC + RTAX_LOCK, +#define RTAX_LOCK RTAX_LOCK + RTAX_MTU, +#define RTAX_MTU RTAX_MTU + RTAX_WINDOW, +#define RTAX_WINDOW RTAX_WINDOW + RTAX_RTT, +#define RTAX_RTT RTAX_RTT + RTAX_RTTVAR, +#define RTAX_RTTVAR RTAX_RTTVAR + RTAX_SSTHRESH, +#define RTAX_SSTHRESH RTAX_SSTHRESH + RTAX_CWND, +#define RTAX_CWND RTAX_CWND + RTAX_ADVMSS, +#define RTAX_ADVMSS RTAX_ADVMSS + RTAX_REORDERING, +#define RTAX_REORDERING RTAX_REORDERING + RTAX_HOPLIMIT, +#define RTAX_HOPLIMIT RTAX_HOPLIMIT + RTAX_INITCWND, +#define RTAX_INITCWND RTAX_INITCWND + RTAX_FEATURES, +#define RTAX_FEATURES RTAX_FEATURES + RTAX_RTO_MIN, +#define RTAX_RTO_MIN RTAX_RTO_MIN + RTAX_INITRWND, +#define RTAX_INITRWND RTAX_INITRWND + __RTAX_MAX +}; + +#define RTAX_MAX (__RTAX_MAX - 1) + +#define RTAX_FEATURE_ECN 0x00000001 +#define RTAX_FEATURE_SACK 0x00000002 +#define RTAX_FEATURE_TIMESTAMP 0x00000004 +#define RTAX_FEATURE_ALLFRAG 0x00000008 + +struct rta_session { + __u8 proto; + __u8 pad1; + __u16 pad2; + + union { + struct { + __u16 sport; + __u16 dport; + } ports; + + struct { + __u8 type; + __u8 code; + __u16 ident; + } icmpt; + + __u32 spi; + } u; +}; + +/**** + * General form of address family dependent message. + ****/ + +struct rtgenmsg { + unsigned char rtgen_family; +}; + +/***************************************************************** + * Link layer specific messages. + ****/ + +/* struct ifinfomsg + * passes link level specific information, not dependent + * on network protocol. + */ + +struct ifinfomsg { + unsigned char ifi_family; + unsigned char __ifi_pad; + unsigned short ifi_type; /* ARPHRD_* */ + int ifi_index; /* Link index */ + unsigned ifi_flags; /* IFF_* flags */ + unsigned ifi_change; /* IFF_* change mask */ +}; + +/******************************************************************** + * prefix information + ****/ + +struct prefixmsg { + unsigned char prefix_family; + unsigned char prefix_pad1; + unsigned short prefix_pad2; + int prefix_ifindex; + unsigned char prefix_type; + unsigned char prefix_len; + unsigned char prefix_flags; + unsigned char prefix_pad3; +}; + +enum +{ + PREFIX_UNSPEC, + PREFIX_ADDRESS, + PREFIX_CACHEINFO, + __PREFIX_MAX +}; + +#define PREFIX_MAX (__PREFIX_MAX - 1) + +struct prefix_cacheinfo { + __u32 preferred_time; + __u32 valid_time; +}; + + +/***************************************************************** + * Traffic control messages. + ****/ + +struct tcmsg { + unsigned char tcm_family; + unsigned char tcm__pad1; + unsigned short tcm__pad2; + int tcm_ifindex; + __u32 tcm_handle; + __u32 tcm_parent; + __u32 tcm_info; +}; + +enum { + TCA_UNSPEC, + TCA_KIND, + TCA_OPTIONS, + TCA_STATS, + TCA_XSTATS, + TCA_RATE, + TCA_FCNT, + TCA_STATS2, + TCA_STAB, + __TCA_MAX +}; + +#define TCA_MAX (__TCA_MAX - 1) + +#define TCA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg)))) +#define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg)) + +/******************************************************************** + * Neighbor Discovery userland options + ****/ + +struct nduseroptmsg { + unsigned char nduseropt_family; + unsigned char nduseropt_pad1; + unsigned short nduseropt_opts_len; /* Total length of options */ + int nduseropt_ifindex; + __u8 nduseropt_icmp_type; + __u8 nduseropt_icmp_code; + unsigned short nduseropt_pad2; + unsigned int nduseropt_pad3; + /* Followed by one or more ND options */ +}; + +enum { + NDUSEROPT_UNSPEC, + NDUSEROPT_SRCADDR, + __NDUSEROPT_MAX +}; + +#define NDUSEROPT_MAX (__NDUSEROPT_MAX - 1) + +#ifndef __KERNEL__ +/* RTnetlink multicast groups - backwards compatibility for userspace */ +#define RTMGRP_LINK 1 +#define RTMGRP_NOTIFY 2 +#define RTMGRP_NEIGH 4 +#define RTMGRP_TC 8 + +#define RTMGRP_IPV4_IFADDR 0x10 +#define RTMGRP_IPV4_MROUTE 0x20 +#define RTMGRP_IPV4_ROUTE 0x40 +#define RTMGRP_IPV4_RULE 0x80 + +#define RTMGRP_IPV6_IFADDR 0x100 +#define RTMGRP_IPV6_MROUTE 0x200 +#define RTMGRP_IPV6_ROUTE 0x400 +#define RTMGRP_IPV6_IFINFO 0x800 + +#define RTMGRP_DECnet_IFADDR 0x1000 +#define RTMGRP_DECnet_ROUTE 0x4000 + +#define RTMGRP_IPV6_PREFIX 0x20000 +#endif + +/* RTnetlink multicast groups */ +enum rtnetlink_groups { + RTNLGRP_NONE, +#define RTNLGRP_NONE RTNLGRP_NONE + RTNLGRP_LINK, +#define RTNLGRP_LINK RTNLGRP_LINK + RTNLGRP_NOTIFY, +#define RTNLGRP_NOTIFY RTNLGRP_NOTIFY + RTNLGRP_NEIGH, +#define RTNLGRP_NEIGH RTNLGRP_NEIGH + RTNLGRP_TC, +#define RTNLGRP_TC RTNLGRP_TC + RTNLGRP_IPV4_IFADDR, +#define RTNLGRP_IPV4_IFADDR RTNLGRP_IPV4_IFADDR + RTNLGRP_IPV4_MROUTE, +#define RTNLGRP_IPV4_MROUTE RTNLGRP_IPV4_MROUTE + RTNLGRP_IPV4_ROUTE, +#define RTNLGRP_IPV4_ROUTE RTNLGRP_IPV4_ROUTE + RTNLGRP_IPV4_RULE, +#define RTNLGRP_IPV4_RULE RTNLGRP_IPV4_RULE + RTNLGRP_IPV6_IFADDR, +#define RTNLGRP_IPV6_IFADDR RTNLGRP_IPV6_IFADDR + RTNLGRP_IPV6_MROUTE, +#define RTNLGRP_IPV6_MROUTE RTNLGRP_IPV6_MROUTE + RTNLGRP_IPV6_ROUTE, +#define RTNLGRP_IPV6_ROUTE RTNLGRP_IPV6_ROUTE + RTNLGRP_IPV6_IFINFO, +#define RTNLGRP_IPV6_IFINFO RTNLGRP_IPV6_IFINFO + RTNLGRP_DECnet_IFADDR, +#define RTNLGRP_DECnet_IFADDR RTNLGRP_DECnet_IFADDR + RTNLGRP_NOP2, + RTNLGRP_DECnet_ROUTE, +#define RTNLGRP_DECnet_ROUTE RTNLGRP_DECnet_ROUTE + RTNLGRP_DECnet_RULE, +#define RTNLGRP_DECnet_RULE RTNLGRP_DECnet_RULE + RTNLGRP_NOP4, + RTNLGRP_IPV6_PREFIX, +#define RTNLGRP_IPV6_PREFIX RTNLGRP_IPV6_PREFIX + RTNLGRP_IPV6_RULE, +#define RTNLGRP_IPV6_RULE RTNLGRP_IPV6_RULE + RTNLGRP_ND_USEROPT, +#define RTNLGRP_ND_USEROPT RTNLGRP_ND_USEROPT + RTNLGRP_PHONET_IFADDR, +#define RTNLGRP_PHONET_IFADDR RTNLGRP_PHONET_IFADDR + RTNLGRP_PHONET_ROUTE, +#define RTNLGRP_PHONET_ROUTE RTNLGRP_PHONET_ROUTE + __RTNLGRP_MAX +}; +#define RTNLGRP_MAX (__RTNLGRP_MAX - 1) + +/* TC action piece */ +struct tcamsg { + unsigned char tca_family; + unsigned char tca__pad1; + unsigned short tca__pad2; +}; +#define TA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcamsg)))) +#define TA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcamsg)) +#define TCA_ACT_TAB 1 /* attr type must be >=1 */ +#define TCAA_MAX 1 + +/* End of information exported to user level */ + +#endif /* __LINUX_RTNETLINK_H */ diff --git a/include/linux/snmp.h b/include/linux/snmp.h new file mode 100644 index 0000000..12b2b18 --- /dev/null +++ b/include/linux/snmp.h @@ -0,0 +1,270 @@ +/* + * Definitions for MIBs + * + * Author: Hideaki YOSHIFUJI + */ + +#ifndef _LINUX_SNMP_H +#define _LINUX_SNMP_H + +/* ipstats mib definitions */ +/* + * RFC 1213: MIB-II + * RFC 2011 (updates 1213): SNMPv2-MIB-IP + * RFC 2863: Interfaces Group MIB + * RFC 2465: IPv6 MIB: General Group + * draft-ietf-ipv6-rfc2011-update-10.txt: MIB for IP: IP Statistics Tables + */ +enum +{ + IPSTATS_MIB_NUM = 0, + IPSTATS_MIB_INPKTS, /* InReceives */ + IPSTATS_MIB_INHDRERRORS, /* InHdrErrors */ + IPSTATS_MIB_INTOOBIGERRORS, /* InTooBigErrors */ + IPSTATS_MIB_INNOROUTES, /* InNoRoutes */ + IPSTATS_MIB_INADDRERRORS, /* InAddrErrors */ + IPSTATS_MIB_INUNKNOWNPROTOS, /* InUnknownProtos */ + IPSTATS_MIB_INTRUNCATEDPKTS, /* InTruncatedPkts */ + IPSTATS_MIB_INDISCARDS, /* InDiscards */ + IPSTATS_MIB_INDELIVERS, /* InDelivers */ + IPSTATS_MIB_OUTFORWDATAGRAMS, /* OutForwDatagrams */ + IPSTATS_MIB_OUTPKTS, /* OutRequests */ + IPSTATS_MIB_OUTDISCARDS, /* OutDiscards */ + IPSTATS_MIB_OUTNOROUTES, /* OutNoRoutes */ + IPSTATS_MIB_REASMTIMEOUT, /* ReasmTimeout */ + IPSTATS_MIB_REASMREQDS, /* ReasmReqds */ + IPSTATS_MIB_REASMOKS, /* ReasmOKs */ + IPSTATS_MIB_REASMFAILS, /* ReasmFails */ + IPSTATS_MIB_FRAGOKS, /* FragOKs */ + IPSTATS_MIB_FRAGFAILS, /* FragFails */ + IPSTATS_MIB_FRAGCREATES, /* FragCreates */ + IPSTATS_MIB_INMCASTPKTS, /* InMcastPkts */ + IPSTATS_MIB_OUTMCASTPKTS, /* OutMcastPkts */ + IPSTATS_MIB_INBCASTPKTS, /* InBcastPkts */ + IPSTATS_MIB_OUTBCASTPKTS, /* OutBcastPkts */ + IPSTATS_MIB_INOCTETS, /* InOctets */ + IPSTATS_MIB_OUTOCTETS, /* OutOctets */ + IPSTATS_MIB_INMCASTOCTETS, /* InMcastOctets */ + IPSTATS_MIB_OUTMCASTOCTETS, /* OutMcastOctets */ + IPSTATS_MIB_INBCASTOCTETS, /* InBcastOctets */ + IPSTATS_MIB_OUTBCASTOCTETS, /* OutBcastOctets */ + __IPSTATS_MIB_MAX +}; + +/* icmp mib definitions */ +/* + * RFC 1213: MIB-II ICMP Group + * RFC 2011 (updates 1213): SNMPv2 MIB for IP: ICMP group + */ +enum +{ + ICMP_MIB_NUM = 0, + ICMP_MIB_INMSGS, /* InMsgs */ + ICMP_MIB_INERRORS, /* InErrors */ + ICMP_MIB_INDESTUNREACHS, /* InDestUnreachs */ + ICMP_MIB_INTIMEEXCDS, /* InTimeExcds */ + ICMP_MIB_INPARMPROBS, /* InParmProbs */ + ICMP_MIB_INSRCQUENCHS, /* InSrcQuenchs */ + ICMP_MIB_INREDIRECTS, /* InRedirects */ + ICMP_MIB_INECHOS, /* InEchos */ + ICMP_MIB_INECHOREPS, /* InEchoReps */ + ICMP_MIB_INTIMESTAMPS, /* InTimestamps */ + ICMP_MIB_INTIMESTAMPREPS, /* InTimestampReps */ + ICMP_MIB_INADDRMASKS, /* InAddrMasks */ + ICMP_MIB_INADDRMASKREPS, /* InAddrMaskReps */ + ICMP_MIB_OUTMSGS, /* OutMsgs */ + ICMP_MIB_OUTERRORS, /* OutErrors */ + ICMP_MIB_OUTDESTUNREACHS, /* OutDestUnreachs */ + ICMP_MIB_OUTTIMEEXCDS, /* OutTimeExcds */ + ICMP_MIB_OUTPARMPROBS, /* OutParmProbs */ + ICMP_MIB_OUTSRCQUENCHS, /* OutSrcQuenchs */ + ICMP_MIB_OUTREDIRECTS, /* OutRedirects */ + ICMP_MIB_OUTECHOS, /* OutEchos */ + ICMP_MIB_OUTECHOREPS, /* OutEchoReps */ + ICMP_MIB_OUTTIMESTAMPS, /* OutTimestamps */ + ICMP_MIB_OUTTIMESTAMPREPS, /* OutTimestampReps */ + ICMP_MIB_OUTADDRMASKS, /* OutAddrMasks */ + ICMP_MIB_OUTADDRMASKREPS, /* OutAddrMaskReps */ + __ICMP_MIB_MAX +}; + +#define __ICMPMSG_MIB_MAX 512 /* Out+In for all 8-bit ICMP types */ + +/* icmp6 mib definitions */ +/* + * RFC 2466: ICMPv6-MIB + */ +enum +{ + ICMP6_MIB_NUM = 0, + ICMP6_MIB_INMSGS, /* InMsgs */ + ICMP6_MIB_INERRORS, /* InErrors */ + ICMP6_MIB_OUTMSGS, /* OutMsgs */ + ICMP6_MIB_OUTERRORS, /* OutErrors */ + __ICMP6_MIB_MAX +}; + +#define __ICMP6MSG_MIB_MAX 512 /* Out+In for all 8-bit ICMPv6 types */ + +/* tcp mib definitions */ +/* + * RFC 1213: MIB-II TCP group + * RFC 2012 (updates 1213): SNMPv2-MIB-TCP + */ +enum +{ + TCP_MIB_NUM = 0, + TCP_MIB_RTOALGORITHM, /* RtoAlgorithm */ + TCP_MIB_RTOMIN, /* RtoMin */ + TCP_MIB_RTOMAX, /* RtoMax */ + TCP_MIB_MAXCONN, /* MaxConn */ + TCP_MIB_ACTIVEOPENS, /* ActiveOpens */ + TCP_MIB_PASSIVEOPENS, /* PassiveOpens */ + TCP_MIB_ATTEMPTFAILS, /* AttemptFails */ + TCP_MIB_ESTABRESETS, /* EstabResets */ + TCP_MIB_CURRESTAB, /* CurrEstab */ + TCP_MIB_INSEGS, /* InSegs */ + TCP_MIB_OUTSEGS, /* OutSegs */ + TCP_MIB_RETRANSSEGS, /* RetransSegs */ + TCP_MIB_INERRS, /* InErrs */ + TCP_MIB_OUTRSTS, /* OutRsts */ + __TCP_MIB_MAX +}; + +/* udp mib definitions */ +/* + * RFC 1213: MIB-II UDP group + * RFC 2013 (updates 1213): SNMPv2-MIB-UDP + */ +enum +{ + UDP_MIB_NUM = 0, + UDP_MIB_INDATAGRAMS, /* InDatagrams */ + UDP_MIB_NOPORTS, /* NoPorts */ + UDP_MIB_INERRORS, /* InErrors */ + UDP_MIB_OUTDATAGRAMS, /* OutDatagrams */ + UDP_MIB_RCVBUFERRORS, /* RcvbufErrors */ + UDP_MIB_SNDBUFERRORS, /* SndbufErrors */ + __UDP_MIB_MAX +}; + +/* linux mib definitions */ +enum +{ + LINUX_MIB_NUM = 0, + LINUX_MIB_SYNCOOKIESSENT, /* SyncookiesSent */ + LINUX_MIB_SYNCOOKIESRECV, /* SyncookiesRecv */ + LINUX_MIB_SYNCOOKIESFAILED, /* SyncookiesFailed */ + LINUX_MIB_EMBRYONICRSTS, /* EmbryonicRsts */ + LINUX_MIB_PRUNECALLED, /* PruneCalled */ + LINUX_MIB_RCVPRUNED, /* RcvPruned */ + LINUX_MIB_OFOPRUNED, /* OfoPruned */ + LINUX_MIB_OUTOFWINDOWICMPS, /* OutOfWindowIcmps */ + LINUX_MIB_LOCKDROPPEDICMPS, /* LockDroppedIcmps */ + LINUX_MIB_ARPFILTER, /* ArpFilter */ + LINUX_MIB_TIMEWAITED, /* TimeWaited */ + LINUX_MIB_TIMEWAITRECYCLED, /* TimeWaitRecycled */ + LINUX_MIB_TIMEWAITKILLED, /* TimeWaitKilled */ + LINUX_MIB_PAWSPASSIVEREJECTED, /* PAWSPassiveRejected */ + LINUX_MIB_PAWSACTIVEREJECTED, /* PAWSActiveRejected */ + LINUX_MIB_PAWSESTABREJECTED, /* PAWSEstabRejected */ + LINUX_MIB_DELAYEDACKS, /* DelayedACKs */ + LINUX_MIB_DELAYEDACKLOCKED, /* DelayedACKLocked */ + LINUX_MIB_DELAYEDACKLOST, /* DelayedACKLost */ + LINUX_MIB_LISTENOVERFLOWS, /* ListenOverflows */ + LINUX_MIB_LISTENDROPS, /* ListenDrops */ + LINUX_MIB_TCPPREQUEUED, /* TCPPrequeued */ + LINUX_MIB_TCPDIRECTCOPYFROMBACKLOG, /* TCPDirectCopyFromBacklog */ + LINUX_MIB_TCPDIRECTCOPYFROMPREQUEUE, /* TCPDirectCopyFromPrequeue */ + LINUX_MIB_TCPPREQUEUEDROPPED, /* TCPPrequeueDropped */ + LINUX_MIB_TCPHPHITS, /* TCPHPHits */ + LINUX_MIB_TCPHPHITSTOUSER, /* TCPHPHitsToUser */ + LINUX_MIB_TCPPUREACKS, /* TCPPureAcks */ + LINUX_MIB_TCPHPACKS, /* TCPHPAcks */ + LINUX_MIB_TCPRENORECOVERY, /* TCPRenoRecovery */ + LINUX_MIB_TCPSACKRECOVERY, /* TCPSackRecovery */ + LINUX_MIB_TCPSACKRENEGING, /* TCPSACKReneging */ + LINUX_MIB_TCPFACKREORDER, /* TCPFACKReorder */ + LINUX_MIB_TCPSACKREORDER, /* TCPSACKReorder */ + LINUX_MIB_TCPRENOREORDER, /* TCPRenoReorder */ + LINUX_MIB_TCPTSREORDER, /* TCPTSReorder */ + LINUX_MIB_TCPFULLUNDO, /* TCPFullUndo */ + LINUX_MIB_TCPPARTIALUNDO, /* TCPPartialUndo */ + LINUX_MIB_TCPDSACKUNDO, /* TCPDSACKUndo */ + LINUX_MIB_TCPLOSSUNDO, /* TCPLossUndo */ + LINUX_MIB_TCPLOSS, /* TCPLoss */ + LINUX_MIB_TCPLOSTRETRANSMIT, /* TCPLostRetransmit */ + LINUX_MIB_TCPRENOFAILURES, /* TCPRenoFailures */ + LINUX_MIB_TCPSACKFAILURES, /* TCPSackFailures */ + LINUX_MIB_TCPLOSSFAILURES, /* TCPLossFailures */ + LINUX_MIB_TCPFASTRETRANS, /* TCPFastRetrans */ + LINUX_MIB_TCPFORWARDRETRANS, /* TCPForwardRetrans */ + LINUX_MIB_TCPSLOWSTARTRETRANS, /* TCPSlowStartRetrans */ + LINUX_MIB_TCPTIMEOUTS, /* TCPTimeouts */ + LINUX_MIB_TCPRENORECOVERYFAIL, /* TCPRenoRecoveryFail */ + LINUX_MIB_TCPSACKRECOVERYFAIL, /* TCPSackRecoveryFail */ + LINUX_MIB_TCPSCHEDULERFAILED, /* TCPSchedulerFailed */ + LINUX_MIB_TCPRCVCOLLAPSED, /* TCPRcvCollapsed */ + LINUX_MIB_TCPDSACKOLDSENT, /* TCPDSACKOldSent */ + LINUX_MIB_TCPDSACKOFOSENT, /* TCPDSACKOfoSent */ + LINUX_MIB_TCPDSACKRECV, /* TCPDSACKRecv */ + LINUX_MIB_TCPDSACKOFORECV, /* TCPDSACKOfoRecv */ + LINUX_MIB_TCPABORTONSYN, /* TCPAbortOnSyn */ + LINUX_MIB_TCPABORTONDATA, /* TCPAbortOnData */ + LINUX_MIB_TCPABORTONCLOSE, /* TCPAbortOnClose */ + LINUX_MIB_TCPABORTONMEMORY, /* TCPAbortOnMemory */ + LINUX_MIB_TCPABORTONTIMEOUT, /* TCPAbortOnTimeout */ + LINUX_MIB_TCPABORTONLINGER, /* TCPAbortOnLinger */ + LINUX_MIB_TCPABORTFAILED, /* TCPAbortFailed */ + LINUX_MIB_TCPMEMORYPRESSURES, /* TCPMemoryPressures */ + LINUX_MIB_TCPSACKDISCARD, /* TCPSACKDiscard */ + LINUX_MIB_TCPDSACKIGNOREDOLD, /* TCPSACKIgnoredOld */ + LINUX_MIB_TCPDSACKIGNOREDNOUNDO, /* TCPSACKIgnoredNoUndo */ + LINUX_MIB_TCPSPURIOUSRTOS, /* TCPSpuriousRTOs */ + LINUX_MIB_TCPMD5NOTFOUND, /* TCPMD5NotFound */ + LINUX_MIB_TCPMD5UNEXPECTED, /* TCPMD5Unexpected */ + LINUX_MIB_SACKSHIFTED, + LINUX_MIB_SACKMERGED, + LINUX_MIB_SACKSHIFTFALLBACK, + LINUX_MIB_TCPBACKLOGDROP, + LINUX_MIB_TCPMINTTLDROP, /* RFC 5082 */ + LINUX_MIB_TCPDEFERACCEPTDROP, + LINUX_MIB_IPRPFILTER, /* IP Reverse Path Filter (rp_filter) */ + LINUX_MIB_TCPTIMEWAITOVERFLOW, /* TCPTimeWaitOverflow */ + __LINUX_MIB_MAX +}; + +/* linux Xfrm mib definitions */ +enum +{ + LINUX_MIB_XFRMNUM = 0, + LINUX_MIB_XFRMINERROR, /* XfrmInError */ + LINUX_MIB_XFRMINBUFFERERROR, /* XfrmInBufferError */ + LINUX_MIB_XFRMINHDRERROR, /* XfrmInHdrError */ + LINUX_MIB_XFRMINNOSTATES, /* XfrmInNoStates */ + LINUX_MIB_XFRMINSTATEPROTOERROR, /* XfrmInStateProtoError */ + LINUX_MIB_XFRMINSTATEMODEERROR, /* XfrmInStateModeError */ + LINUX_MIB_XFRMINSTATESEQERROR, /* XfrmInStateSeqError */ + LINUX_MIB_XFRMINSTATEEXPIRED, /* XfrmInStateExpired */ + LINUX_MIB_XFRMINSTATEMISMATCH, /* XfrmInStateMismatch */ + LINUX_MIB_XFRMINSTATEINVALID, /* XfrmInStateInvalid */ + LINUX_MIB_XFRMINTMPLMISMATCH, /* XfrmInTmplMismatch */ + LINUX_MIB_XFRMINNOPOLS, /* XfrmInNoPols */ + LINUX_MIB_XFRMINPOLBLOCK, /* XfrmInPolBlock */ + LINUX_MIB_XFRMINPOLERROR, /* XfrmInPolError */ + LINUX_MIB_XFRMOUTERROR, /* XfrmOutError */ + LINUX_MIB_XFRMOUTBUNDLEGENERROR, /* XfrmOutBundleGenError */ + LINUX_MIB_XFRMOUTBUNDLECHECKERROR, /* XfrmOutBundleCheckError */ + LINUX_MIB_XFRMOUTNOSTATES, /* XfrmOutNoStates */ + LINUX_MIB_XFRMOUTSTATEPROTOERROR, /* XfrmOutStateProtoError */ + LINUX_MIB_XFRMOUTSTATEMODEERROR, /* XfrmOutStateModeError */ + LINUX_MIB_XFRMOUTSTATESEQERROR, /* XfrmOutStateSeqError */ + LINUX_MIB_XFRMOUTSTATEEXPIRED, /* XfrmOutStateExpired */ + LINUX_MIB_XFRMOUTPOLBLOCK, /* XfrmOutPolBlock */ + LINUX_MIB_XFRMOUTPOLDEAD, /* XfrmOutPolDead */ + LINUX_MIB_XFRMOUTPOLERROR, /* XfrmOutPolError */ + LINUX_MIB_XFRMFWDHDRERROR, /* XfrmFwdHdrError*/ + __LINUX_MIB_XFRMMAX +}; + +#endif /* _LINUX_SNMP_H */ diff --git a/include/linux/tc_ematch/tc_em_meta.h b/include/linux/tc_ematch/tc_em_meta.h new file mode 100644 index 0000000..fe815e2 --- /dev/null +++ b/include/linux/tc_ematch/tc_em_meta.h @@ -0,0 +1,89 @@ +#ifndef __LINUX_TC_EM_META_H +#define __LINUX_TC_EM_META_H + +enum { + TCA_EM_META_UNSPEC, + TCA_EM_META_HDR, + TCA_EM_META_LVALUE, + TCA_EM_META_RVALUE, + __TCA_EM_META_MAX +}; +#define TCA_EM_META_MAX (__TCA_EM_META_MAX - 1) + +struct tcf_meta_val { + __u16 kind; + __u8 shift; + __u8 op; +}; + +#define TCF_META_TYPE_MASK (0xf << 12) +#define TCF_META_TYPE(kind) (((kind) & TCF_META_TYPE_MASK) >> 12) +#define TCF_META_ID_MASK 0x7ff +#define TCF_META_ID(kind) ((kind) & TCF_META_ID_MASK) + +enum { + TCF_META_TYPE_VAR, + TCF_META_TYPE_INT, + __TCF_META_TYPE_MAX +}; +#define TCF_META_TYPE_MAX (__TCF_META_TYPE_MAX - 1) + +enum { + TCF_META_ID_VALUE, + TCF_META_ID_RANDOM, + TCF_META_ID_LOADAVG_0, + TCF_META_ID_LOADAVG_1, + TCF_META_ID_LOADAVG_2, + TCF_META_ID_DEV, + TCF_META_ID_PRIORITY, + TCF_META_ID_PROTOCOL, + TCF_META_ID_PKTTYPE, + TCF_META_ID_PKTLEN, + TCF_META_ID_DATALEN, + TCF_META_ID_MACLEN, + TCF_META_ID_NFMARK, + TCF_META_ID_TCINDEX, + TCF_META_ID_RTCLASSID, + TCF_META_ID_RTIIF, + TCF_META_ID_SK_FAMILY, + TCF_META_ID_SK_STATE, + TCF_META_ID_SK_REUSE, + TCF_META_ID_SK_BOUND_IF, + TCF_META_ID_SK_REFCNT, + TCF_META_ID_SK_SHUTDOWN, + TCF_META_ID_SK_PROTO, + TCF_META_ID_SK_TYPE, + TCF_META_ID_SK_RCVBUF, + TCF_META_ID_SK_RMEM_ALLOC, + TCF_META_ID_SK_WMEM_ALLOC, + TCF_META_ID_SK_OMEM_ALLOC, + TCF_META_ID_SK_WMEM_QUEUED, + TCF_META_ID_SK_RCV_QLEN, + TCF_META_ID_SK_SND_QLEN, + TCF_META_ID_SK_ERR_QLEN, + TCF_META_ID_SK_FORWARD_ALLOCS, + TCF_META_ID_SK_SNDBUF, + TCF_META_ID_SK_ALLOCS, + TCF_META_ID_SK_ROUTE_CAPS, + TCF_META_ID_SK_HASH, + TCF_META_ID_SK_LINGERTIME, + TCF_META_ID_SK_ACK_BACKLOG, + TCF_META_ID_SK_MAX_ACK_BACKLOG, + TCF_META_ID_SK_PRIO, + TCF_META_ID_SK_RCVLOWAT, + TCF_META_ID_SK_RCVTIMEO, + TCF_META_ID_SK_SNDTIMEO, + TCF_META_ID_SK_SENDMSG_OFF, + TCF_META_ID_SK_WRITE_PENDING, + TCF_META_ID_VLAN_TAG, + TCF_META_ID_RXHASH, + __TCF_META_ID_MAX +}; +#define TCF_META_ID_MAX (__TCF_META_ID_MAX - 1) + +struct tcf_meta_hdr { + struct tcf_meta_val left; + struct tcf_meta_val right; +}; + +#endif diff --git a/include/netlink-private/cache-api.h b/include/netlink-private/cache-api.h new file mode 100644 index 0000000..f3d9f01 --- /dev/null +++ b/include/netlink-private/cache-api.h @@ -0,0 +1,270 @@ +/* + * netlink-private/cache-api.h Caching API + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2013 Thomas Graf + */ + +#ifndef NETLINK_CACHE_API_H_ +#define NETLINK_CACHE_API_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @ingroup cache + * @defgroup cache_api Cache Implementation + * @brief + * + * @par 1) Cache Definition + * @code + * struct nl_cache_ops my_cache_ops = { + * .co_name = "route/link", + * .co_protocol = NETLINK_ROUTE, + * .co_hdrsize = sizeof(struct ifinfomsg), + * .co_obj_ops = &my_obj_ops, + * }; + * @endcode + * + * @par 2) + * @code + * // The simplest way to fill a cache is by providing a request-update + * // function which must trigger a complete dump on the kernel-side of + * // whatever the cache covers. + * static int my_request_update(struct nl_cache *cache, + * struct nl_sock *socket) + * { + * // In this example, we request a full dump of the interface table + * return nl_rtgen_request(socket, RTM_GETLINK, AF_UNSPEC, NLM_F_DUMP); + * } + * + * // The resulting netlink messages sent back will be fed into a message + * // parser one at a time. The message parser has to extract all relevant + * // information from the message and create an object reflecting the + * // contents of the message and pass it on to the parser callback function + * // provide which will add the object to the cache. + * static int my_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + * struct nlmsghdr *nlh, struct nl_parser_param *pp) + * { + * struct my_obj *obj; + * + * obj = my_obj_alloc(); + * obj->ce_msgtype = nlh->nlmsg_type; + * + * // Parse the netlink message and continue creating the object. + * + * err = pp->pp_cb((struct nl_object *) obj, pp); + * if (err < 0) + * goto errout; + * } + * + * struct nl_cache_ops my_cache_ops = { + * ... + * .co_request_update = my_request_update, + * .co_msg_parser = my_msg_parser, + * }; + * @endcode + * + * @par 3) Notification based Updates + * @code + * // Caches can be kept up-to-date based on notifications if the kernel + * // sends out notifications whenever an object is added/removed/changed. + * // + * // It is trivial to support this, first a list of groups needs to be + * // defined which are required to join in order to receive all necessary + * // notifications. The groups are separated by address family to support + * // the common situation where a separate group is used for each address + * // family. If there is only one group, simply specify AF_UNSPEC. + * static struct nl_af_group addr_groups[] = { + * { AF_INET, RTNLGRP_IPV4_IFADDR }, + * { AF_INET6, RTNLGRP_IPV6_IFADDR }, + * { END_OF_GROUP_LIST }, + * }; + * + * // In order for the caching system to know the meaning of each message + * // type it requires a table which maps each supported message type to + * // a cache action, e.g. RTM_NEWADDR means address has been added or + * // updated, RTM_DELADDR means address has been removed. + * static struct nl_cache_ops rtnl_addr_ops = { + * ... + * .co_msgtypes = { + * { RTM_NEWADDR, NL_ACT_NEW, "new" }, + * { RTM_DELADDR, NL_ACT_DEL, "del" }, + * { RTM_GETADDR, NL_ACT_GET, "get" }, + * END_OF_MSGTYPES_LIST, + * }, + * .co_groups = addr_groups, + * }; + * + * // It is now possible to keep the cache up-to-date using the cache manager. + * @endcode + * @{ + */ + +#define END_OF_MSGTYPES_LIST { -1, -1, NULL } + +/** + * Message type to cache action association + */ +struct nl_msgtype +{ + /** Netlink message type */ + int mt_id; + + /** Cache action to take */ + int mt_act; + + /** Name of operation for human-readable printing */ + char * mt_name; +}; + +/** + * Address family to netlink group association + */ +struct nl_af_group +{ + /** Address family */ + int ag_family; + + /** Netlink group identifier */ + int ag_group; +}; + +#define END_OF_GROUP_LIST AF_UNSPEC, 0 + +/** + * Parser parameters + * + * This structure is used to configure what kind of parser to use + * when parsing netlink messages to create objects. + */ +struct nl_parser_param +{ + /** Function to parse netlink messages into objects */ + int (*pp_cb)(struct nl_object *, struct nl_parser_param *); + + /** Arbitary argument to be passed to the parser */ + void * pp_arg; +}; + +/** + * Cache Operations + * + * This structure defines the characterstics of a cache type. It contains + * pointers to functions which implement the specifics of the object type + * the cache can hold. + */ +struct nl_cache_ops +{ + /** Name of cache type (must be unique) */ + char * co_name; + + /** Size of family specific netlink header */ + int co_hdrsize; + + /** Netlink protocol */ + int co_protocol; + + /** cache object hash size **/ + int co_hash_size; + + /** cache flags */ + unsigned int co_flags; + + /** Reference counter */ + unsigned int co_refcnt; + + /** Group definition */ + struct nl_af_group * co_groups; + + /** + * Called whenever an update of the cache is required. Must send + * a request message to the kernel requesting a complete dump. + */ + int (*co_request_update)(struct nl_cache *, struct nl_sock *); + + /** + * Called whenever a message was received that needs to be parsed. + * Must parse the message and call the paser callback function + * (nl_parser_param) provided via the argument. + */ + int (*co_msg_parser)(struct nl_cache_ops *, struct sockaddr_nl *, + struct nlmsghdr *, struct nl_parser_param *); + + /** + * The function registered under this callback is called after a + * netlink notification associated with this cache type has been + * parsed into an object and is being considered for inclusio into + * the specified cache. + * + * The purpose of this function is to filter out notifications + * which should be ignored when updating caches. + * + * The function must return NL_SKIP to prevent the object from + * being included, or NL_OK to include it. + * + * @code + * int my_filter(struct nl_cache *cache, struct nl_object *obj) + * { + * if (reason_to_not_include_obj(obj)) + * return NL_SKIP; + * + * return NL_OK; + * } + * @endcode + */ + int (*co_event_filter)(struct nl_cache *, struct nl_object *obj); + + /** + * The function registered under this callback is called when an + * object formed from a notification event needs to be included in + * a cache. + * + * For each modified object, the change callback \c change_cb must + * be called with the \c data argument provided. + * + * If no function is registered, the function nl_cache_include() + * will be used for this purpose. + * + * @see nl_cache_include() + */ + int (*co_include_event)(struct nl_cache *cache, struct nl_object *obj, + change_func_t change_cb, void *data); + + void (*reserved_1)(void); + void (*reserved_2)(void); + void (*reserved_3)(void); + void (*reserved_4)(void); + void (*reserved_5)(void); + void (*reserved_6)(void); + void (*reserved_7)(void); + void (*reserved_8)(void); + + /** Object operations */ + struct nl_object_ops * co_obj_ops; + + /** Internal, do not touch! */ + struct nl_cache_ops *co_next; + + struct nl_cache *co_major_cache; + struct genl_ops * co_genl; + + /* Message type definition */ + struct nl_msgtype co_msgtypes[]; +}; + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink-private/genl.h b/include/netlink-private/genl.h new file mode 100644 index 0000000..5b93db3 --- /dev/null +++ b/include/netlink-private/genl.h @@ -0,0 +1,22 @@ +/* + * netlink-private/genl.h Local Generic Netlink Interface + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2013 Thomas Graf + */ + +#ifndef NETLINK_GENL_PRIV_H_ +#define NETLINK_GENL_PRIV_H_ + +#include +#include + +#define GENL_HDRSIZE(hdrlen) (GENL_HDRLEN + (hdrlen)) + +extern int genl_resolve_id(struct genl_ops *ops); + +#endif diff --git a/include/netlink-private/netlink.h b/include/netlink-private/netlink.h new file mode 100644 index 0000000..2e511bf --- /dev/null +++ b/include/netlink-private/netlink.h @@ -0,0 +1,262 @@ +/* + * netlink-private/netlink.h Local Netlink Interface + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2013 Thomas Graf + */ + +#ifndef NETLINK_LOCAL_H_ +#define NETLINK_LOCAL_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#ifndef SOL_NETLINK +#define SOL_NETLINK 270 +#endif + +#include + +/* local header copies */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef DISABLE_PTHREADS +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +struct trans_tbl { + int i; + const char *a; +}; + +#define __ADD(id, name) { .i = id, .a = #name }, + +struct trans_list { + int i; + char *a; + struct nl_list_head list; +}; + +#ifdef NL_DEBUG +#define NL_DBG(LVL,FMT,ARG...) \ + do { \ + if (LVL <= nl_debug) \ + fprintf(stderr, \ + "DBG<" #LVL ">%20s:%-4u %s: " FMT, \ + __FILE__, __LINE__, \ + __PRETTY_FUNCTION__, ##ARG); \ + } while (0) +#else /* NL_DEBUG */ +#define NL_DBG(LVL,FMT,ARG...) do { } while(0) +#endif /* NL_DEBUG */ + +#define BUG() \ + do { \ + fprintf(stderr, "BUG at file position %s:%d:%s\n", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__); \ + assert(0); \ + } while (0) + +#define APPBUG(msg) \ + do { \ + fprintf(stderr, "APPLICATION BUG: %s:%d:%s: %s\n", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, msg); \ + assert(0); \ + } while(0) + +extern int __nl_read_num_str_file(const char *path, + int (*cb)(long, const char *)); + +extern int __trans_list_add(int, const char *, struct nl_list_head *); +extern void __trans_list_clear(struct nl_list_head *); + +extern char *__type2str(int, char *, size_t, const struct trans_tbl *, size_t); +extern int __str2type(const char *, const struct trans_tbl *, size_t); + +extern char *__list_type2str(int, char *, size_t, struct nl_list_head *); +extern int __list_str2type(const char *, struct nl_list_head *); + +extern char *__flags2str(int, char *, size_t, const struct trans_tbl *, size_t); +extern int __str2flags(const char *, const struct trans_tbl *, size_t); + +extern void dump_from_ops(struct nl_object *, struct nl_dump_params *); + +static inline int nl_cb_call(struct nl_cb *cb, int type, struct nl_msg *msg) +{ + return cb->cb_set[type](msg, cb->cb_args[type]); +} + +#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0])) + +/* This is also defined in stddef.h */ +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +#define __init __attribute__ ((constructor)) +#define __exit __attribute__ ((destructor)) +#undef __deprecated +#define __deprecated __attribute__ ((deprecated)) + +#define min(x,y) ({ \ + typeof(x) _x = (x); \ + typeof(y) _y = (y); \ + (void) (&_x == &_y); \ + _x < _y ? _x : _y; }) + +#define max(x,y) ({ \ + typeof(x) _x = (x); \ + typeof(y) _y = (y); \ + (void) (&_x == &_y); \ + _x > _y ? _x : _y; }) + +#define min_t(type,x,y) \ + ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) +#define max_t(type,x,y) \ + ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) + +extern int nl_cache_parse(struct nl_cache_ops *, struct sockaddr_nl *, + struct nlmsghdr *, struct nl_parser_param *); + + +static inline void rtnl_copy_ratespec(struct rtnl_ratespec *dst, + struct tc_ratespec *src) +{ + dst->rs_cell_log = src->cell_log; + dst->rs_overhead = src->overhead; + dst->rs_cell_align = src->cell_align; + dst->rs_mpu = src->mpu; + dst->rs_rate = src->rate; +} + +static inline void rtnl_rcopy_ratespec(struct tc_ratespec *dst, + struct rtnl_ratespec *src) +{ + dst->cell_log = src->rs_cell_log; + dst->overhead = src->rs_overhead; + dst->cell_align = src->rs_cell_align; + dst->mpu = src->rs_mpu; + dst->rate = src->rs_rate; +} + +static inline char *nl_cache_name(struct nl_cache *cache) +{ + return cache->c_ops ? cache->c_ops->co_name : "unknown"; +} + +#define GENL_FAMILY(id, name) \ + { \ + { id, NL_ACT_UNSPEC, name }, \ + END_OF_MSGTYPES_LIST, \ + } + +static inline int wait_for_ack(struct nl_sock *sk) +{ + if (sk->s_flags & NL_NO_AUTO_ACK) + return 0; + else + return nl_wait_for_ack(sk); +} + +static inline int build_sysconf_path(char **strp, const char *filename) +{ + char *sysconfdir; + + sysconfdir = getenv("NLSYSCONFDIR"); + + if (!sysconfdir) + sysconfdir = SYSCONFDIR; + + return asprintf(strp, "%s/%s", sysconfdir, filename); +} + +#ifndef DISABLE_PTHREADS +#define NL_LOCK(NAME) pthread_mutex_t (NAME) = PTHREAD_MUTEX_INITIALIZER +#define NL_RW_LOCK(NAME) pthread_rwlock_t (NAME) = PTHREAD_RWLOCK_INITIALIZER + +static inline void nl_lock(pthread_mutex_t *lock) +{ + pthread_mutex_lock(lock); +} + +static inline void nl_unlock(pthread_mutex_t *lock) +{ + pthread_mutex_unlock(lock); +} + +static inline void nl_read_lock(pthread_rwlock_t *lock) +{ + pthread_rwlock_rdlock(lock); +} + +static inline void nl_read_unlock(pthread_rwlock_t *lock) +{ + pthread_rwlock_unlock(lock); +} + +static inline void nl_write_lock(pthread_rwlock_t *lock) +{ + pthread_rwlock_wrlock(lock); +} + +static inline void nl_write_unlock(pthread_rwlock_t *lock) +{ + pthread_rwlock_unlock(lock); +} + +#else +#define NL_LOCK(NAME) int __unused_lock_ ##NAME __attribute__((unused)) +#define NL_RW_LOCK(NAME) int __unused_lock_ ##NAME __attribute__((unused)) + +#define nl_lock(LOCK) do { } while(0) +#define nl_unlock(LOCK) do { } while(0) +#define nl_read_lock(LOCK) do { } while(0) +#define nl_read_unlock(LOCK) do { } while(0) +#define nl_write_lock(LOCK) do { } while(0) +#define nl_write_unlock(LOCK) do { } while(0) +#endif + +#endif diff --git a/include/netlink-private/object-api.h b/include/netlink-private/object-api.h new file mode 100644 index 0000000..f4fd71e --- /dev/null +++ b/include/netlink-private/object-api.h @@ -0,0 +1,376 @@ +/* + * netlink-private/object-api.c Object API + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2013 Thomas Graf + */ + +#ifndef NETLINK_OBJECT_API_H_ +#define NETLINK_OBJECT_API_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @ingroup object + * @defgroup object_api Object API + * @brief + * + * @par 1) Object Definition + * @code + * // Define your object starting with the common object header + * struct my_obj { + * NLHDR_COMMON + * int my_data; + * }; + * + * // Fill out the object operations structure + * struct nl_object_ops my_ops = { + * .oo_name = "my_obj", + * .oo_size = sizeof(struct my_obj), + * }; + * + * // At this point the object can be allocated, you may want to provide a + * // separate _alloc() function to ease allocting objects of this kind. + * struct nl_object *obj = nl_object_alloc(&my_ops); + * + * // And release it again... + * nl_object_put(obj); + * @endcode + * + * @par 2) Allocating additional data + * @code + * // You may require to allocate additional data and store it inside + * // object, f.e. assuming there is a field `ptr'. + * struct my_obj { + * NLHDR_COMMON + * void * ptr; + * }; + * + * // And at some point you may assign allocated data to this field: + * my_obj->ptr = calloc(1, ...); + * + * // In order to not introduce any memory leaks you have to release + * // this data again when the last reference is given back. + * static void my_obj_free_data(struct nl_object *obj) + * { + * struct my_obj *my_obj = nl_object_priv(obj); + * + * free(my_obj->ptr); + * } + * + * // Also when the object is cloned, you must ensure for your pointer + * // stay valid even if one of the clones is freed by either making + * // a clone as well or increase the reference count. + * static int my_obj_clone(struct nl_object *src, struct nl_object *dst) + * { + * struct my_obj *my_src = nl_object_priv(src); + * struct my_obj *my_dst = nl_object_priv(dst); + * + * if (src->ptr) { + * dst->ptr = calloc(1, ...); + * memcpy(dst->ptr, src->ptr, ...); + * } + * } + * + * struct nl_object_ops my_ops = { + * ... + * .oo_free_data = my_obj_free_data, + * .oo_clone = my_obj_clone, + * }; + * @endcode + * + * @par 3) Object Dumping + * @code + * static int my_obj_dump_detailed(struct nl_object *obj, + * struct nl_dump_params *params) + * { + * struct my_obj *my_obj = nl_object_priv(obj); + * + * // It is absolutely essential to use nl_dump() when printing + * // any text to make sure the dumping parameters are respected. + * nl_dump(params, "Obj Integer: %d\n", my_obj->my_int); + * + * // Before we can dump the next line, make sure to prefix + * // this line correctly. + * nl_new_line(params); + * + * // You may also split a line into multiple nl_dump() calls. + * nl_dump(params, "String: %s ", my_obj->my_string); + * nl_dump(params, "String-2: %s\n", my_obj->another_string); + * } + * + * struct nl_object_ops my_ops = { + * ... + * .oo_dump[NL_DUMP_FULL] = my_obj_dump_detailed, + * }; + * @endcode + * + * @par 4) Object Attributes + * @code + * // The concept of object attributes is optional but can ease the typical + * // case of objects that have optional attributes, e.g. a route may have a + * // nexthop assigned but it is not required to. + * + * // The first step to define your object specific bitmask listing all + * // attributes + * #define MY_ATTR_FOO (1<<0) + * #define MY_ATTR_BAR (1<<1) + * + * // When assigning an optional attribute to the object, make sure + * // to mark its availability. + * my_obj->foo = 123123; + * my_obj->ce_mask |= MY_ATTR_FOO; + * + * // At any time you may use this mask to check for the availability + * // of the attribute, e.g. while dumping + * if (my_obj->ce_mask & MY_ATTR_FOO) + * nl_dump(params, "foo %d ", my_obj->foo); + * + * // One of the big advantages of this concept is that it allows for + * // standardized comparisons which make it trivial for caches to + * // identify unique objects by use of unified comparison functions. + * // In order for it to work, your object implementation must provide + * // a comparison function and define a list of attributes which + * // combined together make an object unique. + * + * static int my_obj_compare(struct nl_object *_a, struct nl_object *_b, + * uint32_t attrs, int flags) + * { + * struct my_obj *a = nl_object_priv(_a): + * struct my_obj *b = nl_object_priv(_b): + * int diff = 0; + * + * // We help ourselves in defining our own DIFF macro which will + * // call ATTR_DIFF() on both objects which will make sure to only + * // compare the attributes if required. + * #define MY_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MY_ATTR_##ATTR, a, b, EXPR) + * + * // Call our own diff macro for each attribute to build a bitmask + * // representing the attributes which mismatch. + * diff |= MY_DIFF(FOO, a->foo != b->foo) + * diff |= MY_DIFF(BAR, strcmp(a->bar, b->bar)) + * + * return diff; + * } + * + * // In order to identify identical objects with differing attributes + * // you must specify the attributes required to uniquely identify + * // your object. Make sure to not include too many attributes, this + * // list is used when caches look for an old version of an object. + * struct nl_object_ops my_ops = { + * ... + * .oo_id_attrs = MY_ATTR_FOO, + * .oo_compare = my_obj_compare, + * }; + * @endcode + * @{ + */ + +/** + * Common Object Header + * + * This macro must be included as first member in every object + * definition to allow objects to be cached. + */ +#define NLHDR_COMMON \ + int ce_refcnt; \ + struct nl_object_ops * ce_ops; \ + struct nl_cache * ce_cache; \ + struct nl_list_head ce_list; \ + int ce_msgtype; \ + int ce_flags; \ + uint32_t ce_mask; + +struct nl_object +{ + NLHDR_COMMON +}; + + +/** + * Return true if attribute is available in both objects + * @arg A an object + * @arg B another object + * @arg ATTR attribute bit + * + * @return True if the attribute is available, otherwise false is returned. + */ +#define AVAILABLE(A, B, ATTR) (((A)->ce_mask & (B)->ce_mask) & (ATTR)) + +/** + * Return true if attribute is available in only one of both objects + * @arg A an object + * @arg B another object + * @arg ATTR attribute bit + * + * @return True if the attribute is available in only one of both objects, + * otherwise false is returned. + */ +#define AVAILABLE_MISMATCH(A, B, ATTR) (((A)->ce_mask ^ (B)->ce_mask) & (ATTR)) + +/** + * Return true if attributes mismatch + * @arg A an object + * @arg B another object + * @arg ATTR attribute bit + * @arg EXPR Comparison expression + * + * This function will check if the attribute in question is available + * in both objects, if not this will count as a mismatch. + * + * If available the function will execute the expression which must + * return true if the attributes mismatch. + * + * @return True if the attribute mismatch, or false if they match. + */ +#define ATTR_MISMATCH(A, B, ATTR, EXPR) (AVAILABLE_MISMATCH(A, B, ATTR) || \ + (AVAILABLE(A, B, ATTR) && (EXPR))) + +/** + * Return attribute bit if attribute does not match + * @arg LIST list of attributes to be compared + * @arg ATTR attribute bit + * @arg A an object + * @arg B another object + * @arg EXPR Comparison expression + * + * This function will check if the attribute in question is available + * in both objects, if not this will count as a mismatch. + * + * If available the function will execute the expression which must + * return true if the attributes mismatch. + * + * In case the attributes mismatch, the attribute is returned, otherwise + * 0 is returned. + * + * @code + * diff |= ATTR_DIFF(attrs, MY_ATTR_FOO, a, b, a->foo != b->foo); + * @endcode + */ +#define ATTR_DIFF(LIST, ATTR, A, B, EXPR) \ +({ int diff = 0; \ + if (((LIST) & (ATTR)) && ATTR_MISMATCH(A, B, ATTR, EXPR)) \ + diff = ATTR; \ + diff; }) + +/** + * Object Operations + */ +struct nl_object_ops +{ + /** + * Unique name of object type + * + * Must be in the form family/name, e.g. "route/addr" + */ + char * oo_name; + + /** Size of object including its header */ + size_t oo_size; + + /* List of attributes needed to uniquely identify the object */ + uint32_t oo_id_attrs; + + /** + * Constructor function + * + * Will be called when a new object of this type is allocated. + * Can be used to initialize members such as lists etc. + */ + void (*oo_constructor)(struct nl_object *); + + /** + * Destructor function + * + * Will be called when an object is freed. Must free all + * resources which may have been allocated as part of this + * object. + */ + void (*oo_free_data)(struct nl_object *); + + /** + * Cloning function + * + * Will be called when an object needs to be cloned. Please + * note that the generic object code will make an exact + * copy of the object first, therefore you only need to take + * care of members which require reference counting etc. + * + * May return a negative error code to abort cloning. + */ + int (*oo_clone)(struct nl_object *, struct nl_object *); + + /** + * Dumping functions + * + * Will be called when an object is dumped. The implementations + * have to use nl_dump(), nl_dump_line(), and nl_new_line() to + * dump objects. + * + * The functions must return the number of lines printed. + */ + void (*oo_dump[NL_DUMP_MAX+1])(struct nl_object *, + struct nl_dump_params *); + + /** + * Comparison function + * + * Will be called when two objects of the same type are + * compared. It takes the two objects in question, an object + * specific bitmask defining which attributes should be + * compared and flags to control the behaviour. + * + * The function must return a bitmask with the relevant bit + * set for each attribute that mismatches. + */ + int (*oo_compare)(struct nl_object *, struct nl_object *, + uint32_t, int); + + + /** + * update function + * + * Will be called when the object given by first argument + * needs to be updated with the contents of the second object + * + * The function must return 0 for success and error for failure + * to update. In case of failure its assumed that the original + * object is not touched + */ + int (*oo_update)(struct nl_object *, struct nl_object *); + + /** + * Hash Key generator function + * + * When called returns a hash key for the object being + * referenced. This key will be used by higher level hash functions + * to build association lists. Each object type gets to specify + * it's own key formulation + */ + void (*oo_keygen)(struct nl_object *, uint32_t *, uint32_t); + + char *(*oo_attrs2str)(int, char *, size_t); + + /** + * Get key attributes by family function + */ + uint32_t (*oo_id_attrs_get)(struct nl_object *); +}; + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink-private/route/link/api.h b/include/netlink-private/route/link/api.h new file mode 100644 index 0000000..bb98ccc --- /dev/null +++ b/include/netlink-private/route/link/api.h @@ -0,0 +1,153 @@ +/* + * netlink-private/route/link/api.h Link Modules API + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2013 Thomas Graf + */ + +#ifndef NETLINK_LINK_API_H_ +#define NETLINK_LINK_API_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @ingroup link_api + * + * Available operations to modules implementing a link info type. + */ +struct rtnl_link_info_ops +{ + /** Name of link info type, must match name on kernel side */ + char * io_name; + + /** Reference count, DO NOT MODIFY */ + int io_refcnt; + + /** Called to assign an info type to a link. + * Has to allocate enough resources to hold attributes. Can + * use link->l_info to store a pointer. */ + int (*io_alloc)(struct rtnl_link *); + + /** Called to parse the link info attribute. + * Must parse the attribute and assign all values to the link. + */ + int (*io_parse)(struct rtnl_link *, + struct nlattr *, + struct nlattr *); + + /** Called when the link object is dumped. + * Must dump the info type specific attributes. */ + void (*io_dump[NL_DUMP_MAX+1])(struct rtnl_link *, + struct nl_dump_params *); + + /** Called when a link object is cloned. + * Must clone all info type specific attributes. */ + int (*io_clone)(struct rtnl_link *, struct rtnl_link *); + + /** Called when construction a link netlink message. + * Must append all info type specific attributes to the message. */ + int (*io_put_attrs)(struct nl_msg *, struct rtnl_link *); + + /** Called to release all resources previously allocated + * in either io_alloc() or io_parse(). */ + void (*io_free)(struct rtnl_link *); + + struct nl_list_head io_list; +}; + +extern struct rtnl_link_info_ops *rtnl_link_info_ops_lookup(const char *); +extern void rtnl_link_info_ops_put(struct rtnl_link_info_ops *); +extern int rtnl_link_register_info(struct rtnl_link_info_ops *); +extern int rtnl_link_unregister_info(struct rtnl_link_info_ops *); + + +/** + * @ingroup link_api + * + * Available operations to modules implementing a link address family. + */ +struct rtnl_link_af_ops +{ + /** The address family this operations set implements */ + const unsigned int ao_family; + + /** Number of users of this operations, DO NOT MODIFY. */ + int ao_refcnt; + + /** Validation policy for IFLA_PROTINFO attribute. This pointer + * can be set to a nla_policy structure describing the minimal + * requirements the attribute must meet. Failure of meeting these + * requirements will result in a parsing error. */ + const struct nla_policy *ao_protinfo_policy; + + /** Called after address family has been assigned to link. Must + * allocate data buffer to hold address family specific data and + * store it in link->l_af_data. */ + void * (*ao_alloc)(struct rtnl_link *); + + /** Called when the link is cloned, must allocate a clone of the + * address family specific buffer and return it. */ + void * (*ao_clone)(struct rtnl_link *, void *); + + /** Called when the link gets freed. Must free all allocated data */ + void (*ao_free)(struct rtnl_link *, void *); + + /** Called if a IFLA_PROTINFO attribute needs to be parsed. Typically + * stores the parsed data in the address family specific buffer. */ + int (*ao_parse_protinfo)(struct rtnl_link *, + struct nlattr *, void *); + + /** Called if a IFLA_AF_SPEC attribute needs to be parsed. Typically + * stores the parsed data in the address family specific buffer. */ + int (*ao_parse_af)(struct rtnl_link *, + struct nlattr *, void *); + + /** Called if a link message is sent to the kernel. Must append the + * link address family specific attributes to the message. */ + int (*ao_fill_af)(struct rtnl_link *, + struct nl_msg *msg, void *); + + /** Dump address family specific link attributes */ + void (*ao_dump[NL_DUMP_MAX+1])(struct rtnl_link *, + struct nl_dump_params *, + void *); + + /** Comparison function + * + * Will be called when two links are compared for their af data. It + * takes two link objects in question, an object specific bitmask + * defining which attributes should be compared and flags to control + * the behaviour + * + * The function must return a bitmask with the relevant bit set for + * each attribute that mismatches + */ + int (*ao_compare)(struct rtnl_link *, + struct rtnl_link *, int, uint32_t, int); +}; + +extern struct rtnl_link_af_ops *rtnl_link_af_ops_lookup(unsigned int); +extern void rtnl_link_af_ops_put(struct rtnl_link_af_ops *); +extern void * rtnl_link_af_alloc(struct rtnl_link *, + const struct rtnl_link_af_ops *); +extern void * rtnl_link_af_data(const struct rtnl_link *, + const struct rtnl_link_af_ops *); +extern int rtnl_link_af_register(struct rtnl_link_af_ops *); +extern int rtnl_link_af_unregister(struct rtnl_link_af_ops *); +extern int rtnl_link_af_data_compare(struct rtnl_link *a, + struct rtnl_link *b, + int family); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink-private/route/tc-api.h b/include/netlink-private/route/tc-api.h new file mode 100644 index 0000000..bf0c8a3 --- /dev/null +++ b/include/netlink-private/route/tc-api.h @@ -0,0 +1,134 @@ +/* + * netlink-private/route/tc-api.h Traffic Control API + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2011-2013 Thomas Graf + */ + +#ifndef NETLINK_TC_API_H_ +#define NETLINK_TC_API_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Traffic control object operations + * @ingroup tc + * + * This structure holds function pointers and settings implementing + * the features of each traffic control object implementation. + */ +struct rtnl_tc_ops +{ + /** + * Name of traffic control module + */ + char *to_kind; + + /** + * Type of traffic control object + */ + enum rtnl_tc_type to_type; + + + /** + * Size of private data + */ + size_t to_size; + + /** + * Dump callbacks + */ + void (*to_dump[NL_DUMP_MAX+1])(struct rtnl_tc *, void *, + struct nl_dump_params *); + /** + * Used to fill the contents of TCA_OPTIONS + */ + int (*to_msg_fill)(struct rtnl_tc *, void *, struct nl_msg *); + + /** + * Uesd to to fill tc related messages, unlike with to_msg_fill, + * the contents is not encapsulated with a TCA_OPTIONS nested + * attribute. + */ + int (*to_msg_fill_raw)(struct rtnl_tc *, void *, struct nl_msg *); + + /** + * TCA_OPTIONS message parser + */ + int (*to_msg_parser)(struct rtnl_tc *, void *); + + /** + * Called before a tc object is destroyed + */ + void (*to_free_data)(struct rtnl_tc *, void *); + + /** + * Called whenever a classifier object needs to be cloned + */ + int (*to_clone)(void *, void *); + + /** + * Internal, don't touch + */ + struct nl_list_head to_list; +}; + +struct rtnl_tc_type_ops +{ + enum rtnl_tc_type tt_type; + + char *tt_dump_prefix; + + /** + * Dump callbacks + */ + void (*tt_dump[NL_DUMP_MAX+1])(struct rtnl_tc *, + struct nl_dump_params *); +}; + +extern int rtnl_tc_msg_parse(struct nlmsghdr *, + struct rtnl_tc *); +extern int rtnl_tc_msg_build(struct rtnl_tc *, int, + int, struct nl_msg **); + +extern void rtnl_tc_free_data(struct nl_object *); +extern int rtnl_tc_clone(struct nl_object *, + struct nl_object *); +extern void rtnl_tc_dump_line(struct nl_object *, + struct nl_dump_params *); +extern void rtnl_tc_dump_details(struct nl_object *, + struct nl_dump_params *); +extern void rtnl_tc_dump_stats(struct nl_object *, + struct nl_dump_params *); +extern int rtnl_tc_compare(struct nl_object *, + struct nl_object *, + uint32_t, int); + +extern void * rtnl_tc_data(struct rtnl_tc *); +extern void * rtnl_tc_data_check(struct rtnl_tc *, + struct rtnl_tc_ops *); + +extern struct rtnl_tc_ops * rtnl_tc_lookup_ops(enum rtnl_tc_type, + const char *); +extern struct rtnl_tc_ops * rtnl_tc_get_ops(struct rtnl_tc *); +extern int rtnl_tc_register(struct rtnl_tc_ops *); +extern void rtnl_tc_unregister(struct rtnl_tc_ops *); + +extern void rtnl_tc_type_register(struct rtnl_tc_type_ops *); +extern void rtnl_tc_type_unregister(struct rtnl_tc_type_ops *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink-private/tc.h b/include/netlink-private/tc.h new file mode 100644 index 0000000..182adaa --- /dev/null +++ b/include/netlink-private/tc.h @@ -0,0 +1,55 @@ +/* + * netlink-private/tc.h Local Traffic Control Interface + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2013 Thomas Graf + */ + +#ifndef NETLINK_TC_PRIV_H_ +#define NETLINK_TC_PRIV_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define TCA_ATTR_HANDLE 0x0001 +#define TCA_ATTR_PARENT 0x0002 +#define TCA_ATTR_IFINDEX 0x0004 +#define TCA_ATTR_KIND 0x0008 +#define TCA_ATTR_FAMILY 0x0010 +#define TCA_ATTR_INFO 0x0020 +#define TCA_ATTR_OPTS 0x0040 +#define TCA_ATTR_STATS 0x0080 +#define TCA_ATTR_XSTATS 0x0100 +#define TCA_ATTR_LINK 0x0200 +#define TCA_ATTR_MTU 0x0400 +#define TCA_ATTR_MPU 0x0800 +#define TCA_ATTR_OVERHEAD 0x1000 +#define TCA_ATTR_LINKTYPE 0x2000 +#define TCA_ATTR_MAX TCA_ATTR_LINKTYPE + +extern int tca_parse(struct nlattr **, int, struct rtnl_tc *, + struct nla_policy *); + +#define RTNL_TC_RTABLE_SIZE 256 + +extern int rtnl_tc_build_rate_table(struct rtnl_tc *tc, struct rtnl_ratespec *, + uint32_t *); + + +static inline void *tca_xstats(struct rtnl_tc *tca) +{ + return tca->tc_xstats->d_data; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink-private/types.h b/include/netlink-private/types.h new file mode 100644 index 0000000..89f6418 --- /dev/null +++ b/include/netlink-private/types.h @@ -0,0 +1,912 @@ +/* + * netlink-private/types.h Netlink Types (Private) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2013 Thomas Graf + */ + +#ifndef NETLINK_LOCAL_TYPES_H_ +#define NETLINK_LOCAL_TYPES_H_ + +#include +#include +#include +#include +#include +#include + +#define NL_SOCK_BUFSIZE_SET (1<<0) +#define NL_SOCK_PASSCRED (1<<1) +#define NL_OWN_PORT (1<<2) +#define NL_MSG_PEEK (1<<3) +#define NL_NO_AUTO_ACK (1<<4) + +#define NL_MSG_CRED_PRESENT 1 + +struct nl_cache_ops; +struct nl_sock; +struct nl_object; +struct nl_hash_table; + +struct nl_cb +{ + nl_recvmsg_msg_cb_t cb_set[NL_CB_TYPE_MAX+1]; + void * cb_args[NL_CB_TYPE_MAX+1]; + + nl_recvmsg_err_cb_t cb_err; + void * cb_err_arg; + + /** May be used to replace nl_recvmsgs with your own implementation + * in all internal calls to nl_recvmsgs. */ + int (*cb_recvmsgs_ow)(struct nl_sock *, + struct nl_cb *); + + /** Overwrite internal calls to nl_recv, must return the number of + * octets read and allocate a buffer for the received data. */ + int (*cb_recv_ow)(struct nl_sock *, + struct sockaddr_nl *, + unsigned char **, + struct ucred **); + + /** Overwrites internal calls to nl_send, must send the netlink + * message. */ + int (*cb_send_ow)(struct nl_sock *, + struct nl_msg *); + + int cb_refcnt; +}; + +struct nl_sock +{ + struct sockaddr_nl s_local; + struct sockaddr_nl s_peer; + int s_fd; + int s_proto; + unsigned int s_seq_next; + unsigned int s_seq_expect; + int s_flags; + struct nl_cb * s_cb; + size_t s_bufsize; +}; + +struct nl_cache +{ + struct nl_list_head c_items; + int c_nitems; + int c_iarg1; + int c_iarg2; + int c_refcnt; + unsigned int c_flags; + struct nl_hash_table * hashtable; + struct nl_cache_ops * c_ops; +}; + +struct nl_cache_assoc +{ + struct nl_cache * ca_cache; + change_func_t ca_change; + void * ca_change_data; +}; + +struct nl_cache_mngr +{ + int cm_protocol; + int cm_flags; + int cm_nassocs; + struct nl_sock * cm_sock; + struct nl_sock * cm_sync_sock; + struct nl_cache_assoc * cm_assocs; +}; + +struct nl_parser_param; + +#define LOOSE_COMPARISON 1 + +#define NL_OBJ_MARK 1 + +struct nl_data +{ + size_t d_size; + void * d_data; +}; + +struct nl_addr +{ + int a_family; + unsigned int a_maxsize; + unsigned int a_len; + int a_prefixlen; + int a_refcnt; + char a_addr[0]; +}; + +struct nl_msg +{ + int nm_protocol; + int nm_flags; + struct sockaddr_nl nm_src; + struct sockaddr_nl nm_dst; + struct ucred nm_creds; + struct nlmsghdr * nm_nlh; + size_t nm_size; + int nm_refcnt; +}; + +struct rtnl_link_map +{ + uint64_t lm_mem_start; + uint64_t lm_mem_end; + uint64_t lm_base_addr; + uint16_t lm_irq; + uint8_t lm_dma; + uint8_t lm_port; +}; + +#define IFQDISCSIZ 32 + +struct rtnl_link +{ + NLHDR_COMMON + + char l_name[IFNAMSIZ]; + uint32_t l_family; + uint32_t l_arptype; + uint32_t l_index; + uint32_t l_flags; + uint32_t l_change; + uint32_t l_mtu; + uint32_t l_link; + uint32_t l_txqlen; + uint32_t l_weight; + uint32_t l_master; + struct nl_addr * l_addr; + struct nl_addr * l_bcast; + char l_qdisc[IFQDISCSIZ]; + struct rtnl_link_map l_map; + uint64_t l_stats[RTNL_LINK_STATS_MAX+1]; + uint32_t l_flag_mask; + uint32_t l_num_vf; + uint8_t l_operstate; + uint8_t l_linkmode; + /* 2 byte hole */ + char * l_info_kind; + struct rtnl_link_info_ops * l_info_ops; + void * l_af_data[AF_MAX]; + void * l_info; + char * l_ifalias; + uint32_t l_promiscuity; + uint32_t l_num_tx_queues; + uint32_t l_num_rx_queues; + uint32_t l_group; + uint8_t l_carrier; + /* 3 byte hole */ + struct rtnl_link_af_ops * l_af_ops; +}; + +struct rtnl_ncacheinfo +{ + uint32_t nci_confirmed; /**< Time since neighbour validty was last confirmed */ + uint32_t nci_used; /**< Time since neighbour entry was last ued */ + uint32_t nci_updated; /**< Time since last update */ + uint32_t nci_refcnt; /**< Reference counter */ +}; + + +struct rtnl_neigh +{ + NLHDR_COMMON + uint32_t n_family; + uint32_t n_ifindex; + uint16_t n_state; + uint8_t n_flags; + uint8_t n_type; + struct nl_addr *n_lladdr; + struct nl_addr *n_dst; + uint32_t n_probes; + struct rtnl_ncacheinfo n_cacheinfo; + uint32_t n_state_mask; + uint32_t n_flag_mask; + uint32_t n_master; +}; + + +struct rtnl_addr_cacheinfo +{ + /* Preferred lifetime in seconds */ + uint32_t aci_prefered; + + /* Valid lifetime in seconds */ + uint32_t aci_valid; + + /* Timestamp of creation in 1/100s seince boottime */ + uint32_t aci_cstamp; + + /* Timestamp of last update in 1/100s since boottime */ + uint32_t aci_tstamp; +}; + +struct rtnl_addr +{ + NLHDR_COMMON + + uint8_t a_family; + uint8_t a_prefixlen; + uint8_t a_flags; + uint8_t a_scope; + uint32_t a_ifindex; + + struct nl_addr *a_peer; + struct nl_addr *a_local; + struct nl_addr *a_bcast; + struct nl_addr *a_anycast; + struct nl_addr *a_multicast; + + struct rtnl_addr_cacheinfo a_cacheinfo; + + char a_label[IFNAMSIZ]; + uint32_t a_flag_mask; + struct rtnl_link *a_link; +}; + +struct rtnl_nexthop +{ + uint8_t rtnh_flags; + uint8_t rtnh_flag_mask; + uint8_t rtnh_weight; + /* 1 byte spare */ + uint32_t rtnh_ifindex; + struct nl_addr * rtnh_gateway; + uint32_t ce_mask; /* HACK to support attr macros */ + struct nl_list_head rtnh_list; + uint32_t rtnh_realms; +}; + +struct rtnl_route +{ + NLHDR_COMMON + + uint8_t rt_family; + uint8_t rt_dst_len; + uint8_t rt_src_len; + uint8_t rt_tos; + uint8_t rt_protocol; + uint8_t rt_scope; + uint8_t rt_type; + uint8_t rt_nmetrics; + uint32_t rt_flags; + struct nl_addr * rt_dst; + struct nl_addr * rt_src; + uint32_t rt_table; + uint32_t rt_iif; + uint32_t rt_prio; + uint32_t rt_metrics[RTAX_MAX]; + uint32_t rt_metrics_mask; + uint32_t rt_nr_nh; + struct nl_addr * rt_pref_src; + struct nl_list_head rt_nexthops; + struct rtnl_rtcacheinfo rt_cacheinfo; + uint32_t rt_flag_mask; +}; + +struct rtnl_rule +{ + NLHDR_COMMON + uint8_t r_family; + uint8_t r_action; + uint8_t r_dsfield; /* ipv4 only */ + uint8_t r_unused; + uint32_t r_table; + uint32_t r_flags; + uint32_t r_prio; + uint32_t r_mark; + uint32_t r_mask; + uint32_t r_goto; + uint32_t r_flow; /* ipv4 only */ + struct nl_addr *r_src; + struct nl_addr *r_dst; + char r_iifname[IFNAMSIZ]; + char r_oifname[IFNAMSIZ]; +}; + +struct rtnl_neightbl_parms +{ + /** + * Interface index of the device this parameter set is assigned + * to or 0 for the default set. + */ + uint32_t ntp_ifindex; + + /** + * Number of references to this parameter set. + */ + uint32_t ntp_refcnt; + + /** + * Queue length for pending arp requests, i.e. the number of + * packets which are accepted from other layers while the + * neighbour address is still being resolved + */ + uint32_t ntp_queue_len; + + /** + * Number of requests to send to the user level ARP daemon. + * Specify 0 to disable. + */ + uint32_t ntp_app_probes; + + /** + * Maximum number of retries for unicast solicitation. + */ + uint32_t ntp_ucast_probes; + + /** + * Maximum number of retries for multicast solicitation. + */ + uint32_t ntp_mcast_probes; + + /** + * Base value in milliseconds to ompute reachable time, see RFC2461. + */ + uint64_t ntp_base_reachable_time; + + /** + * Actual reachable time (read-only) + */ + uint64_t ntp_reachable_time; /* secs */ + + /** + * The time in milliseconds between retransmitted Neighbor + * Solicitation messages. + */ + uint64_t ntp_retrans_time; + + /** + * Interval in milliseconds to check for stale neighbour + * entries. + */ + uint64_t ntp_gc_stale_time; /* secs */ + + /** + * Delay in milliseconds for the first time probe if + * the neighbour is reachable. + */ + uint64_t ntp_probe_delay; /* secs */ + + /** + * Maximum delay in milliseconds of an answer to a neighbour + * solicitation message. + */ + uint64_t ntp_anycast_delay; + + /** + * Minimum age in milliseconds before a neighbour entry + * may be replaced. + */ + uint64_t ntp_locktime; + + /** + * Delay in milliseconds before answering to an ARP request + * for which a proxy ARP entry exists. + */ + uint64_t ntp_proxy_delay; + + /** + * Queue length for the delayed proxy arp requests. + */ + uint32_t ntp_proxy_qlen; + + /** + * Mask of available parameter attributes + */ + uint32_t ntp_mask; +}; + +#define NTBLNAMSIZ 32 + +/** + * Neighbour table + * @ingroup neightbl + */ +struct rtnl_neightbl +{ + NLHDR_COMMON + + char nt_name[NTBLNAMSIZ]; + uint32_t nt_family; + uint32_t nt_gc_thresh1; + uint32_t nt_gc_thresh2; + uint32_t nt_gc_thresh3; + uint64_t nt_gc_interval; + struct ndt_config nt_config; + struct rtnl_neightbl_parms nt_parms; + struct ndt_stats nt_stats; +}; + +struct rtnl_ratespec +{ + uint8_t rs_cell_log; + uint16_t rs_overhead; + int16_t rs_cell_align; + uint16_t rs_mpu; + uint32_t rs_rate; +}; + +struct rtnl_tstats +{ + struct { + uint64_t bytes; + uint64_t packets; + } tcs_basic; + + struct { + uint32_t bps; + uint32_t pps; + } tcs_rate_est; + + struct { + uint32_t qlen; + uint32_t backlog; + uint32_t drops; + uint32_t requeues; + uint32_t overlimits; + } tcs_queue; +}; + +#define TCKINDSIZ 32 + +#define NL_TC_GENERIC(pre) \ + NLHDR_COMMON \ + uint32_t pre ##_family; \ + uint32_t pre ##_ifindex; \ + uint32_t pre ##_handle; \ + uint32_t pre ##_parent; \ + uint32_t pre ##_info; \ + uint32_t pre ##_mtu; \ + uint32_t pre ##_mpu; \ + uint32_t pre ##_overhead; \ + uint32_t pre ##_linktype; \ + char pre ##_kind[TCKINDSIZ]; \ + struct nl_data * pre ##_opts; \ + uint64_t pre ##_stats[RTNL_TC_STATS_MAX+1]; \ + struct nl_data * pre ##_xstats; \ + struct nl_data * pre ##_subdata; \ + struct rtnl_link * pre ##_link; \ + struct rtnl_tc_ops * pre ##_ops; \ + enum rtnl_tc_type pre ##_type + +struct rtnl_tc +{ + NL_TC_GENERIC(tc); +}; + +struct rtnl_qdisc +{ + NL_TC_GENERIC(q); +}; + +struct rtnl_class +{ + NL_TC_GENERIC(c); +}; + +struct rtnl_cls +{ + NL_TC_GENERIC(c); + uint16_t c_prio; + uint16_t c_protocol; +}; + +struct rtnl_u32 +{ + uint32_t cu_divisor; + uint32_t cu_hash; + uint32_t cu_classid; + uint32_t cu_link; + struct nl_data * cu_pcnt; + struct nl_data * cu_selector; + struct nl_data * cu_act; + struct nl_data * cu_police; + char cu_indev[IFNAMSIZ]; + int cu_mask; +}; + +struct rtnl_cgroup +{ + struct rtnl_ematch_tree *cg_ematch; + int cg_mask; +}; + +struct rtnl_fw +{ + uint32_t cf_classid; + struct nl_data * cf_act; + struct nl_data * cf_police; + char cf_indev[IFNAMSIZ]; + uint32_t cf_fwmask; + int cf_mask; +}; + +struct rtnl_ematch +{ + uint16_t e_id; + uint16_t e_kind; + uint16_t e_flags; + uint16_t e_index; + size_t e_datalen; + + struct nl_list_head e_childs; + struct nl_list_head e_list; + struct rtnl_ematch_ops *e_ops; + + void * e_data; +}; + +struct rtnl_ematch_tree +{ + uint16_t et_progid; + struct nl_list_head et_list; + +}; + +struct rtnl_dsmark_qdisc +{ + uint16_t qdm_indices; + uint16_t qdm_default_index; + uint32_t qdm_set_tc_index; + uint32_t qdm_mask; +}; + +struct rtnl_dsmark_class +{ + uint8_t cdm_bmask; + uint8_t cdm_value; + uint32_t cdm_mask; +}; + +struct rtnl_fifo +{ + uint32_t qf_limit; + uint32_t qf_mask; +}; + +struct rtnl_prio +{ + uint32_t qp_bands; + uint8_t qp_priomap[TC_PRIO_MAX+1]; + uint32_t qp_mask; +}; + +struct rtnl_tbf +{ + uint32_t qt_limit; + struct rtnl_ratespec qt_rate; + uint32_t qt_rate_bucket; + uint32_t qt_rate_txtime; + struct rtnl_ratespec qt_peakrate; + uint32_t qt_peakrate_bucket; + uint32_t qt_peakrate_txtime; + uint32_t qt_mask; +}; + +struct rtnl_sfq +{ + uint32_t qs_quantum; + uint32_t qs_perturb; + uint32_t qs_limit; + uint32_t qs_divisor; + uint32_t qs_flows; + uint32_t qs_mask; +}; + +struct rtnl_netem_corr +{ + uint32_t nmc_delay; + uint32_t nmc_loss; + uint32_t nmc_duplicate; +}; + +struct rtnl_netem_reo +{ + uint32_t nmro_probability; + uint32_t nmro_correlation; +}; + +struct rtnl_netem_crpt +{ + uint32_t nmcr_probability; + uint32_t nmcr_correlation; +}; + +struct rtnl_netem_dist +{ + int16_t * dist_data; + size_t dist_size; +}; + +struct rtnl_netem +{ + uint32_t qnm_latency; + uint32_t qnm_limit; + uint32_t qnm_loss; + uint32_t qnm_gap; + uint32_t qnm_duplicate; + uint32_t qnm_jitter; + uint32_t qnm_mask; + struct rtnl_netem_corr qnm_corr; + struct rtnl_netem_reo qnm_ro; + struct rtnl_netem_crpt qnm_crpt; + struct rtnl_netem_dist qnm_dist; +}; + +struct rtnl_htb_qdisc +{ + uint32_t qh_rate2quantum; + uint32_t qh_defcls; + uint32_t qh_mask; + uint32_t qh_direct_pkts; +}; + +struct rtnl_htb_class +{ + uint32_t ch_prio; + struct rtnl_ratespec ch_rate; + struct rtnl_ratespec ch_ceil; + uint32_t ch_rbuffer; + uint32_t ch_cbuffer; + uint32_t ch_quantum; + uint32_t ch_mask; + uint32_t ch_level; +}; + +struct rtnl_cbq +{ + struct tc_cbq_lssopt cbq_lss; + struct tc_ratespec cbq_rate; + struct tc_cbq_wrropt cbq_wrr; + struct tc_cbq_ovl cbq_ovl; + struct tc_cbq_fopt cbq_fopt; + struct tc_cbq_police cbq_police; +}; + +struct rtnl_red +{ + uint32_t qr_limit; + uint32_t qr_qth_min; + uint32_t qr_qth_max; + uint8_t qr_flags; + uint8_t qr_wlog; + uint8_t qr_plog; + uint8_t qr_scell_log; + uint32_t qr_mask; +}; + +struct rtnl_plug +{ + int action; + uint32_t limit; +}; + +struct flnl_request +{ + NLHDR_COMMON + + struct nl_addr * lr_addr; + uint32_t lr_fwmark; + uint8_t lr_tos; + uint8_t lr_scope; + uint8_t lr_table; +}; + + +struct flnl_result +{ + NLHDR_COMMON + + struct flnl_request * fr_req; + uint8_t fr_table_id; + uint8_t fr_prefixlen; + uint8_t fr_nh_sel; + uint8_t fr_type; + uint8_t fr_scope; + uint32_t fr_error; +}; + +#define GENL_OP_HAS_POLICY 1 +#define GENL_OP_HAS_DOIT 2 +#define GENL_OP_HAS_DUMPIT 4 + +struct genl_family_op +{ + uint32_t o_id; + uint32_t o_flags; + + struct nl_list_head o_list; +}; + +struct genl_family_grp { + struct genl_family *family; /* private */ + struct nl_list_head list; /* private */ + char name[GENL_NAMSIZ]; + u_int32_t id; +}; + +struct genl_family +{ + NLHDR_COMMON + + uint16_t gf_id; + char gf_name[GENL_NAMSIZ]; + uint32_t gf_version; + uint32_t gf_hdrsize; + uint32_t gf_maxattr; + + struct nl_list_head gf_ops; + struct nl_list_head gf_mc_grps; +}; + +union nfnl_ct_proto +{ + struct { + uint16_t src; + uint16_t dst; + } port; + struct { + uint16_t id; + uint8_t type; + uint8_t code; + } icmp; +}; + +struct nfnl_ct_dir { + struct nl_addr * src; + struct nl_addr * dst; + union nfnl_ct_proto proto; + uint64_t packets; + uint64_t bytes; +}; + +union nfnl_ct_protoinfo { + struct { + uint8_t state; + } tcp; +}; + +struct nfnl_ct { + NLHDR_COMMON + + uint8_t ct_family; + uint8_t ct_proto; + union nfnl_ct_protoinfo ct_protoinfo; + + uint32_t ct_status; + uint32_t ct_status_mask; + uint32_t ct_timeout; + uint32_t ct_mark; + uint32_t ct_use; + uint32_t ct_id; + + struct nfnl_ct_dir ct_orig; + struct nfnl_ct_dir ct_repl; +}; + +union nfnl_exp_protodata { + struct { + uint16_t src; + uint16_t dst; + } port; + struct { + uint16_t id; + uint8_t type; + uint8_t code; + } icmp; +}; + +// Allow for different master/expect l4 protocols +struct nfnl_exp_proto +{ + uint8_t l4protonum; + union nfnl_exp_protodata l4protodata; +}; + +struct nfnl_exp_dir { + struct nl_addr * src; + struct nl_addr * dst; + struct nfnl_exp_proto proto; +}; + +struct nfnl_exp { + NLHDR_COMMON + + uint8_t exp_family; + uint32_t exp_timeout; + uint32_t exp_id; + uint16_t exp_zone; + uint32_t exp_class; + uint32_t exp_flags; + char * exp_helper_name; + char * exp_fn; + uint8_t exp_nat_dir; + + struct nfnl_exp_dir exp_expect; + struct nfnl_exp_dir exp_master; + struct nfnl_exp_dir exp_mask; + struct nfnl_exp_dir exp_nat; +}; + +struct nfnl_log { + NLHDR_COMMON + + uint16_t log_group; + uint8_t log_copy_mode; + uint32_t log_copy_range; + uint32_t log_flush_timeout; + uint32_t log_alloc_size; + uint32_t log_queue_threshold; + uint32_t log_flags; + uint32_t log_flag_mask; +}; + +struct nfnl_log_msg { + NLHDR_COMMON + + uint8_t log_msg_family; + uint8_t log_msg_hook; + uint16_t log_msg_hwproto; + uint32_t log_msg_mark; + struct timeval log_msg_timestamp; + uint32_t log_msg_indev; + uint32_t log_msg_outdev; + uint32_t log_msg_physindev; + uint32_t log_msg_physoutdev; + uint8_t log_msg_hwaddr[8]; + int log_msg_hwaddr_len; + void * log_msg_payload; + int log_msg_payload_len; + char * log_msg_prefix; + uint32_t log_msg_uid; + uint32_t log_msg_gid; + uint32_t log_msg_seq; + uint32_t log_msg_seq_global; +}; + +struct nfnl_queue { + NLHDR_COMMON + + uint16_t queue_group; + uint32_t queue_maxlen; + uint32_t queue_copy_range; + uint8_t queue_copy_mode; +}; + +struct nfnl_queue_msg { + NLHDR_COMMON + + uint16_t queue_msg_group; + uint8_t queue_msg_family; + uint8_t queue_msg_hook; + uint16_t queue_msg_hwproto; + uint32_t queue_msg_packetid; + uint32_t queue_msg_mark; + struct timeval queue_msg_timestamp; + uint32_t queue_msg_indev; + uint32_t queue_msg_outdev; + uint32_t queue_msg_physindev; + uint32_t queue_msg_physoutdev; + uint8_t queue_msg_hwaddr[8]; + int queue_msg_hwaddr_len; + void * queue_msg_payload; + int queue_msg_payload_len; + uint32_t queue_msg_verdict; +}; + +struct ematch_quoted { + char * data; + size_t len; + int index; +}; + +#endif diff --git a/include/netlink/addr.h b/include/netlink/addr.h new file mode 100644 index 0000000..db3e4c2 --- /dev/null +++ b/include/netlink/addr.h @@ -0,0 +1,66 @@ +/* + * netlink/addr.h Abstract Address + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2013 Thomas Graf + */ + +#ifndef NETLINK_ADDR_H_ +#define NETLINK_ADDR_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct nl_addr; + +/* Creation */ +extern struct nl_addr * nl_addr_alloc(size_t); +extern struct nl_addr * nl_addr_alloc_attr(struct nlattr *, int); +extern struct nl_addr * nl_addr_build(int, void *, size_t); +extern int nl_addr_parse(const char *, int, struct nl_addr **); +extern struct nl_addr * nl_addr_clone(struct nl_addr *); + +/* Usage Management */ +extern struct nl_addr * nl_addr_get(struct nl_addr *); +extern void nl_addr_put(struct nl_addr *); +extern int nl_addr_shared(struct nl_addr *); + +extern int nl_addr_cmp(struct nl_addr *, struct nl_addr *); +extern int nl_addr_cmp_prefix(struct nl_addr *, struct nl_addr *); +extern int nl_addr_iszero(struct nl_addr *); +extern int nl_addr_valid(char *, int); +extern int nl_addr_guess_family(struct nl_addr *); +extern int nl_addr_fill_sockaddr(struct nl_addr *, + struct sockaddr *, socklen_t *); +extern int nl_addr_info(struct nl_addr *, struct addrinfo **); +extern int nl_addr_resolve(struct nl_addr *, char *, size_t); + +/* Access Functions */ +extern void nl_addr_set_family(struct nl_addr *, int); +extern int nl_addr_get_family(struct nl_addr *); +extern int nl_addr_set_binary_addr(struct nl_addr *, void *, + size_t); +extern void * nl_addr_get_binary_addr(struct nl_addr *); +extern unsigned int nl_addr_get_len(struct nl_addr *); +extern void nl_addr_set_prefixlen(struct nl_addr *, int); +extern unsigned int nl_addr_get_prefixlen(struct nl_addr *); + +/* Address Family Translations */ +extern char * nl_af2str(int, char *, size_t); +extern int nl_str2af(const char *); + +/* Translations to Strings */ +extern char * nl_addr2str(struct nl_addr *, char *, size_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/attr.h b/include/netlink/attr.h new file mode 100644 index 0000000..0ed3da3 --- /dev/null +++ b/include/netlink/attr.h @@ -0,0 +1,285 @@ +/* + * netlink/attr.h Netlink 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-2013 Thomas Graf + */ + +#ifndef NETLINK_ATTR_H_ +#define NETLINK_ATTR_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct nl_msg; + +/** + * @name Basic Attribute Data Types + * @{ + */ + +/** + * @ingroup attr + * Basic attribute data types + * + * See section @core_doc{core_attr_parse,Attribute Parsing} for more details. + */ +enum { + NLA_UNSPEC, /**< Unspecified type, binary data chunk */ + NLA_U8, /**< 8 bit integer */ + NLA_U16, /**< 16 bit integer */ + NLA_U32, /**< 32 bit integer */ + NLA_U64, /**< 64 bit integer */ + NLA_STRING, /**< NUL terminated character string */ + NLA_FLAG, /**< Flag */ + NLA_MSECS, /**< Micro seconds (64bit) */ + NLA_NESTED, /**< Nested attributes */ + __NLA_TYPE_MAX, +}; + +#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1) + +/** @} */ + +/** + * @ingroup attr + * Attribute validation policy. + * + * See section @core_doc{core_attr_parse,Attribute Parsing} for more details. + */ +struct nla_policy { + /** Type of attribute or NLA_UNSPEC */ + uint16_t type; + + /** Minimal length of payload required */ + uint16_t minlen; + + /** Maximal length of payload allowed */ + uint16_t maxlen; +}; + +/* Size calculations */ +extern int nla_attr_size(int payload); +extern int nla_total_size(int payload); +extern int nla_padlen(int payload); + +/* Attribute parsing */ +extern int nla_type(const struct nlattr *); +extern void * nla_data(const struct nlattr *); +extern int nla_len(const struct nlattr *); +extern int nla_ok(const struct nlattr *, int); +extern struct nlattr * nla_next(const struct nlattr *, int *); +extern int nla_parse(struct nlattr **, int, struct nlattr *, + int, struct nla_policy *); +extern int nla_validate(struct nlattr *, int, int, + struct nla_policy *); +extern struct nlattr * nla_find(struct nlattr *, int, int); + +/* Helper Functions */ +extern int nla_memcpy(void *, struct nlattr *, int); +extern size_t nla_strlcpy(char *, const struct nlattr *, size_t); +extern int nla_memcmp(const struct nlattr *, const void *, size_t); +extern int nla_strcmp(const struct nlattr *, const char *); + +/* Unspecific attribute */ +extern struct nlattr * nla_reserve(struct nl_msg *, int, int); +extern int nla_put(struct nl_msg *, int, int, const void *); +extern int nla_put_data(struct nl_msg *, int, struct nl_data *); +extern int nla_put_addr(struct nl_msg *, int, struct nl_addr *); + +/* Integer attribute */ +extern uint8_t nla_get_u8(struct nlattr *); +extern int nla_put_u8(struct nl_msg *, int, uint8_t); +extern uint16_t nla_get_u16(struct nlattr *); +extern int nla_put_u16(struct nl_msg *, int, uint16_t); +extern uint32_t nla_get_u32(struct nlattr *); +extern int nla_put_u32(struct nl_msg *, int, uint32_t); +extern uint64_t nla_get_u64(struct nlattr *); +extern int nla_put_u64(struct nl_msg *, int, uint64_t); + +/* String attribute */ +extern char * nla_get_string(struct nlattr *); +extern char * nla_strdup(struct nlattr *); +extern int nla_put_string(struct nl_msg *, int, const char *); + +/* Flag attribute */ +extern int nla_get_flag(struct nlattr *); +extern int nla_put_flag(struct nl_msg *, int); + +/* Msec attribute */ +extern unsigned long nla_get_msecs(struct nlattr *); +extern int nla_put_msecs(struct nl_msg *, int, unsigned long); + +/* Attribute nesting */ +extern int nla_put_nested(struct nl_msg *, int, struct nl_msg *); +extern struct nlattr * nla_nest_start(struct nl_msg *, int); +extern int nla_nest_end(struct nl_msg *, struct nlattr *); +extern void nla_nest_cancel(struct nl_msg *, struct nlattr *); +extern int nla_parse_nested(struct nlattr **, int, struct nlattr *, + struct nla_policy *); +extern int nla_is_nested(struct nlattr *); + +/** + * @name Attribute Construction (Exception Based) + * @{ + */ + +/** + * @ingroup attr + * Add unspecific attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg attrlen Length of attribute payload. + * @arg data Head of attribute payload. + */ +#define NLA_PUT(msg, attrtype, attrlen, data) \ + do { \ + if (nla_put(msg, attrtype, attrlen, data) < 0) \ + goto nla_put_failure; \ + } while(0) + +/** + * @ingroup attr + * Add atomic type attribute to netlink message. + * @arg msg Netlink message. + * @arg type Atomic type. + * @arg attrtype Attribute type. + * @arg value Head of attribute payload. + */ +#define NLA_PUT_TYPE(msg, type, attrtype, value) \ + do { \ + type __tmp = value; \ + NLA_PUT(msg, attrtype, sizeof(type), &__tmp); \ + } while(0) + +/** + * Add 8 bit integer attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg value Numeric value. + */ +#define NLA_PUT_U8(msg, attrtype, value) \ + NLA_PUT_TYPE(msg, uint8_t, attrtype, value) + +/** + * Add 16 bit integer attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg value Numeric value. + */ +#define NLA_PUT_U16(msg, attrtype, value) \ + NLA_PUT_TYPE(msg, uint16_t, attrtype, value) + +/** + * Add 32 bit integer attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg value Numeric value. + */ +#define NLA_PUT_U32(msg, attrtype, value) \ + NLA_PUT_TYPE(msg, uint32_t, attrtype, value) + +/** + * Add 64 bit integer attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg value Numeric value. + */ +#define NLA_PUT_U64(msg, attrtype, value) \ + NLA_PUT_TYPE(msg, uint64_t, attrtype, value) + +/** + * Add string attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg value NUL terminated character string. + */ +#define NLA_PUT_STRING(msg, attrtype, value) \ + NLA_PUT(msg, attrtype, strlen(value) + 1, value) + +/** + * Add flag attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + */ +#define NLA_PUT_FLAG(msg, attrtype) \ + NLA_PUT(msg, attrtype, 0, NULL) + +/** + * Add msecs attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg msecs Numeric value in micro seconds. + */ +#define NLA_PUT_MSECS(msg, attrtype, msecs) \ + NLA_PUT_U64(msg, attrtype, msecs) + +/** + * Add address attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg addr Abstract address object. + */ +#define NLA_PUT_ADDR(msg, attrtype, addr) \ + NLA_PUT(msg, attrtype, nl_addr_get_len(addr), \ + nl_addr_get_binary_addr(addr)) + +/** + * Add abstract data attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg data Abstract data object. + */ +#define NLA_PUT_DATA(msg, attrtype, data) \ + NLA_PUT(msg, attrtype, nl_data_get_size(data), \ + nl_data_get(data)) + +/** @} */ + +/** + * @name Iterators + * @{ + */ + +/** + * @ingroup attr + * Iterate over a stream of attributes + * @arg pos loop counter, set to current attribute + * @arg head head of attribute stream + * @arg len length of attribute stream + * @arg rem initialized to len, holds bytes currently remaining in stream + */ +#define nla_for_each_attr(pos, head, len, rem) \ + for (pos = head, rem = len; \ + nla_ok(pos, rem); \ + pos = nla_next(pos, &(rem))) + +/** + * @ingroup attr + * Iterate over a stream of nested attributes + * @arg pos loop counter, set to current attribute + * @arg nla attribute containing the nested attributes + * @arg rem initialized to len, holds bytes currently remaining in stream + */ +#define nla_for_each_nested(pos, nla, rem) \ + for (pos = nla_data(nla), rem = nla_len(nla); \ + nla_ok(pos, rem); \ + pos = nla_next(pos, &(rem))) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/cache-api.h b/include/netlink/cache-api.h new file mode 100644 index 0000000..e43c7ca --- /dev/null +++ b/include/netlink/cache-api.h @@ -0,0 +1,20 @@ +/* + * netlink/cache-api.h Caching API + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2013 Thomas Graf + */ + +#ifndef NETLINK_DUMMY_CACHE_API_H_ +#define NETLINK_DUMMY_CACHE_API_H_ + +#include +#include + +#warning "You are including a deprecated header file, include ." + +#endif diff --git a/include/netlink/cache.h b/include/netlink/cache.h new file mode 100644 index 0000000..415bb00 --- /dev/null +++ b/include/netlink/cache.h @@ -0,0 +1,168 @@ +/* + * netlink/cache.h Caching Module + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +#ifndef NETLINK_CACHE_H_ +#define NETLINK_CACHE_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + NL_ACT_UNSPEC, + NL_ACT_NEW, + NL_ACT_DEL, + NL_ACT_GET, + NL_ACT_SET, + NL_ACT_CHANGE, + __NL_ACT_MAX, +}; + +#define NL_ACT_MAX (__NL_ACT_MAX - 1) + +struct nl_cache; +typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int, void *); + +/** + * @ingroup cache + * Explicitely iterate over all address families when updating the cache + */ +#define NL_CACHE_AF_ITER 0x0001 + +/* Access Functions */ +extern int nl_cache_nitems(struct nl_cache *); +extern int nl_cache_nitems_filter(struct nl_cache *, + struct nl_object *); +extern struct nl_cache_ops * nl_cache_get_ops(struct nl_cache *); +extern struct nl_object * nl_cache_get_first(struct nl_cache *); +extern struct nl_object * nl_cache_get_last(struct nl_cache *); +extern struct nl_object * nl_cache_get_next(struct nl_object *); +extern struct nl_object * nl_cache_get_prev(struct nl_object *); + +extern struct nl_cache * nl_cache_alloc(struct nl_cache_ops *); +extern int nl_cache_alloc_and_fill(struct nl_cache_ops *, + struct nl_sock *, + struct nl_cache **); +extern int nl_cache_alloc_name(const char *, + struct nl_cache **); +extern struct nl_cache * nl_cache_subset(struct nl_cache *, + struct nl_object *); +extern struct nl_cache * nl_cache_clone(struct nl_cache *); +extern void nl_cache_clear(struct nl_cache *); +extern void nl_cache_get(struct nl_cache *); +extern void nl_cache_free(struct nl_cache *); +extern void nl_cache_put(struct nl_cache *cache); + +/* Cache modification */ +extern int nl_cache_add(struct nl_cache *, + struct nl_object *); +extern int nl_cache_parse_and_add(struct nl_cache *, + struct nl_msg *); +extern void nl_cache_remove(struct nl_object *); +extern int nl_cache_refill(struct nl_sock *, + struct nl_cache *); +extern int nl_cache_pickup(struct nl_sock *, + struct nl_cache *); +extern int nl_cache_resync(struct nl_sock *, + struct nl_cache *, + change_func_t, + void *); +extern int nl_cache_include(struct nl_cache *, + struct nl_object *, + change_func_t, + void *); +extern void nl_cache_set_arg1(struct nl_cache *, int); +extern void nl_cache_set_arg2(struct nl_cache *, int); +extern void nl_cache_set_flags(struct nl_cache *, unsigned int); + +/* General */ +extern int nl_cache_is_empty(struct nl_cache *); +extern struct nl_object * nl_cache_search(struct nl_cache *, + struct nl_object *); +extern struct nl_object * nl_cache_lookup(struct nl_cache *, + struct nl_object *); +extern void nl_cache_mark_all(struct nl_cache *); + +/* Dumping */ +extern void nl_cache_dump(struct nl_cache *, + struct nl_dump_params *); +extern void nl_cache_dump_filter(struct nl_cache *, + struct nl_dump_params *, + struct nl_object *); + +/* Iterators */ +extern void nl_cache_foreach(struct nl_cache *, + void (*cb)(struct nl_object *, + void *), + void *arg); +extern void nl_cache_foreach_filter(struct nl_cache *, + struct nl_object *, + void (*cb)(struct + nl_object *, + void *), + void *arg); + +/* --- cache management --- */ + +/* Cache type management */ +extern struct nl_cache_ops * nl_cache_ops_lookup(const char *); +extern struct nl_cache_ops * nl_cache_ops_lookup_safe(const char *); +extern struct nl_cache_ops * nl_cache_ops_associate(int, int); +extern struct nl_cache_ops * nl_cache_ops_associate_safe(int, int); +extern struct nl_msgtype * nl_msgtype_lookup(struct nl_cache_ops *, int); +extern void nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *); +extern int nl_cache_mngt_register(struct nl_cache_ops *); +extern int nl_cache_mngt_unregister(struct nl_cache_ops *); + +/* Global cache provisioning/requiring */ +extern void nl_cache_mngt_provide(struct nl_cache *); +extern void nl_cache_mngt_unprovide(struct nl_cache *); +extern struct nl_cache * nl_cache_mngt_require(const char *); +extern struct nl_cache * nl_cache_mngt_require_safe(const char *); +extern struct nl_cache * __nl_cache_mngt_require(const char *); + +struct nl_cache_mngr; + +#define NL_AUTO_PROVIDE 1 +#define NL_ALLOCATED_SOCK 2 /* For internal use only, do not use */ + +extern int nl_cache_mngr_alloc(struct nl_sock *, + int, int, + struct nl_cache_mngr **); +extern int nl_cache_mngr_add(struct nl_cache_mngr *, + const char *, + change_func_t, + void *, + struct nl_cache **); +extern int nl_cache_mngr_add_cache(struct nl_cache_mngr *mngr, + struct nl_cache *cache, + change_func_t cb, void *data); +extern int nl_cache_mngr_get_fd(struct nl_cache_mngr *); +extern int nl_cache_mngr_poll(struct nl_cache_mngr *, + int); +extern int nl_cache_mngr_data_ready(struct nl_cache_mngr *); +extern void nl_cache_mngr_info(struct nl_cache_mngr *, + struct nl_dump_params *); +extern void nl_cache_mngr_free(struct nl_cache_mngr *); + +extern void nl_cache_ops_get(struct nl_cache_ops *); +extern void nl_cache_ops_put(struct nl_cache_ops *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/cli/addr.h b/include/netlink/cli/addr.h new file mode 100644 index 0000000..d0fd055 --- /dev/null +++ b/include/netlink/cli/addr.h @@ -0,0 +1,32 @@ +/* + * netlink/cli/addr.h CLI Address 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 + */ + +#ifndef __NETLINK_CLI_ADDR_H_ +#define __NETLINK_CLI_ADDR_H_ + +#include + +#define nl_cli_addr_alloc_cache(sk) \ + nl_cli_alloc_cache((sk), "address", rtnl_addr_alloc_cache) + +extern struct rtnl_addr *nl_cli_addr_alloc(void); + +extern void nl_cli_addr_parse_family(struct rtnl_addr *, char *); +extern void nl_cli_addr_parse_local(struct rtnl_addr *, char *); +extern void nl_cli_addr_parse_dev(struct rtnl_addr *, struct nl_cache *,char *); +extern void nl_cli_addr_parse_label(struct rtnl_addr *, char *); +extern void nl_cli_addr_parse_peer(struct rtnl_addr *, char *); +extern void nl_cli_addr_parse_scope(struct rtnl_addr *, char *); +extern void nl_cli_addr_parse_broadcast(struct rtnl_addr *, char *); +extern void nl_cli_addr_parse_preferred(struct rtnl_addr *, char *); +extern void nl_cli_addr_parse_valid(struct rtnl_addr *, char *); + +#endif diff --git a/include/netlink/cli/class.h b/include/netlink/cli/class.h new file mode 100644 index 0000000..5001e42 --- /dev/null +++ b/include/netlink/cli/class.h @@ -0,0 +1,21 @@ +/* + * netlink/cli/class.h 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 Thomas Graf + */ + +#ifndef __NETLINK_CLI_CLASS_H_ +#define __NETLINK_CLI_CLASS_H_ + +#include +#include + +extern struct rtnl_class *nl_cli_class_alloc(void); +extern struct nl_cache *nl_cli_class_alloc_cache(struct nl_sock *, int); + +#endif diff --git a/include/netlink/cli/cls.h b/include/netlink/cli/cls.h new file mode 100644 index 0000000..a2707b8 --- /dev/null +++ b/include/netlink/cli/cls.h @@ -0,0 +1,24 @@ +/* + * netlink/cli/cls.h 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 Thomas Graf + */ + +#ifndef __NETLINK_CLI_CLS_H_ +#define __NETLINK_CLI_CLS_H_ + +#include +#include + +extern struct rtnl_cls * nl_cli_cls_alloc(void); +extern struct nl_cache * nl_cli_cls_alloc_cache(struct nl_sock *, + int, uint32_t); +extern void nl_cli_cls_parse_proto(struct rtnl_cls *, char *); +extern struct rtnl_ematch_tree *nl_cli_cls_parse_ematch(struct rtnl_cls *, char *); + +#endif diff --git a/include/netlink/cli/ct.h b/include/netlink/cli/ct.h new file mode 100644 index 0000000..bed776b --- /dev/null +++ b/include/netlink/cli/ct.h @@ -0,0 +1,34 @@ +/* + * netlink/cli/ct.h CLI Conntrack Helper + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2008-2009 Thomas Graf + */ + +#ifndef __NETLINK_CLI_CT_H_ +#define __NETLINK_CLI_CT_H_ + +#include +#include + +extern struct nfnl_ct *nl_cli_ct_alloc(void); +extern struct nl_cache *nl_cli_ct_alloc_cache(struct nl_sock *); + +extern void nl_cli_ct_parse_family(struct nfnl_ct *, char *); +extern void nl_cli_ct_parse_protocol(struct nfnl_ct *, char *); +extern void nl_cli_ct_parse_mark(struct nfnl_ct *, char *); +extern void nl_cli_ct_parse_timeout(struct nfnl_ct *, char *); +extern void nl_cli_ct_parse_id(struct nfnl_ct *, char *); +extern void nl_cli_ct_parse_use(struct nfnl_ct *, char *); +extern void nl_cli_ct_parse_src(struct nfnl_ct *, int, char *); +extern void nl_cli_ct_parse_dst(struct nfnl_ct *, int, char *); +extern void nl_cli_ct_parse_src_port(struct nfnl_ct *, int, char *); +extern void nl_cli_ct_parse_dst_port(struct nfnl_ct *, int, char *); +extern void nl_cli_ct_parse_tcp_state(struct nfnl_ct *, char *); +extern void nl_cli_ct_parse_status(struct nfnl_ct *, char *); + +#endif diff --git a/include/netlink/cli/exp.h b/include/netlink/cli/exp.h new file mode 100644 index 0000000..b2418f8 --- /dev/null +++ b/include/netlink/cli/exp.h @@ -0,0 +1,42 @@ +/* + * netlink/cli/exp.h CLI Expectation Helper + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2012 Rich Fought + * Copyright (c) 2008-2009 Thomas Graf + */ + +#ifndef __NETLINK_CLI_EXP_H_ +#define __NETLINK_CLI_EXP_H_ + +#include +#include + +extern struct nfnl_exp *nl_cli_exp_alloc(void); +extern struct nl_cache *nl_cli_exp_alloc_cache(struct nl_sock *); + +extern void nl_cli_exp_parse_family(struct nfnl_exp *, char *); +extern void nl_cli_exp_parse_timeout(struct nfnl_exp *, char *); +extern void nl_cli_exp_parse_id(struct nfnl_exp *, char *); +extern void nl_cli_exp_parse_helper_name(struct nfnl_exp *, char *); +extern void nl_cli_exp_parse_zone(struct nfnl_exp *, char *); +extern void nl_cli_exp_parse_flags(struct nfnl_exp *, char *); +extern void nl_cli_exp_parse_class(struct nfnl_exp *, char *); +extern void nl_cli_exp_parse_nat_dir(struct nfnl_exp *, char *); +extern void nl_cli_exp_parse_fn(struct nfnl_exp *, char *); + +extern void nl_cli_exp_parse_src(struct nfnl_exp *, int, char *); +extern void nl_cli_exp_parse_dst(struct nfnl_exp *, int, char *); +extern void nl_cli_exp_parse_l4protonum(struct nfnl_exp *, int, char *); +extern void nl_cli_exp_parse_src_port(struct nfnl_exp *, int, char *); +extern void nl_cli_exp_parse_dst_port(struct nfnl_exp *, int, char *); +extern void nl_cli_exp_parse_icmp_id(struct nfnl_exp *, int, char *); +extern void nl_cli_exp_parse_icmp_type(struct nfnl_exp *, int, char *); +extern void nl_cli_exp_parse_icmp_code(struct nfnl_exp *, int, char *); + + +#endif diff --git a/include/netlink/cli/link.h b/include/netlink/cli/link.h new file mode 100644 index 0000000..3f37948 --- /dev/null +++ b/include/netlink/cli/link.h @@ -0,0 +1,30 @@ +/* + * netlink/cli/link.h CLI Link 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-2010 Thomas Graf + */ + +#ifndef __NETLINK_CLI_LINK_H_ +#define __NETLINK_CLI_LINK_H_ + +#include +#include + +extern struct rtnl_link *nl_cli_link_alloc(void); +extern struct nl_cache *nl_cli_link_alloc_cache_family(struct nl_sock *, int); +extern struct nl_cache *nl_cli_link_alloc_cache(struct nl_sock *); + +extern void nl_cli_link_parse_family(struct rtnl_link *, char *); +extern void nl_cli_link_parse_name(struct rtnl_link *, char *); +extern void nl_cli_link_parse_mtu(struct rtnl_link *, char *); +extern void nl_cli_link_parse_ifindex(struct rtnl_link *, char *); +extern void nl_cli_link_parse_txqlen(struct rtnl_link *, char *); +extern void nl_cli_link_parse_weight(struct rtnl_link *, char *); +extern void nl_cli_link_parse_ifalias(struct rtnl_link *, char *); + +#endif diff --git a/include/netlink/cli/neigh.h b/include/netlink/cli/neigh.h new file mode 100644 index 0000000..5440012 --- /dev/null +++ b/include/netlink/cli/neigh.h @@ -0,0 +1,27 @@ +/* + * netlink/cli/neighbour.h CLI Neighbour 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 + */ + +#ifndef __NETLINK_CLI_NEIGH_H_ +#define __NETLINK_CLI_NEIGH_H_ + +#include + +#define nl_cli_neigh_alloc_cache(sk) \ + nl_cli_alloc_cache((sk), "neighbour", rtnl_neigh_alloc_cache) + +extern struct rtnl_neigh *nl_cli_neigh_alloc(void); +extern void nl_cli_neigh_parse_dst(struct rtnl_neigh *, char *); +extern void nl_cli_neigh_parse_lladdr(struct rtnl_neigh *, char *); +extern void nl_cli_neigh_parse_dev(struct rtnl_neigh *, struct nl_cache *, char *); +extern void nl_cli_neigh_parse_family(struct rtnl_neigh *, char *); +extern void nl_cli_neigh_parse_state(struct rtnl_neigh *, char *); + +#endif diff --git a/include/netlink/cli/qdisc.h b/include/netlink/cli/qdisc.h new file mode 100644 index 0000000..b102da4 --- /dev/null +++ b/include/netlink/cli/qdisc.h @@ -0,0 +1,23 @@ +/* + * netlink/cli/qdisc.h CLI QDisc 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-2011 Thomas Graf + */ + +#ifndef __NETLINK_CLI_QDISC_H_ +#define __NETLINK_CLI_QDISC_H_ + +#include + +#define nl_cli_qdisc_alloc_cache(sk) \ + nl_cli_alloc_cache((sk), "queueing disciplines", \ + rtnl_qdisc_alloc_cache) + +extern struct rtnl_qdisc *nl_cli_qdisc_alloc(void); + +#endif diff --git a/include/netlink/cli/route.h b/include/netlink/cli/route.h new file mode 100644 index 0000000..089c658 --- /dev/null +++ b/include/netlink/cli/route.h @@ -0,0 +1,34 @@ +/* + * netlink/cli//route.h CLI Route 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 + */ + +#ifndef __NETLINK_CLI_ROUTE_H_ +#define __NETLINK_CLI_ROUTE_H_ + +#include + +extern struct rtnl_route *nl_cli_route_alloc(void); + +extern struct nl_cache *nl_cli_route_alloc_cache(struct nl_sock *, int); + +extern void nl_cli_route_parse_family(struct rtnl_route *, char *); +extern void nl_cli_route_parse_dst(struct rtnl_route *, char *); +extern void nl_cli_route_parse_src(struct rtnl_route *, char *); +extern void nl_cli_route_parse_pref_src(struct rtnl_route *, char *); +extern void nl_cli_route_parse_metric(struct rtnl_route *, char *); +extern void nl_cli_route_parse_nexthop(struct rtnl_route *, char *, struct nl_cache *); +extern void nl_cli_route_parse_table(struct rtnl_route *, char *); +extern void nl_cli_route_parse_prio(struct rtnl_route *, char *); +extern void nl_cli_route_parse_scope(struct rtnl_route *, char *); +extern void nl_cli_route_parse_protocol(struct rtnl_route *, char *); +extern void nl_cli_route_parse_type(struct rtnl_route *, char *); +extern void nl_cli_route_parse_iif(struct rtnl_route *, char *, struct nl_cache *); + +#endif diff --git a/include/netlink/cli/rule.h b/include/netlink/cli/rule.h new file mode 100644 index 0000000..61cd63e --- /dev/null +++ b/include/netlink/cli/rule.h @@ -0,0 +1,21 @@ +/* + * netlink/cli/rule.h CLI Routing Rule 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 + */ + +#ifndef __NETLINK_CLI_RULE_H_ +#define __NETLINK_CLI_RULE_H_ + +#include + +extern struct rtnl_rule *nl_cli_rule_alloc(void); +extern struct nl_cache *nl_cli_rule_alloc_cache(struct nl_sock *); +extern void nl_cli_rule_parse_family(struct rtnl_rule *, char *); + +#endif diff --git a/include/netlink/cli/tc.h b/include/netlink/cli/tc.h new file mode 100644 index 0000000..77042c7 --- /dev/null +++ b/include/netlink/cli/tc.h @@ -0,0 +1,41 @@ +/* + * netlink/cli/tc.h 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-2011 Thomas Graf + */ + +#ifndef __NETLINK_CLI_TC_H_ +#define __NETLINK_CLI_TC_H_ + +#include + +struct rtnl_tc_ops; + +extern void nl_cli_tc_parse_dev(struct rtnl_tc *, struct nl_cache *, char *); +extern void nl_cli_tc_parse_parent(struct rtnl_tc *, char *); +extern void nl_cli_tc_parse_handle(struct rtnl_tc *, char *, int); +extern void nl_cli_tc_parse_mtu(struct rtnl_tc *, char *); +extern void nl_cli_tc_parse_mpu(struct rtnl_tc *, char *); +extern void nl_cli_tc_parse_overhead(struct rtnl_tc *, char *); +extern void nl_cli_tc_parse_linktype(struct rtnl_tc *, char *); +extern void nl_cli_tc_parse_kind(struct rtnl_tc *, char *); + +struct nl_cli_tc_module +{ + const char * tm_name; + enum rtnl_tc_type tm_type; + struct rtnl_tc_ops * tm_ops; + void (*tm_parse_argv)(struct rtnl_tc *, int, char **); + struct nl_list_head tm_list; +}; + +extern struct nl_cli_tc_module *nl_cli_tc_lookup(struct rtnl_tc_ops *); +extern void nl_cli_tc_register(struct nl_cli_tc_module *); +extern void nl_cli_tc_unregister(struct nl_cli_tc_module *); + +#endif diff --git a/include/netlink/cli/utils.h b/include/netlink/cli/utils.h new file mode 100644 index 0000000..da41c10 --- /dev/null +++ b/include/netlink/cli/utils.h @@ -0,0 +1,82 @@ +/* + * src/utils.h Utilities + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2009 Thomas Graf + */ + +#ifndef __NETLINK_CLI_UTILS_H_ +#define __NETLINK_CLI_UTILS_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __init +#define __init __attribute__((constructor)) +#endif + +#ifndef __exit +#define __exit __attribute__((destructor)) +#endif + +extern uint32_t nl_cli_parse_u32(const char *); +extern void nl_cli_print_version(void); +extern void nl_cli_fatal(int, const char *, ...); +extern struct nl_addr * nl_cli_addr_parse(const char *, int); +extern int nl_cli_connect(struct nl_sock *, int); +extern struct nl_sock * nl_cli_alloc_socket(void); +extern int nl_cli_parse_dumptype(const char *); +extern int nl_cli_confirm(struct nl_object *, + struct nl_dump_params *, int); + +extern struct nl_cache *nl_cli_alloc_cache(struct nl_sock *, const char *, + int (*ac)(struct nl_sock *, struct nl_cache **)); + +extern void nl_cli_load_module(const char *, const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/data.h b/include/netlink/data.h new file mode 100644 index 0000000..071159e --- /dev/null +++ b/include/netlink/data.h @@ -0,0 +1,41 @@ +/* + * netlink/data.h Abstract Data + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + */ + +#ifndef NETLINK_DATA_H_ +#define NETLINK_DATA_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct nl_data; + +/* General */ +extern struct nl_data * nl_data_alloc(void *, size_t); +extern struct nl_data * nl_data_alloc_attr(struct nlattr *); +extern struct nl_data * nl_data_clone(struct nl_data *); +extern int nl_data_append(struct nl_data *, void *, size_t); +extern void nl_data_free(struct nl_data *); + +/* Access Functions */ +extern void * nl_data_get(struct nl_data *); +extern size_t nl_data_get_size(struct nl_data *); + +/* Misc */ +extern int nl_data_cmp(struct nl_data *, struct nl_data *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/errno.h b/include/netlink/errno.h new file mode 100644 index 0000000..f8b5130 --- /dev/null +++ b/include/netlink/errno.h @@ -0,0 +1,64 @@ +/* + * netlink/errno.h Error Numbers + * + * 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 Thomas Graf + */ + +#ifndef NETLINK_ERRNO_H_ +#define NETLINK_ERRNO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define NLE_SUCCESS 0 +#define NLE_FAILURE 1 +#define NLE_INTR 2 +#define NLE_BAD_SOCK 3 +#define NLE_AGAIN 4 +#define NLE_NOMEM 5 +#define NLE_EXIST 6 +#define NLE_INVAL 7 +#define NLE_RANGE 8 +#define NLE_MSGSIZE 9 +#define NLE_OPNOTSUPP 10 +#define NLE_AF_NOSUPPORT 11 +#define NLE_OBJ_NOTFOUND 12 +#define NLE_NOATTR 13 +#define NLE_MISSING_ATTR 14 +#define NLE_AF_MISMATCH 15 +#define NLE_SEQ_MISMATCH 16 +#define NLE_MSG_OVERFLOW 17 +#define NLE_MSG_TRUNC 18 +#define NLE_NOADDR 19 +#define NLE_SRCRT_NOSUPPORT 20 +#define NLE_MSG_TOOSHORT 21 +#define NLE_MSGTYPE_NOSUPPORT 22 +#define NLE_OBJ_MISMATCH 23 +#define NLE_NOCACHE 24 +#define NLE_BUSY 25 +#define NLE_PROTO_MISMATCH 26 +#define NLE_NOACCESS 27 +#define NLE_PERM 28 +#define NLE_PKTLOC_FILE 29 +#define NLE_PARSE_ERR 30 +#define NLE_NODEV 31 +#define NLE_IMMUTABLE 32 +#define NLE_DUMP_INTR 33 + +#define NLE_MAX NLE_DUMP_INTR + +extern const char * nl_geterror(int); +extern void nl_perror(int, const char *); +extern int nl_syserr2nlerr(int); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/fib_lookup/lookup.h b/include/netlink/fib_lookup/lookup.h new file mode 100644 index 0000000..8bf27b8 --- /dev/null +++ b/include/netlink/fib_lookup/lookup.h @@ -0,0 +1,42 @@ +/* + * netlink/fib_lookup/fib_lookup.h FIB Lookup + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + */ + +#ifndef NETLINK_FIB_LOOKUP_H_ +#define NETLINK_FIB_LOOKUP_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct flnl_result; + +extern struct flnl_result * flnl_result_alloc(void); +extern void flnl_result_put(struct flnl_result *); + +extern struct nl_cache * flnl_result_alloc_cache(void); + +extern int flnl_lookup_build_request(struct flnl_request *, + int, + struct nl_msg **); +extern int flnl_lookup(struct nl_sock *, + struct flnl_request *, + struct nl_cache *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/fib_lookup/request.h b/include/netlink/fib_lookup/request.h new file mode 100644 index 0000000..60e8820 --- /dev/null +++ b/include/netlink/fib_lookup/request.h @@ -0,0 +1,51 @@ +/* + * netlink/fib_lookup/request.h FIB Lookup Request + * + * 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 + */ + +#ifndef NETLINK_FIB_LOOKUP_REQUEST_H_ +#define NETLINK_FIB_LOOKUP_REQUEST_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct flnl_request; + +#define REQUEST_CAST(ptr) ((struct flnl_request *) (ptr)) + +extern struct flnl_request * flnl_request_alloc(void); + +extern void flnl_request_set_fwmark(struct flnl_request *, + uint64_t); +extern uint64_t flnl_request_get_fwmark(struct flnl_request *); +extern void flnl_request_set_tos(struct flnl_request *, + int); +extern int flnl_request_get_tos(struct flnl_request *); +extern void flnl_request_set_scope(struct flnl_request *, + int); +extern int flnl_request_get_scope(struct flnl_request *); +extern void flnl_request_set_table(struct flnl_request *, + int); +extern int flnl_request_get_table(struct flnl_request *); +extern int flnl_request_set_addr(struct flnl_request *, + struct nl_addr *); +extern struct nl_addr * flnl_request_get_addr(struct flnl_request *); + +extern int flnl_request_cmp(struct flnl_request *, + struct flnl_request *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/genl/ctrl.h b/include/netlink/genl/ctrl.h new file mode 100644 index 0000000..017b8fd --- /dev/null +++ b/include/netlink/genl/ctrl.h @@ -0,0 +1,40 @@ +/* + * netlink/genl/ctrl.h Generic Netlink Controller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +#ifndef NETLINK_GENL_CTRL_H_ +#define NETLINK_GENL_CTRL_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct genl_family; + +extern int genl_ctrl_alloc_cache(struct nl_sock *, + struct nl_cache **); +extern struct genl_family * genl_ctrl_search(struct nl_cache *, int); +extern struct genl_family * genl_ctrl_search_by_name(struct nl_cache *, + const char *); +extern int genl_ctrl_resolve(struct nl_sock *, + const char *); +extern int genl_ctrl_resolve_grp(struct nl_sock *sk, + const char *family, + const char *grp); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/genl/family.h b/include/netlink/genl/family.h new file mode 100644 index 0000000..5432b59 --- /dev/null +++ b/include/netlink/genl/family.h @@ -0,0 +1,47 @@ +/* + * netlink/genl/family.h Generic Netlink Family + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +#ifndef NETLINK_GENL_FAMILY_H_ +#define NETLINK_GENL_FAMILY_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct genl_family; + +extern struct genl_family * genl_family_alloc(void); +extern void genl_family_put(struct genl_family *); + +extern unsigned int genl_family_get_id(struct genl_family *); +extern void genl_family_set_id(struct genl_family *, unsigned int); +extern char * genl_family_get_name(struct genl_family *); +extern void genl_family_set_name(struct genl_family *, const char *); +extern uint8_t genl_family_get_version(struct genl_family *); +extern void genl_family_set_version(struct genl_family *, uint8_t); +extern uint32_t genl_family_get_hdrsize(struct genl_family *); +extern void genl_family_set_hdrsize(struct genl_family *, uint32_t); +extern uint32_t genl_family_get_maxattr(struct genl_family *); +extern void genl_family_set_maxattr(struct genl_family *, uint32_t); + +extern int genl_family_add_op(struct genl_family *, int, int); +extern int genl_family_add_grp(struct genl_family *, uint32_t , + const char *); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/genl/genl.h b/include/netlink/genl/genl.h new file mode 100644 index 0000000..e455581 --- /dev/null +++ b/include/netlink/genl/genl.h @@ -0,0 +1,52 @@ +/* + * netlink/genl/genl.h Generic Netlink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +#ifndef NETLINK_GENL_H_ +#define NETLINK_GENL_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int genl_connect(struct nl_sock *); +extern int genl_send_simple(struct nl_sock *, int, int, + int, int); + +extern void * genlmsg_put(struct nl_msg *, uint32_t, uint32_t, + int, int, int, uint8_t, uint8_t); + +extern int genlmsg_valid_hdr(struct nlmsghdr *, int); +extern int genlmsg_validate(struct nlmsghdr *, int, int, + struct nla_policy *); +extern int genlmsg_parse(struct nlmsghdr *, int, struct nlattr **, + int, struct nla_policy *); +extern struct genlmsghdr * + genlmsg_hdr(struct nlmsghdr *); +extern void * genlmsg_data(const struct genlmsghdr *); +extern void * genlmsg_user_hdr(const struct genlmsghdr *); +extern void * genlmsg_user_data(const struct genlmsghdr *, const int); +extern int genlmsg_user_datalen(const struct genlmsghdr *, + const int); +extern int genlmsg_len(const struct genlmsghdr *); +extern struct nlattr * genlmsg_attrdata(const struct genlmsghdr *, int); +extern int genlmsg_attrlen(const struct genlmsghdr *, int); + +extern char * genl_op2name(int, int, char *, size_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/genl/mngt.h b/include/netlink/genl/mngt.h new file mode 100644 index 0000000..8a51ccd --- /dev/null +++ b/include/netlink/genl/mngt.h @@ -0,0 +1,176 @@ +/* + * netlink/genl/mngt.h Generic Netlink Management + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +#ifndef NETLINK_GENL_MNGT_H_ +#define NETLINK_GENL_MNGT_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct nl_cache_ops; + +/** + * @ingroup genl_mngt + * @struct genl_info netlink/genl/mngt.h + * + * Informative structure passed on to message parser callbacks + * + * This structure is passed on to all message parser callbacks and contains + * information about the sender of the message as well as pointers to all + * relevant sections of the parsed message. + * + * @see genl_cmd::c_msg_parser + */ +struct genl_info +{ + /** Socket address of sender */ + struct sockaddr_nl * who; + + /** Pointer to Netlink message header */ + struct nlmsghdr * nlh; + + /** Pointer to Generic Netlink message header */ + struct genlmsghdr * genlhdr; + + /** Pointer to user header */ + void * userhdr; + + /** Pointer to array of parsed attributes */ + struct nlattr ** attrs; +}; + +/** + * @ingroup genl_mngt + * @struct genl_cmd netlink/genl/mngt.h + * + * Definition of a Generic Netlink command. + * + * This structure is used to define the list of available commands on the + * receiving side. + * + * @par Example: + * @code + * static struct genl_cmd foo_cmds[] = { + * { + * .c_id = FOO_CMD_NEW, + * .c_name = "NEWFOO" , + * .c_maxattr = FOO_ATTR_MAX, + * .c_attr_policy = foo_policy, + * .c_msg_parser = foo_msg_parser, + * }, + * { + * .c_id = FOO_CMD_DEL, + * .c_name = "DELFOO" , + * }, + * }; + * + * static struct genl_ops my_genl_ops = { + * [...] + * .o_cmds = foo_cmds, + * .o_ncmds = ARRAY_SIZE(foo_cmds), + * }; + * @endcode + */ +struct genl_cmd +{ + /** Numeric command identifier (required) */ + int c_id; + + /** Human readable name (required) */ + char * c_name; + + /** Maximum attribute identifier that the command is prepared to handle. */ + int c_maxattr; + + /** Called whenever a message for this command is received */ + int (*c_msg_parser)(struct nl_cache_ops *, + struct genl_cmd *, + struct genl_info *, void *); + + /** Attribute validation policy, enforced before the callback is called */ + struct nla_policy * c_attr_policy; +}; + +/** + * @ingroup genl_mngt + * @struct genl_ops netlink/genl/mngt.h + * + * Definition of a Generic Netlink family + * + * @par Example: + * @code + * static struct genl_cmd foo_cmds[] = { + * [...] + * }; + * + * static struct genl_ops my_genl_ops = { + * .o_name = "foo", + * .o_hdrsize = sizeof(struct my_hdr), + * .o_cmds = foo_cmds, + * .o_ncmds = ARRAY_SIZE(foo_cmds), + * }; + * + * if ((err = genl_register_family(&my_genl_ops)) < 0) + * // ERROR + * @endcode + * + * @see genl_cmd + */ +struct genl_ops +{ + /** Length of user header */ + unsigned int o_hdrsize; + + /** Numeric identifier, automatically filled in by genl_ops_resolve() */ + int o_id; + + /** Human readable name, used by genl_ops_resolve() to resolve numeric id */ + char * o_name; + + /** + * If registered via genl_register(), will point to the related + * cache operations. + */ + struct nl_cache_ops * o_cache_ops; + + /** Optional array defining the available Generic Netlink commands */ + struct genl_cmd * o_cmds; + + /** Number of elements in \c o_cmds array */ + int o_ncmds; + + /** + * @private + * Used internally to link together all registered operations. + */ + struct nl_list_head o_list; +}; + +extern int genl_register_family(struct genl_ops *); +extern int genl_unregister_family(struct genl_ops *); +extern int genl_handle_msg(struct nl_msg *, void *); + +extern int genl_register(struct nl_cache_ops *); +extern void genl_unregister(struct nl_cache_ops *); + +extern int genl_ops_resolve(struct nl_sock *, struct genl_ops *); +extern int genl_mngt_resolve(struct nl_sock *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/handlers.h b/include/netlink/handlers.h new file mode 100644 index 0000000..dfa2809 --- /dev/null +++ b/include/netlink/handlers.h @@ -0,0 +1,146 @@ +/* + * netlink/handlers.c default netlink message handlers + * + * 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 + */ + +#ifndef NETLINK_HANDLERS_H_ +#define NETLINK_HANDLERS_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct nl_cb; +struct nl_sock; +struct nl_msg; +struct ucred; + +/** + * @name Callback Typedefs + * @{ + */ + +/** + * nl_recvmsgs() callback for message processing customization + * @ingroup cb + * @arg msg netlink message being processed + * @arg arg argument passwd on through caller + */ +typedef int (*nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg); + +/** + * nl_recvmsgs() callback for error message processing customization + * @ingroup cb + * @arg nla netlink address of the peer + * @arg nlerr netlink error message being processed + * @arg arg argument passed on through caller + */ +typedef int (*nl_recvmsg_err_cb_t)(struct sockaddr_nl *nla, + struct nlmsgerr *nlerr, void *arg); + +/** @} */ + +/** + * Callback actions + * @ingroup cb + */ +enum nl_cb_action { + /** Proceed with wathever would come next */ + NL_OK, + /** Skip this message */ + NL_SKIP, + /** Stop parsing altogether and discard remaining messages */ + NL_STOP, +}; + +/** + * Callback kinds + * @ingroup cb + */ +enum nl_cb_kind { + /** Default handlers (quiet) */ + NL_CB_DEFAULT, + /** Verbose default handlers (error messages printed) */ + NL_CB_VERBOSE, + /** Debug handlers for debugging */ + NL_CB_DEBUG, + /** Customized handler specified by the user */ + NL_CB_CUSTOM, + __NL_CB_KIND_MAX, +}; + +#define NL_CB_KIND_MAX (__NL_CB_KIND_MAX - 1) + +/** + * Callback types + * @ingroup cb + */ +enum nl_cb_type { + /** Message is valid */ + NL_CB_VALID, + /** Last message in a series of multi part messages received */ + NL_CB_FINISH, + /** Report received that data was lost */ + NL_CB_OVERRUN, + /** Message wants to be skipped */ + NL_CB_SKIPPED, + /** Message is an acknowledge */ + NL_CB_ACK, + /** Called for every message received */ + NL_CB_MSG_IN, + /** Called for every message sent out except for nl_sendto() */ + NL_CB_MSG_OUT, + /** Message is malformed and invalid */ + NL_CB_INVALID, + /** Called instead of internal sequence number checking */ + NL_CB_SEQ_CHECK, + /** Sending of an acknowledge message has been requested */ + NL_CB_SEND_ACK, + /** Flag NLM_F_DUMP_INTR is set in message */ + NL_CB_DUMP_INTR, + __NL_CB_TYPE_MAX, +}; + +#define NL_CB_TYPE_MAX (__NL_CB_TYPE_MAX - 1) + +extern struct nl_cb * nl_cb_alloc(enum nl_cb_kind); +extern struct nl_cb * nl_cb_clone(struct nl_cb *); +extern struct nl_cb * nl_cb_get(struct nl_cb *); +extern void nl_cb_put(struct nl_cb *); + +extern int nl_cb_set(struct nl_cb *, enum nl_cb_type, enum nl_cb_kind, + nl_recvmsg_msg_cb_t, void *); +extern int nl_cb_set_all(struct nl_cb *, enum nl_cb_kind, + nl_recvmsg_msg_cb_t, void *); +extern int nl_cb_err(struct nl_cb *, enum nl_cb_kind, nl_recvmsg_err_cb_t, + void *); + +extern void nl_cb_overwrite_recvmsgs(struct nl_cb *, + int (*func)(struct nl_sock *, + struct nl_cb *)); +extern void nl_cb_overwrite_recv(struct nl_cb *, + int (*func)(struct nl_sock *, + struct sockaddr_nl *, + unsigned char **, + struct ucred **)); +extern void nl_cb_overwrite_send(struct nl_cb *, + int (*func)(struct nl_sock *, + struct nl_msg *)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/hash.h b/include/netlink/hash.h new file mode 100644 index 0000000..0bda74e --- /dev/null +++ b/include/netlink/hash.h @@ -0,0 +1,69 @@ +/* + * This file was taken from http://ccodearchive.net/info/hash.html + * Changes to the original file include cleanups and removal of unwanted code + * and also code that depended on build_asert + */ +#ifndef CCAN_HASH_H +#define CCAN_HASH_H +#include +#include +#include + +/* Stolen mostly from: lookup3.c, by Bob Jenkins, May 2006, Public Domain. + * + * http://burtleburtle.net/bob/c/lookup3.c + */ + +#ifdef __LITTLE_ENDIAN +# define HAVE_LITTLE_ENDIAN 1 +#elif __BIG_ENDIAN +# define HAVE_BIG_ENDIAN 1 +#else +#error Unknown endianness. Failure in endian.h +#endif + +/** + * hash - fast hash of an array for internal use + * @p: the array or pointer to first element + * @num: the number of elements to hash + * @base: the base number to roll into the hash (usually 0) + * + * The memory region pointed to by p is combined with the base to form + * a 32-bit hash. + * + * This hash will have different results on different machines, so is + * only useful for internal hashes (ie. not hashes sent across the + * network or saved to disk). + * + * It may also change with future versions: it could even detect at runtime + * what the fastest hash to use is. + * + * See also: hash64, hash_stable. + * + * Example: + * #include + * #include + * #include + * #include + * + * // Simple demonstration: idential strings will have the same hash, but + * // two different strings will probably not. + * int main(int argc, char *argv[]) + * { + * uint32_t hash1, hash2; + * + * if (argc != 3) + * err(1, "Usage: %s ", argv[0]); + * + * hash1 = __nl_hash(argv[1], strlen(argv[1]), 0); + * hash2 = __nl_hash(argv[2], strlen(argv[2]), 0); + * printf("Hash is %s\n", hash1 == hash2 ? "same" : "different"); + * return 0; + * } + */ +#define __nl_hash(p, num, base) nl_hash_any((p), (num)*sizeof(*(p)), (base)) + +/* Our underlying operations. */ +uint32_t nl_hash_any(const void *key, size_t length, uint32_t base); + +#endif /* HASH_H */ diff --git a/include/netlink/hashtable.h b/include/netlink/hashtable.h new file mode 100644 index 0000000..d9e6ee4 --- /dev/null +++ b/include/netlink/hashtable.h @@ -0,0 +1,52 @@ +/* + * netlink/hashtable.h Netlink hashtable Utilities + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2012 Cumulus Networks, Inc + */ + +#ifndef NETLINK_HASHTABLE_H_ +#define NETLINK_HASHTABLE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct nl_hash_node { + uint32_t key; + uint32_t key_size; + struct nl_object * obj; + struct nl_hash_node * next; +} nl_hash_node_t; + +typedef struct nl_hash_table { + int size; + nl_hash_node_t ** nodes; +} nl_hash_table_t; + +/* Default hash table size */ +#define NL_MAX_HASH_ENTRIES 1024 + +/* Access Functions */ +extern nl_hash_table_t * nl_hash_table_alloc(int size); +extern void nl_hash_table_free(nl_hash_table_t *ht); + +extern int nl_hash_table_add(nl_hash_table_t *ht, + struct nl_object *obj); +extern int nl_hash_table_del(nl_hash_table_t *ht, + struct nl_object *obj); + +extern struct nl_object * nl_hash_table_lookup(nl_hash_table_t *ht, + struct nl_object *obj); +extern uint32_t nl_hash(void *k, size_t length, + uint32_t initval); + +#ifdef __cplusplus +} +#endif + +#endif /* NETLINK_HASHTABLE_H_ */ diff --git a/include/netlink/list.h b/include/netlink/list.h new file mode 100644 index 0000000..28712ed --- /dev/null +++ b/include/netlink/list.h @@ -0,0 +1,93 @@ +/* + * netlink/list.h Netlink List Utilities + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2006 Thomas Graf + */ + +#ifndef NETLINK_LIST_H_ +#define NETLINK_LIST_H_ + +struct nl_list_head +{ + struct nl_list_head * next; + struct nl_list_head * prev; +}; + +static inline void NL_INIT_LIST_HEAD(struct nl_list_head *list) +{ + list->next = list; + list->prev = list; +} + +static inline void __nl_list_add(struct nl_list_head *obj, + struct nl_list_head *prev, + struct nl_list_head *next) +{ + prev->next = obj; + obj->prev = prev; + next->prev = obj; + obj->next = next; +} + +static inline void nl_list_add_tail(struct nl_list_head *obj, + struct nl_list_head *head) +{ + __nl_list_add(obj, head->prev, head); +} + +static inline void nl_list_add_head(struct nl_list_head *obj, + struct nl_list_head *head) +{ + __nl_list_add(obj, head, head->next); +} + +static inline void nl_list_del(struct nl_list_head *obj) +{ + obj->next->prev = obj->prev; + obj->prev->next = obj->next; +} + +static inline int nl_list_empty(struct nl_list_head *head) +{ + return head->next == head; +} + +#define nl_container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - ((size_t) &((type *)0)->member));}) + +#define nl_list_entry(ptr, type, member) \ + nl_container_of(ptr, type, member) + +#define nl_list_at_tail(pos, head, member) \ + ((pos)->member.next == (head)) + +#define nl_list_at_head(pos, head, member) \ + ((pos)->member.prev == (head)) + +#define NL_LIST_HEAD(name) \ + struct nl_list_head name = { &(name), &(name) } + +#define nl_list_first_entry(head, type, member) \ + nl_list_entry((head)->next, type, member) + +#define nl_list_for_each_entry(pos, head, member) \ + for (pos = nl_list_entry((head)->next, typeof(*pos), member); \ + &(pos)->member != (head); \ + (pos) = nl_list_entry((pos)->member.next, typeof(*(pos)), member)) + +#define nl_list_for_each_entry_safe(pos, n, head, member) \ + for (pos = nl_list_entry((head)->next, typeof(*pos), member), \ + n = nl_list_entry(pos->member.next, typeof(*pos), member); \ + &(pos)->member != (head); \ + pos = n, n = nl_list_entry(n->member.next, typeof(*n), member)) + +#define nl_init_list_head(head) \ + do { (head)->next = (head); (head)->prev = (head); } while (0) + +#endif diff --git a/include/netlink/msg.h b/include/netlink/msg.h new file mode 100644 index 0000000..f3d50ae --- /dev/null +++ b/include/netlink/msg.h @@ -0,0 +1,147 @@ +/* + * netlink/msg.c Netlink Messages Interface + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2006 Thomas Graf + */ + +#ifndef NETLINK_MSG_H_ +#define NETLINK_MSG_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define NL_DONTPAD 0 + +/** + * @ingroup msg + * @brief + * Will cause the netlink port to be set to the port assigned to + * the netlink icoket ust before sending the message off. + * + * @note Requires the use of nl_send_auto()! + */ +#define NL_AUTO_PORT 0 +#define NL_AUTO_PID NL_AUTO_PORT + +/** + * @ingroup msg + * @brief + * May be used to refer to a sequence number which should be + * automatically set just before sending the message off. + * + * @note Requires the use of nl_send_auto()! + */ +#define NL_AUTO_SEQ 0 + +struct nl_msg; +struct nl_tree; +struct ucred; + +extern int nlmsg_size(int); +extern int nlmsg_total_size(int); +extern int nlmsg_padlen(int); + +extern void * nlmsg_data(const struct nlmsghdr *); +extern int nlmsg_datalen(const struct nlmsghdr *); +extern void * nlmsg_tail(const struct nlmsghdr *); + +/* attribute access */ +extern struct nlattr * nlmsg_attrdata(const struct nlmsghdr *, int); +extern int nlmsg_attrlen(const struct nlmsghdr *, int); + +/* message parsing */ +extern int nlmsg_valid_hdr(const struct nlmsghdr *, int); +extern int nlmsg_ok(const struct nlmsghdr *, int); +extern struct nlmsghdr * nlmsg_next(struct nlmsghdr *, int *); +extern int nlmsg_parse(struct nlmsghdr *, int, struct nlattr **, + int, struct nla_policy *); +extern struct nlattr * nlmsg_find_attr(struct nlmsghdr *, int, int); +extern int nlmsg_validate(struct nlmsghdr *, int, int, + struct nla_policy *); + +extern struct nl_msg * nlmsg_alloc(void); +extern struct nl_msg * nlmsg_alloc_size(size_t); +extern struct nl_msg * nlmsg_alloc_simple(int, int); +extern void nlmsg_set_default_size(size_t); +extern struct nl_msg * nlmsg_inherit(struct nlmsghdr *); +extern struct nl_msg * nlmsg_convert(struct nlmsghdr *); +extern void * nlmsg_reserve(struct nl_msg *, size_t, int); +extern int nlmsg_append(struct nl_msg *, void *, size_t, int); +extern int nlmsg_expand(struct nl_msg *, size_t); + +extern struct nlmsghdr * nlmsg_put(struct nl_msg *, uint32_t, uint32_t, + int, int, int); +extern struct nlmsghdr * nlmsg_hdr(struct nl_msg *); +extern void nlmsg_get(struct nl_msg *); +extern void nlmsg_free(struct nl_msg *); + +/* attribute modification */ +extern void nlmsg_set_proto(struct nl_msg *, int); +extern int nlmsg_get_proto(struct nl_msg *); +extern size_t nlmsg_get_max_size(struct nl_msg *); +extern void nlmsg_set_src(struct nl_msg *, struct sockaddr_nl *); +extern struct sockaddr_nl *nlmsg_get_src(struct nl_msg *); +extern void nlmsg_set_dst(struct nl_msg *, struct sockaddr_nl *); +extern struct sockaddr_nl *nlmsg_get_dst(struct nl_msg *); +extern void nlmsg_set_creds(struct nl_msg *, struct ucred *); +extern struct ucred * nlmsg_get_creds(struct nl_msg *); + +extern char * nl_nlmsgtype2str(int, char *, size_t); +extern int nl_str2nlmsgtype(const char *); + +extern char * nl_nlmsg_flags2str(int, char *, size_t); + +extern int nl_msg_parse(struct nl_msg *, + void (*cb)(struct nl_object *, void *), + void *); + +extern void nl_msg_dump(struct nl_msg *, FILE *); + +/** + * @name Iterators + * @{ + */ + +/** + * @ingroup msg + * Iterate over a stream of attributes in a message + * @arg pos loop counter, set to current attribute + * @arg nlh netlink message header + * @arg hdrlen length of family header + * @arg rem initialized to len, holds bytes currently remaining in stream + */ +#define nlmsg_for_each_attr(pos, nlh, hdrlen, rem) \ + nla_for_each_attr(pos, nlmsg_attrdata(nlh, hdrlen), \ + nlmsg_attrlen(nlh, hdrlen), rem) + +/** + * Iterate over a stream of messages + * @arg pos loop counter, set to current message + * @arg head head of message stream + * @arg len length of message stream + */ +#define nlmsg_for_each(pos, head, len) \ + for (int rem = len, pos = head; \ + nlmsg_ok(pos, rem); \ + pos = nlmsg_next(pos, &rem)) + +#define nlmsg_for_each_msg(pos, head, len, rem) \ + nlmsg_for_each(pos, head, len) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/netfilter/ct.h b/include/netlink/netfilter/ct.h new file mode 100644 index 0000000..57fbe53 --- /dev/null +++ b/include/netlink/netfilter/ct.h @@ -0,0 +1,126 @@ +/* + * netlink/netfilter/ct.h Conntrack + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + */ + +#ifndef NETLINK_CT_H_ +#define NETLINK_CT_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct nfnl_ct; + +extern struct nl_object_ops ct_obj_ops; + +extern struct nfnl_ct * nfnl_ct_alloc(void); +extern int nfnl_ct_alloc_cache(struct nl_sock *, struct nl_cache **); + +extern int nfnlmsg_ct_group(struct nlmsghdr *); +extern int nfnlmsg_ct_parse(struct nlmsghdr *, struct nfnl_ct **); + +extern void nfnl_ct_get(struct nfnl_ct *); +extern void nfnl_ct_put(struct nfnl_ct *); + +extern int nfnl_ct_dump_request(struct nl_sock *); + +extern int nfnl_ct_build_add_request(const struct nfnl_ct *, int, + struct nl_msg **); +extern int nfnl_ct_add(struct nl_sock *, const struct nfnl_ct *, int); + +extern int nfnl_ct_build_delete_request(const struct nfnl_ct *, int, + struct nl_msg **); +extern int nfnl_ct_del(struct nl_sock *, const struct nfnl_ct *, int); + +extern int nfnl_ct_build_query_request(const struct nfnl_ct *, int, + struct nl_msg **); +extern int nfnl_ct_query(struct nl_sock *, const struct nfnl_ct *, int); + +extern void nfnl_ct_set_family(struct nfnl_ct *, uint8_t); +extern uint8_t nfnl_ct_get_family(const struct nfnl_ct *); + +extern void nfnl_ct_set_proto(struct nfnl_ct *, uint8_t); +extern int nfnl_ct_test_proto(const struct nfnl_ct *); +extern uint8_t nfnl_ct_get_proto(const struct nfnl_ct *); + +extern void nfnl_ct_set_tcp_state(struct nfnl_ct *, uint8_t); +extern int nfnl_ct_test_tcp_state(const struct nfnl_ct *); +extern uint8_t nfnl_ct_get_tcp_state(const struct nfnl_ct *); +extern char * nfnl_ct_tcp_state2str(uint8_t, char *, size_t); +extern int nfnl_ct_str2tcp_state(const char *name); + +extern void nfnl_ct_set_status(struct nfnl_ct *, uint32_t); +extern void nfnl_ct_unset_status(struct nfnl_ct *, uint32_t); +extern uint32_t nfnl_ct_get_status(const struct nfnl_ct *); +extern char * nfnl_ct_status2str(int, char *, size_t); +extern int nfnl_ct_str2status(const char *); + +extern void nfnl_ct_set_timeout(struct nfnl_ct *, uint32_t); +extern int nfnl_ct_test_timeout(const struct nfnl_ct *); +extern uint32_t nfnl_ct_get_timeout(const struct nfnl_ct *); + +extern void nfnl_ct_set_mark(struct nfnl_ct *, uint32_t); +extern int nfnl_ct_test_mark(const struct nfnl_ct *); +extern uint32_t nfnl_ct_get_mark(const struct nfnl_ct *); + +extern void nfnl_ct_set_use(struct nfnl_ct *, uint32_t); +extern int nfnl_ct_test_use(const struct nfnl_ct *); +extern uint32_t nfnl_ct_get_use(const struct nfnl_ct *); + +extern void nfnl_ct_set_id(struct nfnl_ct *, uint32_t); +extern int nfnl_ct_test_id(const struct nfnl_ct *); +extern uint32_t nfnl_ct_get_id(const struct nfnl_ct *); + +extern int nfnl_ct_set_src(struct nfnl_ct *, int, struct nl_addr *); +extern struct nl_addr * nfnl_ct_get_src(const struct nfnl_ct *, int); + +extern int nfnl_ct_set_dst(struct nfnl_ct *, int, struct nl_addr *); +extern struct nl_addr * nfnl_ct_get_dst(const struct nfnl_ct *, int); + +extern void nfnl_ct_set_src_port(struct nfnl_ct *, int, uint16_t); +extern int nfnl_ct_test_src_port(const struct nfnl_ct *, int); +extern uint16_t nfnl_ct_get_src_port(const struct nfnl_ct *, int); + +extern void nfnl_ct_set_dst_port(struct nfnl_ct *, int, uint16_t); +extern int nfnl_ct_test_dst_port(const struct nfnl_ct *, int); +extern uint16_t nfnl_ct_get_dst_port(const struct nfnl_ct *, int); + +extern void nfnl_ct_set_icmp_id(struct nfnl_ct *, int, uint16_t); +extern int nfnl_ct_test_icmp_id(const struct nfnl_ct *, int); +extern uint16_t nfnl_ct_get_icmp_id(const struct nfnl_ct *, int); + +extern void nfnl_ct_set_icmp_type(struct nfnl_ct *, int, uint8_t); +extern int nfnl_ct_test_icmp_type(const struct nfnl_ct *, int); +extern uint8_t nfnl_ct_get_icmp_type(const struct nfnl_ct *, int); + +extern void nfnl_ct_set_icmp_code(struct nfnl_ct *, int, uint8_t); +extern int nfnl_ct_test_icmp_code(const struct nfnl_ct *, int); +extern uint8_t nfnl_ct_get_icmp_code(const struct nfnl_ct *, int); + +extern void nfnl_ct_set_packets(struct nfnl_ct *, int, uint64_t); +extern int nfnl_ct_test_packets(const struct nfnl_ct *, int); +extern uint64_t nfnl_ct_get_packets(const struct nfnl_ct *,int); + +extern void nfnl_ct_set_bytes(struct nfnl_ct *, int, uint64_t); +extern int nfnl_ct_test_bytes(const struct nfnl_ct *, int); +extern uint64_t nfnl_ct_get_bytes(const struct nfnl_ct *, int); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/netfilter/exp.h b/include/netlink/netfilter/exp.h new file mode 100644 index 0000000..4e95014 --- /dev/null +++ b/include/netlink/netfilter/exp.h @@ -0,0 +1,129 @@ +/* + * netlink/netfilter/exp.h Conntrack Expectation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c) 2012 Rich Fought + */ + +#ifndef NETLINK_EXP_H_ +#define NETLINK_EXP_H_ + +#include +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct nfnl_exp; + +enum nfnl_exp_tuples { + NFNL_EXP_TUPLE_EXPECT, + NFNL_EXP_TUPLE_MASTER, + NFNL_EXP_TUPLE_MASK, + NFNL_EXP_TUPLE_NAT, + NFNL_EXP_TUPLE_MAX +}; + +extern struct nl_object_ops exp_obj_ops; + +extern struct nfnl_exp * nfnl_exp_alloc(void); +extern int nfnl_exp_alloc_cache(struct nl_sock *, struct nl_cache **); + +extern int nfnlmsg_exp_group(struct nlmsghdr *); +extern int nfnlmsg_exp_parse(struct nlmsghdr *, struct nfnl_exp **); + +extern void nfnl_exp_get(struct nfnl_exp *); +extern void nfnl_exp_put(struct nfnl_exp *); + +extern int nfnl_exp_dump_request(struct nl_sock *); + +extern int nfnl_exp_build_add_request(const struct nfnl_exp *, int, + struct nl_msg **); +extern int nfnl_exp_add(struct nl_sock *, const struct nfnl_exp *, int); + +extern int nfnl_exp_build_delete_request(const struct nfnl_exp *, int, + struct nl_msg **); +extern int nfnl_exp_del(struct nl_sock *, const struct nfnl_exp *, int); + +extern int nfnl_exp_build_query_request(const struct nfnl_exp *, int, + struct nl_msg **); +extern int nfnl_exp_query(struct nl_sock *, const struct nfnl_exp *, int); + +extern void nfnl_exp_set_family(struct nfnl_exp *, uint8_t); +extern uint8_t nfnl_exp_get_family(const struct nfnl_exp *); + +extern void nfnl_exp_set_timeout(struct nfnl_exp *, uint32_t); +extern int nfnl_exp_test_timeout(const struct nfnl_exp *); +extern uint32_t nfnl_exp_get_timeout(const struct nfnl_exp *); + +extern void nfnl_exp_set_id(struct nfnl_exp *, uint32_t); +extern int nfnl_exp_test_id(const struct nfnl_exp *); +extern uint32_t nfnl_exp_get_id(const struct nfnl_exp *); + +extern int nfnl_exp_set_helper_name(struct nfnl_exp *, void *); +extern int nfnl_exp_test_helper_name(const struct nfnl_exp *); +extern const char * nfnl_exp_get_helper_name(const struct nfnl_exp *); + +extern void nfnl_exp_set_zone(struct nfnl_exp *, uint16_t); +extern int nfnl_exp_test_zone(const struct nfnl_exp *); +extern uint16_t nfnl_exp_get_zone(const struct nfnl_exp *); + +extern void nfnl_exp_set_flags(struct nfnl_exp *, uint32_t); +extern int nfnl_exp_test_flags(const struct nfnl_exp *); +extern uint32_t nfnl_exp_get_flags(const struct nfnl_exp *); + +extern void nfnl_exp_set_class(struct nfnl_exp *, uint32_t); +extern int nfnl_exp_test_class(const struct nfnl_exp *); +extern uint32_t nfnl_exp_get_class(const struct nfnl_exp *); + +extern int nfnl_exp_set_fn(struct nfnl_exp *, void *); +extern int nfnl_exp_test_fn(const struct nfnl_exp *); +extern const char * nfnl_exp_get_fn(const struct nfnl_exp *); + +extern void nfnl_exp_set_nat_dir(struct nfnl_exp *, uint8_t); +extern int nfnl_exp_test_nat_dir(const struct nfnl_exp *); +extern uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *); + +// The int argument specifies which nfnl_exp_dir (expect, master, mask or nat) +// Expectation objects only use orig, not reply + +extern int nfnl_exp_set_src(struct nfnl_exp *, int, struct nl_addr *); +extern int nfnl_exp_test_src(const struct nfnl_exp *, int); +extern struct nl_addr * nfnl_exp_get_src(const struct nfnl_exp *, int); + +extern int nfnl_exp_set_dst(struct nfnl_exp *, int, struct nl_addr *); +extern int nfnl_exp_test_dst(const struct nfnl_exp *, int); +extern struct nl_addr * nfnl_exp_get_dst(const struct nfnl_exp *, int); + +extern void nfnl_exp_set_l4protonum(struct nfnl_exp *, int, uint8_t); +extern int nfnl_exp_test_l4protonum(const struct nfnl_exp *, int); +extern uint8_t nfnl_exp_get_l4protonum(const struct nfnl_exp *, int); + +extern void nfnl_exp_set_ports(struct nfnl_exp *, int, uint16_t, uint16_t); +extern int nfnl_exp_test_ports(const struct nfnl_exp *, int); +extern uint16_t nfnl_exp_get_src_port(const struct nfnl_exp *, int); +extern uint16_t nfnl_exp_get_dst_port(const struct nfnl_exp *, int); + +extern void nfnl_exp_set_icmp(struct nfnl_exp *, int, uint16_t, uint8_t, uint8_t); +extern int nfnl_exp_test_icmp(const struct nfnl_exp *, int); +extern uint16_t nfnl_exp_get_icmp_id(const struct nfnl_exp *, int); +extern uint8_t nfnl_exp_get_icmp_type(const struct nfnl_exp *, int); +extern uint8_t nfnl_exp_get_icmp_code(const struct nfnl_exp *, int); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/netfilter/log.h b/include/netlink/netfilter/log.h new file mode 100644 index 0000000..2002fa8 --- /dev/null +++ b/include/netlink/netfilter/log.h @@ -0,0 +1,109 @@ +/* + * netlink/netfilter/log.h Netfilter Log + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2006 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c) 2008 Patrick McHardy + */ + +#ifndef NETLINK_LOG_H_ +#define NETLINK_LOG_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct nl_sock; +struct nlmsghdr; +struct nfnl_log; + +extern struct nl_object_ops log_obj_ops; + +enum nfnl_log_copy_mode { + NFNL_LOG_COPY_NONE, + NFNL_LOG_COPY_META, + NFNL_LOG_COPY_PACKET, +}; + +enum nfnl_log_flags { + NFNL_LOG_FLAG_SEQ = 0x1, + NFNL_LOG_FLAG_SEQ_GLOBAL = 0x2, +}; + +/* General */ +extern struct nfnl_log * nfnl_log_alloc(void); +extern int nfnlmsg_log_parse(struct nlmsghdr *, + struct nfnl_log **); + +extern void nfnl_log_get(struct nfnl_log *); +extern void nfnl_log_put(struct nfnl_log *); + +/* Attributes */ +extern void nfnl_log_set_group(struct nfnl_log *, uint16_t); +extern int nfnl_log_test_group(const struct nfnl_log *); +extern uint16_t nfnl_log_get_group(const struct nfnl_log *); + +extern void nfnl_log_set_copy_mode(struct nfnl_log *, + enum nfnl_log_copy_mode); +extern int nfnl_log_test_copy_mode(const struct nfnl_log *); +extern enum nfnl_log_copy_mode nfnl_log_get_copy_mode(const struct nfnl_log *); + +extern char * nfnl_log_copy_mode2str(enum nfnl_log_copy_mode, + char *, size_t); +extern enum nfnl_log_copy_mode nfnl_log_str2copy_mode(const char *); + +extern void nfnl_log_set_copy_range(struct nfnl_log *, uint32_t); +extern int nfnl_log_test_copy_range(const struct nfnl_log *); +extern uint32_t nfnl_log_get_copy_range(const struct nfnl_log *); + +extern void nfnl_log_set_flush_timeout(struct nfnl_log *, uint32_t); +extern int nfnl_log_test_flush_timeout(const struct nfnl_log *); +extern uint32_t nfnl_log_get_flush_timeout(const struct nfnl_log *); + +extern void nfnl_log_set_alloc_size(struct nfnl_log *, uint32_t); +extern int nfnl_log_test_alloc_size(const struct nfnl_log *); +extern uint32_t nfnl_log_get_alloc_size(const struct nfnl_log *); + +extern void nfnl_log_set_queue_threshold(struct nfnl_log *, uint32_t); +extern int nfnl_log_test_queue_threshold(const struct nfnl_log *); +extern uint32_t nfnl_log_get_queue_threshold(const struct nfnl_log *); + +extern void nfnl_log_set_flags(struct nfnl_log *, unsigned int); +extern void nfnl_log_unset_flags(struct nfnl_log *, unsigned int); +extern unsigned int nfnl_log_get_flags(const struct nfnl_log *); + +extern char * nfnl_log_flags2str(unsigned int, char *, size_t); +extern unsigned int nfnl_log_str2flags(const char *); + +extern int nfnl_log_build_pf_bind(uint8_t, struct nl_msg **); +extern int nfnl_log_pf_bind(struct nl_sock *, uint8_t); + +extern int nfnl_log_build_pf_unbind(uint8_t, struct nl_msg **); +extern int nfnl_log_pf_unbind(struct nl_sock *, uint8_t); + +extern int nfnl_log_build_create_request(const struct nfnl_log *, + struct nl_msg **); +extern int nfnl_log_create(struct nl_sock *, const struct nfnl_log *); + +extern int nfnl_log_build_change_request(const struct nfnl_log *, + struct nl_msg **); +extern int nfnl_log_change(struct nl_sock *, const struct nfnl_log *); + +extern int nfnl_log_build_delete_request(const struct nfnl_log *, + struct nl_msg **); +extern int nfnl_log_delete(struct nl_sock *, const struct nfnl_log *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/netlink/netfilter/log_msg.h b/include/netlink/netfilter/log_msg.h new file mode 100644 index 0000000..63b0f64 --- /dev/null +++ b/include/netlink/netfilter/log_msg.h @@ -0,0 +1,98 @@ +/* + * netlink/netfilter/log_msg.h Netfilter Log Message + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c) 2008 Patrick McHardy + */ + +#ifndef NETLINK_LOG_MSG_H_ +#define NETLINK_LOG_MSG_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct nlmsghdr; +struct nfnl_log_msg; + +extern struct nl_object_ops log_msg_obj_ops; + +/* General */ +extern struct nfnl_log_msg *nfnl_log_msg_alloc(void); +extern int nfnlmsg_log_msg_parse(struct nlmsghdr *, + struct nfnl_log_msg **); + +extern void nfnl_log_msg_get(struct nfnl_log_msg *); +extern void nfnl_log_msg_put(struct nfnl_log_msg *); + +extern void nfnl_log_msg_set_family(struct nfnl_log_msg *, uint8_t); +extern uint8_t nfnl_log_msg_get_family(const struct nfnl_log_msg *); + +extern void nfnl_log_msg_set_hwproto(struct nfnl_log_msg *, uint16_t); +extern int nfnl_log_msg_test_hwproto(const struct nfnl_log_msg *); +extern uint16_t nfnl_log_msg_get_hwproto(const struct nfnl_log_msg *); + +extern void nfnl_log_msg_set_hook(struct nfnl_log_msg *, uint8_t); +extern int nfnl_log_msg_test_hook(const struct nfnl_log_msg *); +extern uint8_t nfnl_log_msg_get_hook(const struct nfnl_log_msg *); + +extern void nfnl_log_msg_set_mark(struct nfnl_log_msg *, uint32_t); +extern int nfnl_log_msg_test_mark(const struct nfnl_log_msg *); +extern uint32_t nfnl_log_msg_get_mark(const struct nfnl_log_msg *); + +extern void nfnl_log_msg_set_timestamp(struct nfnl_log_msg *, + struct timeval *); +extern const struct timeval *nfnl_log_msg_get_timestamp(const struct nfnl_log_msg *); + +extern void nfnl_log_msg_set_indev(struct nfnl_log_msg *, uint32_t); +extern uint32_t nfnl_log_msg_get_indev(const struct nfnl_log_msg *); + +extern void nfnl_log_msg_set_outdev(struct nfnl_log_msg *, uint32_t); +extern uint32_t nfnl_log_msg_get_outdev(const struct nfnl_log_msg *); + +extern void nfnl_log_msg_set_physindev(struct nfnl_log_msg *, uint32_t); +extern uint32_t nfnl_log_msg_get_physindev(const struct nfnl_log_msg *); + +extern void nfnl_log_msg_set_physoutdev(struct nfnl_log_msg *, uint32_t); +extern uint32_t nfnl_log_msg_get_physoutdev(const struct nfnl_log_msg *); + +extern void nfnl_log_msg_set_hwaddr(struct nfnl_log_msg *, uint8_t *, int); +extern const uint8_t * nfnl_log_msg_get_hwaddr(const struct nfnl_log_msg *, int *); + +extern int nfnl_log_msg_set_payload(struct nfnl_log_msg *, uint8_t *, int); +extern const void * nfnl_log_msg_get_payload(const struct nfnl_log_msg *, int *); + +extern int nfnl_log_msg_set_prefix(struct nfnl_log_msg *, void *); +extern const char * nfnl_log_msg_get_prefix(const struct nfnl_log_msg *); + +extern void nfnl_log_msg_set_uid(struct nfnl_log_msg *, uint32_t); +extern int nfnl_log_msg_test_uid(const struct nfnl_log_msg *); +extern uint32_t nfnl_log_msg_get_uid(const struct nfnl_log_msg *); + +extern void nfnl_log_msg_set_gid(struct nfnl_log_msg *, uint32_t); +extern int nfnl_log_msg_test_gid(const struct nfnl_log_msg *); +extern uint32_t nfnl_log_msg_get_gid(const struct nfnl_log_msg *); + +extern void nfnl_log_msg_set_seq(struct nfnl_log_msg *, uint32_t); +extern int nfnl_log_msg_test_seq(const struct nfnl_log_msg *); +extern uint32_t nfnl_log_msg_get_seq(const struct nfnl_log_msg *); + +extern void nfnl_log_msg_set_seq_global(struct nfnl_log_msg *, uint32_t); +extern int nfnl_log_msg_test_seq_global(const struct nfnl_log_msg *); +extern uint32_t nfnl_log_msg_get_seq_global(const struct nfnl_log_msg *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/netlink/netfilter/netfilter.h b/include/netlink/netfilter/netfilter.h new file mode 100644 index 0000000..dd3589c --- /dev/null +++ b/include/netlink/netfilter/netfilter.h @@ -0,0 +1,31 @@ +/* + * netlink/netfilter/netfilter.h Netfilter generic functions + * + * 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 Patrick McHardy + */ + +#ifndef NETLINK_NETFILTER_H_ +#define NETLINK_NETFILTER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern char * nfnl_verdict2str(unsigned int, char *, size_t); +extern unsigned int nfnl_str2verdict(const char *); + +extern char * nfnl_inet_hook2str(unsigned int, char *, size_t); +extern unsigned int nfnl_str2inet_hook(const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/netfilter/nfnl.h b/include/netlink/netfilter/nfnl.h new file mode 100644 index 0000000..8da4ba1 --- /dev/null +++ b/include/netlink/netfilter/nfnl.h @@ -0,0 +1,44 @@ +/* + * netlink/nfnl/nfnl.h Netfilter Netlink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + */ + +#ifndef NETLINK_NFNL_H_ +#define NETLINK_NFNL_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define NFNL_HDRLEN NLMSG_ALIGN(sizeof(struct nfgenmsg)) +#define NFNLMSG_TYPE(subsys, subtype) (((subsys) << 8) | (subtype)) + +extern int nfnl_connect(struct nl_sock *); + +extern uint8_t nfnlmsg_subsys(struct nlmsghdr *); +extern uint8_t nfnlmsg_subtype(struct nlmsghdr *); +extern uint8_t nfnlmsg_family(struct nlmsghdr *); +extern uint16_t nfnlmsg_res_id(struct nlmsghdr *); + +extern int nfnl_send_simple(struct nl_sock *, uint8_t, uint8_t, + int, uint8_t, uint16_t); +extern struct nl_msg * nfnlmsg_alloc_simple(uint8_t, uint8_t, int, + uint8_t, uint16_t); +extern int nfnlmsg_put(struct nl_msg *, uint32_t, uint32_t, + uint8_t, uint8_t, int, uint8_t, uint16_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/netfilter/queue.h b/include/netlink/netfilter/queue.h new file mode 100644 index 0000000..664610d --- /dev/null +++ b/include/netlink/netfilter/queue.h @@ -0,0 +1,90 @@ +/* + * netlink/netfilter/queue.h Netfilter Queue + * + * 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) 2007, 2008 Patrick McHardy + */ + +#ifndef NETLINK_QUEUE_H_ +#define NETLINK_QUEUE_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct nl_sock; +struct nlmsghdr; +struct nfnl_queue; + +extern struct nl_object_ops queue_obj_ops; + +enum nfnl_queue_copy_mode { + NFNL_QUEUE_COPY_NONE, + NFNL_QUEUE_COPY_META, + NFNL_QUEUE_COPY_PACKET, +}; + +/* General */ +extern struct nl_sock * nfnl_queue_socket_alloc(void); + +extern struct nfnl_queue * nfnl_queue_alloc(void); + +extern void nfnl_queue_get(struct nfnl_queue *); +extern void nfnl_queue_put(struct nfnl_queue *); + +/* Attributes */ +extern void nfnl_queue_set_group(struct nfnl_queue *, uint16_t); +extern int nfnl_queue_test_group(const struct nfnl_queue *); +extern uint16_t nfnl_queue_get_group(const struct nfnl_queue *); + +extern void nfnl_queue_set_maxlen(struct nfnl_queue *, uint32_t); +extern int nfnl_queue_test_maxlen(const struct nfnl_queue *); +extern uint32_t nfnl_queue_get_maxlen(const struct nfnl_queue *); + +extern void nfnl_queue_set_copy_mode(struct nfnl_queue *, + enum nfnl_queue_copy_mode); +extern int nfnl_queue_test_copy_mode(const struct nfnl_queue *); +extern enum nfnl_queue_copy_mode nfnl_queue_get_copy_mode(const struct nfnl_queue *); + +extern char * nfnl_queue_copy_mode2str(enum nfnl_queue_copy_mode, + char *, size_t); +extern enum nfnl_queue_copy_mode nfnl_queue_str2copy_mode(const char *); + +extern void nfnl_queue_set_copy_range(struct nfnl_queue *, + uint32_t); +extern int nfnl_queue_test_copy_range(const struct nfnl_queue *); +extern uint32_t nfnl_queue_get_copy_range(const struct nfnl_queue *); + +extern int nfnl_queue_build_pf_bind(uint8_t, struct nl_msg **); +extern int nfnl_queue_pf_bind(struct nl_sock *, uint8_t); + +extern int nfnl_queue_build_pf_unbind(uint8_t, struct nl_msg **); +extern int nfnl_queue_pf_unbind(struct nl_sock *, uint8_t); + +extern int nfnl_queue_build_create_request(const struct nfnl_queue *, + struct nl_msg **); +extern int nfnl_queue_create(struct nl_sock *, + const struct nfnl_queue *); + +extern int nfnl_queue_build_change_request(const struct nfnl_queue *, + struct nl_msg **); +extern int nfnl_queue_change(struct nl_sock *, + const struct nfnl_queue *); + +extern int nfnl_queue_build_delete_request(const struct nfnl_queue *, + struct nl_msg **); +extern int nfnl_queue_delete(struct nl_sock *, + const struct nfnl_queue *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/netlink/netfilter/queue_msg.h b/include/netlink/netfilter/queue_msg.h new file mode 100644 index 0000000..24ed081 --- /dev/null +++ b/include/netlink/netfilter/queue_msg.h @@ -0,0 +1,104 @@ +/* + * netlink/netfilter/queue_msg.h Netfilter Queue Messages + * + * 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) 2007, 2008 Patrick McHardy + */ + +#ifndef NETLINK_QUEUE_MSG_H_ +#define NETLINK_QUEUE_MSG_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct nl_sock; +struct nlmsghdr; +struct nfnl_queue_msg; + +extern struct nl_object_ops queue_msg_obj_ops; + +/* General */ +extern struct nfnl_queue_msg * nfnl_queue_msg_alloc(void); +extern int nfnlmsg_queue_msg_parse(struct nlmsghdr *, + struct nfnl_queue_msg **); + +extern void nfnl_queue_msg_get(struct nfnl_queue_msg *); +extern void nfnl_queue_msg_put(struct nfnl_queue_msg *); + +extern void nfnl_queue_msg_set_group(struct nfnl_queue_msg *, uint16_t); +extern int nfnl_queue_msg_test_group(const struct nfnl_queue_msg *); +extern uint16_t nfnl_queue_msg_get_group(const struct nfnl_queue_msg *); + +extern void nfnl_queue_msg_set_family(struct nfnl_queue_msg *, uint8_t); +extern int nfnl_queue_msg_test_family(const struct nfnl_queue_msg *); +extern uint8_t nfnl_queue_msg_get_family(const struct nfnl_queue_msg *); + +extern void nfnl_queue_msg_set_packetid(struct nfnl_queue_msg *, uint32_t); +extern int nfnl_queue_msg_test_packetid(const struct nfnl_queue_msg *); +extern uint32_t nfnl_queue_msg_get_packetid(const struct nfnl_queue_msg *); + +extern void nfnl_queue_msg_set_hwproto(struct nfnl_queue_msg *, uint16_t); +extern int nfnl_queue_msg_test_hwproto(const struct nfnl_queue_msg *); +extern uint16_t nfnl_queue_msg_get_hwproto(const struct nfnl_queue_msg *); + +extern void nfnl_queue_msg_set_hook(struct nfnl_queue_msg *, uint8_t); +extern int nfnl_queue_msg_test_hook(const struct nfnl_queue_msg *); +extern uint8_t nfnl_queue_msg_get_hook(const struct nfnl_queue_msg *); + +extern void nfnl_queue_msg_set_mark(struct nfnl_queue_msg *, uint32_t); +extern int nfnl_queue_msg_test_mark(const struct nfnl_queue_msg *); +extern uint32_t nfnl_queue_msg_get_mark(const struct nfnl_queue_msg *); + +extern void nfnl_queue_msg_set_timestamp(struct nfnl_queue_msg *, + struct timeval *); +extern int nfnl_queue_msg_test_timestamp(const struct nfnl_queue_msg *); +extern const struct timeval * nfnl_queue_msg_get_timestamp(const struct nfnl_queue_msg *); + +extern void nfnl_queue_msg_set_indev(struct nfnl_queue_msg *, uint32_t); +extern int nfnl_queue_msg_test_indev(const struct nfnl_queue_msg *); +extern uint32_t nfnl_queue_msg_get_indev(const struct nfnl_queue_msg *); + +extern void nfnl_queue_msg_set_outdev(struct nfnl_queue_msg *, uint32_t); +extern int nfnl_queue_msg_test_outdev(const struct nfnl_queue_msg *); +extern uint32_t nfnl_queue_msg_get_outdev(const struct nfnl_queue_msg *); + +extern void nfnl_queue_msg_set_physindev(struct nfnl_queue_msg *, uint32_t); +extern int nfnl_queue_msg_test_physindev(const struct nfnl_queue_msg *); +extern uint32_t nfnl_queue_msg_get_physindev(const struct nfnl_queue_msg *); + +extern void nfnl_queue_msg_set_physoutdev(struct nfnl_queue_msg *, uint32_t); +extern int nfnl_queue_msg_test_physoutdev(const struct nfnl_queue_msg *); +extern uint32_t nfnl_queue_msg_get_physoutdev(const struct nfnl_queue_msg *); + +extern void nfnl_queue_msg_set_hwaddr(struct nfnl_queue_msg *, uint8_t *, int); +extern int nfnl_queue_msg_test_hwaddr(const struct nfnl_queue_msg *); +extern const uint8_t * nfnl_queue_msg_get_hwaddr(const struct nfnl_queue_msg *, int *); + +extern int nfnl_queue_msg_set_payload(struct nfnl_queue_msg *, uint8_t *, int); +extern int nfnl_queue_msg_test_payload(const struct nfnl_queue_msg *); +extern const void * nfnl_queue_msg_get_payload(const struct nfnl_queue_msg *, int *); + +extern void nfnl_queue_msg_set_verdict(struct nfnl_queue_msg *, + unsigned int); +extern int nfnl_queue_msg_test_verdict(const struct nfnl_queue_msg *); +extern unsigned int nfnl_queue_msg_get_verdict(const struct nfnl_queue_msg *); + +extern struct nl_msg * nfnl_queue_msg_build_verdict(const struct nfnl_queue_msg *); +extern int nfnl_queue_msg_send_verdict(struct nl_sock *, + const struct nfnl_queue_msg *); +extern int nfnl_queue_msg_send_verdict_payload(struct nl_sock *, + const struct nfnl_queue_msg *, + const void *, unsigned ); +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/netlink/netlink-compat.h b/include/netlink/netlink-compat.h new file mode 100644 index 0000000..17ec9fc --- /dev/null +++ b/include/netlink/netlink-compat.h @@ -0,0 +1,50 @@ +/* + * netlink/netlink-compat.h Netlink Compatability + * + * 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 + */ + +#ifndef NETLINK_COMPAT_H_ +#define NETLINK_COMPAT_H_ + +#if !defined _LINUX_SOCKET_H && !defined _BITS_SOCKADDR_H +typedef unsigned short sa_family_t; +#endif + +#ifndef IFNAMSIZ +/** Maximum length of a interface name */ +#define IFNAMSIZ 16 +#endif + +/* patch 2.4.x if_arp */ +#ifndef ARPHRD_INFINIBAND +#define ARPHRD_INFINIBAND 32 +#endif + +/* patch 2.4.x eth header file */ +#ifndef ETH_P_MPLS_UC +#define ETH_P_MPLS_UC 0x8847 +#endif + +#ifndef ETH_P_MPLS_MC +#define ETH_P_MPLS_MC 0x8848 +#endif + +#ifndef ETH_P_EDP2 +#define ETH_P_EDP2 0x88A2 +#endif + +#ifndef ETH_P_HDLC +#define ETH_P_HDLC 0x0019 +#endif + +#ifndef AF_LLC +#define AF_LLC 26 +#endif + +#endif diff --git a/include/netlink/netlink-kernel.h b/include/netlink/netlink-kernel.h new file mode 100644 index 0000000..f09051d --- /dev/null +++ b/include/netlink/netlink-kernel.h @@ -0,0 +1,293 @@ +#ifndef __NETLINK_KERNEL_H_ +#define __NETLINK_KERNEL_H_ + +#if 0 + +/* + * FIXME: Goal is to preseve the documentation but make it simple + * to keep linux/netlink.h in sync. Maybe use named documentation + * sections. + */ + +/** + * Netlink socket address + * @ingroup nl + */ +struct sockaddr_nl +{ + /** socket family (AF_NETLINK) */ + sa_family_t nl_family; + + /** Padding (unused) */ + unsigned short nl_pad; + + /** Unique process ID */ + uint32_t nl_pid; + + /** Multicast group subscriptions */ + uint32_t nl_groups; +}; + +/** + * @addtogroup msg + * @{ + */ + + +/** + * Netlink message header + */ +struct nlmsghdr +{ + /** Length of message including header and padding. */ + uint32_t nlmsg_len; + + /** Message type (content type) */ + uint16_t nlmsg_type; + + /** Message flags */ + uint16_t nlmsg_flags; + + /** Sequence number of message \see core_sk_seq_num. */ + uint32_t nlmsg_seq; + + /** Netlink port */ + uint32_t nlmsg_pid; +}; + +/** + * @name Standard message flags + * @{ + */ + +/** + * Must be set on all request messages (typically from user space to + * kernel space). + */ +#define NLM_F_REQUEST 1 + +/** + * Indicates the message is part of a multipart message terminated + * by NLMSG_DONE. + */ +#define NLM_F_MULTI 2 + +/** + * Request for an acknowledgment on success. + */ +#define NLM_F_ACK 4 + +/** + * Echo this request + */ +#define NLM_F_ECHO 8 + +/** @} */ + +/** + * @name Additional message flags for GET requests + * @{ + */ + +/** + * Return the complete table instead of a single entry. + */ +#define NLM_F_ROOT 0x100 + +/** + * Return all entries matching criteria passed in message content. + */ +#define NLM_F_MATCH 0x200 + +/** + * Return an atomic snapshot of the table being referenced. This + * may require special privileges because it has the potential to + * interrupt service in the FE for a longer time. + */ +#define NLM_F_ATOMIC 0x400 + +/** + * Dump all entries + */ +#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH) + +/** @} */ + +/** + * @name Additional messsage flags for NEW requests + * @{ + */ + +/** + * Replace existing matching config object with this request. + */ +#define NLM_F_REPLACE 0x100 + +/** + * Don't replace the config object if it already exists. + */ +#define NLM_F_EXCL 0x200 + +/** + * Create config object if it doesn't already exist. + */ +#define NLM_F_CREATE 0x400 + +/** + * Add to the end of the object list. + */ +#define NLM_F_APPEND 0x800 + +/** @} */ + +/** + * @name Standard Message types + * @{ + */ + +/** + * No operation, message must be ignored + */ +#define NLMSG_NOOP 0x1 + +/** + * The message signals an error and the payload contains a nlmsgerr + * structure. This can be looked at as a NACK and typically it is + * from FEC to CPC. + */ +#define NLMSG_ERROR 0x2 + +/** + * Message terminates a multipart message. + */ +#define NLMSG_DONE 0x3 + +/** + * The message signals that data got lost + */ +#define NLMSG_OVERRUN 0x4 + +/** + * Lower limit of reserved message types + */ +#define NLMSG_MIN_TYPE 0x10 + +/** @} */ + +/** + * Netlink error message header + */ +struct nlmsgerr +{ + /** Error code (errno number) */ + int error; + + /** Original netlink message causing the error */ + struct nlmsghdr msg; +}; + +struct nl_pktinfo +{ + __u32 group; +}; + +/** + * Netlink alignment constant, all boundries within messages must be align to this. + * + * See \ref core_msg_fmt_align for more information on message alignment. + */ +#define NLMSG_ALIGNTO 4 + +/** + * Returns \p len properly aligned to NLMSG_ALIGNTO. + * + * See \ref core_msg_fmt_align for more information on message alignment. + */ +#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) ) + +/** + * Length of a netlink message header including padding. + * + * See \ref core_msg_fmt_align for more information on message alignment. + */ +#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr))) + +/** @} */ + +/** + * @addtogroup attr + * @{ + */ + +/* + */ + +/** + * Netlink attribute structure + * + * @code + * <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)--> + * +---------------------+- - -+- - - - - - - - - -+- - -+ + * | Header | Pad | Payload | Pad | + * | (struct nlattr) | ing | | ing | + * +---------------------+- - -+- - - - - - - - - -+- - -+ + * <-------------- nlattr->nla_len --------------> + * @endcode + */ +struct nlattr { + /** + * Attribute length in bytes including header + */ + __u16 nla_len; + + /** + * Netlink attribute type + */ + __u16 nla_type; +}; + +/** + * @name Attribute Type Flags + * + * @code + * nla_type (16 bits) + * +---+---+-------------------------------+ + * | N | O | Attribute Type | + * +---+---+-------------------------------+ + * N := Carries nested attributes + * O := Payload stored in network byte order + * @endcode + * + * @note The N and O flag are mutually exclusive. + * + * @{ + */ + +/* + */ +#define NLA_F_NESTED (1 << 15) +#define NLA_F_NET_BYTEORDER (1 << 14) +#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER) + +/** @} */ + +#define NLA_ALIGNTO 4 + +/** + * Returns \p len properly aligned to NLA_ALIGNTO. + * + * See \ref core_msg_fmt_align for more information on message alignment. + */ +#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1)) + +/** + * Length of a netlink attribute header including padding. + * + * See \ref core_msg_fmt_align for more information on message alignment. + */ +#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr))) + +/** @} */ + +#endif +#endif /* __LINUX_NETLINK_H */ diff --git a/include/netlink/netlink.h b/include/netlink/netlink.h new file mode 100644 index 0000000..1d74ba1 --- /dev/null +++ b/include/netlink/netlink.h @@ -0,0 +1,97 @@ +/* + * netlink/netlink.h Netlink Interface + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2013 Thomas Graf + */ + +#ifndef NETLINK_NETLINK_H_ +#define NETLINK_NETLINK_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct ucred; +struct nl_cache_ops; +struct nl_parser_param; +struct nl_object; +struct nl_sock; + +extern int nl_debug; +extern struct nl_dump_params nl_debug_dp; + +/* Connection Management */ +extern int nl_connect(struct nl_sock *, int); +extern void nl_close(struct nl_sock *); + +/* Send */ +extern int nl_sendto(struct nl_sock *, void *, size_t); +extern int nl_sendmsg(struct nl_sock *, struct nl_msg *, + struct msghdr *); +extern int nl_send(struct nl_sock *, struct nl_msg *); +extern int nl_send_iovec(struct nl_sock *, struct nl_msg *, + struct iovec *, unsigned); +extern void nl_complete_msg(struct nl_sock *, + struct nl_msg *); +extern void nl_auto_complete(struct nl_sock *, + struct nl_msg *); +extern int nl_send_auto(struct nl_sock *, struct nl_msg *); +extern int nl_send_auto_complete(struct nl_sock *, + struct nl_msg *); +extern int nl_send_sync(struct nl_sock *, struct nl_msg *); +extern int nl_send_simple(struct nl_sock *, int, int, + void *, size_t); + +/* Receive */ +extern int nl_recv(struct nl_sock *, + struct sockaddr_nl *, unsigned char **, + struct ucred **); + +extern int nl_recvmsgs(struct nl_sock *, struct nl_cb *); +extern int nl_recvmsgs_report(struct nl_sock *, struct nl_cb *); + +extern int nl_recvmsgs_default(struct nl_sock *); + +extern int nl_wait_for_ack(struct nl_sock *); + +extern int nl_pickup(struct nl_sock *, + int (*parser)(struct nl_cache_ops *, + struct sockaddr_nl *, + struct nlmsghdr *, + struct nl_parser_param *), + struct nl_object **); +/* Netlink Family Translations */ +extern char * nl_nlfamily2str(int, char *, size_t); +extern int nl_str2nlfamily(const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/object-api.h b/include/netlink/object-api.h new file mode 100644 index 0000000..75f29cb --- /dev/null +++ b/include/netlink/object-api.h @@ -0,0 +1,19 @@ +/* + * netlink/object-api.h Object API + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2013 Thomas Graf + */ + +#ifndef NETLINK_DUMMY_OBJECT_API_H_ +#define NETLINK_DUMMY_OBJECT_API_H_ + +#include +#include +#include + +#endif diff --git a/include/netlink/object.h b/include/netlink/object.h new file mode 100644 index 0000000..a95feda --- /dev/null +++ b/include/netlink/object.h @@ -0,0 +1,80 @@ +/* + * netlink/object.c Generic Cacheable Object + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +#ifndef NETLINK_OBJECT_H_ +#define NETLINK_OBJECT_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct nl_cache; +struct nl_object; +struct nl_object_ops; + +#define OBJ_CAST(ptr) ((struct nl_object *) (ptr)) + +/* General */ +extern struct nl_object * nl_object_alloc(struct nl_object_ops *); +extern int nl_object_alloc_name(const char *, + struct nl_object **); +extern void nl_object_free(struct nl_object *); +extern struct nl_object * nl_object_clone(struct nl_object *obj); +extern int nl_object_update(struct nl_object *dst, + struct nl_object *src); +extern void nl_object_get(struct nl_object *); +extern void nl_object_put(struct nl_object *); +extern int nl_object_shared(struct nl_object *); +extern void nl_object_dump(struct nl_object *, + struct nl_dump_params *); +extern void nl_object_dump_buf(struct nl_object *, char *, size_t); +extern int nl_object_identical(struct nl_object *, + struct nl_object *); +extern uint32_t nl_object_diff(struct nl_object *, + struct nl_object *); +extern int nl_object_match_filter(struct nl_object *, + struct nl_object *); +extern char * nl_object_attrs2str(struct nl_object *, + uint32_t attrs, char *buf, + size_t); +extern char * nl_object_attr_list(struct nl_object *, + char *, size_t); +extern void nl_object_keygen(struct nl_object *, + uint32_t *, uint32_t); + +/* Marks */ +extern void nl_object_mark(struct nl_object *); +extern void nl_object_unmark(struct nl_object *); +extern int nl_object_is_marked(struct nl_object *); + +/* Access Functions */ +extern int nl_object_get_refcnt(struct nl_object *); +extern struct nl_cache * nl_object_get_cache(struct nl_object *); +extern const char * nl_object_get_type(const struct nl_object *); +extern int nl_object_get_msgtype(const struct nl_object *); +struct nl_object_ops * nl_object_get_ops(const struct nl_object *); +uint32_t nl_object_get_id_attrs(struct nl_object *obj); + + +static inline void * nl_object_priv(struct nl_object *obj) +{ + return obj; +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/addr.h b/include/netlink/route/addr.h new file mode 100644 index 0000000..56c12e7 --- /dev/null +++ b/include/netlink/route/addr.h @@ -0,0 +1,98 @@ +/* + * netlink/route/addr.c rtnetlink addr layer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + * Copyright (c) 2003-2006 Baruch Even , + * Mediatrix Telecom, inc. + */ + +#ifndef NETADDR_ADDR_H_ +#define NETADDR_ADDR_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct rtnl_addr; + +/* General */ +extern struct rtnl_addr *rtnl_addr_alloc(void); +extern void rtnl_addr_put(struct rtnl_addr *); + +extern int rtnl_addr_alloc_cache(struct nl_sock *, struct nl_cache **); +extern struct rtnl_addr * + rtnl_addr_get(struct nl_cache *, int, struct nl_addr *); + +extern int rtnl_addr_build_add_request(struct rtnl_addr *, int, + struct nl_msg **); +extern int rtnl_addr_add(struct nl_sock *, struct rtnl_addr *, int); + +extern int rtnl_addr_build_delete_request(struct rtnl_addr *, int, + struct nl_msg **); +extern int rtnl_addr_delete(struct nl_sock *, + struct rtnl_addr *, int); + +extern char * rtnl_addr_flags2str(int, char *, size_t); +extern int rtnl_addr_str2flags(const char *); + +extern int rtnl_addr_set_label(struct rtnl_addr *, const char *); +extern char * rtnl_addr_get_label(struct rtnl_addr *); + +extern void rtnl_addr_set_ifindex(struct rtnl_addr *, int); +extern int rtnl_addr_get_ifindex(struct rtnl_addr *); + +extern void rtnl_addr_set_link(struct rtnl_addr *, struct rtnl_link *); +extern struct rtnl_link * + rtnl_addr_get_link(struct rtnl_addr *); + +extern void rtnl_addr_set_family(struct rtnl_addr *, int); +extern int rtnl_addr_get_family(struct rtnl_addr *); + +extern void rtnl_addr_set_prefixlen(struct rtnl_addr *, int); +extern int rtnl_addr_get_prefixlen(struct rtnl_addr *); + +extern void rtnl_addr_set_scope(struct rtnl_addr *, int); +extern int rtnl_addr_get_scope(struct rtnl_addr *); + +extern void rtnl_addr_set_flags(struct rtnl_addr *, unsigned int); +extern void rtnl_addr_unset_flags(struct rtnl_addr *, unsigned int); +extern unsigned int rtnl_addr_get_flags(struct rtnl_addr *); + +extern int rtnl_addr_set_local(struct rtnl_addr *, + struct nl_addr *); +extern struct nl_addr *rtnl_addr_get_local(struct rtnl_addr *); + +extern int rtnl_addr_set_peer(struct rtnl_addr *, struct nl_addr *); +extern struct nl_addr *rtnl_addr_get_peer(struct rtnl_addr *); + +extern int rtnl_addr_set_broadcast(struct rtnl_addr *, struct nl_addr *); +extern struct nl_addr *rtnl_addr_get_broadcast(struct rtnl_addr *); + +extern int rtnl_addr_set_multicast(struct rtnl_addr *, struct nl_addr *); +extern struct nl_addr *rtnl_addr_get_multicast(struct rtnl_addr *); + +extern int rtnl_addr_set_anycast(struct rtnl_addr *, struct nl_addr *); +extern struct nl_addr *rtnl_addr_get_anycast(struct rtnl_addr *); + +extern uint32_t rtnl_addr_get_valid_lifetime(struct rtnl_addr *); +extern void rtnl_addr_set_valid_lifetime(struct rtnl_addr *, uint32_t); +extern uint32_t rtnl_addr_get_preferred_lifetime(struct rtnl_addr *); +extern void rtnl_addr_set_preferred_lifetime(struct rtnl_addr *, uint32_t); +extern uint32_t rtnl_addr_get_create_time(struct rtnl_addr *); +extern uint32_t rtnl_addr_get_last_update_time(struct rtnl_addr *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/class.h b/include/netlink/route/class.h new file mode 100644 index 0000000..e73b60a --- /dev/null +++ b/include/netlink/route/class.h @@ -0,0 +1,66 @@ +/* + * netlink/route/class.h Traffic Classes + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + */ + +#ifndef NETLINK_CLASS_H_ +#define NETLINK_CLASS_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct rtnl_class; + +extern struct rtnl_class * + rtnl_class_alloc(void); +extern void rtnl_class_put(struct rtnl_class *); + +extern int rtnl_class_alloc_cache(struct nl_sock *, int, + struct nl_cache **); +extern struct rtnl_class * + rtnl_class_get(struct nl_cache *, int, uint32_t); + +extern struct rtnl_qdisc * + rtnl_class_leaf_qdisc(struct rtnl_class *, + struct nl_cache *); + +extern int rtnl_class_build_add_request(struct rtnl_class *, int, + struct nl_msg **); +extern int rtnl_class_add(struct nl_sock *, struct rtnl_class *, + int); + +extern int rtnl_class_build_delete_request(struct rtnl_class *, + struct nl_msg **); +extern int rtnl_class_delete(struct nl_sock *, + struct rtnl_class *); + +/* deprecated functions */ +extern void rtnl_class_foreach_child(struct rtnl_class *, + struct nl_cache *, + void (*cb)(struct nl_object *, + void *), + void *) + __attribute__((deprecated)); +extern void rtnl_class_foreach_cls(struct rtnl_class *, + struct nl_cache *, + void (*cb)(struct nl_object *, + void *), + void *) + __attribute__((deprecated)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/classifier.h b/include/netlink/route/classifier.h new file mode 100644 index 0000000..647bf1e --- /dev/null +++ b/include/netlink/route/classifier.h @@ -0,0 +1,51 @@ +/* + * netlink/route/classifier.h Classifiers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + */ + +#ifndef NETLINK_CLASSIFIER_H_ +#define NETLINK_CLASSIFIER_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct rtnl_cls *rtnl_cls_alloc(void); +extern void rtnl_cls_put(struct rtnl_cls *); + +extern int rtnl_cls_alloc_cache(struct nl_sock *, int, uint32_t, + struct nl_cache **); + +extern int rtnl_cls_build_add_request(struct rtnl_cls *, int, + struct nl_msg **); +extern int rtnl_cls_add(struct nl_sock *, struct rtnl_cls *, int); + +extern int rtnl_cls_build_change_request(struct rtnl_cls *, int, + struct nl_msg **); +extern int rtnl_cls_build_delete_request(struct rtnl_cls *, int, + struct nl_msg **); +extern int rtnl_cls_delete(struct nl_sock *, struct rtnl_cls *, + int); + +extern void rtnl_cls_set_prio(struct rtnl_cls *, uint16_t); +extern uint16_t rtnl_cls_get_prio(struct rtnl_cls *); + +extern void rtnl_cls_set_protocol(struct rtnl_cls *, uint16_t); +extern uint16_t rtnl_cls_get_protocol(struct rtnl_cls *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/cls/basic.h b/include/netlink/route/cls/basic.h new file mode 100644 index 0000000..603fa88 --- /dev/null +++ b/include/netlink/route/cls/basic.h @@ -0,0 +1,33 @@ +/* + * netlink/route/cls/basic.h Basic Classifier + * + * 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-2010 Thomas Graf + */ + +#ifndef NETLINK_BASIC_H_ +#define NETLINK_BASIC_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern void rtnl_basic_set_target(struct rtnl_cls *, uint32_t); +extern uint32_t rtnl_basic_get_target(struct rtnl_cls *); +extern void rtnl_basic_set_ematch(struct rtnl_cls *, + struct rtnl_ematch_tree *); +extern struct rtnl_ematch_tree *rtnl_basic_get_ematch(struct rtnl_cls *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/cls/cgroup.h b/include/netlink/route/cls/cgroup.h new file mode 100644 index 0000000..9cd4845 --- /dev/null +++ b/include/netlink/route/cls/cgroup.h @@ -0,0 +1,32 @@ +/* + * netlink/route/cls/cgroup.h Control Groups Classifier + * + * 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) 2009-2010 Thomas Graf + */ + +#ifndef NETLINK_CLS_CGROUP_H_ +#define NETLINK_CLS_CGROUP_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern void rtnl_cgroup_set_ematch(struct rtnl_cls *, + struct rtnl_ematch_tree *); +struct rtnl_ematch_tree * rtnl_cgroup_get_ematch(struct rtnl_cls *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/cls/ematch.h b/include/netlink/route/cls/ematch.h new file mode 100644 index 0000000..13f9c32 --- /dev/null +++ b/include/netlink/route/cls/ematch.h @@ -0,0 +1,95 @@ +/* + * netlink/route/cls/ematch.h Extended Matches + * + * 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-2010 Thomas Graf + */ + +#ifndef NETLINK_CLS_EMATCH_H_ +#define NETLINK_CLS_EMATCH_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* FIXME: Should be moved to the kernel header at some point */ +#define RTNL_EMATCH_PROGID 2 + +struct rtnl_ematch; +struct rtnl_ematch_tree; + +/** + * Extended Match Operations + */ +struct rtnl_ematch_ops +{ + int eo_kind; + const char * eo_name; + size_t eo_minlen; + size_t eo_datalen; + + int (*eo_parse)(struct rtnl_ematch *, void *, size_t); + void (*eo_dump)(struct rtnl_ematch *, + struct nl_dump_params *); + int (*eo_fill)(struct rtnl_ematch *, struct nl_msg *); + void (*eo_free)(struct rtnl_ematch *); + struct nl_list_head eo_list; +}; + +extern int rtnl_ematch_register(struct rtnl_ematch_ops *); +extern struct rtnl_ematch_ops * rtnl_ematch_lookup_ops(int); +extern struct rtnl_ematch_ops * rtnl_ematch_lookup_ops_by_name(const char *); + +extern struct rtnl_ematch * rtnl_ematch_alloc(void); +extern int rtnl_ematch_add_child(struct rtnl_ematch *, + struct rtnl_ematch *); +extern void rtnl_ematch_unlink(struct rtnl_ematch *); +extern void rtnl_ematch_free(struct rtnl_ematch *); + +extern void * rtnl_ematch_data(struct rtnl_ematch *); +extern void rtnl_ematch_set_flags(struct rtnl_ematch *, + uint16_t); +extern void rtnl_ematch_unset_flags(struct rtnl_ematch *, + uint16_t); +extern uint16_t rtnl_ematch_get_flags(struct rtnl_ematch *); +extern int rtnl_ematch_set_ops(struct rtnl_ematch *, + struct rtnl_ematch_ops *); +extern int rtnl_ematch_set_kind(struct rtnl_ematch *, + uint16_t); +extern int rtnl_ematch_set_name(struct rtnl_ematch *, + const char *); + +extern struct rtnl_ematch_tree *rtnl_ematch_tree_alloc(uint16_t); +extern void rtnl_ematch_tree_free(struct rtnl_ematch_tree *); +extern void rtnl_ematch_tree_add(struct rtnl_ematch_tree *, + struct rtnl_ematch *); + +extern int rtnl_ematch_parse_attr(struct nlattr *, + struct rtnl_ematch_tree **); +extern int rtnl_ematch_fill_attr(struct nl_msg *, int, + struct rtnl_ematch_tree *); +extern void rtnl_ematch_tree_dump(struct rtnl_ematch_tree *, + struct nl_dump_params *); + + +extern int rtnl_ematch_parse_expr(const char *, char **, + struct rtnl_ematch_tree **); + +extern char * rtnl_ematch_offset2txt(uint8_t, uint16_t, + char *, size_t); +extern char * rtnl_ematch_opnd2txt(uint8_t, char *, size_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/cls/ematch/cmp.h b/include/netlink/route/cls/ematch/cmp.h new file mode 100644 index 0000000..308113e --- /dev/null +++ b/include/netlink/route/cls/ematch/cmp.h @@ -0,0 +1,32 @@ +/* + * netlink/route/cls/ematch/cmp.h Simple Comparison + * + * 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-2010 Thomas Graf + */ + +#ifndef NETLINK_CLS_EMATCH_CMP_H_ +#define NETLINK_CLS_EMATCH_CMP_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern void rtnl_ematch_cmp_set(struct rtnl_ematch *, + struct tcf_em_cmp *); +extern struct tcf_em_cmp * + rtnl_ematch_cmp_get(struct rtnl_ematch *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/cls/ematch/meta.h b/include/netlink/route/cls/ematch/meta.h new file mode 100644 index 0000000..2fe5899 --- /dev/null +++ b/include/netlink/route/cls/ematch/meta.h @@ -0,0 +1,41 @@ +/* + * netlink/route/cls/ematch/meta.h Metadata Match + * + * 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 + */ + +#ifndef NETLINK_CLS_EMATCH_META_H_ +#define NETLINK_CLS_EMATCH_META_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct rtnl_meta_value; + +extern struct rtnl_meta_value * rtnl_meta_value_alloc_int(uint64_t); +extern struct rtnl_meta_value * rtnl_meta_value_alloc_var(void *, size_t); +extern struct rtnl_meta_value * rtnl_meta_value_alloc_id(uint8_t, uint16_t, + uint8_t, uint64_t); +extern void rtnl_meta_value_put(struct rtnl_meta_value *); + +extern void rtnl_ematch_meta_set_lvalue(struct rtnl_ematch *, + struct rtnl_meta_value *); +void rtnl_ematch_meta_set_rvalue(struct rtnl_ematch *, + struct rtnl_meta_value *); +extern void rtnl_ematch_meta_set_operand(struct rtnl_ematch *, uint8_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/cls/ematch/nbyte.h b/include/netlink/route/cls/ematch/nbyte.h new file mode 100644 index 0000000..014c719 --- /dev/null +++ b/include/netlink/route/cls/ematch/nbyte.h @@ -0,0 +1,36 @@ +/* + * netlink/route/cls/ematch/nbyte.h N-Byte Comparison + * + * 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 + */ + +#ifndef NETLINK_CLS_EMATCH_NBYTE_H_ +#define NETLINK_CLS_EMATCH_NBYTE_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern void rtnl_ematch_nbyte_set_offset(struct rtnl_ematch *, + uint8_t, uint16_t); +extern uint16_t rtnl_ematch_nbyte_get_offset(struct rtnl_ematch *); +extern uint8_t rtnl_ematch_nbyte_get_layer(struct rtnl_ematch *); +extern void rtnl_ematch_nbyte_set_pattern(struct rtnl_ematch *, + uint8_t *, size_t); +extern uint8_t * rtnl_ematch_nbyte_get_pattern(struct rtnl_ematch *); +extern size_t rtnl_ematch_nbyte_get_len(struct rtnl_ematch *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/cls/ematch/text.h b/include/netlink/route/cls/ematch/text.h new file mode 100644 index 0000000..e599abf --- /dev/null +++ b/include/netlink/route/cls/ematch/text.h @@ -0,0 +1,42 @@ +/* + * netlink/route/cls/ematch/text.h Text Search + * + * 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 + */ + +#ifndef NETLINK_CLS_EMATCH_TEXT_H_ +#define NETLINK_CLS_EMATCH_TEXT_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern void rtnl_ematch_text_set_from(struct rtnl_ematch *, + uint8_t, uint16_t); +extern uint16_t rtnl_ematch_text_get_from_offset(struct rtnl_ematch *); +extern uint8_t rtnl_ematch_text_get_from_layer(struct rtnl_ematch *); +extern void rtnl_ematch_text_set_to(struct rtnl_ematch *, + uint8_t, uint16_t); +extern uint16_t rtnl_ematch_text_get_to_offset(struct rtnl_ematch *); +extern uint8_t rtnl_ematch_text_get_to_layer(struct rtnl_ematch *); +extern void rtnl_ematch_text_set_pattern(struct rtnl_ematch *, + char *, size_t); +extern char * rtnl_ematch_text_get_pattern(struct rtnl_ematch *); +extern size_t rtnl_ematch_text_get_len(struct rtnl_ematch *); +extern void rtnl_ematch_text_set_algo(struct rtnl_ematch *, const char *); +extern char * rtnl_ematch_text_get_algo(struct rtnl_ematch *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/cls/fw.h b/include/netlink/route/cls/fw.h new file mode 100644 index 0000000..2e1bade --- /dev/null +++ b/include/netlink/route/cls/fw.h @@ -0,0 +1,31 @@ +/* + * netlink/route/cls/fw.h fw classifier + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2006 Thomas Graf + * Copyright (c) 2006 Petr Gotthard + * Copyright (c) 2006 Siemens AG Oesterreich + */ + +#ifndef NETLINK_FW_H_ +#define NETLINK_FW_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_fw_set_classid(struct rtnl_cls *, uint32_t); +extern int rtnl_fw_set_mask(struct rtnl_cls *, uint32_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/cls/police.h b/include/netlink/route/cls/police.h new file mode 100644 index 0000000..cd1efb0 --- /dev/null +++ b/include/netlink/route/cls/police.h @@ -0,0 +1,29 @@ +/* + * netlink/route/cls/police.h Policer + * + * 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 + */ + +#ifndef NETLINK_CLS_POLICE_H_ +#define NETLINK_CLS_POLICE_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern char * nl_police2str(int, char *, size_t); +extern int nl_str2police(const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/cls/u32.h b/include/netlink/route/cls/u32.h new file mode 100644 index 0000000..59bed33 --- /dev/null +++ b/include/netlink/route/cls/u32.h @@ -0,0 +1,49 @@ +/* + * netlink/route/cls/u32.h u32 classifier + * + * 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 + */ + +#ifndef NETLINK_U32_H_ +#define NETLINK_U32_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern void rtnl_u32_set_handle(struct rtnl_cls *, int, int, int); +extern int rtnl_u32_set_classid(struct rtnl_cls *, uint32_t); +extern int rtnl_u32_set_divisor(struct rtnl_cls *, uint32_t); +extern int rtnl_u32_set_link(struct rtnl_cls *, uint32_t); +extern int rtnl_u32_set_hashtable(struct rtnl_cls *, uint32_t); +extern int rtnl_u32_set_hashmask(struct rtnl_cls *, uint32_t, uint32_t); +extern int rtnl_u32_set_cls_terminal(struct rtnl_cls *); + +extern int rtnl_u32_set_flags(struct rtnl_cls *, int); +extern int rtnl_u32_add_key(struct rtnl_cls *, uint32_t, uint32_t, + int, int); +extern int rtnl_u32_add_key_uint8(struct rtnl_cls *, uint8_t, uint8_t, + int, int); +extern int rtnl_u32_add_key_uint16(struct rtnl_cls *, uint16_t, uint16_t, + int, int); +extern int rtnl_u32_add_key_uint32(struct rtnl_cls *, uint32_t, uint32_t, + int, int); +extern int rtnl_u32_add_key_in_addr(struct rtnl_cls *, struct in_addr *, + uint8_t, int, int); +extern int rtnl_u32_add_key_in6_addr(struct rtnl_cls *, struct in6_addr *, + uint8_t, int, int); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h new file mode 100644 index 0000000..321a80d --- /dev/null +++ b/include/netlink/route/link.h @@ -0,0 +1,235 @@ +/* + * netlink/route/link.h Links (Interfaces) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +#ifndef NETLINK_LINK_H_ +#define NETLINK_LINK_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @struct rtnl_link link.h "netlink/route/link.h" + * @brief Link object + * @implements nl_object + * @ingroup link + * + * @copydoc private_struct + */ +struct rtnl_link; + +/** + * @ingroup link + */ +typedef enum { + RTNL_LINK_RX_PACKETS, /*!< Packets received */ + RTNL_LINK_TX_PACKETS, /*!< Packets sent */ + RTNL_LINK_RX_BYTES, /*!< Bytes received */ + RTNL_LINK_TX_BYTES, /*!< Bytes sent */ + RTNL_LINK_RX_ERRORS, /*!< Receive errors */ + RTNL_LINK_TX_ERRORS, /*!< Send errors */ + RTNL_LINK_RX_DROPPED, /*!< Received packets dropped */ + RTNL_LINK_TX_DROPPED, /*!< Packets dropped during transmit */ + RTNL_LINK_RX_COMPRESSED, /*!< Compressed packets received */ + RTNL_LINK_TX_COMPRESSED, /*!< Compressed packets sent */ + RTNL_LINK_RX_FIFO_ERR, /*!< Receive FIFO errors */ + RTNL_LINK_TX_FIFO_ERR, /*!< Send FIFO errors */ + RTNL_LINK_RX_LEN_ERR, /*!< Length errors */ + RTNL_LINK_RX_OVER_ERR, /*!< Over errors */ + RTNL_LINK_RX_CRC_ERR, /*!< CRC errors */ + RTNL_LINK_RX_FRAME_ERR, /*!< Frame errors */ + RTNL_LINK_RX_MISSED_ERR, /*!< Missed errors */ + RTNL_LINK_TX_ABORT_ERR, /*!< Aborted errors */ + RTNL_LINK_TX_CARRIER_ERR, /*!< Carrier errors */ + RTNL_LINK_TX_HBEAT_ERR, /*!< Heartbeat errors */ + RTNL_LINK_TX_WIN_ERR, /*!< Window errors */ + RTNL_LINK_COLLISIONS, /*!< Send collisions */ + RTNL_LINK_MULTICAST, /*!< Multicast */ + RTNL_LINK_IP6_INPKTS, /*!< IPv6 SNMP InReceives */ + RTNL_LINK_IP6_INHDRERRORS, /*!< IPv6 SNMP InHdrErrors */ + RTNL_LINK_IP6_INTOOBIGERRORS, /*!< IPv6 SNMP InTooBigErrors */ + RTNL_LINK_IP6_INNOROUTES, /*!< IPv6 SNMP InNoRoutes */ + RTNL_LINK_IP6_INADDRERRORS, /*!< IPv6 SNMP InAddrErrors */ + RTNL_LINK_IP6_INUNKNOWNPROTOS, /*!< IPv6 SNMP InUnknownProtos */ + RTNL_LINK_IP6_INTRUNCATEDPKTS, /*!< IPv6 SNMP InTruncatedPkts */ + RTNL_LINK_IP6_INDISCARDS, /*!< IPv6 SNMP InDiscards */ + RTNL_LINK_IP6_INDELIVERS, /*!< IPv6 SNMP InDelivers */ + RTNL_LINK_IP6_OUTFORWDATAGRAMS, /*!< IPv6 SNMP OutForwDatagrams */ + RTNL_LINK_IP6_OUTPKTS, /*!< IPv6 SNMP OutRequests */ + RTNL_LINK_IP6_OUTDISCARDS, /*!< IPv6 SNMP OutDiscards */ + RTNL_LINK_IP6_OUTNOROUTES, /*!< IPv6 SNMP OutNoRoutes */ + RTNL_LINK_IP6_REASMTIMEOUT, /*!< IPv6 SNMP ReasmTimeout */ + RTNL_LINK_IP6_REASMREQDS, /*!< IPv6 SNMP ReasmReqds */ + RTNL_LINK_IP6_REASMOKS, /*!< IPv6 SNMP ReasmOKs */ + RTNL_LINK_IP6_REASMFAILS, /*!< IPv6 SNMP ReasmFails */ + RTNL_LINK_IP6_FRAGOKS, /*!< IPv6 SNMP FragOKs */ + RTNL_LINK_IP6_FRAGFAILS, /*!< IPv6 SNMP FragFails */ + RTNL_LINK_IP6_FRAGCREATES, /*!< IPv6 SNMP FragCreates */ + RTNL_LINK_IP6_INMCASTPKTS, /*!< IPv6 SNMP InMcastPkts */ + RTNL_LINK_IP6_OUTMCASTPKTS, /*!< IPv6 SNMP OutMcastPkts */ + RTNL_LINK_IP6_INBCASTPKTS, /*!< IPv6 SNMP InBcastPkts */ + RTNL_LINK_IP6_OUTBCASTPKTS, /*!< IPv6 SNMP OutBcastPkts */ + RTNL_LINK_IP6_INOCTETS, /*!< IPv6 SNMP InOctets */ + RTNL_LINK_IP6_OUTOCTETS, /*!< IPv6 SNMP OutOctets */ + RTNL_LINK_IP6_INMCASTOCTETS, /*!< IPv6 SNMP InMcastOctets */ + RTNL_LINK_IP6_OUTMCASTOCTETS, /*!< IPv6 SNMP OutMcastOctets */ + RTNL_LINK_IP6_INBCASTOCTETS, /*!< IPv6 SNMP InBcastOctets */ + RTNL_LINK_IP6_OUTBCASTOCTETS, /*!< IPv6 SNMP OutBcastOctets */ + RTNL_LINK_ICMP6_INMSGS, /*!< ICMPv6 SNMP InMsgs */ + RTNL_LINK_ICMP6_INERRORS, /*!< ICMPv6 SNMP InErrors */ + RTNL_LINK_ICMP6_OUTMSGS, /*!< ICMPv6 SNMP OutMsgs */ + RTNL_LINK_ICMP6_OUTERRORS, /*!< ICMPv6 SNMP OutErrors */ + __RTNL_LINK_STATS_MAX, +} rtnl_link_stat_id_t; + +#define RTNL_LINK_STATS_MAX (__RTNL_LINK_STATS_MAX - 1) + +extern struct rtnl_link *rtnl_link_alloc(void); +extern void rtnl_link_put(struct rtnl_link *); + +extern int rtnl_link_alloc_cache(struct nl_sock *, int, struct nl_cache **); +extern struct rtnl_link *rtnl_link_get(struct nl_cache *, int); +extern struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *, const char *); + + +extern int rtnl_link_build_add_request(struct rtnl_link *, int, + struct nl_msg **); +extern int rtnl_link_add(struct nl_sock *, struct rtnl_link *, int); +extern int rtnl_link_build_change_request(struct rtnl_link *, + struct rtnl_link *, int, + struct nl_msg **); +extern int rtnl_link_change(struct nl_sock *, struct rtnl_link *, + struct rtnl_link *, int); + +extern int rtnl_link_build_delete_request(const struct rtnl_link *, + struct nl_msg **); +extern int rtnl_link_delete(struct nl_sock *, const struct rtnl_link *); +extern int rtnl_link_build_get_request(int, const char *, + struct nl_msg **); +extern int rtnl_link_get_kernel(struct nl_sock *, int, const char *, + struct rtnl_link **); + +/* Name <-> Index Translations */ +extern char * rtnl_link_i2name(struct nl_cache *, int, char *, size_t); +extern int rtnl_link_name2i(struct nl_cache *, const char *); + +/* Name <-> Statistic Translations */ +extern char * rtnl_link_stat2str(int, char *, size_t); +extern int rtnl_link_str2stat(const char *); + +/* Link Flags Translations */ +extern char * rtnl_link_flags2str(int, char *, size_t); +extern int rtnl_link_str2flags(const char *); + +extern char * rtnl_link_operstate2str(uint8_t, char *, size_t); +extern int rtnl_link_str2operstate(const char *); + +extern char * rtnl_link_mode2str(uint8_t, char *, size_t); +extern int rtnl_link_str2mode(const char *); + +/* Carrier State Translations */ +extern char * rtnl_link_carrier2str(uint8_t, char *, size_t); +extern int rtnl_link_str2carrier(const char *); + +/* Access Functions */ +extern void rtnl_link_set_qdisc(struct rtnl_link *, const char *); +extern char * rtnl_link_get_qdisc(struct rtnl_link *); + +extern void rtnl_link_set_name(struct rtnl_link *, const char *); +extern char * rtnl_link_get_name(struct rtnl_link *); + +extern void rtnl_link_set_group(struct rtnl_link *, uint32_t); +extern uint32_t rtnl_link_get_group(struct rtnl_link *); + +extern void rtnl_link_set_flags(struct rtnl_link *, unsigned int); +extern void rtnl_link_unset_flags(struct rtnl_link *, unsigned int); +extern unsigned int rtnl_link_get_flags(struct rtnl_link *); + +extern void rtnl_link_set_mtu(struct rtnl_link *, unsigned int); +extern unsigned int rtnl_link_get_mtu(struct rtnl_link *); + +extern void rtnl_link_set_txqlen(struct rtnl_link *, unsigned int); +extern unsigned int rtnl_link_get_txqlen(struct rtnl_link *); + +extern void rtnl_link_set_ifindex(struct rtnl_link *, int); +extern int rtnl_link_get_ifindex(struct rtnl_link *); + +extern void rtnl_link_set_family(struct rtnl_link *, int); +extern int rtnl_link_get_family(struct rtnl_link *); + +extern void rtnl_link_set_arptype(struct rtnl_link *, unsigned int); +extern unsigned int rtnl_link_get_arptype(struct rtnl_link *); + +extern void rtnl_link_set_addr(struct rtnl_link *, struct nl_addr *); +extern struct nl_addr *rtnl_link_get_addr(struct rtnl_link *); + +extern void rtnl_link_set_broadcast(struct rtnl_link *, struct nl_addr *); +extern struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *); + +extern void rtnl_link_set_link(struct rtnl_link *, int); +extern int rtnl_link_get_link(struct rtnl_link *); + +extern void rtnl_link_set_master(struct rtnl_link *, int); +extern int rtnl_link_get_master(struct rtnl_link *); + +extern void rtnl_link_set_carrier(struct rtnl_link *, uint8_t); +extern uint8_t rtnl_link_get_carrier(struct rtnl_link *); + +extern void rtnl_link_set_operstate(struct rtnl_link *, uint8_t); +extern uint8_t rtnl_link_get_operstate(struct rtnl_link *); + +extern void rtnl_link_set_linkmode(struct rtnl_link *, uint8_t); +extern uint8_t rtnl_link_get_linkmode(struct rtnl_link *); + +extern const char * rtnl_link_get_ifalias(struct rtnl_link *); +extern void rtnl_link_set_ifalias(struct rtnl_link *, const char *); + +extern int rtnl_link_get_num_vf(struct rtnl_link *, uint32_t *); + +extern uint64_t rtnl_link_get_stat(struct rtnl_link *, rtnl_link_stat_id_t); +extern int rtnl_link_set_stat(struct rtnl_link *, rtnl_link_stat_id_t, + const uint64_t); + +extern int rtnl_link_set_type(struct rtnl_link *, const char *); +extern char * rtnl_link_get_type(struct rtnl_link *); + +extern void rtnl_link_set_promiscuity(struct rtnl_link *, uint32_t); +extern uint32_t rtnl_link_get_promiscuity(struct rtnl_link *); + +extern void rtnl_link_set_num_tx_queues(struct rtnl_link *, uint32_t); +extern uint32_t rtnl_link_get_num_tx_queues(struct rtnl_link *); + +extern void rtnl_link_set_num_rx_queues(struct rtnl_link *, uint32_t); +extern uint32_t rtnl_link_get_num_rx_queues(struct rtnl_link *); + +extern int rtnl_link_enslave_ifindex(struct nl_sock *, int, int); +extern int rtnl_link_enslave(struct nl_sock *, struct rtnl_link *, + struct rtnl_link *); +extern int rtnl_link_release_ifindex(struct nl_sock *, int); +extern int rtnl_link_release(struct nl_sock *, struct rtnl_link *); + +/* deprecated */ +extern int rtnl_link_set_info_type(struct rtnl_link *, const char *) __attribute__((deprecated)); +extern char * rtnl_link_get_info_type(struct rtnl_link *) __attribute__((deprecated)); +extern void rtnl_link_set_weight(struct rtnl_link *, unsigned int) __attribute__((deprecated)); +extern unsigned int rtnl_link_get_weight(struct rtnl_link *) __attribute__((deprecated)); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/api.h b/include/netlink/route/link/api.h new file mode 100644 index 0000000..03b1e5e --- /dev/null +++ b/include/netlink/route/link/api.h @@ -0,0 +1,20 @@ +/* + * netlink/route/link/api.h Link Modules API + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2013 Thomas Graf + */ + +#ifndef NETLINK_DUMMY_LINK_API_H_ +#define NETLINK_DUMMY_LINK_API_H_ + +#include +#include + +#warning "You are including a deprecated header file, include ." + +#endif diff --git a/include/netlink/route/link/bonding.h b/include/netlink/route/link/bonding.h new file mode 100644 index 0000000..5c34662 --- /dev/null +++ b/include/netlink/route/link/bonding.h @@ -0,0 +1,39 @@ +/* + * netlink/route/link/bonding.h Bonding Interface + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2011-2013 Thomas Graf + */ + +#ifndef NETLINK_LINK_BONDING_H_ +#define NETLINK_LINK_BONDING_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct rtnl_link *rtnl_link_bond_alloc(void); + +extern int rtnl_link_bond_add(struct nl_sock *, const char *, + struct rtnl_link *); + +extern int rtnl_link_bond_enslave_ifindex(struct nl_sock *, int, int); +extern int rtnl_link_bond_enslave(struct nl_sock *, struct rtnl_link *, + struct rtnl_link *); + +extern int rtnl_link_bond_release_ifindex(struct nl_sock *, int); +extern int rtnl_link_bond_release(struct nl_sock *, struct rtnl_link *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/netlink/route/link/bridge.h b/include/netlink/route/link/bridge.h new file mode 100644 index 0000000..71dcc24 --- /dev/null +++ b/include/netlink/route/link/bridge.h @@ -0,0 +1,56 @@ +/* + * netlink/route/link/bridge.h Bridge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2013 Thomas Graf + */ + +#ifndef NETLINK_LINK_BRIDGE_H_ +#define NETLINK_LINK_BRIDGE_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Bridge flags + * @ingroup bridge + */ +enum rtnl_link_bridge_flags { + RTNL_BRIDGE_HAIRPIN_MODE = 0x0001, + RTNL_BRIDGE_BPDU_GUARD = 0x0002, + RTNL_BRIDGE_ROOT_BLOCK = 0x0004, + RTNL_BRIDGE_FAST_LEAVE = 0x0008, +}; + +extern struct rtnl_link *rtnl_link_bridge_alloc(void); + +extern int rtnl_link_is_bridge(struct rtnl_link *); +extern int rtnl_link_bridge_has_ext_info(struct rtnl_link *); + +extern int rtnl_link_bridge_set_port_state(struct rtnl_link *, uint8_t ); +extern int rtnl_link_bridge_get_port_state(struct rtnl_link *); + +extern int rtnl_link_bridge_set_priority(struct rtnl_link *, uint16_t); +extern int rtnl_link_bridge_get_priority(struct rtnl_link *); + +extern int rtnl_link_bridge_set_cost(struct rtnl_link *, uint32_t); +extern int rtnl_link_bridge_get_cost(struct rtnl_link *, uint32_t *); + +extern int rtnl_link_bridge_unset_flags(struct rtnl_link *, unsigned int); +extern int rtnl_link_bridge_set_flags(struct rtnl_link *, unsigned int); +extern int rtnl_link_bridge_get_flags(struct rtnl_link *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/netlink/route/link/can.h b/include/netlink/route/link/can.h new file mode 100644 index 0000000..61c9f47 --- /dev/null +++ b/include/netlink/route/link/can.h @@ -0,0 +1,60 @@ +/* + * netlink/route/link/can.h CAN interface + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2012 Benedikt Spranger + */ + +#ifndef NETLINK_LINK_CAN_H_ +#define NETLINK_LINK_CAN_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_link_is_can(struct rtnl_link *link); + +extern char *rtnl_link_can_ctrlmode2str(int, char *, size_t); +extern int rtnl_link_can_str2ctrlmode(const char *); + +extern int rtnl_link_can_restart(struct rtnl_link *); +extern int rtnl_link_can_freq(struct rtnl_link *, uint32_t *); +extern int rtnl_link_can_state(struct rtnl_link *, uint32_t *); + +extern int rtnl_link_can_berr_rx(struct rtnl_link *); +extern int rtnl_link_can_berr_tx(struct rtnl_link *); +extern int rtnl_link_can_berr(struct rtnl_link *, struct can_berr_counter *); + +extern int rtnl_link_can_get_bt_const(struct rtnl_link *, + struct can_bittiming_const *); +extern int rtnl_link_can_get_bittiming(struct rtnl_link *, + struct can_bittiming *); +extern int rtnl_link_can_set_bittiming(struct rtnl_link *, + struct can_bittiming *); + +extern int rtnl_link_can_get_bitrate(struct rtnl_link *, uint32_t *); +extern int rtnl_link_can_set_bitrate(struct rtnl_link *, uint32_t); + +extern int rtnl_link_can_get_sample_point(struct rtnl_link *, uint32_t *); +extern int rtnl_link_can_set_sample_point(struct rtnl_link *, uint32_t); + +extern int rtnl_link_can_get_restart_ms(struct rtnl_link *, uint32_t *); +extern int rtnl_link_can_set_restart_ms(struct rtnl_link *, uint32_t); + +extern int rtnl_link_can_get_ctrlmode(struct rtnl_link *, uint32_t *); +extern int rtnl_link_can_set_ctrlmode(struct rtnl_link *, uint32_t); +extern int rtnl_link_can_unset_ctrlmode(struct rtnl_link *, uint32_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/inet.h b/include/netlink/route/link/inet.h new file mode 100644 index 0000000..506542f --- /dev/null +++ b/include/netlink/route/link/inet.h @@ -0,0 +1,33 @@ +/* + * netlink/route/link/inet.h INET Link Module + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2010 Thomas Graf + */ + +#ifndef NETLINK_LINK_INET_H_ +#define NETLINK_LINK_INET_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern const char * rtnl_link_inet_devconf2str(int, char *, size_t); +extern int rtnl_link_inet_str2devconf(const char *); + +extern int rtnl_link_inet_get_conf(struct rtnl_link *, + const unsigned int, uint32_t *); +extern int rtnl_link_inet_set_conf(struct rtnl_link *, + const unsigned int, uint32_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/info-api.h b/include/netlink/route/link/info-api.h new file mode 100644 index 0000000..1087ad4 --- /dev/null +++ b/include/netlink/route/link/info-api.h @@ -0,0 +1,20 @@ +/* + * netlink/route/link/info-api.h Link Modules API + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2013 Thomas Graf + */ + +#ifndef NETLINK_DUMMY_LINK_INFO_API_H_ +#define NETLINK_DUMMY_LINK_INFO_API_H_ + +#include +#include + +#warning "You are including a deprecated header file, include ." + +#endif diff --git a/include/netlink/route/link/vlan.h b/include/netlink/route/link/vlan.h new file mode 100644 index 0000000..f274163 --- /dev/null +++ b/include/netlink/route/link/vlan.h @@ -0,0 +1,59 @@ +/* + * netlink/route/link/vlan.h VLAN interface + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2013 Thomas Graf + */ + +#ifndef NETLINK_LINK_VLAN_H_ +#define NETLINK_LINK_VLAN_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct vlan_map +{ + uint32_t vm_from; + uint32_t vm_to; +}; + +#define VLAN_PRIO_MAX 7 + +extern struct rtnl_link *rtnl_link_vlan_alloc(void); + +extern int rtnl_link_is_vlan(struct rtnl_link *); + +extern char * rtnl_link_vlan_flags2str(int, char *, size_t); +extern int rtnl_link_vlan_str2flags(const char *); + +extern int rtnl_link_vlan_set_id(struct rtnl_link *, uint16_t); +extern int rtnl_link_vlan_get_id(struct rtnl_link *); + +extern int rtnl_link_vlan_set_flags(struct rtnl_link *, + unsigned int); +extern int rtnl_link_vlan_unset_flags(struct rtnl_link *, + unsigned int); +extern int rtnl_link_vlan_get_flags(struct rtnl_link *); + +extern int rtnl_link_vlan_set_ingress_map(struct rtnl_link *, + int, uint32_t); +extern uint32_t * rtnl_link_vlan_get_ingress_map(struct rtnl_link *); + +extern int rtnl_link_vlan_set_egress_map(struct rtnl_link *, + uint32_t, int); +extern struct vlan_map *rtnl_link_vlan_get_egress_map(struct rtnl_link *, + int *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/neighbour.h b/include/netlink/route/neighbour.h new file mode 100644 index 0000000..1d1179b --- /dev/null +++ b/include/netlink/route/neighbour.h @@ -0,0 +1,81 @@ +/* + * netlink/route/neighbour.h Neighbours + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + */ + +#ifndef NETLINK_NEIGHBOUR_H_ +#define NETLINK_NEIGHBOUR_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct rtnl_neigh; + +extern struct rtnl_neigh *rtnl_neigh_alloc(void); +extern void rtnl_neigh_put(struct rtnl_neigh *); + +extern int rtnl_neigh_alloc_cache(struct nl_sock *, struct nl_cache **); +extern struct rtnl_neigh *rtnl_neigh_get(struct nl_cache *, int, + struct nl_addr *); + +extern int rtnl_neigh_parse(struct nlmsghdr *, struct rtnl_neigh **); + +extern char * rtnl_neigh_state2str(int, char *, size_t); +extern int rtnl_neigh_str2state(const char *); + +extern char * rtnl_neigh_flags2str(int, char *, size_t); +extern int rtnl_neigh_str2flag(const char *); + +extern int rtnl_neigh_add(struct nl_sock *, struct rtnl_neigh *, int); +extern int rtnl_neigh_build_add_request(struct rtnl_neigh *, int, + struct nl_msg **); + +extern int rtnl_neigh_delete(struct nl_sock *, struct rtnl_neigh *, int); +extern int rtnl_neigh_build_delete_request(struct rtnl_neigh *, int, + struct nl_msg **); + +extern void rtnl_neigh_set_state(struct rtnl_neigh *, int); +extern int rtnl_neigh_get_state(struct rtnl_neigh *); +extern void rtnl_neigh_unset_state(struct rtnl_neigh *, + int); + +extern void rtnl_neigh_set_flags(struct rtnl_neigh *, + unsigned int); +extern void rtnl_neigh_unset_flags(struct rtnl_neigh *, + unsigned int); +extern unsigned int rtnl_neigh_get_flags(struct rtnl_neigh *); + +extern void rtnl_neigh_set_ifindex(struct rtnl_neigh *, + int); +extern int rtnl_neigh_get_ifindex(struct rtnl_neigh *); + +extern void rtnl_neigh_set_lladdr(struct rtnl_neigh *, + struct nl_addr *); +extern struct nl_addr * rtnl_neigh_get_lladdr(struct rtnl_neigh *); + +extern int rtnl_neigh_set_dst(struct rtnl_neigh *, + struct nl_addr *); +extern struct nl_addr * rtnl_neigh_get_dst(struct rtnl_neigh *); + +extern void rtnl_neigh_set_type(struct rtnl_neigh *, int); +extern int rtnl_neigh_get_type(struct rtnl_neigh *); + +extern void rtnl_neigh_set_family(struct rtnl_neigh *, int); +extern int rtnl_neigh_get_family(struct rtnl_neigh *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/neightbl.h b/include/netlink/route/neightbl.h new file mode 100644 index 0000000..412c3e9 --- /dev/null +++ b/include/netlink/route/neightbl.h @@ -0,0 +1,65 @@ +/* + * netlink/route/neightbl.h Neighbour Tables + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + */ + +#ifndef NETLINK_NEIGHTBL_H_ +#define NETLINK_NEIGHTBL_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct rtnl_neightbl; + +extern struct rtnl_neightbl *rtnl_neightbl_alloc(void); +extern void rtnl_neightbl_put(struct rtnl_neightbl *); +extern void rtnl_neightbl_free(struct rtnl_neightbl *); +extern int rtnl_neightbl_alloc_cache(struct nl_sock *, struct nl_cache **); +extern struct rtnl_neightbl *rtnl_neightbl_get(struct nl_cache *, + const char *, int); +extern void rtnl_neightbl_dump(struct rtnl_neightbl *, FILE *, + struct nl_dump_params *); + +extern int rtnl_neightbl_build_change_request(struct rtnl_neightbl *, + struct rtnl_neightbl *, + struct nl_msg **); +extern int rtnl_neightbl_change(struct nl_sock *, struct rtnl_neightbl *, + struct rtnl_neightbl *); + +extern void rtnl_neightbl_set_family(struct rtnl_neightbl *, int); +extern void rtnl_neightbl_set_gc_tresh1(struct rtnl_neightbl *, int); +extern void rtnl_neightbl_set_gc_tresh2(struct rtnl_neightbl *, int); +extern void rtnl_neightbl_set_gc_tresh3(struct rtnl_neightbl *, int); +extern void rtnl_neightbl_set_name(struct rtnl_neightbl *, const char *); +extern void rtnl_neightbl_set_dev(struct rtnl_neightbl *, int); +extern void rtnl_neightbl_set_queue_len(struct rtnl_neightbl *, int); +extern void rtnl_neightbl_set_proxy_queue_len(struct rtnl_neightbl *, int); +extern void rtnl_neightbl_set_app_probes(struct rtnl_neightbl *, int); +extern void rtnl_neightbl_set_ucast_probes(struct rtnl_neightbl *, int); +extern void rtnl_neightbl_set_mcast_probes(struct rtnl_neightbl *, int); +extern void rtnl_neightbl_set_base_reachable_time(struct rtnl_neightbl *, + uint64_t); +extern void rtnl_neightbl_set_retrans_time(struct rtnl_neightbl *, uint64_t); +extern void rtnl_neightbl_set_gc_stale_time(struct rtnl_neightbl *, uint64_t); +extern void rtnl_neightbl_set_delay_probe_time(struct rtnl_neightbl *, + uint64_t); +extern void rtnl_neightbl_set_anycast_delay(struct rtnl_neightbl *, uint64_t); +extern void rtnl_neightbl_set_proxy_delay(struct rtnl_neightbl *, uint64_t); +extern void rtnl_neightbl_set_locktime(struct rtnl_neightbl *, uint64_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/nexthop.h b/include/netlink/route/nexthop.h new file mode 100644 index 0000000..2aa44dc --- /dev/null +++ b/include/netlink/route/nexthop.h @@ -0,0 +1,65 @@ +/* + * netlink/route/nexthop.h Routing Nexthop + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + */ + +#ifndef NETLINK_ROUTE_NEXTHOP_H_ +#define NETLINK_ROUTE_NEXTHOP_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct rtnl_nexthop; + +enum { + NH_DUMP_FROM_ONELINE = -2, + NH_DUMP_FROM_DETAILS = -1, + NH_DUMP_FROM_ENV = 0, + /* > 0 reserved for nexthop index */ +}; + +extern struct rtnl_nexthop * rtnl_route_nh_alloc(void); +extern struct rtnl_nexthop * rtnl_route_nh_clone(struct rtnl_nexthop *); +extern void rtnl_route_nh_free(struct rtnl_nexthop *); + +extern int rtnl_route_nh_compare(struct rtnl_nexthop *, + struct rtnl_nexthop *, + uint32_t, int); + +extern void rtnl_route_nh_dump(struct rtnl_nexthop *, + struct nl_dump_params *); + +extern void rtnl_route_nh_set_weight(struct rtnl_nexthop *, uint8_t); +extern uint8_t rtnl_route_nh_get_weight(struct rtnl_nexthop *); +extern void rtnl_route_nh_set_ifindex(struct rtnl_nexthop *, int); +extern int rtnl_route_nh_get_ifindex(struct rtnl_nexthop *); +extern void rtnl_route_nh_set_gateway(struct rtnl_nexthop *, + struct nl_addr *); +extern struct nl_addr * rtnl_route_nh_get_gateway(struct rtnl_nexthop *); +extern void rtnl_route_nh_set_flags(struct rtnl_nexthop *, + unsigned int); +extern void rtnl_route_nh_unset_flags(struct rtnl_nexthop *, + unsigned int); +extern unsigned int rtnl_route_nh_get_flags(struct rtnl_nexthop *); +extern void rtnl_route_nh_set_realms(struct rtnl_nexthop *, + uint32_t); +extern uint32_t rtnl_route_nh_get_realms(struct rtnl_nexthop *); + +extern char * rtnl_route_nh_flags2str(int, char *, size_t); +extern int rtnl_route_nh_str2flags(const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/pktloc.h b/include/netlink/route/pktloc.h new file mode 100644 index 0000000..c3768ce --- /dev/null +++ b/include/netlink/route/pktloc.h @@ -0,0 +1,49 @@ +/* + * netlink/route/pktloc.h Packet Location Aliasing + * + * 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 + */ + +#ifndef NETLINK_PKTLOC_H_ +#define NETLINK_PKTLOC_H_ + +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct rtnl_pktloc +{ + char * name; + uint8_t layer; + uint8_t shift; + uint16_t offset; + uint16_t align; + uint32_t mask; + uint32_t refcnt; + + struct nl_list_head list; +}; + +extern int rtnl_pktloc_lookup(const char *, struct rtnl_pktloc **); +extern struct rtnl_pktloc *rtnl_pktloc_alloc(void); +extern void rtnl_pktloc_put(struct rtnl_pktloc *); +extern int rtnl_pktloc_add(struct rtnl_pktloc *); +extern void rtnl_pktloc_foreach(void (*cb)(struct rtnl_pktloc *, void *), + void *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/qdisc.h b/include/netlink/route/qdisc.h new file mode 100644 index 0000000..10b85c5 --- /dev/null +++ b/include/netlink/route/qdisc.h @@ -0,0 +1,73 @@ +/* + * netlink/route/qdisc.h 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-2011 Thomas Graf + */ + +#ifndef NETLINK_QDISC_H_ +#define NETLINK_QDISC_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct rtnl_qdisc; + +extern struct rtnl_qdisc * + rtnl_qdisc_alloc(void); +extern void rtnl_qdisc_put(struct rtnl_qdisc *); + +extern int rtnl_qdisc_alloc_cache(struct nl_sock *, struct nl_cache **); + +extern struct rtnl_qdisc * + rtnl_qdisc_get(struct nl_cache *, int, uint32_t); + +extern struct rtnl_qdisc * + rtnl_qdisc_get_by_parent(struct nl_cache *, int, uint32_t); + +extern int rtnl_qdisc_build_add_request(struct rtnl_qdisc *, int, + struct nl_msg **); +extern int rtnl_qdisc_add(struct nl_sock *, struct rtnl_qdisc *, int); + +extern int rtnl_qdisc_build_update_request(struct rtnl_qdisc *, + struct rtnl_qdisc *, + int, struct nl_msg **); + +extern int rtnl_qdisc_update(struct nl_sock *, struct rtnl_qdisc *, + struct rtnl_qdisc *, int); + +extern int rtnl_qdisc_build_delete_request(struct rtnl_qdisc *, + struct nl_msg **); +extern int rtnl_qdisc_delete(struct nl_sock *, struct rtnl_qdisc *); + +/* Deprecated functions */ +extern void rtnl_qdisc_foreach_child(struct rtnl_qdisc *, struct nl_cache *, + void (*cb)(struct nl_object *, void *), + void *) __attribute__ ((deprecated)); + +extern void rtnl_qdisc_foreach_cls(struct rtnl_qdisc *, struct nl_cache *, + void (*cb)(struct nl_object *, void *), + void *) __attribute__ ((deprecated)); + +extern int rtnl_qdisc_build_change_request(struct rtnl_qdisc *, + struct rtnl_qdisc *, + struct nl_msg **) + __attribute__ ((deprecated)); + +extern int rtnl_qdisc_change(struct nl_sock *, struct rtnl_qdisc *, + struct rtnl_qdisc *) __attribute__ ((deprecated)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/qdisc/cbq.h b/include/netlink/route/qdisc/cbq.h new file mode 100644 index 0000000..3dbdd2d --- /dev/null +++ b/include/netlink/route/qdisc/cbq.h @@ -0,0 +1,30 @@ +/* + * netlink/route/sch/cbq.h Class Based Queueing + * + * 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 + */ + +#ifndef NETLINK_CBQ_H_ +#define NETLINK_CBQ_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern char * nl_ovl_strategy2str(int, char *, size_t); +extern int nl_str2ovl_strategy(const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/qdisc/dsmark.h b/include/netlink/route/qdisc/dsmark.h new file mode 100644 index 0000000..06bd9d3 --- /dev/null +++ b/include/netlink/route/qdisc/dsmark.h @@ -0,0 +1,43 @@ +/* + * netlink/route/sch/dsmark.h DSMARK + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + */ + +#ifndef NETLINK_DSMARK_H_ +#define NETLINK_DSMARK_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_class_dsmark_set_bitmask(struct rtnl_class *, uint8_t); +extern int rtnl_class_dsmark_get_bitmask(struct rtnl_class *); + +extern int rtnl_class_dsmark_set_value(struct rtnl_class *, uint8_t); +extern int rtnl_class_dsmark_get_value(struct rtnl_class *); + +extern int rtnl_qdisc_dsmark_set_indices(struct rtnl_qdisc *, uint16_t); +extern int rtnl_qdisc_dsmark_get_indices(struct rtnl_qdisc *); + +extern int rtnl_qdisc_dsmark_set_default_index(struct rtnl_qdisc *, + uint16_t); +extern int rtnl_qdisc_dsmark_get_default_index(struct rtnl_qdisc *); + +extern int rtnl_qdisc_dsmark_set_set_tc_index(struct rtnl_qdisc *, int); +extern int rtnl_qdisc_dsmark_get_set_tc_index(struct rtnl_qdisc *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/qdisc/fifo.h b/include/netlink/route/qdisc/fifo.h new file mode 100644 index 0000000..c033427 --- /dev/null +++ b/include/netlink/route/qdisc/fifo.h @@ -0,0 +1,29 @@ +/* + * netlink/route/sch/fifo.c FIFO Qdisc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2006 Thomas Graf + */ + +#ifndef NETLINK_FIFO_H_ +#define NETLINK_FIFO_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_qdisc_fifo_set_limit(struct rtnl_qdisc *, int); +extern int rtnl_qdisc_fifo_get_limit(struct rtnl_qdisc *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/qdisc/htb.h b/include/netlink/route/qdisc/htb.h new file mode 100644 index 0000000..c909f84 --- /dev/null +++ b/include/netlink/route/qdisc/htb.h @@ -0,0 +1,49 @@ +/* + * netlink/route/sch/htb.h HTB Qdisc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + * Copyright (c) 2005 Petr Gotthard + * Copyright (c) 2005 Siemens AG Oesterreich + */ + +#ifndef NETLINK_HTB_H_ +#define NETLINK_HTB_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint32_t rtnl_htb_get_rate2quantum(struct rtnl_qdisc *); +extern int rtnl_htb_set_rate2quantum(struct rtnl_qdisc *, uint32_t); +extern uint32_t rtnl_htb_get_defcls(struct rtnl_qdisc *); +extern int rtnl_htb_set_defcls(struct rtnl_qdisc *, uint32_t); + +extern uint32_t rtnl_htb_get_prio(struct rtnl_class *); +extern int rtnl_htb_set_prio(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_rate(struct rtnl_class *); +extern int rtnl_htb_set_rate(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_ceil(struct rtnl_class *); +extern int rtnl_htb_set_ceil(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *); +extern int rtnl_htb_set_rbuffer(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_cbuffer(struct rtnl_class *); +extern int rtnl_htb_set_cbuffer(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_quantum(struct rtnl_class *); +extern int rtnl_htb_set_quantum(struct rtnl_class *, uint32_t); +extern int rtnl_htb_get_level(struct rtnl_class *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/qdisc/netem.h b/include/netlink/route/qdisc/netem.h new file mode 100644 index 0000000..4b071bf --- /dev/null +++ b/include/netlink/route/qdisc/netem.h @@ -0,0 +1,76 @@ +/* + * netlink/route/sch/netem.h Network Emulator Qdisc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2006 Thomas Graf + */ + +#ifndef NETLINK_NETEM_H_ +#define NETLINK_NETEM_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern void rtnl_netem_set_limit(struct rtnl_qdisc *, int); +extern int rtnl_netem_get_limit(struct rtnl_qdisc *); + +/* Packet Re-ordering */ +extern void rtnl_netem_set_gap(struct rtnl_qdisc *, int); +extern int rtnl_netem_get_gap(struct rtnl_qdisc *); + +extern void rtnl_netem_set_reorder_probability(struct rtnl_qdisc *, int); +extern int rtnl_netem_get_reorder_probability(struct rtnl_qdisc *); + +extern void rtnl_netem_set_reorder_correlation(struct rtnl_qdisc *, int); +extern int rtnl_netem_get_reorder_correlation(struct rtnl_qdisc *); + +/* Corruption */ +extern void rtnl_netem_set_corruption_probability(struct rtnl_qdisc *, int); +extern int rtnl_netem_get_corruption_probability(struct rtnl_qdisc *); + +extern void rtnl_netem_set_corruption_correlation(struct rtnl_qdisc *, int); +extern int rtnl_netem_get_corruption_correlation(struct rtnl_qdisc *); + +/* Packet Loss */ +extern void rtnl_netem_set_loss(struct rtnl_qdisc *, int); +extern int rtnl_netem_get_loss(struct rtnl_qdisc *); + +extern void rtnl_netem_set_loss_correlation(struct rtnl_qdisc *, int); +extern int rtnl_netem_get_loss_correlation(struct rtnl_qdisc *); + +/* Packet Duplication */ +extern void rtnl_netem_set_duplicate(struct rtnl_qdisc *, int); +extern int rtnl_netem_get_duplicate(struct rtnl_qdisc *); + +extern void rtnl_netem_set_duplicate_correlation(struct rtnl_qdisc *, int); +extern int rtnl_netem_get_duplicate_correlation(struct rtnl_qdisc *); + +/* Packet Delay */ +extern void rtnl_netem_set_delay(struct rtnl_qdisc *, int); +extern int rtnl_netem_get_delay(struct rtnl_qdisc *); + +extern void rtnl_netem_set_jitter(struct rtnl_qdisc *, int); +extern int rtnl_netem_get_jitter(struct rtnl_qdisc *); + +extern void rtnl_netem_set_delay_correlation(struct rtnl_qdisc *, int); +extern int rtnl_netem_get_delay_correlation(struct rtnl_qdisc *); + +/* Delay Distribution */ +#define MAXDIST 65536 +extern int rtnl_netem_set_delay_distribution(struct rtnl_qdisc *, const char *); +extern int rtnl_netem_get_delay_distribution_size(struct rtnl_qdisc *); +extern int rtnl_netem_get_delay_distribution(struct rtnl_qdisc *, int16_t **); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/qdisc/plug.h b/include/netlink/route/qdisc/plug.h new file mode 100644 index 0000000..40f7e53 --- /dev/null +++ b/include/netlink/route/qdisc/plug.h @@ -0,0 +1,31 @@ +/* + * netlink/route/qdisc/plug.c PLUG Qdisc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2012 Shriram Rajagopalan + */ + +#ifndef NETLINK_PLUG_H_ +#define NETLINK_PLUG_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_qdisc_plug_set_limit(struct rtnl_qdisc *, int); +extern int rtnl_qdisc_plug_buffer(struct rtnl_qdisc *); +extern int rtnl_qdisc_plug_release_one(struct rtnl_qdisc *); +extern int rtnl_qdisc_plug_release_indefinite(struct rtnl_qdisc *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/qdisc/prio.h b/include/netlink/route/qdisc/prio.h new file mode 100644 index 0000000..636a8f9 --- /dev/null +++ b/include/netlink/route/qdisc/prio.h @@ -0,0 +1,54 @@ +/* + * netlink/route/sch/prio.c PRIO Qdisc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + */ + +#ifndef NETLINK_PRIO_H_ +#define NETLINK_PRIO_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Default Values + * @{ + */ + +/** + * Default number of bands. + * @ingroup prio + */ +#define QDISC_PRIO_DEFAULT_BANDS 3 + +/** + * Default priority mapping. + * @ingroup prio + */ +#define QDISC_PRIO_DEFAULT_PRIOMAP \ + { 1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 } + +/** @} */ + +extern void rtnl_qdisc_prio_set_bands(struct rtnl_qdisc *, int); +extern int rtnl_qdisc_prio_get_bands(struct rtnl_qdisc *); +extern int rtnl_qdisc_prio_set_priomap(struct rtnl_qdisc *, uint8_t[], int); +extern uint8_t *rtnl_qdisc_prio_get_priomap(struct rtnl_qdisc *); + +extern char * rtnl_prio2str(int, char *, size_t); +extern int rtnl_str2prio(const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/qdisc/red.h b/include/netlink/route/qdisc/red.h new file mode 100644 index 0000000..a4e8642 --- /dev/null +++ b/include/netlink/route/qdisc/red.h @@ -0,0 +1,17 @@ +/* + * netlink/route/sch/red.h RED Qdisc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2006 Thomas Graf + */ + +#ifndef NETLINK_RED_H_ +#define NETLINK_RED_H_ + +#include + +#endif diff --git a/include/netlink/route/qdisc/sfq.h b/include/netlink/route/qdisc/sfq.h new file mode 100644 index 0000000..77d2e29 --- /dev/null +++ b/include/netlink/route/qdisc/sfq.h @@ -0,0 +1,37 @@ +/* + * netlink/route/sch/sfq.c SFQ Qdisc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + */ + +#ifndef NETLINK_SFQ_H_ +#define NETLINK_SFQ_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern void rtnl_sfq_set_quantum(struct rtnl_qdisc *, int); +extern int rtnl_sfq_get_quantum(struct rtnl_qdisc *); + +extern void rtnl_sfq_set_limit(struct rtnl_qdisc *, int); +extern int rtnl_sfq_get_limit(struct rtnl_qdisc *); + +extern void rtnl_sfq_set_perturb(struct rtnl_qdisc *, int); +extern int rtnl_sfq_get_perturb(struct rtnl_qdisc *); + +extern int rtnl_sfq_get_divisor(struct rtnl_qdisc *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/qdisc/tbf.h b/include/netlink/route/qdisc/tbf.h new file mode 100644 index 0000000..ce31c54 --- /dev/null +++ b/include/netlink/route/qdisc/tbf.h @@ -0,0 +1,41 @@ +/* + * netlink/route/sch/tbf.h TBF Qdisc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + */ + +#ifndef NETLINK_TBF_H_ +#define NETLINK_TBF_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern void rtnl_qdisc_tbf_set_limit(struct rtnl_qdisc *, int); +extern int rtnl_qdisc_tbf_set_limit_by_latency(struct rtnl_qdisc *, int); +extern int rtnl_qdisc_tbf_get_limit(struct rtnl_qdisc *); + +extern void rtnl_qdisc_tbf_set_rate(struct rtnl_qdisc *, int, int, int); +extern int rtnl_qdisc_tbf_get_rate(struct rtnl_qdisc *); +extern int rtnl_qdisc_tbf_get_rate_bucket(struct rtnl_qdisc *); +extern int rtnl_qdisc_tbf_get_rate_cell(struct rtnl_qdisc *); + +extern int rtnl_qdisc_tbf_set_peakrate(struct rtnl_qdisc *, int, int, int); +extern int rtnl_qdisc_tbf_get_peakrate(struct rtnl_qdisc *); +extern int rtnl_qdisc_tbf_get_peakrate_bucket(struct rtnl_qdisc *); +extern int rtnl_qdisc_tbf_get_peakrate_cell(struct rtnl_qdisc *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/route.h b/include/netlink/route/route.h new file mode 100644 index 0000000..477250d --- /dev/null +++ b/include/netlink/route/route.h @@ -0,0 +1,128 @@ +/* + * netlink/route/route.h Routes + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +#ifndef NETLINK_ROUTE_H_ +#define NETLINK_ROUTE_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @ingroup route + * When passed to rtnl_route_alloc_cache() the cache will + * correspond to the contents of the routing cache instead + * of the actual routes. + */ +#define ROUTE_CACHE_CONTENT 1 + +struct rtnl_route; + +struct rtnl_rtcacheinfo +{ + uint32_t rtci_clntref; + uint32_t rtci_last_use; + uint32_t rtci_expires; + int32_t rtci_error; + uint32_t rtci_used; + uint32_t rtci_id; + uint32_t rtci_ts; + uint32_t rtci_tsage; +}; + +extern struct nl_object_ops route_obj_ops; + +extern struct rtnl_route * rtnl_route_alloc(void); +extern void rtnl_route_put(struct rtnl_route *); +extern int rtnl_route_alloc_cache(struct nl_sock *, int, int, + struct nl_cache **); + +extern void rtnl_route_get(struct rtnl_route *); + +extern int rtnl_route_parse(struct nlmsghdr *, struct rtnl_route **); +extern int rtnl_route_build_msg(struct nl_msg *, struct rtnl_route *); + +extern int rtnl_route_build_add_request(struct rtnl_route *, int, + struct nl_msg **); +extern int rtnl_route_add(struct nl_sock *, struct rtnl_route *, int); +extern int rtnl_route_build_del_request(struct rtnl_route *, int, + struct nl_msg **); +extern int rtnl_route_delete(struct nl_sock *, struct rtnl_route *, int); + +extern void rtnl_route_set_table(struct rtnl_route *, uint32_t); +extern uint32_t rtnl_route_get_table(struct rtnl_route *); +extern void rtnl_route_set_scope(struct rtnl_route *, uint8_t); +extern uint8_t rtnl_route_get_scope(struct rtnl_route *); +extern void rtnl_route_set_tos(struct rtnl_route *, uint8_t); +extern uint8_t rtnl_route_get_tos(struct rtnl_route *); +extern void rtnl_route_set_protocol(struct rtnl_route *, uint8_t); +extern uint8_t rtnl_route_get_protocol(struct rtnl_route *); +extern void rtnl_route_set_priority(struct rtnl_route *, uint32_t); +extern uint32_t rtnl_route_get_priority(struct rtnl_route *); +extern int rtnl_route_set_family(struct rtnl_route *, uint8_t); +extern uint8_t rtnl_route_get_family(struct rtnl_route *); +extern int rtnl_route_set_type(struct rtnl_route *, uint8_t); +extern uint8_t rtnl_route_get_type(struct rtnl_route *); +extern void rtnl_route_set_flags(struct rtnl_route *, uint32_t); +extern void rtnl_route_unset_flags(struct rtnl_route *, uint32_t); +extern uint32_t rtnl_route_get_flags(struct rtnl_route *); +extern int rtnl_route_set_metric(struct rtnl_route *, int, unsigned int); +extern int rtnl_route_unset_metric(struct rtnl_route *, int); +extern int rtnl_route_get_metric(struct rtnl_route *, int, uint32_t *); +extern int rtnl_route_set_dst(struct rtnl_route *, struct nl_addr *); +extern struct nl_addr *rtnl_route_get_dst(struct rtnl_route *); +extern int rtnl_route_set_src(struct rtnl_route *, struct nl_addr *); +extern struct nl_addr *rtnl_route_get_src(struct rtnl_route *); +extern int rtnl_route_set_pref_src(struct rtnl_route *, struct nl_addr *); +extern struct nl_addr *rtnl_route_get_pref_src(struct rtnl_route *); +extern void rtnl_route_set_iif(struct rtnl_route *, int); +extern int rtnl_route_get_iif(struct rtnl_route *); +extern int rtnl_route_get_src_len(struct rtnl_route *); + +extern void rtnl_route_add_nexthop(struct rtnl_route *, + struct rtnl_nexthop *); +extern void rtnl_route_remove_nexthop(struct rtnl_route *, + struct rtnl_nexthop *); +extern struct nl_list_head *rtnl_route_get_nexthops(struct rtnl_route *); +extern int rtnl_route_get_nnexthops(struct rtnl_route *); + +extern void rtnl_route_foreach_nexthop(struct rtnl_route *r, + void (*cb)(struct rtnl_nexthop *, void *), + void *arg); + +extern struct rtnl_nexthop * rtnl_route_nexthop_n(struct rtnl_route *r, int n); + +extern int rtnl_route_guess_scope(struct rtnl_route *); + +extern char * rtnl_route_table2str(int, char *, size_t); +extern int rtnl_route_str2table(const char *); +extern int rtnl_route_read_table_names(const char *); + +extern char * rtnl_route_proto2str(int, char *, size_t); +extern int rtnl_route_str2proto(const char *); +extern int rtnl_route_read_protocol_names(const char *); + +extern char * rtnl_route_metric2str(int, char *, size_t); +extern int rtnl_route_str2metric(const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/rtnl.h b/include/netlink/route/rtnl.h new file mode 100644 index 0000000..f551a5d --- /dev/null +++ b/include/netlink/route/rtnl.h @@ -0,0 +1,69 @@ +/* + * netlink/route/rtnl.h Routing Netlink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + */ + +#ifndef NETLINK_RTNL_H_ +#define NETLINK_RTNL_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Realms + * @{ + */ + +/** + * Mask specying the size of each realm part + * @ingroup rtnl + */ +#define RTNL_REALM_MASK (0xFFFF) + +/** + * Extract FROM realm from a realms field + */ +#define RTNL_REALM_FROM(realm) ((realm) >> 16) + +/** + * Extract TO realm from a realms field + */ +#define RTNL_REALM_TO(realm) ((realm) & RTNL_REALM_MASK) + +/** + * Build a realms field + */ +#define RTNL_MAKE_REALM(from, to) \ + ((RTNL_REALM_TO(from) << 16) & RTNL_REALM_TO(to)) + +/** @} */ + + +/* General */ +extern int nl_rtgen_request(struct nl_sock *, int, int, int); + +/* Routing Type Translations */ +extern char * nl_rtntype2str(int, char *, size_t); +extern int nl_str2rtntype(const char *); + +/* Scope Translations */ +extern char * rtnl_scope2str(int, char *, size_t); +extern int rtnl_str2scope(const char *); + +/* Realms Translations */ +extern char * rtnl_realms2str(uint32_t, char *, size_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/rule.h b/include/netlink/route/rule.h new file mode 100644 index 0000000..760b782 --- /dev/null +++ b/include/netlink/route/rule.h @@ -0,0 +1,75 @@ +/* + * netlink/route/rule.h Rules + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2010 Thomas Graf + */ + +#ifndef NETLINK_RULE_H_ +#define NETLINK_RULE_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct rtnl_rule; + +/* General */ +extern struct rtnl_rule * rtnl_rule_alloc(void); +extern void rtnl_rule_put(struct rtnl_rule *); + +extern int rtnl_rule_alloc_cache(struct nl_sock *, int, + struct nl_cache **); +extern void rtnl_rule_dump(struct rtnl_rule *, FILE *, struct nl_dump_params *); + +extern int rtnl_rule_build_add_request(struct rtnl_rule *, int, + struct nl_msg **); +extern int rtnl_rule_add(struct nl_sock *, struct rtnl_rule *, int); +extern int rtnl_rule_build_delete_request(struct rtnl_rule *, int, + struct nl_msg **); +extern int rtnl_rule_delete(struct nl_sock *, struct rtnl_rule *, int); + + +/* attribute modification */ +extern void rtnl_rule_set_family(struct rtnl_rule *, int); +extern int rtnl_rule_get_family(struct rtnl_rule *); +extern void rtnl_rule_set_prio(struct rtnl_rule *, uint32_t); +extern uint32_t rtnl_rule_get_prio(struct rtnl_rule *); +extern void rtnl_rule_set_mark(struct rtnl_rule *, uint32_t); +extern uint32_t rtnl_rule_get_mark(struct rtnl_rule *); +extern void rtnl_rule_set_mask(struct rtnl_rule *, uint32_t); +extern uint32_t rtnl_rule_get_mask(struct rtnl_rule *); +extern void rtnl_rule_set_table(struct rtnl_rule *, uint32_t); +extern uint32_t rtnl_rule_get_table(struct rtnl_rule *); +extern void rtnl_rule_set_dsfield(struct rtnl_rule *, uint8_t); +extern uint8_t rtnl_rule_get_dsfield(struct rtnl_rule *); +extern int rtnl_rule_set_src(struct rtnl_rule *, struct nl_addr *); +extern struct nl_addr * rtnl_rule_get_src(struct rtnl_rule *); +extern int rtnl_rule_set_dst(struct rtnl_rule *, struct nl_addr *); +extern struct nl_addr * rtnl_rule_get_dst(struct rtnl_rule *); +extern void rtnl_rule_set_action(struct rtnl_rule *, uint8_t); +extern uint8_t rtnl_rule_get_action(struct rtnl_rule *); +extern int rtnl_rule_set_iif(struct rtnl_rule *, const char *); +extern char * rtnl_rule_get_iif(struct rtnl_rule *); +extern int rtnl_rule_set_oif(struct rtnl_rule *, const char *); +extern char * rtnl_rule_get_oif(struct rtnl_rule *); +extern void rtnl_rule_set_realms(struct rtnl_rule *, uint32_t); +extern uint32_t rtnl_rule_get_realms(struct rtnl_rule *); +extern void rtnl_rule_set_goto(struct rtnl_rule *, uint32_t); +extern uint32_t rtnl_rule_get_goto(struct rtnl_rule *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/tc-api.h b/include/netlink/route/tc-api.h new file mode 100644 index 0000000..b7771b5 --- /dev/null +++ b/include/netlink/route/tc-api.h @@ -0,0 +1,21 @@ +/* + * netlink/route/tc-api.h Traffic Control API + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2013 Thomas Graf + */ + +#ifndef NETLINK_DUMMY_TC_API_H_ +#define NETLINK_DUMMY_TC_API_H_ + +#include +#include +#include + +#warning "You are including a deprecated header file, include ." + +#endif diff --git a/include/netlink/route/tc.h b/include/netlink/route/tc.h new file mode 100644 index 0000000..836f7b1 --- /dev/null +++ b/include/netlink/route/tc.h @@ -0,0 +1,114 @@ +/* + * netlink/route/tc.h Traffic Control + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + */ + +#ifndef NETLINK_TC_H_ +#define NETLINK_TC_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum rtnl_tc_type { + RTNL_TC_TYPE_QDISC, + RTNL_TC_TYPE_CLASS, + RTNL_TC_TYPE_CLS, + __RTNL_TC_TYPE_MAX, +}; + +#define RTNL_TC_TYPE_MAX (__RTNL_TC_TYPE_MAX - 1) + +/** + * Compute tc handle based on major and minor parts + * @ingroup tc + */ +#define TC_HANDLE(maj, min) (TC_H_MAJ((maj) << 16) | TC_H_MIN(min)) + +/** + * Traffic control object + * @ingroup tc + */ +struct rtnl_tc; + +/** + * Macro to cast qdisc/class/classifier to tc object + * @ingroup tc + * + * @code + * rtnl_tc_set_mpu(TC_CAST(qdisc), 40); + * @endcode + */ +#define TC_CAST(ptr) ((struct rtnl_tc *) (ptr)) + +/** + * Traffic control statistical identifier + * @ingroup tc + * + * @code + * uint64_t n = rtnl_tc_get_stat(TC_CAST(class), RTNL_TC_PACKETS); + * @endcode + */ +enum rtnl_tc_stat { + RTNL_TC_PACKETS, /**< Number of packets seen */ + RTNL_TC_BYTES, /**< Total bytes seen */ + RTNL_TC_RATE_BPS, /**< Current bits/s (rate estimator) */ + RTNL_TC_RATE_PPS, /**< Current packet/s (rate estimator) */ + RTNL_TC_QLEN, /**< Current queue length */ + RTNL_TC_BACKLOG, /**< Current backlog length */ + RTNL_TC_DROPS, /**< Total number of packets dropped */ + RTNL_TC_REQUEUES, /**< Total number of requeues */ + RTNL_TC_OVERLIMITS, /**< Total number of overlimits */ + __RTNL_TC_STATS_MAX, +}; + +#define RTNL_TC_STATS_MAX (__RTNL_TC_STATS_MAX - 1) + +extern void rtnl_tc_set_ifindex(struct rtnl_tc *, int); +extern int rtnl_tc_get_ifindex(struct rtnl_tc *); +extern void rtnl_tc_set_link(struct rtnl_tc *, struct rtnl_link *); +extern struct rtnl_link *rtnl_tc_get_link(struct rtnl_tc *); +extern void rtnl_tc_set_mtu(struct rtnl_tc *, uint32_t); +extern uint32_t rtnl_tc_get_mtu(struct rtnl_tc *); +extern void rtnl_tc_set_mpu(struct rtnl_tc *, uint32_t); +extern uint32_t rtnl_tc_get_mpu(struct rtnl_tc *); +extern void rtnl_tc_set_overhead(struct rtnl_tc *, uint32_t); +extern uint32_t rtnl_tc_get_overhead(struct rtnl_tc *); +extern void rtnl_tc_set_linktype(struct rtnl_tc *, uint32_t); +extern uint32_t rtnl_tc_get_linktype(struct rtnl_tc *); +extern void rtnl_tc_set_handle(struct rtnl_tc *, uint32_t); +extern uint32_t rtnl_tc_get_handle(struct rtnl_tc *); +extern void rtnl_tc_set_parent(struct rtnl_tc *, uint32_t); +extern uint32_t rtnl_tc_get_parent(struct rtnl_tc *); +extern int rtnl_tc_set_kind(struct rtnl_tc *, const char *); +extern char * rtnl_tc_get_kind(struct rtnl_tc *); +extern uint64_t rtnl_tc_get_stat(struct rtnl_tc *, enum rtnl_tc_stat); + +extern int rtnl_tc_calc_txtime(int, int); +extern int rtnl_tc_calc_bufsize(int, int); +extern int rtnl_tc_calc_cell_log(int); + +extern int rtnl_tc_read_classid_file(void); +extern char * rtnl_tc_handle2str(uint32_t, char *, size_t); +extern int rtnl_tc_str2handle(const char *, uint32_t *); +extern int rtnl_classid_generate(const char *, uint32_t *, + uint32_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/socket.h b/include/netlink/socket.h new file mode 100644 index 0000000..1007eba --- /dev/null +++ b/include/netlink/socket.h @@ -0,0 +1,71 @@ +/* + * netlink/socket.h Netlink Socket + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + */ + +#ifndef NETLINK_SOCKET_H_ +#define NETLINK_SOCKET_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct nl_sock * nl_socket_alloc(void); +extern struct nl_sock * nl_socket_alloc_cb(struct nl_cb *); +extern void nl_socket_free(struct nl_sock *); + +extern uint32_t nl_socket_get_local_port(const struct nl_sock *); +extern void nl_socket_set_local_port(struct nl_sock *, uint32_t); + +extern int nl_socket_add_memberships(struct nl_sock *, int, ...); +extern int nl_socket_add_membership(struct nl_sock *, int); +extern int nl_socket_drop_memberships(struct nl_sock *, int, ...); +extern int nl_socket_drop_membership(struct nl_sock *, + int); +extern void nl_join_groups(struct nl_sock *, int); + + +extern uint32_t nl_socket_get_peer_port(const struct nl_sock *); +extern void nl_socket_set_peer_port(struct nl_sock *, + uint32_t); +extern uint32_t nl_socket_get_peer_groups(const struct nl_sock *sk); +extern void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups); +extern struct nl_cb * nl_socket_get_cb(const struct nl_sock *); +extern void nl_socket_set_cb(struct nl_sock *, + struct nl_cb *); +extern int nl_socket_modify_cb(struct nl_sock *, enum nl_cb_type, + enum nl_cb_kind, + nl_recvmsg_msg_cb_t, void *); +extern int nl_socket_modify_err_cb(struct nl_sock *, enum nl_cb_kind, + nl_recvmsg_err_cb_t, void *); + +extern int nl_socket_set_buffer_size(struct nl_sock *, int, int); +extern int nl_socket_set_msg_buf_size(struct nl_sock *, size_t); +extern size_t nl_socket_get_msg_buf_size(struct nl_sock *); +extern int nl_socket_set_passcred(struct nl_sock *, int); +extern int nl_socket_recv_pktinfo(struct nl_sock *, int); + +extern void nl_socket_disable_seq_check(struct nl_sock *); +extern unsigned int nl_socket_use_seq(struct nl_sock *); +extern void nl_socket_disable_auto_ack(struct nl_sock *); +extern void nl_socket_enable_auto_ack(struct nl_sock *); + +extern int nl_socket_get_fd(const struct nl_sock *); +extern int nl_socket_set_nonblocking(const struct nl_sock *); +extern void nl_socket_enable_msg_peek(struct nl_sock *); +extern void nl_socket_disable_msg_peek(struct nl_sock *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/types.h b/include/netlink/types.h new file mode 100644 index 0000000..09cc5bd --- /dev/null +++ b/include/netlink/types.h @@ -0,0 +1,110 @@ +/* + * netlink/types.h Definition of public types + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +#ifndef __NETLINK_TYPES_H_ +#define __NETLINK_TYPES_H_ + +#include + +/** + * @ingroup utils + * Enumeration of dumping variations (dp_type) + */ +enum nl_dump_type { + NL_DUMP_LINE, /**< Dump object briefly on one line */ + NL_DUMP_DETAILS, /**< Dump all attributes but no statistics */ + NL_DUMP_STATS, /**< Dump all attributes including statistics */ + __NL_DUMP_MAX, +}; +#define NL_DUMP_MAX (__NL_DUMP_MAX - 1) + +/** + * @ingroup utils + * Dumping parameters + */ +struct nl_dump_params +{ + /** + * Specifies the type of dump that is requested. + */ + enum nl_dump_type dp_type; + + /** + * Specifies the number of whitespaces to be put in front + * of every new line (indentation). + */ + int dp_prefix; + + /** + * Causes the cache index to be printed for each element. + */ + int dp_print_index; + + /** + * Causes each element to be prefixed with the message type. + */ + int dp_dump_msgtype; + + /** + * A callback invoked for output + * + * Passed arguments are: + * - dumping parameters + * - string to append to the output + */ + void (*dp_cb)(struct nl_dump_params *, char *); + + /** + * A callback invoked for every new line, can be used to + * customize the indentation. + * + * Passed arguments are: + * - dumping parameters + * - line number starting from 0 + */ + void (*dp_nl_cb)(struct nl_dump_params *, int); + + /** + * User data pointer, can be used to pass data to callbacks. + */ + void *dp_data; + + /** + * File descriptor the dumping output should go to + */ + FILE * dp_fd; + + /** + * Alternatively the output may be redirected into a buffer + */ + char * dp_buf; + + /** + * Length of the buffer dp_buf + */ + size_t dp_buflen; + + /** + * PRIVATE + * Set if a dump was performed prior to the actual dump handler. + */ + int dp_pre_dump; + + /** + * PRIVATE + * Owned by the current caller + */ + int dp_ivar; + + unsigned int dp_line; +}; + +#endif diff --git a/include/netlink/utils.h b/include/netlink/utils.h new file mode 100644 index 0000000..502341a --- /dev/null +++ b/include/netlink/utils.h @@ -0,0 +1,86 @@ +/* + * netlink/utils.h Utility Functions + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +#ifndef NETLINK_UTILS_H_ +#define NETLINK_UTILS_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Probability Constants + * @{ + */ + +/** + * Lower probability limit + * @ingroup utils + */ +#define NL_PROB_MIN 0x0 + +/** + * Upper probability limit nl_dump_type + * @ingroup utils + */ +#define NL_PROB_MAX 0xffffffff + +/** @} */ + +enum { + NL_BYTE_RATE, + NL_BIT_RATE, +}; + +/* unit pretty-printing */ +extern double nl_cancel_down_bytes(unsigned long long, char **); +extern double nl_cancel_down_bits(unsigned long long, char **); +extern int nl_rate2str(unsigned long long, int, char *, size_t); +extern double nl_cancel_down_us(uint32_t, char **); + +/* generic unit translations */ +extern long nl_size2int(const char *); +extern char * nl_size2str(const size_t, char *, const size_t); +extern long nl_prob2int(const char *); + +/* time translations */ +extern int nl_get_user_hz(void); +extern int nl_get_psched_hz(void); +extern uint32_t nl_us2ticks(uint32_t); +extern uint32_t nl_ticks2us(uint32_t); +extern int nl_str2msec(const char *, uint64_t *); +extern char * nl_msec2str(uint64_t, char *, size_t); + +/* link layer protocol translations */ +extern char * nl_llproto2str(int, char *, size_t); +extern int nl_str2llproto(const char *); + +/* ethernet protocol translations */ +extern char * nl_ether_proto2str(int, char *, size_t); +extern int nl_str2ether_proto(const char *); + +/* IP protocol translations */ +extern char * nl_ip_proto2str(int, char *, size_t); +extern int nl_str2ip_proto(const char *); + +/* Dumping helpers */ +extern void nl_new_line(struct nl_dump_params *); +extern void nl_dump(struct nl_dump_params *, const char *, ...); +extern void nl_dump_line(struct nl_dump_params *, const char *, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/version.h b/include/netlink/version.h new file mode 100644 index 0000000..ccb8bed --- /dev/null +++ b/include/netlink/version.h @@ -0,0 +1,37 @@ +/* + * netlink/version.h Versioning Information + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2008-2011 Thomas Graf + */ + +#ifndef NETLINK_VERSION_H_ +#define NETLINK_VERSION_H_ + +/* Compile Time Versioning Information */ + +#define LIBNL_STRING "libnl 3.2.22" +#define LIBNL_VERSION "3.2.22" + +#define LIBNL_VER_MAJ 3 +#define LIBNL_VER_MIN 2 +#define LIBNL_VER_MIC 22 +#define LIBNL_VER(maj,min) ((maj) << 8 | (min)) +#define LIBNL_VER_NUM LIBNL_VER(LIBNL_VER_MAJ, LIBNL_VER_MIN) + +#define LIBNL_CURRENT 217 +#define LIBNL_REVISION 0 +#define LIBNL_AGE 17 + +/* Run-time version information */ + +extern const int nl_ver_num; +extern const int nl_ver_maj; +extern const int nl_ver_min; +extern const int nl_ver_mic; + +#endif diff --git a/include/netlink/version.h.in b/include/netlink/version.h.in new file mode 100644 index 0000000..35bf2aa --- /dev/null +++ b/include/netlink/version.h.in @@ -0,0 +1,37 @@ +/* + * netlink/version.h Versioning Information + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2008-2011 Thomas Graf + */ + +#ifndef NETLINK_VERSION_H_ +#define NETLINK_VERSION_H_ + +/* Compile Time Versioning Information */ + +#define LIBNL_STRING "@PACKAGE_STRING@" +#define LIBNL_VERSION "@PACKAGE_VERSION@" + +#define LIBNL_VER_MAJ @MAJ_VERSION@ +#define LIBNL_VER_MIN @MIN_VERSION@ +#define LIBNL_VER_MIC @MIC_VERSION@ +#define LIBNL_VER(maj,min) ((maj) << 8 | (min)) +#define LIBNL_VER_NUM LIBNL_VER(LIBNL_VER_MAJ, LIBNL_VER_MIN) + +#define LIBNL_CURRENT @LT_CURRENT@ +#define LIBNL_REVISION @LT_REVISION@ +#define LIBNL_AGE @LT_AGE@ + +/* Run-time version information */ + +extern const int nl_ver_num; +extern const int nl_ver_maj; +extern const int nl_ver_min; +extern const int nl_ver_mic; + +#endif diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 0000000..677a89c --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1,118 @@ +# -*- Makefile -*- + +AM_CPPFLAGS = \ + -Wall \ + -I${top_srcdir}/include \ + -I${top_builddir}/include \ + -I${builddir}/route \ + -I${builddir}/route/cls \ + -D_GNU_SOURCE \ + -DSYSCONFDIR=\"$(sysconfdir)/libnl\" + +AM_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) + +lib_LTLIBRARIES = \ + libnl-3.la libnl-genl-3.la libnl-route-3.la libnl-nf-3.la + +libnl_3_la_SOURCES = \ + addr.c attr.c cache.c cache_mngr.c cache_mngt.c data.c \ + error.c handlers.c msg.c nl.c object.c socket.c utils.c \ + version.c hash.c hashtable.c + +libnl_genl_3_la_LIBADD = libnl-3.la +libnl_genl_3_la_SOURCES = \ + genl/ctrl.c genl/family.c genl/genl.c genl/mngt.c + +libnl_nf_3_la_LIBADD = libnl-route-3.la +libnl_nf_3_la_SOURCES = \ + netfilter/ct.c netfilter/ct_obj.c netfilter/log.c \ + netfilter/log_msg.c netfilter/log_msg_obj.c netfilter/log_obj.c \ + netfilter/netfilter.c netfilter/nfnl.c netfilter/queue.c \ + netfilter/queue_msg.c netfilter/queue_msg_obj.c netfilter/queue_obj.c \ + netfilter/exp.c netfilter/exp_obj.c + +CLEANFILES = \ + route/pktloc_grammar.c route/pktloc_grammar.h \ + route/pktloc_syntax.c route/pktloc_syntax.h \ + route/cls/ematch_grammar.c route/cls/ematch_grammar.h \ + route/cls/ematch_syntax.c route/cls/ematch_syntax.h + +# Hack to avoid using ylwrap. It does not function correctly in combination +# with --header-file= +route/pktloc_grammar.c: route/pktloc_grammar.l + $(AM_V_GEN) $(FLEX) --header-file=route/pktloc_grammar.h $(LFLAGS) -o $@ $^ + +route/pktloc_syntax.c: route/pktloc_syntax.y + $(AM_V_GEN) $(YACC) -d $(YFLAGS) -o $@ $^ + +route/cls/ematch_grammar.c: route/cls/ematch_grammar.l + $(AM_V_GEN) $(FLEX) --header-file=route/cls/ematch_grammar.h $(LFLAGS) -o $@ $^ + +route/cls/ematch_syntax.c: route/cls/ematch_syntax.y + $(AM_V_GEN) $(YACC) -d $(YFLAGS) -o $@ $^ + +libnl_route_3_la_LIBADD = libnl-3.la +libnl_route_3_la_SOURCES = \ + route/addr.c route/class.c route/cls.c route/link.c \ + route/neigh.c route/neightbl.c route/nexthop.c route/qdisc.c \ + route/route.c route/route_obj.c route/route_utils.c route/rtnl.c \ + route/rule.c route/tc.c route/classid.c \ + \ + route/cls/fw.c route/cls/police.c route/cls/u32.c route/cls/basic.c \ + route/cls/cgroup.c \ + \ + route/cls/ematch.c \ + route/cls/ematch/container.c route/cls/ematch/cmp.c \ + route/cls/ematch/nbyte.c route/cls/ematch/text.c \ + route/cls/ematch/meta.c \ + \ + route/link/api.c route/link/vlan.c route/link/dummy.c \ + route/link/bridge.c route/link/inet6.c route/link/inet.c \ + route/link/bonding.c route/link/can.c \ + \ + route/qdisc/blackhole.c route/qdisc/cbq.c route/qdisc/dsmark.c \ + route/qdisc/fifo.c route/qdisc/htb.c route/qdisc/netem.c \ + route/qdisc/prio.c route/qdisc/red.c route/qdisc/sfq.c \ + route/qdisc/tbf.c route/qdisc/plug.c \ + \ + fib_lookup/lookup.c fib_lookup/request.c \ + \ + route/pktloc.c + +nodist_libnl_route_3_la_SOURCES = \ + route/pktloc_syntax.c route/pktloc_syntax.h \ + route/pktloc_grammar.c route/pktloc_grammar.h \ + route/cls/ematch_syntax.c route/cls/ematch_syntax.h \ + route/cls/ematch_grammar.c route/cls/ematch_grammar.h + +BUILT_SOURCES = \ + route/cls/ematch_grammar.c \ + route/cls/ematch_syntax.c \ + route/pktloc_grammar.c \ + route/pktloc_syntax.c + +EXTRA_DIST = \ + route/pktloc_grammar.l \ + route/pktloc_syntax.y \ + route/cls/ematch_grammar.l \ + route/cls/ematch_syntax.y + +if ENABLE_CLI +nobase_pkglib_LTLIBRARIES = \ + cli/qdisc/htb.la \ + cli/qdisc/blackhole.la \ + cli/qdisc/pfifo.la \ + cli/qdisc/plug.la \ + cli/qdisc/bfifo.la \ + cli/cls/basic.la \ + cli/cls/cgroup.la + +cli_qdisc_htb_la_LDFLAGS = -module -avoid-version +cli_qdisc_blackhole_la_LDFLAGS = -module -avoid-version +cli_qdisc_pfifo_la_LDFLAGS = -module -avoid-version +cli_qdisc_plug_la_LDFLAGS = -module -avoid-version +cli_qdisc_bfifo_la_LDFLAGS = -module -avoid-version +cli_cls_basic_la_LDFLAGS = -module -avoid-version +cli_cls_cgroup_la_LDFLAGS = -module -avoid-version +endif diff --git a/lib/Makefile.in b/lib/Makefile.in new file mode 100644 index 0000000..bf6a68e --- /dev/null +++ b/lib/Makefile.in @@ -0,0 +1,1370 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# -*- Makefile -*- + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = lib +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/defs.h.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = defs.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkglibdir)" +LTLIBRARIES = $(lib_LTLIBRARIES) $(nobase_pkglib_LTLIBRARIES) +cli_cls_basic_la_LIBADD = +cli_cls_basic_la_SOURCES = cli/cls/basic.c +am__dirstamp = $(am__leading_dot)dirstamp +cli_cls_basic_la_OBJECTS = cli/cls/basic.lo +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +cli_cls_basic_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(cli_cls_basic_la_LDFLAGS) $(LDFLAGS) \ + -o $@ +@ENABLE_CLI_TRUE@am_cli_cls_basic_la_rpath = -rpath \ +@ENABLE_CLI_TRUE@ $(pkglibdir)/cli/cls +cli_cls_cgroup_la_LIBADD = +cli_cls_cgroup_la_SOURCES = cli/cls/cgroup.c +cli_cls_cgroup_la_OBJECTS = cli/cls/cgroup.lo +cli_cls_cgroup_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(cli_cls_cgroup_la_LDFLAGS) $(LDFLAGS) \ + -o $@ +@ENABLE_CLI_TRUE@am_cli_cls_cgroup_la_rpath = -rpath \ +@ENABLE_CLI_TRUE@ $(pkglibdir)/cli/cls +cli_qdisc_bfifo_la_LIBADD = +cli_qdisc_bfifo_la_SOURCES = cli/qdisc/bfifo.c +cli_qdisc_bfifo_la_OBJECTS = cli/qdisc/bfifo.lo +cli_qdisc_bfifo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(cli_qdisc_bfifo_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@ENABLE_CLI_TRUE@am_cli_qdisc_bfifo_la_rpath = -rpath \ +@ENABLE_CLI_TRUE@ $(pkglibdir)/cli/qdisc +cli_qdisc_blackhole_la_LIBADD = +cli_qdisc_blackhole_la_SOURCES = cli/qdisc/blackhole.c +cli_qdisc_blackhole_la_OBJECTS = cli/qdisc/blackhole.lo +cli_qdisc_blackhole_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(cli_qdisc_blackhole_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@ENABLE_CLI_TRUE@am_cli_qdisc_blackhole_la_rpath = -rpath \ +@ENABLE_CLI_TRUE@ $(pkglibdir)/cli/qdisc +cli_qdisc_htb_la_LIBADD = +cli_qdisc_htb_la_SOURCES = cli/qdisc/htb.c +cli_qdisc_htb_la_OBJECTS = cli/qdisc/htb.lo +cli_qdisc_htb_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(cli_qdisc_htb_la_LDFLAGS) $(LDFLAGS) \ + -o $@ +@ENABLE_CLI_TRUE@am_cli_qdisc_htb_la_rpath = -rpath \ +@ENABLE_CLI_TRUE@ $(pkglibdir)/cli/qdisc +cli_qdisc_pfifo_la_LIBADD = +cli_qdisc_pfifo_la_SOURCES = cli/qdisc/pfifo.c +cli_qdisc_pfifo_la_OBJECTS = cli/qdisc/pfifo.lo +cli_qdisc_pfifo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(cli_qdisc_pfifo_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@ENABLE_CLI_TRUE@am_cli_qdisc_pfifo_la_rpath = -rpath \ +@ENABLE_CLI_TRUE@ $(pkglibdir)/cli/qdisc +cli_qdisc_plug_la_LIBADD = +cli_qdisc_plug_la_SOURCES = cli/qdisc/plug.c +cli_qdisc_plug_la_OBJECTS = cli/qdisc/plug.lo +cli_qdisc_plug_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(cli_qdisc_plug_la_LDFLAGS) $(LDFLAGS) \ + -o $@ +@ENABLE_CLI_TRUE@am_cli_qdisc_plug_la_rpath = -rpath \ +@ENABLE_CLI_TRUE@ $(pkglibdir)/cli/qdisc +libnl_3_la_LIBADD = +am_libnl_3_la_OBJECTS = addr.lo attr.lo cache.lo cache_mngr.lo \ + cache_mngt.lo data.lo error.lo handlers.lo msg.lo nl.lo \ + object.lo socket.lo utils.lo version.lo hash.lo hashtable.lo +libnl_3_la_OBJECTS = $(am_libnl_3_la_OBJECTS) +libnl_genl_3_la_DEPENDENCIES = libnl-3.la +am_libnl_genl_3_la_OBJECTS = genl/ctrl.lo genl/family.lo genl/genl.lo \ + genl/mngt.lo +libnl_genl_3_la_OBJECTS = $(am_libnl_genl_3_la_OBJECTS) +libnl_nf_3_la_DEPENDENCIES = libnl-route-3.la +am_libnl_nf_3_la_OBJECTS = netfilter/ct.lo netfilter/ct_obj.lo \ + netfilter/log.lo netfilter/log_msg.lo netfilter/log_msg_obj.lo \ + netfilter/log_obj.lo netfilter/netfilter.lo netfilter/nfnl.lo \ + netfilter/queue.lo netfilter/queue_msg.lo \ + netfilter/queue_msg_obj.lo netfilter/queue_obj.lo \ + netfilter/exp.lo netfilter/exp_obj.lo +libnl_nf_3_la_OBJECTS = $(am_libnl_nf_3_la_OBJECTS) +libnl_route_3_la_DEPENDENCIES = libnl-3.la +am_libnl_route_3_la_OBJECTS = route/addr.lo route/class.lo \ + route/cls.lo route/link.lo route/neigh.lo route/neightbl.lo \ + route/nexthop.lo route/qdisc.lo route/route.lo \ + route/route_obj.lo route/route_utils.lo route/rtnl.lo \ + route/rule.lo route/tc.lo route/classid.lo route/cls/fw.lo \ + route/cls/police.lo route/cls/u32.lo route/cls/basic.lo \ + route/cls/cgroup.lo route/cls/ematch.lo \ + route/cls/ematch/container.lo route/cls/ematch/cmp.lo \ + route/cls/ematch/nbyte.lo route/cls/ematch/text.lo \ + route/cls/ematch/meta.lo route/link/api.lo route/link/vlan.lo \ + route/link/dummy.lo route/link/bridge.lo route/link/inet6.lo \ + route/link/inet.lo route/link/bonding.lo route/link/can.lo \ + route/qdisc/blackhole.lo route/qdisc/cbq.lo \ + route/qdisc/dsmark.lo route/qdisc/fifo.lo route/qdisc/htb.lo \ + route/qdisc/netem.lo route/qdisc/prio.lo route/qdisc/red.lo \ + route/qdisc/sfq.lo route/qdisc/tbf.lo route/qdisc/plug.lo \ + fib_lookup/lookup.lo fib_lookup/request.lo route/pktloc.lo +nodist_libnl_route_3_la_OBJECTS = route/pktloc_syntax.lo \ + route/pktloc_grammar.lo route/cls/ematch_syntax.lo \ + route/cls/ematch_grammar.lo +libnl_route_3_la_OBJECTS = $(am_libnl_route_3_la_OBJECTS) \ + $(nodist_libnl_route_3_la_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = cli/cls/basic.c cli/cls/cgroup.c cli/qdisc/bfifo.c \ + cli/qdisc/blackhole.c cli/qdisc/htb.c cli/qdisc/pfifo.c \ + cli/qdisc/plug.c $(libnl_3_la_SOURCES) \ + $(libnl_genl_3_la_SOURCES) $(libnl_nf_3_la_SOURCES) \ + $(libnl_route_3_la_SOURCES) $(nodist_libnl_route_3_la_SOURCES) +DIST_SOURCES = cli/cls/basic.c cli/cls/cgroup.c cli/qdisc/bfifo.c \ + cli/qdisc/blackhole.c cli/qdisc/htb.c cli/qdisc/pfifo.c \ + cli/qdisc/plug.c $(libnl_3_la_SOURCES) \ + $(libnl_genl_3_la_SOURCES) $(libnl_nf_3_la_SOURCES) \ + $(libnl_route_3_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_CFLAGS = @CHECK_CFLAGS@ +CHECK_LIBS = @CHECK_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FLEX = @FLEX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBNL_VERSION = @LIBNL_VERSION@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_CURRENT = @LT_CURRENT@ +LT_REVISION = @LT_REVISION@ +MAJ_VERSION = @MAJ_VERSION@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIC_VERSION = @MIC_VERSION@ +MIN_VERSION = @MIN_VERSION@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgconfigdir = @pkgconfigdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = \ + -Wall \ + -I${top_srcdir}/include \ + -I${top_builddir}/include \ + -I${builddir}/route \ + -I${builddir}/route/cls \ + -D_GNU_SOURCE \ + -DSYSCONFDIR=\"$(sysconfdir)/libnl\" + +AM_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) + +lib_LTLIBRARIES = \ + libnl-3.la libnl-genl-3.la libnl-route-3.la libnl-nf-3.la + +libnl_3_la_SOURCES = \ + addr.c attr.c cache.c cache_mngr.c cache_mngt.c data.c \ + error.c handlers.c msg.c nl.c object.c socket.c utils.c \ + version.c hash.c hashtable.c + +libnl_genl_3_la_LIBADD = libnl-3.la +libnl_genl_3_la_SOURCES = \ + genl/ctrl.c genl/family.c genl/genl.c genl/mngt.c + +libnl_nf_3_la_LIBADD = libnl-route-3.la +libnl_nf_3_la_SOURCES = \ + netfilter/ct.c netfilter/ct_obj.c netfilter/log.c \ + netfilter/log_msg.c netfilter/log_msg_obj.c netfilter/log_obj.c \ + netfilter/netfilter.c netfilter/nfnl.c netfilter/queue.c \ + netfilter/queue_msg.c netfilter/queue_msg_obj.c netfilter/queue_obj.c \ + netfilter/exp.c netfilter/exp_obj.c + +CLEANFILES = \ + route/pktloc_grammar.c route/pktloc_grammar.h \ + route/pktloc_syntax.c route/pktloc_syntax.h \ + route/cls/ematch_grammar.c route/cls/ematch_grammar.h \ + route/cls/ematch_syntax.c route/cls/ematch_syntax.h + +libnl_route_3_la_LIBADD = libnl-3.la +libnl_route_3_la_SOURCES = \ + route/addr.c route/class.c route/cls.c route/link.c \ + route/neigh.c route/neightbl.c route/nexthop.c route/qdisc.c \ + route/route.c route/route_obj.c route/route_utils.c route/rtnl.c \ + route/rule.c route/tc.c route/classid.c \ + \ + route/cls/fw.c route/cls/police.c route/cls/u32.c route/cls/basic.c \ + route/cls/cgroup.c \ + \ + route/cls/ematch.c \ + route/cls/ematch/container.c route/cls/ematch/cmp.c \ + route/cls/ematch/nbyte.c route/cls/ematch/text.c \ + route/cls/ematch/meta.c \ + \ + route/link/api.c route/link/vlan.c route/link/dummy.c \ + route/link/bridge.c route/link/inet6.c route/link/inet.c \ + route/link/bonding.c route/link/can.c \ + \ + route/qdisc/blackhole.c route/qdisc/cbq.c route/qdisc/dsmark.c \ + route/qdisc/fifo.c route/qdisc/htb.c route/qdisc/netem.c \ + route/qdisc/prio.c route/qdisc/red.c route/qdisc/sfq.c \ + route/qdisc/tbf.c route/qdisc/plug.c \ + \ + fib_lookup/lookup.c fib_lookup/request.c \ + \ + route/pktloc.c + +nodist_libnl_route_3_la_SOURCES = \ + route/pktloc_syntax.c route/pktloc_syntax.h \ + route/pktloc_grammar.c route/pktloc_grammar.h \ + route/cls/ematch_syntax.c route/cls/ematch_syntax.h \ + route/cls/ematch_grammar.c route/cls/ematch_grammar.h + +BUILT_SOURCES = \ + route/cls/ematch_grammar.c \ + route/cls/ematch_syntax.c \ + route/pktloc_grammar.c \ + route/pktloc_syntax.c + +EXTRA_DIST = \ + route/pktloc_grammar.l \ + route/pktloc_syntax.y \ + route/cls/ematch_grammar.l \ + route/cls/ematch_syntax.y + +@ENABLE_CLI_TRUE@nobase_pkglib_LTLIBRARIES = \ +@ENABLE_CLI_TRUE@ cli/qdisc/htb.la \ +@ENABLE_CLI_TRUE@ cli/qdisc/blackhole.la \ +@ENABLE_CLI_TRUE@ cli/qdisc/pfifo.la \ +@ENABLE_CLI_TRUE@ cli/qdisc/plug.la \ +@ENABLE_CLI_TRUE@ cli/qdisc/bfifo.la \ +@ENABLE_CLI_TRUE@ cli/cls/basic.la \ +@ENABLE_CLI_TRUE@ cli/cls/cgroup.la + +@ENABLE_CLI_TRUE@cli_qdisc_htb_la_LDFLAGS = -module -avoid-version +@ENABLE_CLI_TRUE@cli_qdisc_blackhole_la_LDFLAGS = -module -avoid-version +@ENABLE_CLI_TRUE@cli_qdisc_pfifo_la_LDFLAGS = -module -avoid-version +@ENABLE_CLI_TRUE@cli_qdisc_plug_la_LDFLAGS = -module -avoid-version +@ENABLE_CLI_TRUE@cli_qdisc_bfifo_la_LDFLAGS = -module -avoid-version +@ENABLE_CLI_TRUE@cli_cls_basic_la_LDFLAGS = -module -avoid-version +@ENABLE_CLI_TRUE@cli_cls_cgroup_la_LDFLAGS = -module -avoid-version +all: $(BUILT_SOURCES) defs.h + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign lib/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +defs.h: stamp-h1 + @if test ! -f $@; then rm -f stamp-h1; else :; fi + @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi + +stamp-h1: $(srcdir)/defs.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status lib/defs.h +$(srcdir)/defs.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f defs.h stamp-h1 +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +install-nobase_pkglibLTLIBRARIES: $(nobase_pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(nobase_pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + fi; \ + for p in $$list; do if test -f "$$p"; then echo "$$p $$p"; else :; fi; done | \ + sed '/ .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { cur = "." } \ + { if ($$2 == cur) { files = files " " $$1 } \ + else { print cur, files; files = $$1; cur = $$2 } } \ + END { print cur, files }' | \ + while read dir files; do \ + test -z "$$files" || { \ + test "x$$dir" = x. || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)/$$dir'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)/$$dir"; }; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$files '$(DESTDIR)$(pkglibdir)/$$dir'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$files "$(DESTDIR)$(pkglibdir)/$$dir" || exit $$?; \ + }; \ + done + +uninstall-nobase_pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(nobase_pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + f=$$p; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-nobase_pkglibLTLIBRARIES: + -test -z "$(nobase_pkglib_LTLIBRARIES)" || rm -f $(nobase_pkglib_LTLIBRARIES) + @list='$(nobase_pkglib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +cli/cls/$(am__dirstamp): + @$(MKDIR_P) cli/cls + @: > cli/cls/$(am__dirstamp) +cli/cls/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) cli/cls/$(DEPDIR) + @: > cli/cls/$(DEPDIR)/$(am__dirstamp) +cli/cls/basic.lo: cli/cls/$(am__dirstamp) \ + cli/cls/$(DEPDIR)/$(am__dirstamp) +cli/cls/basic.la: $(cli_cls_basic_la_OBJECTS) $(cli_cls_basic_la_DEPENDENCIES) $(EXTRA_cli_cls_basic_la_DEPENDENCIES) cli/cls/$(am__dirstamp) + $(AM_V_CCLD)$(cli_cls_basic_la_LINK) $(am_cli_cls_basic_la_rpath) $(cli_cls_basic_la_OBJECTS) $(cli_cls_basic_la_LIBADD) $(LIBS) +cli/cls/cgroup.lo: cli/cls/$(am__dirstamp) \ + cli/cls/$(DEPDIR)/$(am__dirstamp) +cli/cls/cgroup.la: $(cli_cls_cgroup_la_OBJECTS) $(cli_cls_cgroup_la_DEPENDENCIES) $(EXTRA_cli_cls_cgroup_la_DEPENDENCIES) cli/cls/$(am__dirstamp) + $(AM_V_CCLD)$(cli_cls_cgroup_la_LINK) $(am_cli_cls_cgroup_la_rpath) $(cli_cls_cgroup_la_OBJECTS) $(cli_cls_cgroup_la_LIBADD) $(LIBS) +cli/qdisc/$(am__dirstamp): + @$(MKDIR_P) cli/qdisc + @: > cli/qdisc/$(am__dirstamp) +cli/qdisc/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) cli/qdisc/$(DEPDIR) + @: > cli/qdisc/$(DEPDIR)/$(am__dirstamp) +cli/qdisc/bfifo.lo: cli/qdisc/$(am__dirstamp) \ + cli/qdisc/$(DEPDIR)/$(am__dirstamp) +cli/qdisc/bfifo.la: $(cli_qdisc_bfifo_la_OBJECTS) $(cli_qdisc_bfifo_la_DEPENDENCIES) $(EXTRA_cli_qdisc_bfifo_la_DEPENDENCIES) cli/qdisc/$(am__dirstamp) + $(AM_V_CCLD)$(cli_qdisc_bfifo_la_LINK) $(am_cli_qdisc_bfifo_la_rpath) $(cli_qdisc_bfifo_la_OBJECTS) $(cli_qdisc_bfifo_la_LIBADD) $(LIBS) +cli/qdisc/blackhole.lo: cli/qdisc/$(am__dirstamp) \ + cli/qdisc/$(DEPDIR)/$(am__dirstamp) +cli/qdisc/blackhole.la: $(cli_qdisc_blackhole_la_OBJECTS) $(cli_qdisc_blackhole_la_DEPENDENCIES) $(EXTRA_cli_qdisc_blackhole_la_DEPENDENCIES) cli/qdisc/$(am__dirstamp) + $(AM_V_CCLD)$(cli_qdisc_blackhole_la_LINK) $(am_cli_qdisc_blackhole_la_rpath) $(cli_qdisc_blackhole_la_OBJECTS) $(cli_qdisc_blackhole_la_LIBADD) $(LIBS) +cli/qdisc/htb.lo: cli/qdisc/$(am__dirstamp) \ + cli/qdisc/$(DEPDIR)/$(am__dirstamp) +cli/qdisc/htb.la: $(cli_qdisc_htb_la_OBJECTS) $(cli_qdisc_htb_la_DEPENDENCIES) $(EXTRA_cli_qdisc_htb_la_DEPENDENCIES) cli/qdisc/$(am__dirstamp) + $(AM_V_CCLD)$(cli_qdisc_htb_la_LINK) $(am_cli_qdisc_htb_la_rpath) $(cli_qdisc_htb_la_OBJECTS) $(cli_qdisc_htb_la_LIBADD) $(LIBS) +cli/qdisc/pfifo.lo: cli/qdisc/$(am__dirstamp) \ + cli/qdisc/$(DEPDIR)/$(am__dirstamp) +cli/qdisc/pfifo.la: $(cli_qdisc_pfifo_la_OBJECTS) $(cli_qdisc_pfifo_la_DEPENDENCIES) $(EXTRA_cli_qdisc_pfifo_la_DEPENDENCIES) cli/qdisc/$(am__dirstamp) + $(AM_V_CCLD)$(cli_qdisc_pfifo_la_LINK) $(am_cli_qdisc_pfifo_la_rpath) $(cli_qdisc_pfifo_la_OBJECTS) $(cli_qdisc_pfifo_la_LIBADD) $(LIBS) +cli/qdisc/plug.lo: cli/qdisc/$(am__dirstamp) \ + cli/qdisc/$(DEPDIR)/$(am__dirstamp) +cli/qdisc/plug.la: $(cli_qdisc_plug_la_OBJECTS) $(cli_qdisc_plug_la_DEPENDENCIES) $(EXTRA_cli_qdisc_plug_la_DEPENDENCIES) cli/qdisc/$(am__dirstamp) + $(AM_V_CCLD)$(cli_qdisc_plug_la_LINK) $(am_cli_qdisc_plug_la_rpath) $(cli_qdisc_plug_la_OBJECTS) $(cli_qdisc_plug_la_LIBADD) $(LIBS) +libnl-3.la: $(libnl_3_la_OBJECTS) $(libnl_3_la_DEPENDENCIES) $(EXTRA_libnl_3_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) -rpath $(libdir) $(libnl_3_la_OBJECTS) $(libnl_3_la_LIBADD) $(LIBS) +genl/$(am__dirstamp): + @$(MKDIR_P) genl + @: > genl/$(am__dirstamp) +genl/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) genl/$(DEPDIR) + @: > genl/$(DEPDIR)/$(am__dirstamp) +genl/ctrl.lo: genl/$(am__dirstamp) genl/$(DEPDIR)/$(am__dirstamp) +genl/family.lo: genl/$(am__dirstamp) genl/$(DEPDIR)/$(am__dirstamp) +genl/genl.lo: genl/$(am__dirstamp) genl/$(DEPDIR)/$(am__dirstamp) +genl/mngt.lo: genl/$(am__dirstamp) genl/$(DEPDIR)/$(am__dirstamp) +libnl-genl-3.la: $(libnl_genl_3_la_OBJECTS) $(libnl_genl_3_la_DEPENDENCIES) $(EXTRA_libnl_genl_3_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) -rpath $(libdir) $(libnl_genl_3_la_OBJECTS) $(libnl_genl_3_la_LIBADD) $(LIBS) +netfilter/$(am__dirstamp): + @$(MKDIR_P) netfilter + @: > netfilter/$(am__dirstamp) +netfilter/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) netfilter/$(DEPDIR) + @: > netfilter/$(DEPDIR)/$(am__dirstamp) +netfilter/ct.lo: netfilter/$(am__dirstamp) \ + netfilter/$(DEPDIR)/$(am__dirstamp) +netfilter/ct_obj.lo: netfilter/$(am__dirstamp) \ + netfilter/$(DEPDIR)/$(am__dirstamp) +netfilter/log.lo: netfilter/$(am__dirstamp) \ + netfilter/$(DEPDIR)/$(am__dirstamp) +netfilter/log_msg.lo: netfilter/$(am__dirstamp) \ + netfilter/$(DEPDIR)/$(am__dirstamp) +netfilter/log_msg_obj.lo: netfilter/$(am__dirstamp) \ + netfilter/$(DEPDIR)/$(am__dirstamp) +netfilter/log_obj.lo: netfilter/$(am__dirstamp) \ + netfilter/$(DEPDIR)/$(am__dirstamp) +netfilter/netfilter.lo: netfilter/$(am__dirstamp) \ + netfilter/$(DEPDIR)/$(am__dirstamp) +netfilter/nfnl.lo: netfilter/$(am__dirstamp) \ + netfilter/$(DEPDIR)/$(am__dirstamp) +netfilter/queue.lo: netfilter/$(am__dirstamp) \ + netfilter/$(DEPDIR)/$(am__dirstamp) +netfilter/queue_msg.lo: netfilter/$(am__dirstamp) \ + netfilter/$(DEPDIR)/$(am__dirstamp) +netfilter/queue_msg_obj.lo: netfilter/$(am__dirstamp) \ + netfilter/$(DEPDIR)/$(am__dirstamp) +netfilter/queue_obj.lo: netfilter/$(am__dirstamp) \ + netfilter/$(DEPDIR)/$(am__dirstamp) +netfilter/exp.lo: netfilter/$(am__dirstamp) \ + netfilter/$(DEPDIR)/$(am__dirstamp) +netfilter/exp_obj.lo: netfilter/$(am__dirstamp) \ + netfilter/$(DEPDIR)/$(am__dirstamp) +libnl-nf-3.la: $(libnl_nf_3_la_OBJECTS) $(libnl_nf_3_la_DEPENDENCIES) $(EXTRA_libnl_nf_3_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) -rpath $(libdir) $(libnl_nf_3_la_OBJECTS) $(libnl_nf_3_la_LIBADD) $(LIBS) +route/$(am__dirstamp): + @$(MKDIR_P) route + @: > route/$(am__dirstamp) +route/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) route/$(DEPDIR) + @: > route/$(DEPDIR)/$(am__dirstamp) +route/addr.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) +route/class.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) +route/cls.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) +route/link.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) +route/neigh.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) +route/neightbl.lo: route/$(am__dirstamp) \ + route/$(DEPDIR)/$(am__dirstamp) +route/nexthop.lo: route/$(am__dirstamp) \ + route/$(DEPDIR)/$(am__dirstamp) +route/qdisc.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) +route/route.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) +route/route_obj.lo: route/$(am__dirstamp) \ + route/$(DEPDIR)/$(am__dirstamp) +route/route_utils.lo: route/$(am__dirstamp) \ + route/$(DEPDIR)/$(am__dirstamp) +route/rtnl.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) +route/rule.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) +route/tc.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) +route/classid.lo: route/$(am__dirstamp) \ + route/$(DEPDIR)/$(am__dirstamp) +route/cls/$(am__dirstamp): + @$(MKDIR_P) route/cls + @: > route/cls/$(am__dirstamp) +route/cls/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) route/cls/$(DEPDIR) + @: > route/cls/$(DEPDIR)/$(am__dirstamp) +route/cls/fw.lo: route/cls/$(am__dirstamp) \ + route/cls/$(DEPDIR)/$(am__dirstamp) +route/cls/police.lo: route/cls/$(am__dirstamp) \ + route/cls/$(DEPDIR)/$(am__dirstamp) +route/cls/u32.lo: route/cls/$(am__dirstamp) \ + route/cls/$(DEPDIR)/$(am__dirstamp) +route/cls/basic.lo: route/cls/$(am__dirstamp) \ + route/cls/$(DEPDIR)/$(am__dirstamp) +route/cls/cgroup.lo: route/cls/$(am__dirstamp) \ + route/cls/$(DEPDIR)/$(am__dirstamp) +route/cls/ematch.lo: route/cls/$(am__dirstamp) \ + route/cls/$(DEPDIR)/$(am__dirstamp) +route/cls/ematch/$(am__dirstamp): + @$(MKDIR_P) route/cls/ematch + @: > route/cls/ematch/$(am__dirstamp) +route/cls/ematch/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) route/cls/ematch/$(DEPDIR) + @: > route/cls/ematch/$(DEPDIR)/$(am__dirstamp) +route/cls/ematch/container.lo: route/cls/ematch/$(am__dirstamp) \ + route/cls/ematch/$(DEPDIR)/$(am__dirstamp) +route/cls/ematch/cmp.lo: route/cls/ematch/$(am__dirstamp) \ + route/cls/ematch/$(DEPDIR)/$(am__dirstamp) +route/cls/ematch/nbyte.lo: route/cls/ematch/$(am__dirstamp) \ + route/cls/ematch/$(DEPDIR)/$(am__dirstamp) +route/cls/ematch/text.lo: route/cls/ematch/$(am__dirstamp) \ + route/cls/ematch/$(DEPDIR)/$(am__dirstamp) +route/cls/ematch/meta.lo: route/cls/ematch/$(am__dirstamp) \ + route/cls/ematch/$(DEPDIR)/$(am__dirstamp) +route/link/$(am__dirstamp): + @$(MKDIR_P) route/link + @: > route/link/$(am__dirstamp) +route/link/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) route/link/$(DEPDIR) + @: > route/link/$(DEPDIR)/$(am__dirstamp) +route/link/api.lo: route/link/$(am__dirstamp) \ + route/link/$(DEPDIR)/$(am__dirstamp) +route/link/vlan.lo: route/link/$(am__dirstamp) \ + route/link/$(DEPDIR)/$(am__dirstamp) +route/link/dummy.lo: route/link/$(am__dirstamp) \ + route/link/$(DEPDIR)/$(am__dirstamp) +route/link/bridge.lo: route/link/$(am__dirstamp) \ + route/link/$(DEPDIR)/$(am__dirstamp) +route/link/inet6.lo: route/link/$(am__dirstamp) \ + route/link/$(DEPDIR)/$(am__dirstamp) +route/link/inet.lo: route/link/$(am__dirstamp) \ + route/link/$(DEPDIR)/$(am__dirstamp) +route/link/bonding.lo: route/link/$(am__dirstamp) \ + route/link/$(DEPDIR)/$(am__dirstamp) +route/link/can.lo: route/link/$(am__dirstamp) \ + route/link/$(DEPDIR)/$(am__dirstamp) +route/qdisc/$(am__dirstamp): + @$(MKDIR_P) route/qdisc + @: > route/qdisc/$(am__dirstamp) +route/qdisc/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) route/qdisc/$(DEPDIR) + @: > route/qdisc/$(DEPDIR)/$(am__dirstamp) +route/qdisc/blackhole.lo: route/qdisc/$(am__dirstamp) \ + route/qdisc/$(DEPDIR)/$(am__dirstamp) +route/qdisc/cbq.lo: route/qdisc/$(am__dirstamp) \ + route/qdisc/$(DEPDIR)/$(am__dirstamp) +route/qdisc/dsmark.lo: route/qdisc/$(am__dirstamp) \ + route/qdisc/$(DEPDIR)/$(am__dirstamp) +route/qdisc/fifo.lo: route/qdisc/$(am__dirstamp) \ + route/qdisc/$(DEPDIR)/$(am__dirstamp) +route/qdisc/htb.lo: route/qdisc/$(am__dirstamp) \ + route/qdisc/$(DEPDIR)/$(am__dirstamp) +route/qdisc/netem.lo: route/qdisc/$(am__dirstamp) \ + route/qdisc/$(DEPDIR)/$(am__dirstamp) +route/qdisc/prio.lo: route/qdisc/$(am__dirstamp) \ + route/qdisc/$(DEPDIR)/$(am__dirstamp) +route/qdisc/red.lo: route/qdisc/$(am__dirstamp) \ + route/qdisc/$(DEPDIR)/$(am__dirstamp) +route/qdisc/sfq.lo: route/qdisc/$(am__dirstamp) \ + route/qdisc/$(DEPDIR)/$(am__dirstamp) +route/qdisc/tbf.lo: route/qdisc/$(am__dirstamp) \ + route/qdisc/$(DEPDIR)/$(am__dirstamp) +route/qdisc/plug.lo: route/qdisc/$(am__dirstamp) \ + route/qdisc/$(DEPDIR)/$(am__dirstamp) +fib_lookup/$(am__dirstamp): + @$(MKDIR_P) fib_lookup + @: > fib_lookup/$(am__dirstamp) +fib_lookup/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) fib_lookup/$(DEPDIR) + @: > fib_lookup/$(DEPDIR)/$(am__dirstamp) +fib_lookup/lookup.lo: fib_lookup/$(am__dirstamp) \ + fib_lookup/$(DEPDIR)/$(am__dirstamp) +fib_lookup/request.lo: fib_lookup/$(am__dirstamp) \ + fib_lookup/$(DEPDIR)/$(am__dirstamp) +route/pktloc.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) +route/pktloc_syntax.lo: route/$(am__dirstamp) \ + route/$(DEPDIR)/$(am__dirstamp) +route/pktloc_grammar.lo: route/$(am__dirstamp) \ + route/$(DEPDIR)/$(am__dirstamp) +route/cls/ematch_syntax.lo: route/cls/$(am__dirstamp) \ + route/cls/$(DEPDIR)/$(am__dirstamp) +route/cls/ematch_grammar.lo: route/cls/$(am__dirstamp) \ + route/cls/$(DEPDIR)/$(am__dirstamp) +libnl-route-3.la: $(libnl_route_3_la_OBJECTS) $(libnl_route_3_la_DEPENDENCIES) $(EXTRA_libnl_route_3_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) -rpath $(libdir) $(libnl_route_3_la_OBJECTS) $(libnl_route_3_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f cli/cls/basic.$(OBJEXT) + -rm -f cli/cls/basic.lo + -rm -f cli/cls/cgroup.$(OBJEXT) + -rm -f cli/cls/cgroup.lo + -rm -f cli/qdisc/bfifo.$(OBJEXT) + -rm -f cli/qdisc/bfifo.lo + -rm -f cli/qdisc/blackhole.$(OBJEXT) + -rm -f cli/qdisc/blackhole.lo + -rm -f cli/qdisc/htb.$(OBJEXT) + -rm -f cli/qdisc/htb.lo + -rm -f cli/qdisc/pfifo.$(OBJEXT) + -rm -f cli/qdisc/pfifo.lo + -rm -f cli/qdisc/plug.$(OBJEXT) + -rm -f cli/qdisc/plug.lo + -rm -f fib_lookup/lookup.$(OBJEXT) + -rm -f fib_lookup/lookup.lo + -rm -f fib_lookup/request.$(OBJEXT) + -rm -f fib_lookup/request.lo + -rm -f genl/ctrl.$(OBJEXT) + -rm -f genl/ctrl.lo + -rm -f genl/family.$(OBJEXT) + -rm -f genl/family.lo + -rm -f genl/genl.$(OBJEXT) + -rm -f genl/genl.lo + -rm -f genl/mngt.$(OBJEXT) + -rm -f genl/mngt.lo + -rm -f netfilter/ct.$(OBJEXT) + -rm -f netfilter/ct.lo + -rm -f netfilter/ct_obj.$(OBJEXT) + -rm -f netfilter/ct_obj.lo + -rm -f netfilter/exp.$(OBJEXT) + -rm -f netfilter/exp.lo + -rm -f netfilter/exp_obj.$(OBJEXT) + -rm -f netfilter/exp_obj.lo + -rm -f netfilter/log.$(OBJEXT) + -rm -f netfilter/log.lo + -rm -f netfilter/log_msg.$(OBJEXT) + -rm -f netfilter/log_msg.lo + -rm -f netfilter/log_msg_obj.$(OBJEXT) + -rm -f netfilter/log_msg_obj.lo + -rm -f netfilter/log_obj.$(OBJEXT) + -rm -f netfilter/log_obj.lo + -rm -f netfilter/netfilter.$(OBJEXT) + -rm -f netfilter/netfilter.lo + -rm -f netfilter/nfnl.$(OBJEXT) + -rm -f netfilter/nfnl.lo + -rm -f netfilter/queue.$(OBJEXT) + -rm -f netfilter/queue.lo + -rm -f netfilter/queue_msg.$(OBJEXT) + -rm -f netfilter/queue_msg.lo + -rm -f netfilter/queue_msg_obj.$(OBJEXT) + -rm -f netfilter/queue_msg_obj.lo + -rm -f netfilter/queue_obj.$(OBJEXT) + -rm -f netfilter/queue_obj.lo + -rm -f route/addr.$(OBJEXT) + -rm -f route/addr.lo + -rm -f route/class.$(OBJEXT) + -rm -f route/class.lo + -rm -f route/classid.$(OBJEXT) + -rm -f route/classid.lo + -rm -f route/cls.$(OBJEXT) + -rm -f route/cls.lo + -rm -f route/cls/basic.$(OBJEXT) + -rm -f route/cls/basic.lo + -rm -f route/cls/cgroup.$(OBJEXT) + -rm -f route/cls/cgroup.lo + -rm -f route/cls/ematch.$(OBJEXT) + -rm -f route/cls/ematch.lo + -rm -f route/cls/ematch/cmp.$(OBJEXT) + -rm -f route/cls/ematch/cmp.lo + -rm -f route/cls/ematch/container.$(OBJEXT) + -rm -f route/cls/ematch/container.lo + -rm -f route/cls/ematch/meta.$(OBJEXT) + -rm -f route/cls/ematch/meta.lo + -rm -f route/cls/ematch/nbyte.$(OBJEXT) + -rm -f route/cls/ematch/nbyte.lo + -rm -f route/cls/ematch/text.$(OBJEXT) + -rm -f route/cls/ematch/text.lo + -rm -f route/cls/ematch_grammar.$(OBJEXT) + -rm -f route/cls/ematch_grammar.lo + -rm -f route/cls/ematch_syntax.$(OBJEXT) + -rm -f route/cls/ematch_syntax.lo + -rm -f route/cls/fw.$(OBJEXT) + -rm -f route/cls/fw.lo + -rm -f route/cls/police.$(OBJEXT) + -rm -f route/cls/police.lo + -rm -f route/cls/u32.$(OBJEXT) + -rm -f route/cls/u32.lo + -rm -f route/link.$(OBJEXT) + -rm -f route/link.lo + -rm -f route/link/api.$(OBJEXT) + -rm -f route/link/api.lo + -rm -f route/link/bonding.$(OBJEXT) + -rm -f route/link/bonding.lo + -rm -f route/link/bridge.$(OBJEXT) + -rm -f route/link/bridge.lo + -rm -f route/link/can.$(OBJEXT) + -rm -f route/link/can.lo + -rm -f route/link/dummy.$(OBJEXT) + -rm -f route/link/dummy.lo + -rm -f route/link/inet.$(OBJEXT) + -rm -f route/link/inet.lo + -rm -f route/link/inet6.$(OBJEXT) + -rm -f route/link/inet6.lo + -rm -f route/link/vlan.$(OBJEXT) + -rm -f route/link/vlan.lo + -rm -f route/neigh.$(OBJEXT) + -rm -f route/neigh.lo + -rm -f route/neightbl.$(OBJEXT) + -rm -f route/neightbl.lo + -rm -f route/nexthop.$(OBJEXT) + -rm -f route/nexthop.lo + -rm -f route/pktloc.$(OBJEXT) + -rm -f route/pktloc.lo + -rm -f route/pktloc_grammar.$(OBJEXT) + -rm -f route/pktloc_grammar.lo + -rm -f route/pktloc_syntax.$(OBJEXT) + -rm -f route/pktloc_syntax.lo + -rm -f route/qdisc.$(OBJEXT) + -rm -f route/qdisc.lo + -rm -f route/qdisc/blackhole.$(OBJEXT) + -rm -f route/qdisc/blackhole.lo + -rm -f route/qdisc/cbq.$(OBJEXT) + -rm -f route/qdisc/cbq.lo + -rm -f route/qdisc/dsmark.$(OBJEXT) + -rm -f route/qdisc/dsmark.lo + -rm -f route/qdisc/fifo.$(OBJEXT) + -rm -f route/qdisc/fifo.lo + -rm -f route/qdisc/htb.$(OBJEXT) + -rm -f route/qdisc/htb.lo + -rm -f route/qdisc/netem.$(OBJEXT) + -rm -f route/qdisc/netem.lo + -rm -f route/qdisc/plug.$(OBJEXT) + -rm -f route/qdisc/plug.lo + -rm -f route/qdisc/prio.$(OBJEXT) + -rm -f route/qdisc/prio.lo + -rm -f route/qdisc/red.$(OBJEXT) + -rm -f route/qdisc/red.lo + -rm -f route/qdisc/sfq.$(OBJEXT) + -rm -f route/qdisc/sfq.lo + -rm -f route/qdisc/tbf.$(OBJEXT) + -rm -f route/qdisc/tbf.lo + -rm -f route/route.$(OBJEXT) + -rm -f route/route.lo + -rm -f route/route_obj.$(OBJEXT) + -rm -f route/route_obj.lo + -rm -f route/route_utils.$(OBJEXT) + -rm -f route/route_utils.lo + -rm -f route/rtnl.$(OBJEXT) + -rm -f route/rtnl.lo + -rm -f route/rule.$(OBJEXT) + -rm -f route/rule.lo + -rm -f route/tc.$(OBJEXT) + -rm -f route/tc.lo + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cache.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cache_mngr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cache_mngt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/data.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/handlers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hashtable.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cli/cls/$(DEPDIR)/basic.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cli/cls/$(DEPDIR)/cgroup.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cli/qdisc/$(DEPDIR)/bfifo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cli/qdisc/$(DEPDIR)/blackhole.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cli/qdisc/$(DEPDIR)/htb.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cli/qdisc/$(DEPDIR)/pfifo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cli/qdisc/$(DEPDIR)/plug.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@fib_lookup/$(DEPDIR)/lookup.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@fib_lookup/$(DEPDIR)/request.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@genl/$(DEPDIR)/ctrl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@genl/$(DEPDIR)/family.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@genl/$(DEPDIR)/genl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@genl/$(DEPDIR)/mngt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/ct.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/ct_obj.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/exp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/exp_obj.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/log.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/log_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/log_msg_obj.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/log_obj.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/netfilter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/nfnl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/queue.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/queue_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/queue_msg_obj.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/queue_obj.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/addr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/class.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/classid.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/cls.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/link.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/neigh.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/neightbl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/nexthop.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/pktloc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/pktloc_grammar.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/pktloc_syntax.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/qdisc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/route.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/route_obj.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/route_utils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/rtnl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/rule.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/tc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/cls/$(DEPDIR)/basic.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/cls/$(DEPDIR)/cgroup.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/cls/$(DEPDIR)/ematch.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/cls/$(DEPDIR)/ematch_grammar.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/cls/$(DEPDIR)/ematch_syntax.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/cls/$(DEPDIR)/fw.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/cls/$(DEPDIR)/police.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/cls/$(DEPDIR)/u32.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/cls/ematch/$(DEPDIR)/cmp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/cls/ematch/$(DEPDIR)/container.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/cls/ematch/$(DEPDIR)/meta.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/cls/ematch/$(DEPDIR)/nbyte.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/cls/ematch/$(DEPDIR)/text.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/link/$(DEPDIR)/api.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/link/$(DEPDIR)/bonding.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/link/$(DEPDIR)/bridge.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/link/$(DEPDIR)/can.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/link/$(DEPDIR)/dummy.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/link/$(DEPDIR)/inet.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/link/$(DEPDIR)/inet6.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/link/$(DEPDIR)/vlan.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/blackhole.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/cbq.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/dsmark.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/fifo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/htb.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/netem.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/plug.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/prio.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/red.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/sfq.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/tbf.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + -rm -rf cli/cls/.libs cli/cls/_libs + -rm -rf cli/qdisc/.libs cli/qdisc/_libs + -rm -rf fib_lookup/.libs fib_lookup/_libs + -rm -rf genl/.libs genl/_libs + -rm -rf netfilter/.libs netfilter/_libs + -rm -rf route/.libs route/_libs + -rm -rf route/cls/.libs route/cls/_libs + -rm -rf route/cls/ematch/.libs route/cls/ematch/_libs + -rm -rf route/link/.libs route/link/_libs + -rm -rf route/qdisc/.libs route/qdisc/_libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) defs.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) defs.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) defs.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) defs.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) defs.h +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f cli/cls/$(DEPDIR)/$(am__dirstamp) + -rm -f cli/cls/$(am__dirstamp) + -rm -f cli/qdisc/$(DEPDIR)/$(am__dirstamp) + -rm -f cli/qdisc/$(am__dirstamp) + -rm -f fib_lookup/$(DEPDIR)/$(am__dirstamp) + -rm -f fib_lookup/$(am__dirstamp) + -rm -f genl/$(DEPDIR)/$(am__dirstamp) + -rm -f genl/$(am__dirstamp) + -rm -f netfilter/$(DEPDIR)/$(am__dirstamp) + -rm -f netfilter/$(am__dirstamp) + -rm -f route/$(DEPDIR)/$(am__dirstamp) + -rm -f route/$(am__dirstamp) + -rm -f route/cls/$(DEPDIR)/$(am__dirstamp) + -rm -f route/cls/$(am__dirstamp) + -rm -f route/cls/ematch/$(DEPDIR)/$(am__dirstamp) + -rm -f route/cls/ematch/$(am__dirstamp) + -rm -f route/link/$(DEPDIR)/$(am__dirstamp) + -rm -f route/link/$(am__dirstamp) + -rm -f route/qdisc/$(DEPDIR)/$(am__dirstamp) + -rm -f route/qdisc/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-nobase_pkglibLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) cli/cls/$(DEPDIR) cli/qdisc/$(DEPDIR) fib_lookup/$(DEPDIR) genl/$(DEPDIR) netfilter/$(DEPDIR) route/$(DEPDIR) route/cls/$(DEPDIR) route/cls/ematch/$(DEPDIR) route/link/$(DEPDIR) route/qdisc/$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES \ + install-nobase_pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) cli/cls/$(DEPDIR) cli/qdisc/$(DEPDIR) fib_lookup/$(DEPDIR) genl/$(DEPDIR) netfilter/$(DEPDIR) route/$(DEPDIR) route/cls/$(DEPDIR) route/cls/ematch/$(DEPDIR) route/link/$(DEPDIR) route/qdisc/$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES \ + uninstall-nobase_pkglibLTLIBRARIES + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool \ + clean-nobase_pkglibLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-hdr \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-libLTLIBRARIES install-man \ + install-nobase_pkglibLTLIBRARIES install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-libLTLIBRARIES \ + uninstall-nobase_pkglibLTLIBRARIES + + +# Hack to avoid using ylwrap. It does not function correctly in combination +# with --header-file= +route/pktloc_grammar.c: route/pktloc_grammar.l + $(AM_V_GEN) $(FLEX) --header-file=route/pktloc_grammar.h $(LFLAGS) -o $@ $^ + +route/pktloc_syntax.c: route/pktloc_syntax.y + $(AM_V_GEN) $(YACC) -d $(YFLAGS) -o $@ $^ + +route/cls/ematch_grammar.c: route/cls/ematch_grammar.l + $(AM_V_GEN) $(FLEX) --header-file=route/cls/ematch_grammar.h $(LFLAGS) -o $@ $^ + +route/cls/ematch_syntax.c: route/cls/ematch_syntax.y + $(AM_V_GEN) $(YACC) -d $(YFLAGS) -o $@ $^ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lib/addr.c b/lib/addr.c new file mode 100644 index 0000000..86e7e58 --- /dev/null +++ b/lib/addr.c @@ -0,0 +1,1067 @@ +/* + * lib/addr.c Network Address + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2013 Thomas Graf + */ + +/** + * @ingroup core_types + * @defgroup addr Network Address + * + * Abstract data type representing any kind of network address + * + * Related sections in the development guide: + * - @core_doc{_abstract_address, Network Addresses} + * + * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ + */ + +#include +#include +#include +#include +#include + +/* All this DECnet stuff is stolen from iproute2, thanks to whoever wrote + * this, probably Alexey. */ +static inline uint16_t dn_ntohs(uint16_t addr) +{ + union { + uint8_t byte[2]; + uint16_t word; + } u = { + .word = addr, + }; + + return ((uint16_t) u.byte[0]) | (((uint16_t) u.byte[1]) << 8); +} + +static inline int do_digit(char *str, uint16_t *addr, uint16_t scale, + size_t *pos, size_t len, int *started) +{ + uint16_t tmp = *addr / scale; + + if (*pos == len) + return 1; + + if (((tmp) > 0) || *started || (scale == 1)) { + *str = tmp + '0'; + *started = 1; + (*pos)++; + *addr -= (tmp * scale); + } + + return 0; +} + +static const char *dnet_ntop(char *addrbuf, size_t addrlen, char *str, + size_t len) +{ + uint16_t addr = dn_ntohs(*(uint16_t *)addrbuf); + uint16_t area = addr >> 10; + size_t pos = 0; + int started = 0; + + if (addrlen != 2) + return NULL; + + addr &= 0x03ff; + + if (len == 0) + return str; + + if (do_digit(str + pos, &area, 10, &pos, len, &started)) + return str; + + if (do_digit(str + pos, &area, 1, &pos, len, &started)) + return str; + + if (pos == len) + return str; + + *(str + pos) = '.'; + pos++; + started = 0; + + if (do_digit(str + pos, &addr, 1000, &pos, len, &started)) + return str; + + if (do_digit(str + pos, &addr, 100, &pos, len, &started)) + return str; + + if (do_digit(str + pos, &addr, 10, &pos, len, &started)) + return str; + + if (do_digit(str + pos, &addr, 1, &pos, len, &started)) + return str; + + if (pos == len) + return str; + + *(str + pos) = 0; + + return str; +} + +static int dnet_num(const char *src, uint16_t * dst) +{ + int rv = 0; + int tmp; + *dst = 0; + + while ((tmp = *src++) != 0) { + tmp -= '0'; + if ((tmp < 0) || (tmp > 9)) + return rv; + + rv++; + (*dst) *= 10; + (*dst) += tmp; + } + + return rv; +} + +static inline int dnet_pton(const char *src, char *addrbuf) +{ + uint16_t area = 0; + uint16_t node = 0; + int pos; + + pos = dnet_num(src, &area); + if ((pos == 0) || (area > 63) || + ((*(src + pos) != '.') && (*(src + pos) != ','))) + return -NLE_INVAL; + + pos = dnet_num(src + pos + 1, &node); + if ((pos == 0) || (node > 1023)) + return -NLE_INVAL; + + *(uint16_t *)addrbuf = dn_ntohs((area << 10) | node); + + return 1; +} + +static void addr_destroy(struct nl_addr *addr) +{ + if (!addr) + return; + + if (addr->a_refcnt != 1) + BUG(); + + free(addr); +} + +/** + * @name Creating Abstract Network Addresses + * @{ + */ + +/** + * Allocate empty abstract address + * @arg maxsize Upper limit of the binary address to be stored + * + * The new address object will be empty with a prefix length of 0 and will + * be capable of holding binary addresses up to the specified limit. + * + * @see nl_addr_build() + * @see nl_addr_parse() + * @see nl_addr_put() + * + * @return Allocated address object or NULL upon failure. + */ +struct nl_addr *nl_addr_alloc(size_t maxsize) +{ + struct nl_addr *addr; + + addr = calloc(1, sizeof(*addr) + maxsize); + if (!addr) + return NULL; + + addr->a_refcnt = 1; + addr->a_maxsize = maxsize; + + return addr; +} + +/** + * Allocate abstract address based on a binary address. + * @arg family Address family + * @arg buf Binary address + * @arg size Length of binary address + * + * This function will allocate an abstract address capable of holding the + * binary address specified. The prefix length will be set to the full + * length of the binary address provided. + * + * @see nl_addr_alloc() + * @see nl_addr_alloc_attr() + * @see nl_addr_parse() + * @see nl_addr_put() + * + * @return Allocated address object or NULL upon failure. + */ +struct nl_addr *nl_addr_build(int family, void *buf, size_t size) +{ + struct nl_addr *addr; + + addr = nl_addr_alloc(size); + if (!addr) + return NULL; + + addr->a_family = family; + addr->a_len = size; + addr->a_prefixlen = size*8; + + if (size) + memcpy(addr->a_addr, buf, size); + + return addr; +} + +/** + * Allocate abstract address based on Netlink attribute. + * @arg nla Netlink attribute + * @arg family Address family. + * + * Allocates an abstract address based on the specified Netlink attribute + * by interpreting the payload of the Netlink attribute as the binary + * address. + * + * This function is identical to: + * @code + * nl_addr_build(family, nla_data(nla), nla_len(nla)); + * @endcode + * + * @see nl_addr_alloc() + * @see nl_addr_build() + * @see nl_addr_parse() + * @see nl_addr_put() + * + * @return Allocated address object or NULL upon failure. + */ +struct nl_addr *nl_addr_alloc_attr(struct nlattr *nla, int family) +{ + return nl_addr_build(family, nla_data(nla), nla_len(nla)); +} + +/** + * Allocate abstract address based on character string + * @arg addrstr Address represented as character string. + * @arg hint Address family hint or AF_UNSPEC. + * @arg result Pointer to store resulting address. + * + * Regognizes the following address formats: + * @code + * Format Len Family + * ---------------------------------------------------------------- + * IPv6 address format 16 AF_INET6 + * ddd.ddd.ddd.ddd 4 AF_INET + * HH:HH:HH:HH:HH:HH 6 AF_LLC + * AA{.|,}NNNN 2 AF_DECnet + * HH:HH:HH:... variable AF_UNSPEC + * @endcode + * + * Special values: + * - none: All bits and length set to 0. + * - {default|all|any}: All bits set to 0, length based on hint or + * AF_INET if no hint is given. + * + * The prefix length may be appened at the end prefixed with a + * slash, e.g. 10.0.0.0/8. + * + * @see nl_addr_alloc() + * @see nl_addr_build() + * @see nl_addr_put() + * + * @return 0 on success or a negative error code. + */ +int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result) +{ + int err, copy = 0, len = 0, family = AF_UNSPEC; + char *str, *prefix, buf[32]; + struct nl_addr *addr = NULL; /* gcc ain't that smart */ + + str = strdup(addrstr); + if (!str) { + err = -NLE_NOMEM; + goto errout; + } + + prefix = strchr(str, '/'); + if (prefix) + *prefix = '\0'; + + if (!strcasecmp(str, "none")) { + family = hint; + goto prefix; + } + + if (!strcasecmp(str, "default") || + !strcasecmp(str, "all") || + !strcasecmp(str, "any")) { + + len = 0; + + switch (hint) { + case AF_INET: + case AF_UNSPEC: + /* Kind of a hack, we assume that if there is + * no hint given the user wants to have a IPv4 + * address given back. */ + family = AF_INET; + goto prefix; + + case AF_INET6: + family = AF_INET6; + goto prefix; + + case AF_LLC: + family = AF_LLC; + goto prefix; + + default: + err = -NLE_AF_NOSUPPORT; + goto errout; + } + } + + copy = 1; + + if (hint == AF_INET || hint == AF_UNSPEC) { + if (inet_pton(AF_INET, str, buf) > 0) { + family = AF_INET; + len = 4; + goto prefix; + } + if (hint == AF_INET) { + err = -NLE_NOADDR; + goto errout; + } + } + + if (hint == AF_INET6 || hint == AF_UNSPEC) { + if (inet_pton(AF_INET6, str, buf) > 0) { + family = AF_INET6; + len = 16; + goto prefix; + } + if (hint == AF_INET6) { + err = -NLE_NOADDR; + goto errout; + } + } + + if ((hint == AF_LLC || hint == AF_UNSPEC) && strchr(str, ':')) { + unsigned int a, b, c, d, e, f; + + if (sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x", + &a, &b, &c, &d, &e, &f) == 6) { + family = AF_LLC; + len = 6; + buf[0] = (unsigned char) a; + buf[1] = (unsigned char) b; + buf[2] = (unsigned char) c; + buf[3] = (unsigned char) d; + buf[4] = (unsigned char) e; + buf[5] = (unsigned char) f; + goto prefix; + } + + if (hint == AF_LLC) { + err = -NLE_NOADDR; + goto errout; + } + } + + if ((hint == AF_DECnet || hint == AF_UNSPEC) && + (strchr(str, '.') || strchr(str, ','))) { + if (dnet_pton(str, buf) > 0) { + family = AF_DECnet; + len = 2; + goto prefix; + } + if (hint == AF_DECnet) { + err = -NLE_NOADDR; + goto errout; + } + } + + if (hint == AF_UNSPEC && strchr(str, ':')) { + size_t i = 0; + char *s = str, *p; + for (;;) { + long l = strtol(s, &p, 16); + + if (s == p || l > 0xff || i >= sizeof(buf)) { + err = -NLE_INVAL; + goto errout; + } + + buf[i++] = (unsigned char) l; + if (*p == '\0') + break; + s = ++p; + } + + len = i; + family = AF_UNSPEC; + goto prefix; + } + + err = -NLE_NOADDR; + goto errout; + +prefix: + addr = nl_addr_alloc(len); + if (!addr) { + err = -NLE_NOMEM; + goto errout; + } + + nl_addr_set_family(addr, family); + + if (copy) + nl_addr_set_binary_addr(addr, buf, len); + + if (prefix) { + char *p; + long pl = strtol(++prefix, &p, 0); + if (p == prefix) { + addr_destroy(addr); + err = -NLE_INVAL; + goto errout; + } + nl_addr_set_prefixlen(addr, pl); + } else + nl_addr_set_prefixlen(addr, len * 8); + + *result = addr; + err = 0; +errout: + free(str); + + return err; +} + +/** + * Clone existing abstract address object + * @arg addr Abstract address object + * + * Allocates new abstract address representing an identical clone of an + * existing address. + * + * @see nl_addr_alloc() + * @see nl_addr_put() + * + * @return Allocated abstract address or NULL upon failure. + */ +struct nl_addr *nl_addr_clone(struct nl_addr *addr) +{ + struct nl_addr *new; + + new = nl_addr_build(addr->a_family, addr->a_addr, addr->a_len); + if (new) + new->a_prefixlen = addr->a_prefixlen; + + return new; +} + +/** @} */ + +/** + * @name Managing Usage References + * @{ + */ + +/** + * Increase the reference counter of an abstract address + * @arg addr Abstract address + * + * Increases the reference counter of the address and thus prevents the + * release of the memory resources until the reference is given back + * using the function nl_addr_put(). + * + * @see nl_addr_put() + * + * @return Pointer to the existing abstract address + */ +struct nl_addr *nl_addr_get(struct nl_addr *addr) +{ + addr->a_refcnt++; + + return addr; +} + +/** + * Decrease the reference counter of an abstract address + * @arg addr Abstract addr + * + * @note The resources of the abstract address will be freed after the + * last reference to the address has been returned. + * + * @see nl_addr_get() + */ +void nl_addr_put(struct nl_addr *addr) +{ + if (!addr) + return; + + if (addr->a_refcnt == 1) + addr_destroy(addr); + else + addr->a_refcnt--; +} + +/** + * Check whether an abstract address is shared. + * @arg addr Abstract address object. + * + * @return Non-zero if the abstract address is shared, otherwise 0. + */ +int nl_addr_shared(struct nl_addr *addr) +{ + return addr->a_refcnt > 1; +} + +/** @} */ + +/** + * @name Miscellaneous + * @{ + */ + +/** + * Compare abstract addresses + * @arg a An abstract address + * @arg b Another abstract address + * + * Verifies whether the address family, address length, prefix length, and + * binary addresses of two abstract addresses matches. + * + * @note This function will *not* respect the prefix length in the sense + * that only the actual prefix will be compared. Please refer to the + * nl_addr_cmp_prefix() function if you require this functionality. + * + * @see nl_addr_cmp_prefix() + * + * @return Integer less than, equal to or greather than zero if the two + * addresses match. + */ +int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b) +{ + int d = a->a_family - b->a_family; + + if (d == 0) { + d = a->a_len - b->a_len; + + if (a->a_len && d == 0) { + d = memcmp(a->a_addr, b->a_addr, a->a_len); + + if (d == 0) + return (a->a_prefixlen - b->a_prefixlen); + } + } + + return d; +} + +/** + * Compare the prefix of two abstract addresses + * @arg a An abstract address + * @arg b Another abstract address + * + * Verifies whether the address family and the binary address covered by + * the smaller prefix length of the two abstract addresses matches. + * + * @see nl_addr_cmp() + * + * @return Integer less than, equal to or greather than zero if the two + * addresses match. + */ +int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b) +{ + int d = a->a_family - b->a_family; + + if (d == 0) { + int len = min(a->a_prefixlen, b->a_prefixlen); + int bytes = len / 8; + + d = memcmp(a->a_addr, b->a_addr, bytes); + if (d == 0 && (len % 8) != 0) { + int mask = (0xFF00 >> (len % 8)) & 0xFF; + + d = (a->a_addr[bytes] & mask) - + (b->a_addr[bytes] & mask); + } + } + + return d; +} + +/** + * Returns true if the address consists of all zeros + * @arg addr Abstract address + * + * @return 1 if the binary address consists of all zeros, 0 otherwise. + */ +int nl_addr_iszero(struct nl_addr *addr) +{ + unsigned int i; + + for (i = 0; i < addr->a_len; i++) + if (addr->a_addr[i]) + return 0; + + return 1; +} + +/** + * Check if address string is parseable for a specific address family + * @arg addr Address represented as character string. + * @arg family Desired address family. + * + * @return 1 if the address is parseable assuming the specified address family, + * otherwise 0 is returned. + */ +int nl_addr_valid(char *addr, int family) +{ + int ret; + char buf[32]; + + switch (family) { + case AF_INET: + case AF_INET6: + ret = inet_pton(family, addr, buf); + if (ret <= 0) + return 0; + break; + + case AF_DECnet: + ret = dnet_pton(addr, buf); + if (ret <= 0) + return 0; + break; + + case AF_LLC: + if (sscanf(addr, "%*02x:%*02x:%*02x:%*02x:%*02x:%*02x") != 6) + return 0; + break; + } + + return 1; +} + +/** + * Guess address family of abstract address based on address size + * @arg addr Abstract address object. + * + * @return Numeric address family or AF_UNSPEC + */ +int nl_addr_guess_family(struct nl_addr *addr) +{ + switch (addr->a_len) { + case 4: + return AF_INET; + case 6: + return AF_LLC; + case 16: + return AF_INET6; + default: + return AF_UNSPEC; + } +} + +/** + * Fill out sockaddr structure with values from abstract address object. + * @arg addr Abstract address object. + * @arg sa Destination sockaddr structure buffer. + * @arg salen Length of sockaddr structure buffer. + * + * Fills out the specified sockaddr structure with the data found in the + * specified abstract address. The salen argument needs to be set to the + * size of sa but will be modified to the actual size used during before + * the function exits. + * + * @return 0 on success or a negative error code + */ +int nl_addr_fill_sockaddr(struct nl_addr *addr, struct sockaddr *sa, + socklen_t *salen) +{ + switch (addr->a_family) { + case AF_INET: { + struct sockaddr_in *sai = (struct sockaddr_in *) sa; + + if (*salen < sizeof(*sai)) + return -NLE_INVAL; + + sai->sin_family = addr->a_family; + memcpy(&sai->sin_addr, addr->a_addr, 4); + *salen = sizeof(*sai); + } + break; + + case AF_INET6: { + struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sa; + + if (*salen < sizeof(*sa6)) + return -NLE_INVAL; + + sa6->sin6_family = addr->a_family; + memcpy(&sa6->sin6_addr, addr->a_addr, 16); + *salen = sizeof(*sa6); + } + break; + + default: + return -NLE_INVAL; + } + + return 0; +} + + +/** @} */ + +/** + * @name Getting Information About Addresses + * @{ + */ + +/** + * Call getaddrinfo() for an abstract address object. + * @arg addr Abstract address object. + * @arg result Pointer to store resulting address list. + * + * Calls getaddrinfo() for the specified abstract address in AI_NUMERICHOST + * mode. + * + * @note The caller is responsible for freeing the linked list using the + * interface provided by getaddrinfo(3). + * + * @return 0 on success or a negative error code. + */ +int nl_addr_info(struct nl_addr *addr, struct addrinfo **result) +{ + int err; + char buf[INET6_ADDRSTRLEN+5]; + struct addrinfo hint = { + .ai_flags = AI_NUMERICHOST, + .ai_family = addr->a_family, + }; + + nl_addr2str(addr, buf, sizeof(buf)); + + err = getaddrinfo(buf, NULL, &hint, result); + if (err != 0) { + switch (err) { + case EAI_ADDRFAMILY: return -NLE_AF_NOSUPPORT; + case EAI_AGAIN: return -NLE_AGAIN; + case EAI_BADFLAGS: return -NLE_INVAL; + case EAI_FAIL: return -NLE_NOADDR; + case EAI_FAMILY: return -NLE_AF_NOSUPPORT; + case EAI_MEMORY: return -NLE_NOMEM; + case EAI_NODATA: return -NLE_NOADDR; + case EAI_NONAME: return -NLE_OBJ_NOTFOUND; + case EAI_SERVICE: return -NLE_OPNOTSUPP; + case EAI_SOCKTYPE: return -NLE_BAD_SOCK; + default: return -NLE_FAILURE; + } + } + + return 0; +} + +/** + * Resolve abstract address object to a name using getnameinfo(). + * @arg addr Abstract address object. + * @arg host Destination buffer for host name. + * @arg hostlen Length of destination buffer. + * + * Resolves the abstract address to a name and writes the looked up result + * into the host buffer. getnameinfo() is used to perform the lookup and + * is put into NI_NAMEREQD mode so the function will fail if the lookup + * couldn't be performed. + * + * @return 0 on success or a negative error code. + */ +int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen) +{ + int err; + struct sockaddr_in6 buf; + socklen_t salen = sizeof(buf); + + err = nl_addr_fill_sockaddr(addr, (struct sockaddr *) &buf, &salen); + if (err < 0) + return err; + + err = getnameinfo((struct sockaddr *) &buf, salen, host, hostlen, + NULL, 0, NI_NAMEREQD); + if (err < 0) + return nl_syserr2nlerr(err); + + return 0; +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ + +/** + * Set address family + * @arg addr Abstract address object + * @arg family Address family + * + * @see nl_addr_get_family() + */ +void nl_addr_set_family(struct nl_addr *addr, int family) +{ + addr->a_family = family; +} + +/** + * Return address family + * @arg addr Abstract address object + * + * @see nl_addr_set_family() + * + * @return The numeric address family or `AF_UNSPEC` + */ +int nl_addr_get_family(struct nl_addr *addr) +{ + return addr->a_family; +} + +/** + * Set binary address of abstract address object. + * @arg addr Abstract address object. + * @arg buf Buffer containing binary address. + * @arg len Length of buffer containing binary address. + * + * Modifies the binary address portion of the abstract address. The + * abstract address must be capable of holding the required amount + * or this function will fail. + * + * @note This function will *not* modify the prefix length. It is within + * the responsibility of the caller to set the prefix length to the + * desirable length. + * + * @see nl_addr_alloc() + * @see nl_addr_get_binary_addr() + * @see nl_addr_get_len() + * + * @return 0 on success or a negative error code. + */ +int nl_addr_set_binary_addr(struct nl_addr *addr, void *buf, size_t len) +{ + if (len > addr->a_maxsize) + return -NLE_RANGE; + + addr->a_len = len; + memset(addr->a_addr, 0, addr->a_maxsize); + + if (len) + memcpy(addr->a_addr, buf, len); + + return 0; +} + +/** + * Get binary address of abstract address object. + * @arg addr Abstract address object. + * + * @see nl_addr_set_binary_addr() + * @see nl_addr_get_len() + * + * @return Pointer to binary address of length nl_addr_get_len() + */ +void *nl_addr_get_binary_addr(struct nl_addr *addr) +{ + return addr->a_addr; +} + +/** + * Get length of binary address of abstract address object. + * @arg addr Abstract address object. + * + * @see nl_addr_get_binary_addr() + * @see nl_addr_set_binary_addr() + */ +unsigned int nl_addr_get_len(struct nl_addr *addr) +{ + return addr->a_len; +} + +/** + * Set the prefix length of an abstract address + * @arg addr Abstract address object + * @arg prefixlen New prefix length + * + * @see nl_addr_get_prefixlen() + */ +void nl_addr_set_prefixlen(struct nl_addr *addr, int prefixlen) +{ + addr->a_prefixlen = prefixlen; +} + +/** + * Return prefix length of abstract address object. + * @arg addr Abstract address object + * + * @see nl_addr_set_prefixlen() + */ +unsigned int nl_addr_get_prefixlen(struct nl_addr *addr) +{ + return addr->a_prefixlen; +} + +/** @} */ + +/** + * @name Translations to Strings + * @{ + */ + +/** + * Convert abstract address object to character string. + * @arg addr Abstract address object. + * @arg buf Destination buffer. + * @arg size Size of destination buffer. + * + * Converts an abstract address to a character string and stores + * the result in the specified destination buffer. + * + * @return Address represented in ASCII stored in destination buffer. + */ +char *nl_addr2str(struct nl_addr *addr, char *buf, size_t size) +{ + unsigned int i; + char tmp[16]; + + if (!addr || !addr->a_len) { + snprintf(buf, size, "none"); + if (addr) + goto prefix; + else + return buf; + } + + switch (addr->a_family) { + case AF_INET: + inet_ntop(AF_INET, addr->a_addr, buf, size); + break; + + case AF_INET6: + inet_ntop(AF_INET6, addr->a_addr, buf, size); + break; + + case AF_DECnet: + dnet_ntop(addr->a_addr, addr->a_len, buf, size); + break; + + case AF_LLC: + default: + snprintf(buf, size, "%02x", + (unsigned char) addr->a_addr[0]); + for (i = 1; i < addr->a_len; i++) { + snprintf(tmp, sizeof(tmp), ":%02x", + (unsigned char) addr->a_addr[i]); + strncat(buf, tmp, size - strlen(buf) - 1); + } + break; + } + +prefix: + if (addr->a_prefixlen != (8 * addr->a_len)) { + snprintf(tmp, sizeof(tmp), "/%u", addr->a_prefixlen); + strncat(buf, tmp, size - strlen(buf) - 1); + } + + return buf; +} + +/** @} */ + +/** + * @name Address Family Transformations + * @{ + */ + +static const struct trans_tbl afs[] = { + __ADD(AF_UNSPEC,unspec) + __ADD(AF_UNIX,unix) + __ADD(AF_INET,inet) + __ADD(AF_AX25,ax25) + __ADD(AF_IPX,ipx) + __ADD(AF_APPLETALK,appletalk) + __ADD(AF_NETROM,netrom) + __ADD(AF_BRIDGE,bridge) + __ADD(AF_ATMPVC,atmpvc) + __ADD(AF_X25,x25) + __ADD(AF_INET6,inet6) + __ADD(AF_ROSE,rose) + __ADD(AF_DECnet,decnet) + __ADD(AF_NETBEUI,netbeui) + __ADD(AF_SECURITY,security) + __ADD(AF_KEY,key) + __ADD(AF_NETLINK,netlink) + __ADD(AF_PACKET,packet) + __ADD(AF_ASH,ash) + __ADD(AF_ECONET,econet) + __ADD(AF_ATMSVC,atmsvc) + __ADD(AF_RDS,rds) + __ADD(AF_SNA,sna) + __ADD(AF_IRDA,irda) + __ADD(AF_PPPOX,pppox) + __ADD(AF_WANPIPE,wanpipe) + __ADD(AF_LLC,llc) + __ADD(AF_CAN,can) + __ADD(AF_TIPC,tipc) + __ADD(AF_BLUETOOTH,bluetooth) + __ADD(AF_IUCV,iucv) + __ADD(AF_RXRPC,rxrpc) + __ADD(AF_ISDN,isdn) + __ADD(AF_PHONET,phonet) +#ifdef AF_IEEE802154 + __ADD(AF_IEEE802154,ieee802154) +#endif +#ifdef AF_CAIF + __ADD(AF_CAIF,caif) +#endif +#ifdef AF_ALG + __ADD(AF_ALG,alg) +#endif +#ifdef AF_NFC + __ADD(AF_NFC,nfc) +#endif +}; + +char *nl_af2str(int family, char *buf, size_t size) +{ + return __type2str(family, buf, size, afs, ARRAY_SIZE(afs)); +} + +int nl_str2af(const char *name) +{ + int fam = __str2type(name, afs, ARRAY_SIZE(afs)); + return fam >= 0 ? fam : -EINVAL; +} + +/** @} */ + +/** @} */ diff --git a/lib/attr.c b/lib/attr.c new file mode 100644 index 0000000..535f10c --- /dev/null +++ b/lib/attr.c @@ -0,0 +1,907 @@ +/* + * lib/attr.c Netlink 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-2013 Thomas Graf + */ + +#include +#include +#include +#include +#include +#include +#include + +/** + * @ingroup msg + * @defgroup attr Attributes + * Netlink Attributes Construction/Parsing Interface + * + * Related sections in the development guide: + * - @core_doc{core_attr,Netlink Attributes} + * + * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ + */ + +/** + * @name Attribute Size Calculation + * @{ + */ + +/** + * Return size of attribute whithout padding. + * @arg payload Payload length of attribute. + * + * @code + * <-------- nla_attr_size(payload) ---------> + * +------------------+- - -+- - - - - - - - - +- - -+ + * | Attribute Header | Pad | Payload | Pad | + * +------------------+- - -+- - - - - - - - - +- - -+ + * @endcode + * + * @return Size of attribute in bytes without padding. + */ +int nla_attr_size(int payload) +{ + return NLA_HDRLEN + payload; +} + +/** + * Return size of attribute including padding. + * @arg payload Payload length of attribute. + * + * @code + * <----------- nla_total_size(payload) -----------> + * +------------------+- - -+- - - - - - - - - +- - -+ + * | Attribute Header | Pad | Payload | Pad | + * +------------------+- - -+- - - - - - - - - +- - -+ + * @endcode + * + * @return Size of attribute in bytes. + */ +int nla_total_size(int payload) +{ + return NLA_ALIGN(nla_attr_size(payload)); +} + +/** + * Return length of padding at the tail of the attribute. + * @arg payload Payload length of attribute. + * + * @code + * +------------------+- - -+- - - - - - - - - +- - -+ + * | Attribute Header | Pad | Payload | Pad | + * +------------------+- - -+- - - - - - - - - +- - -+ + * <---> + * @endcode + * + * @return Length of padding in bytes. + */ +int nla_padlen(int payload) +{ + return nla_total_size(payload) - nla_attr_size(payload); +} + +/** @} */ + +/** + * @name Parsing Attributes + * @{ + */ + +/** + * Return type of the attribute. + * @arg nla Attribute. + * + * @return Type of attribute. + */ +int nla_type(const struct nlattr *nla) +{ + return nla->nla_type & NLA_TYPE_MASK; +} + +/** + * Return pointer to the payload section. + * @arg nla Attribute. + * + * @return Pointer to start of payload section. + */ +void *nla_data(const struct nlattr *nla) +{ + return (char *) nla + NLA_HDRLEN; +} + +/** + * Return length of the payload . + * @arg nla Attribute + * + * @return Length of payload in bytes. + */ +int nla_len(const struct nlattr *nla) +{ + return nla->nla_len - NLA_HDRLEN; +} + +/** + * Check if the attribute header and payload can be accessed safely. + * @arg nla Attribute of any kind. + * @arg remaining Number of bytes remaining in attribute stream. + * + * Verifies that the header and payload do not exceed the number of + * bytes left in the attribute stream. This function must be called + * before access the attribute header or payload when iterating over + * the attribute stream using nla_next(). + * + * @return True if the attribute can be accessed safely, false otherwise. + */ +int nla_ok(const struct nlattr *nla, int remaining) +{ + return remaining >= sizeof(*nla) && + nla->nla_len >= sizeof(*nla) && + nla->nla_len <= remaining; +} + +/** + * Return next attribute in a stream of attributes. + * @arg nla Attribute of any kind. + * @arg remaining Variable to count remaining bytes in stream. + * + * Calculates the offset to the next attribute based on the attribute + * given. The attribute provided is assumed to be accessible, the + * caller is responsible to use nla_ok() beforehand. The offset (length + * of specified attribute including padding) is then subtracted from + * the remaining bytes variable and a pointer to the next attribute is + * returned. + * + * nla_next() can be called as long as remainig is >0. + * + * @return Pointer to next attribute. + */ +struct nlattr *nla_next(const struct nlattr *nla, int *remaining) +{ + int totlen = NLA_ALIGN(nla->nla_len); + + *remaining -= totlen; + return (struct nlattr *) ((char *) nla + totlen); +} + +static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = { + [NLA_U8] = sizeof(uint8_t), + [NLA_U16] = sizeof(uint16_t), + [NLA_U32] = sizeof(uint32_t), + [NLA_U64] = sizeof(uint64_t), + [NLA_STRING] = 1, + [NLA_FLAG] = 0, +}; + +static int validate_nla(struct nlattr *nla, int maxtype, + struct nla_policy *policy) +{ + struct nla_policy *pt; + unsigned int minlen = 0; + int type = nla_type(nla); + + if (type <= 0 || type > maxtype) + return 0; + + pt = &policy[type]; + + if (pt->type > NLA_TYPE_MAX) + BUG(); + + if (pt->minlen) + minlen = pt->minlen; + else if (pt->type != NLA_UNSPEC) + minlen = nla_attr_minlen[pt->type]; + + if (nla_len(nla) < minlen) + return -NLE_RANGE; + + if (pt->maxlen && nla_len(nla) > pt->maxlen) + return -NLE_RANGE; + + if (pt->type == NLA_STRING) { + char *data = nla_data(nla); + if (data[nla_len(nla) - 1] != '\0') + return -NLE_INVAL; + } + + return 0; +} + + +/** + * Create attribute index based on a stream of attributes. + * @arg tb Index array to be filled (maxtype+1 elements). + * @arg maxtype Maximum attribute type expected and accepted. + * @arg head Head of attribute stream. + * @arg len Length of attribute stream. + * @arg policy Attribute validation policy. + * + * Iterates over the stream of attributes and stores a pointer to each + * attribute in the index array using the attribute type as index to + * the array. Attribute with a type greater than the maximum type + * specified will be silently ignored in order to maintain backwards + * compatibility. If \a policy is not NULL, the attribute will be + * validated using the specified policy. + * + * @see nla_validate + * @return 0 on success or a negative error code. + */ +int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, + struct nla_policy *policy) +{ + struct nlattr *nla; + int rem, err; + + memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); + + nla_for_each_attr(nla, head, len, rem) { + int type = nla_type(nla); + + /* Padding attributes */ + if (type == 0) + continue; + + if (type > maxtype) + continue; + + if (policy) { + err = validate_nla(nla, maxtype, policy); + if (err < 0) + goto errout; + } + + if (tb[type]) + NL_DBG(1, "Attribute of type %#x found multiple times in message, " + "previous attribute is being ignored.\n", type); + + tb[type] = nla; + } + + if (rem > 0) + NL_DBG(1, "netlink: %d bytes leftover after parsing " + "attributes.\n", rem); + + err = 0; +errout: + return err; +} + +/** + * Validate a stream of attributes. + * @arg head Head of attributes stream. + * @arg len Length of attributes stream. + * @arg maxtype Maximum attribute type expected and accepted. + * @arg policy Validation policy. + * + * Iterates over the stream of attributes and validates each attribute + * one by one using the specified policy. Attributes with a type greater + * than the maximum type specified will be silently ignored in order to + * maintain backwards compatibility. + * + * See section @core_doc{core_attr_parse,Attribute Parsing} for more details. + * + * @return 0 on success or a negative error code. + */ +int nla_validate(struct nlattr *head, int len, int maxtype, + struct nla_policy *policy) +{ + struct nlattr *nla; + int rem, err; + + nla_for_each_attr(nla, head, len, rem) { + err = validate_nla(nla, maxtype, policy); + if (err < 0) + goto errout; + } + + err = 0; +errout: + return err; +} + +/** + * Find a single attribute in a stream of attributes. + * @arg head Head of attributes stream. + * @arg len Length of attributes stream. + * @arg attrtype Attribute type to look for. + * + * Iterates over the stream of attributes and compares each type with + * the type specified. Returns the first attribute which matches the + * type. + * + * @return Pointer to attribute found or NULL. + */ +struct nlattr *nla_find(struct nlattr *head, int len, int attrtype) +{ + struct nlattr *nla; + int rem; + + nla_for_each_attr(nla, head, len, rem) + if (nla_type(nla) == attrtype) + return nla; + + return NULL; +} + +/** @} */ + +/** + * @name Helper Functions + * @{ + */ + +/** + * Copy attribute payload to another memory area. + * @arg dest Pointer to destination memory area. + * @arg src Attribute + * @arg count Number of bytes to copy at most. + * + * Note: The number of bytes copied is limited by the length of + * the attribute payload. + * + * @return The number of bytes copied to dest. + */ +int nla_memcpy(void *dest, struct nlattr *src, int count) +{ + int minlen; + + if (!src) + return 0; + + minlen = min_t(int, count, nla_len(src)); + memcpy(dest, nla_data(src), minlen); + + return minlen; +} + +/** + * Copy string attribute payload to a buffer. + * @arg dst Pointer to destination buffer. + * @arg nla Attribute of type NLA_STRING. + * @arg dstsize Size of destination buffer in bytes. + * + * Copies at most dstsize - 1 bytes to the destination buffer. + * The result is always a valid NUL terminated string. Unlike + * strlcpy the destination buffer is always padded out. + * + * @return The length of string attribute without the terminating NUL. + */ +size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize) +{ + size_t srclen = nla_len(nla); + char *src = nla_data(nla); + + if (srclen > 0 && src[srclen - 1] == '\0') + srclen--; + + if (dstsize > 0) { + size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen; + + memset(dst, 0, dstsize); + memcpy(dst, src, len); + } + + return srclen; +} + +/** + * Compare attribute payload with memory area. + * @arg nla Attribute. + * @arg data Memory area to compare to. + * @arg size Number of bytes to compare. + * + * @see memcmp(3) + * @return An integer less than, equal to, or greater than zero. + */ +int nla_memcmp(const struct nlattr *nla, const void *data, size_t size) +{ + int d = nla_len(nla) - size; + + if (d == 0) + d = memcmp(nla_data(nla), data, size); + + return d; +} + +/** + * Compare string attribute payload with string + * @arg nla Attribute of type NLA_STRING. + * @arg str NUL terminated string. + * + * @see strcmp(3) + * @return An integer less than, equal to, or greater than zero. + */ +int nla_strcmp(const struct nlattr *nla, const char *str) +{ + int len = strlen(str) + 1; + int d = nla_len(nla) - len; + + if (d == 0) + d = memcmp(nla_data(nla), str, len); + + return d; +} + +/** @} */ + +/** + * @name Unspecific Attribute + * @{ + */ + +/** + * Reserve space for a attribute. + * @arg msg Netlink Message. + * @arg attrtype Attribute Type. + * @arg attrlen Length of payload. + * + * Reserves room for a attribute in the specified netlink message and + * fills in the attribute header (type, length). Returns NULL if there + * is unsuficient space for the attribute. + * + * Any padding between payload and the start of the next attribute is + * zeroed out. + * + * @return Pointer to start of attribute or NULL on failure. + */ +struct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int attrlen) +{ + struct nlattr *nla; + int tlen; + + tlen = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) + nla_total_size(attrlen); + + if (tlen > msg->nm_size) + return NULL; + + nla = (struct nlattr *) nlmsg_tail(msg->nm_nlh); + nla->nla_type = attrtype; + nla->nla_len = nla_attr_size(attrlen); + + if (attrlen) + memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen)); + msg->nm_nlh->nlmsg_len = tlen; + + NL_DBG(2, "msg %p: attr <%p> %d: Reserved %d (%d) bytes at offset +%td " + "nlmsg_len=%d\n", msg, nla, nla->nla_type, + nla_total_size(attrlen), attrlen, + (void *) nla - nlmsg_data(msg->nm_nlh), + msg->nm_nlh->nlmsg_len); + + return nla; +} + +/** + * Add a unspecific attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg datalen Length of data to be used as payload. + * @arg data Pointer to data to be used as attribute payload. + * + * Reserves room for a unspecific attribute and copies the provided data + * into the message as payload of the attribute. Returns an error if there + * is insufficient space for the attribute. + * + * @see nla_reserve + * @return 0 on success or a negative error code. + */ +int nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data) +{ + struct nlattr *nla; + + nla = nla_reserve(msg, attrtype, datalen); + if (!nla) + return -NLE_NOMEM; + + if (datalen > 0) { + memcpy(nla_data(nla), data, datalen); + NL_DBG(2, "msg %p: attr <%p> %d: Wrote %d bytes at offset +%td\n", + msg, nla, nla->nla_type, datalen, + (void *) nla - nlmsg_data(msg->nm_nlh)); + } + + return 0; +} + +/** + * Add abstract data as unspecific attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg data Abstract data object. + * + * Equivalent to nla_put() except that the length of the payload is + * derived from the abstract data object. + * + * @see nla_put + * @return 0 on success or a negative error code. + */ +int nla_put_data(struct nl_msg *msg, int attrtype, struct nl_data *data) +{ + return nla_put(msg, attrtype, nl_data_get_size(data), + nl_data_get(data)); +} + +/** + * Add abstract address as unspecific attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg addr Abstract address object. + * + * @see nla_put + * @return 0 on success or a negative error code. + */ +int nla_put_addr(struct nl_msg *msg, int attrtype, struct nl_addr *addr) +{ + return nla_put(msg, attrtype, nl_addr_get_len(addr), + nl_addr_get_binary_addr(addr)); +} + +/** @} */ + +/** + * @name Integer Attributes + */ + +/** + * Add 8 bit integer attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg value Numeric value to store as payload. + * + * @see nla_put + * @return 0 on success or a negative error code. + */ +int nla_put_u8(struct nl_msg *msg, int attrtype, uint8_t value) +{ + return nla_put(msg, attrtype, sizeof(uint8_t), &value); +} + +/** + * Return value of 8 bit integer attribute. + * @arg nla 8 bit integer attribute + * + * @return Payload as 8 bit integer. + */ +uint8_t nla_get_u8(struct nlattr *nla) +{ + return *(uint8_t *) nla_data(nla); +} + +/** + * Add 16 bit integer attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg value Numeric value to store as payload. + * + * @see nla_put + * @return 0 on success or a negative error code. + */ +int nla_put_u16(struct nl_msg *msg, int attrtype, uint16_t value) +{ + return nla_put(msg, attrtype, sizeof(uint16_t), &value); +} + +/** + * Return payload of 16 bit integer attribute. + * @arg nla 16 bit integer attribute + * + * @return Payload as 16 bit integer. + */ +uint16_t nla_get_u16(struct nlattr *nla) +{ + return *(uint16_t *) nla_data(nla); +} + +/** + * Add 32 bit integer attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg value Numeric value to store as payload. + * + * @see nla_put + * @return 0 on success or a negative error code. + */ +int nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value) +{ + return nla_put(msg, attrtype, sizeof(uint32_t), &value); +} + +/** + * Return payload of 32 bit integer attribute. + * @arg nla 32 bit integer attribute. + * + * @return Payload as 32 bit integer. + */ +uint32_t nla_get_u32(struct nlattr *nla) +{ + return *(uint32_t *) nla_data(nla); +} + +/** + * Add 64 bit integer attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg value Numeric value to store as payload. + * + * @see nla_put + * @return 0 on success or a negative error code. + */ +int nla_put_u64(struct nl_msg *msg, int attrtype, uint64_t value) +{ + return nla_put(msg, attrtype, sizeof(uint64_t), &value); +} + +/** + * Return payload of u64 attribute + * @arg nla u64 netlink attribute + * + * @return Payload as 64 bit integer. + */ +uint64_t nla_get_u64(struct nlattr *nla) +{ + uint64_t tmp; + + nla_memcpy(&tmp, nla, sizeof(tmp)); + + return tmp; +} + +/** @} */ + +/** + * @name String Attribute + */ + +/** + * Add string attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg str NUL terminated string. + * + * @see nla_put + * @return 0 on success or a negative error code. + */ +int nla_put_string(struct nl_msg *msg, int attrtype, const char *str) +{ + return nla_put(msg, attrtype, strlen(str) + 1, str); +} + +/** + * Return payload of string attribute. + * @arg nla String attribute. + * + * @return Pointer to attribute payload. + */ +char *nla_get_string(struct nlattr *nla) +{ + return (char *) nla_data(nla); +} + +char *nla_strdup(struct nlattr *nla) +{ + return strdup(nla_get_string(nla)); +} + +/** @} */ + +/** + * @name Flag Attribute + */ + +/** + * Add flag netlink attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * + * @see nla_put + * @return 0 on success or a negative error code. + */ +int nla_put_flag(struct nl_msg *msg, int attrtype) +{ + return nla_put(msg, attrtype, 0, NULL); +} + +/** + * Return true if flag attribute is set. + * @arg nla Flag netlink attribute. + * + * @return True if flag is set, otherwise false. + */ +int nla_get_flag(struct nlattr *nla) +{ + return !!nla; +} + +/** @} */ + +/** + * @name Microseconds Attribute + */ + +/** + * Add a msecs netlink attribute to a netlink message + * @arg n netlink message + * @arg attrtype attribute type + * @arg msecs number of msecs + */ +int nla_put_msecs(struct nl_msg *n, int attrtype, unsigned long msecs) +{ + return nla_put_u64(n, attrtype, msecs); +} + +/** + * Return payload of msecs attribute + * @arg nla msecs netlink attribute + * + * @return the number of milliseconds. + */ +unsigned long nla_get_msecs(struct nlattr *nla) +{ + return nla_get_u64(nla); +} + +/** @} */ + +/** + * @name Nested Attribute + */ + +/** + * Add nested attributes to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg nested Message containing attributes to be nested. + * + * Takes the attributes found in the \a nested message and appends them + * to the message \a msg nested in a container of the type \a attrtype. + * The \a nested message may not have a family specific header. + * + * @see nla_put + * @return 0 on success or a negative error code. + */ +int nla_put_nested(struct nl_msg *msg, int attrtype, struct nl_msg *nested) +{ + NL_DBG(2, "msg %p: attr <> %d: adding msg %p as nested attribute\n", + msg, attrtype, nested); + + return nla_put(msg, attrtype, nlmsg_datalen(nested->nm_nlh), + nlmsg_data(nested->nm_nlh)); +} + + +/** + * Start a new level of nested attributes. + * @arg msg Netlink message. + * @arg attrtype Attribute type of container. + * + * @return Pointer to container attribute. + */ +struct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype) +{ + struct nlattr *start = (struct nlattr *) nlmsg_tail(msg->nm_nlh); + + if (nla_put(msg, attrtype, 0, NULL) < 0) + return NULL; + + NL_DBG(2, "msg %p: attr <%p> %d: starting nesting\n", + msg, start, start->nla_type); + + return start; +} + +/** + * Finalize nesting of attributes. + * @arg msg Netlink message. + * @arg start Container attribute as returned from nla_nest_start(). + * + * Corrects the container attribute header to include the appeneded attributes. + * + * @return 0 + */ +int nla_nest_end(struct nl_msg *msg, struct nlattr *start) +{ + size_t pad, len; + + len = (void *) nlmsg_tail(msg->nm_nlh) - (void *) start; + + if (len == NLA_HDRLEN) { + /* + * Kernel can't handle empty nested attributes, trim the + * attribute header again + */ + nla_nest_cancel(msg, start); + + return 0; + } + + start->nla_len = len; + + pad = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) - msg->nm_nlh->nlmsg_len; + if (pad > 0) { + /* + * Data inside attribute does not end at a alignment boundry. + * Pad accordingly and accoun for the additional space in + * the message. nlmsg_reserve() may never fail in this situation, + * the allocate message buffer must be a multiple of NLMSG_ALIGNTO. + */ + if (!nlmsg_reserve(msg, pad, 0)) + BUG(); + + NL_DBG(2, "msg %p: attr <%p> %d: added %zu bytes of padding\n", + msg, start, start->nla_type, pad); + } + + NL_DBG(2, "msg %p: attr <%p> %d: closing nesting, len=%u\n", + msg, start, start->nla_type, start->nla_len); + + return 0; +} + +/** + * Cancel the addition of a nested attribute + * @arg msg Netlink message + * @arg attr Nested netlink attribute + * + * Removes any partially added nested Netlink attribute from the message + * by resetting the message to the size before the call to nla_nest_start() + * and by overwriting any potentially touched message segments with 0. + */ +void nla_nest_cancel(struct nl_msg *msg, struct nlattr *attr) +{ + ssize_t len; + + len = (void *) nlmsg_tail(msg->nm_nlh) - (void *) attr; + if (len < 0) + BUG(); + else if (len > 0) { + msg->nm_nlh->nlmsg_len -= len; + memset(nlmsg_tail(msg->nm_nlh), 0, len); + } +} + +/** + * Create attribute index based on nested attribute + * @arg tb Index array to be filled (maxtype+1 elements). + * @arg maxtype Maximum attribute type expected and accepted. + * @arg nla Nested Attribute. + * @arg policy Attribute validation policy. + * + * Feeds the stream of attributes nested into the specified attribute + * to nla_parse(). + * + * @see nla_parse + * @return 0 on success or a negative error code. + */ +int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, + struct nla_policy *policy) +{ + return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy); +} + +/** + * Return true if attribute has NLA_F_NESTED flag set + * @arg attr Netlink attribute + * + * @return True if attribute has NLA_F_NESTED flag set, oterhwise False. + */ +int nla_is_nested(struct nlattr *attr) +{ + return !!(attr->nla_type & NLA_F_NESTED); +} + +/** @} */ + +/** @} */ diff --git a/lib/cache.c b/lib/cache.c new file mode 100644 index 0000000..e99e9d2 --- /dev/null +++ b/lib/cache.c @@ -0,0 +1,1220 @@ +/* + * lib/cache.c Caching Module + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +/** + * @ingroup cache_mngt + * @defgroup cache Cache + * + * @code + * Cache Management | | Type Specific Cache Operations + * + * | | +----------------+ +------------+ + * | request update | | msg_parser | + * | | +----------------+ +------------+ + * +- - - - -^- - - - - - - -^- -|- - - - + * nl_cache_update: | | | | + * 1) --------- co_request_update ------+ | | + * | | | + * 2) destroy old cache +----------- pp_cb ---------|---+ + * | | | + * 3) ---------- nl_recvmsgs ----------+ +- cb_valid -+ + * +--------------+ | | | | + * | nl_cache_add |<-----+ + - - -v- -|- - - - - - - - - - - + * +--------------+ | | +-------------+ + * | nl_recvmsgs | + * | | +-----|-^-----+ + * +---v-|---+ + * | | | nl_recv | + * +---------+ + * | | Core Netlink + * @endcode + * + * Related sections in the development guide: + * - @core_doc{core_cache, Caching System} + * + * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ + */ + +#include +#include +#include +#include +#include +#include + +/** + * @name Access Functions + * @{ + */ + +/** + * Return the number of items in the cache + * @arg cache cache handle + */ +int nl_cache_nitems(struct nl_cache *cache) +{ + return cache->c_nitems; +} + +/** + * Return the number of items matching a filter in the cache + * @arg cache Cache object. + * @arg filter Filter object. + */ +int nl_cache_nitems_filter(struct nl_cache *cache, struct nl_object *filter) +{ + struct nl_object *obj; + int nitems = 0; + + if (cache->c_ops == NULL) + BUG(); + + nl_list_for_each_entry(obj, &cache->c_items, ce_list) { + if (filter && !nl_object_match_filter(obj, filter)) + continue; + + nitems++; + } + + return nitems; +} + +/** + * Returns \b true if the cache is empty. + * @arg cache Cache to check + * @return \a true if the cache is empty, otherwise \b false is returned. + */ +int nl_cache_is_empty(struct nl_cache *cache) +{ + return nl_list_empty(&cache->c_items); +} + +/** + * Return the operations set of the cache + * @arg cache cache handle + */ +struct nl_cache_ops *nl_cache_get_ops(struct nl_cache *cache) +{ + return cache->c_ops; +} + +/** + * Return the first element in the cache + * @arg cache cache handle + */ +struct nl_object *nl_cache_get_first(struct nl_cache *cache) +{ + if (nl_list_empty(&cache->c_items)) + return NULL; + + return nl_list_entry(cache->c_items.next, + struct nl_object, ce_list); +} + +/** + * Return the last element in the cache + * @arg cache cache handle + */ +struct nl_object *nl_cache_get_last(struct nl_cache *cache) +{ + if (nl_list_empty(&cache->c_items)) + return NULL; + + return nl_list_entry(cache->c_items.prev, + struct nl_object, ce_list); +} + +/** + * Return the next element in the cache + * @arg obj current object + */ +struct nl_object *nl_cache_get_next(struct nl_object *obj) +{ + if (nl_list_at_tail(obj, &obj->ce_cache->c_items, ce_list)) + return NULL; + else + return nl_list_entry(obj->ce_list.next, + struct nl_object, ce_list); +} + +/** + * Return the previous element in the cache + * @arg obj current object + */ +struct nl_object *nl_cache_get_prev(struct nl_object *obj) +{ + if (nl_list_at_head(obj, &obj->ce_cache->c_items, ce_list)) + return NULL; + else + return nl_list_entry(obj->ce_list.prev, + struct nl_object, ce_list); +} + +/** @} */ + +/** + * @name Cache Allocation/Deletion + * @{ + */ + +/** + * Allocate new cache + * @arg ops Cache operations + * + * Allocate and initialize a new cache based on the cache operations + * provided. + * + * @return Allocated cache or NULL if allocation failed. + */ +struct nl_cache *nl_cache_alloc(struct nl_cache_ops *ops) +{ + struct nl_cache *cache; + + cache = calloc(1, sizeof(*cache)); + if (!cache) + return NULL; + + nl_init_list_head(&cache->c_items); + cache->c_ops = ops; + cache->c_flags |= ops->co_flags; + cache->c_refcnt = 1; + + /* + * If object type provides a hash keygen + * functions, allocate a hash table for the + * cache objects for faster lookups + */ + if (ops->co_obj_ops->oo_keygen) { + int hashtable_size; + + if (ops->co_hash_size) + hashtable_size = ops->co_hash_size; + else + hashtable_size = NL_MAX_HASH_ENTRIES; + + cache->hashtable = nl_hash_table_alloc(hashtable_size); + } + + NL_DBG(2, "Allocated cache %p <%s>.\n", cache, nl_cache_name(cache)); + + return cache; +} + +/** + * Allocate new cache and fill it + * @arg ops Cache operations + * @arg sock Netlink socket + * @arg result Result pointer + * + * Allocate new cache and fill it. Equivalent to calling: + * @code + * cache = nl_cache_alloc(ops); + * nl_cache_refill(sock, cache); + * @endcode + * + * @see nl_cache_alloc + * + * @return 0 on success or a negative error code. + */ +int nl_cache_alloc_and_fill(struct nl_cache_ops *ops, struct nl_sock *sock, + struct nl_cache **result) +{ + struct nl_cache *cache; + int err; + + if (!(cache = nl_cache_alloc(ops))) + return -NLE_NOMEM; + + if (sock && (err = nl_cache_refill(sock, cache)) < 0) { + nl_cache_free(cache); + return err; + } + + *result = cache; + return 0; +} + +/** + * Allocate new cache based on type name + * @arg kind Name of cache type + * @arg result Result pointer + * + * Lookup cache ops via nl_cache_ops_lookup() and allocate the cache + * by calling nl_cache_alloc(). Stores the allocated cache in the + * result pointer provided. + * + * @see nl_cache_alloc + * + * @return 0 on success or a negative error code. + */ +int nl_cache_alloc_name(const char *kind, struct nl_cache **result) +{ + struct nl_cache_ops *ops; + struct nl_cache *cache; + + ops = nl_cache_ops_lookup_safe(kind); + if (!ops) + return -NLE_NOCACHE; + + cache = nl_cache_alloc(ops); + nl_cache_ops_put(ops); + if (!cache) + return -NLE_NOMEM; + + *result = cache; + return 0; +} + +/** + * Allocate new cache containing a subset of an existing cache + * @arg orig Original cache to base new cache on + * @arg filter Filter defining the subset to be filled into the new cache + * + * Allocates a new cache matching the type of the cache specified by + * \p orig. Iterates over the \p orig cache applying the specified + * \p filter and copies all objects that match to the new cache. + * + * The copied objects are clones but do not contain a reference to each + * other. Later modifications to objects in the original cache will + * not affect objects in the new cache. + * + * @return A newly allocated cache or NULL. + */ +struct nl_cache *nl_cache_subset(struct nl_cache *orig, + struct nl_object *filter) +{ + struct nl_cache *cache; + struct nl_object *obj; + + if (!filter) + BUG(); + + cache = nl_cache_alloc(orig->c_ops); + if (!cache) + return NULL; + + NL_DBG(2, "Filling subset of cache %p <%s> with filter %p into %p\n", + orig, nl_cache_name(orig), filter, cache); + + nl_list_for_each_entry(obj, &orig->c_items, ce_list) { + if (!nl_object_match_filter(obj, filter)) + continue; + + nl_cache_add(cache, obj); + } + + return cache; +} + +/** + * Allocate new cache and copy the contents of an existing cache + * @arg cache Original cache to base new cache on + * + * Allocates a new cache matching the type of the cache specified by + * \p cache. Iterates over the \p cache cache and copies all objects + * to the new cache. + * + * The copied objects are clones but do not contain a reference to each + * other. Later modifications to objects in the original cache will + * not affect objects in the new cache. + * + * @return A newly allocated cache or NULL. + */ +struct nl_cache *nl_cache_clone(struct nl_cache *cache) +{ + struct nl_cache_ops *ops = nl_cache_get_ops(cache); + struct nl_cache *clone; + struct nl_object *obj; + + clone = nl_cache_alloc(ops); + if (!clone) + return NULL; + + NL_DBG(2, "Cloning %p into %p\n", cache, clone); + + nl_list_for_each_entry(obj, &cache->c_items, ce_list) + nl_cache_add(clone, obj); + + return clone; +} + +/** + * Remove all objects of a cache. + * @arg cache Cache to clear + * + * The objects are unliked/removed from the cache by calling + * nl_cache_remove() on each object in the cache. If any of the objects + * to not contain any further references to them, those objects will + * be freed. + * + * Unlike with nl_cache_free(), the cache is not freed just emptied. + */ +void nl_cache_clear(struct nl_cache *cache) +{ + struct nl_object *obj, *tmp; + + NL_DBG(2, "Clearing cache %p <%s>...\n", cache, nl_cache_name(cache)); + + nl_list_for_each_entry_safe(obj, tmp, &cache->c_items, ce_list) + nl_cache_remove(obj); +} + +static void __nl_cache_free(struct nl_cache *cache) +{ + nl_cache_clear(cache); + + if (cache->hashtable) + nl_hash_table_free(cache->hashtable); + + NL_DBG(2, "Freeing cache %p <%s>...\n", cache, nl_cache_name(cache)); + free(cache); +} + +/** + * Increase reference counter of cache + * @arg cache Cache + */ +void nl_cache_get(struct nl_cache *cache) +{ + cache->c_refcnt++; + + NL_DBG(3, "Incremented cache %p <%s> reference count to %d\n", + cache, nl_cache_name(cache), cache->c_refcnt); +} + +/** + * Free a cache. + * @arg cache Cache to free. + * + * Calls nl_cache_clear() to remove all objects associated with the + * cache and frees the cache afterwards. + * + * @see nl_cache_clear() + */ +void nl_cache_free(struct nl_cache *cache) +{ + if (!cache) + return; + + cache->c_refcnt--; + + NL_DBG(3, "Decremented cache %p <%s> reference count, %d remaining\n", + cache, nl_cache_name(cache), cache->c_refcnt); + + if (cache->c_refcnt <= 0) + __nl_cache_free(cache); +} + +void nl_cache_put(struct nl_cache *cache) +{ + return nl_cache_free(cache); +} + +/** @} */ + +/** + * @name Cache Modifications + * @{ + */ + +static int __cache_add(struct nl_cache *cache, struct nl_object *obj) +{ + int ret; + + obj->ce_cache = cache; + + if (cache->hashtable) { + ret = nl_hash_table_add(cache->hashtable, obj); + if (ret < 0) { + obj->ce_cache = NULL; + return ret; + } + } + + nl_list_add_tail(&obj->ce_list, &cache->c_items); + cache->c_nitems++; + + NL_DBG(3, "Added object %p to cache %p <%s>, nitems %d\n", + obj, cache, nl_cache_name(cache), cache->c_nitems); + + return 0; +} + +/** + * Add object to cache. + * @arg cache Cache + * @arg obj Object to be added to the cache + * + * Adds the object \p obj to the specified \p cache. In case the object + * is already associated with another cache, the object is cloned before + * adding it to the cache. In this case, the sole reference to the object + * will be the one of the cache. Therefore clearing/freeing the cache + * will result in the object being freed again. + * + * If the object has not been associated with a cache yet, the reference + * counter of the object is incremented to account for the additional + * reference. + * + * The type of the object and cache must match, otherwise an error is + * returned (-NLE_OBJ_MISMATCH). + * + * @see nl_cache_move() + * + * @return 0 or a negative error code. + */ +int nl_cache_add(struct nl_cache *cache, struct nl_object *obj) +{ + struct nl_object *new; + int ret = 0; + + if (cache->c_ops->co_obj_ops != obj->ce_ops) + return -NLE_OBJ_MISMATCH; + + if (!nl_list_empty(&obj->ce_list)) { + NL_DBG(3, "Object %p already in cache, cloning new object\n", obj); + + new = nl_object_clone(obj); + if (!new) + return -NLE_NOMEM; + } else { + nl_object_get(obj); + new = obj; + } + + ret = __cache_add(cache, new); + if (ret < 0) + nl_object_put(new); + + return ret; +} + +/** + * Move object from one cache to another + * @arg cache Cache to move object to. + * @arg obj Object subject to be moved + * + * Removes the the specified object \p obj from its associated cache + * and moves it to another cache. + * + * If the object is not associated with a cache, the function behaves + * just like nl_cache_add(). + * + * The type of the object and cache must match, otherwise an error is + * returned (-NLE_OBJ_MISMATCH). + * + * @see nl_cache_add() + * + * @return 0 on success or a negative error code. + */ +int nl_cache_move(struct nl_cache *cache, struct nl_object *obj) +{ + if (cache->c_ops->co_obj_ops != obj->ce_ops) + return -NLE_OBJ_MISMATCH; + + NL_DBG(3, "Moving object %p from cache %p to cache %p\n", + obj, obj->ce_cache, cache); + + /* Acquire reference, if already in a cache this will be + * reverted during removal */ + nl_object_get(obj); + + if (!nl_list_empty(&obj->ce_list)) + nl_cache_remove(obj); + + return __cache_add(cache, obj); +} + +/** + * Remove object from cache. + * @arg obj Object to remove from cache + * + * Removes the object \c obj from the cache it is associated with. The + * reference counter of the object will be decremented. If the reference + * to the object was the only one remaining, the object will be freed. + * + * If no cache is associated with the object, this function is a NOP. + */ +void nl_cache_remove(struct nl_object *obj) +{ + int ret; + struct nl_cache *cache = obj->ce_cache; + + if (cache == NULL) + return; + + if (cache->hashtable) { + ret = nl_hash_table_del(cache->hashtable, obj); + if (ret < 0) + NL_DBG(2, "Failed to delete %p from cache %p <%s>.\n", + obj, cache, nl_cache_name(cache)); + } + + nl_list_del(&obj->ce_list); + obj->ce_cache = NULL; + nl_object_put(obj); + cache->c_nitems--; + + NL_DBG(2, "Deleted object %p from cache %p <%s>.\n", + obj, cache, nl_cache_name(cache)); +} + +/** @} */ + +/** + * @name Synchronization + * @{ + */ + +/** + * Set synchronization arg1 of cache + * @arg cache Cache + * @arg arg argument + * + * Synchronization arguments are used to specify filters when + * requesting dumps from the kernel. + */ +void nl_cache_set_arg1(struct nl_cache *cache, int arg) +{ + cache->c_iarg1 = arg; +} + +/** + * Set synchronization arg2 of cache + * @arg cache Cache + * @arg arg argument + * + * Synchronization arguments are used to specify filters when + * requesting dumps from the kernel. + */ +void nl_cache_set_arg2(struct nl_cache *cache, int arg) +{ + cache->c_iarg2 = arg; +} + +/** + * Set cache flags + * @arg cache Cache + * @arg flags Flags + */ +void nl_cache_set_flags(struct nl_cache *cache, unsigned int flags) +{ + cache->c_flags |= flags; +} + +/** + * Invoke the request-update operation + * @arg sk Netlink socket. + * @arg cache Cache + * + * This function causes the \e request-update function of the cache + * operations to be invoked. This usually causes a dump request to + * be sent over the netlink socket which triggers the kernel to dump + * all objects of a specific type to be dumped onto the netlink + * socket for pickup. + * + * The behaviour of this function depends on the implemenation of + * the \e request_update function of each individual type of cache. + * + * This function will not have any effects on the cache (unless the + * request_update implementation of the cache operations does so). + * + * Use nl_cache_pickup() to pick-up (read) the objects from the socket + * and fill them into the cache. + * + * @see nl_cache_pickup(), nl_cache_resync() + * + * @return 0 on success or a negative error code. + */ +static int nl_cache_request_full_dump(struct nl_sock *sk, + struct nl_cache *cache) +{ + if (cache->c_ops->co_request_update == NULL) + return -NLE_OPNOTSUPP; + + NL_DBG(2, "Requesting update from kernel for cache %p <%s>\n", + cache, nl_cache_name(cache)); + + return cache->c_ops->co_request_update(cache, sk); +} + +/** @cond SKIP */ +struct update_xdata { + struct nl_cache_ops *ops; + struct nl_parser_param *params; +}; + +static int update_msg_parser(struct nl_msg *msg, void *arg) +{ + struct update_xdata *x = arg; + int ret = 0; + + ret = nl_cache_parse(x->ops, &msg->nm_src, msg->nm_nlh, x->params); + if (ret == -NLE_EXIST) + return NL_SKIP; + else + return ret; +} +/** @endcond */ + +/** + * Pick-up a netlink request-update with your own parser + * @arg sk Netlink socket + * @arg cache Cache + * @arg param Parser parameters + */ +static int __cache_pickup(struct nl_sock *sk, struct nl_cache *cache, + struct nl_parser_param *param) +{ + int err; + struct nl_cb *cb; + struct update_xdata x = { + .ops = cache->c_ops, + .params = param, + }; + + NL_DBG(2, "Picking up answer for cache %p <%s>\n", + cache, nl_cache_name(cache)); + + cb = nl_cb_clone(sk->s_cb); + if (cb == NULL) + return -NLE_NOMEM; + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, update_msg_parser, &x); + + err = nl_recvmsgs(sk, cb); + if (err < 0) + NL_DBG(2, "While picking up for %p <%s>, recvmsgs() returned %d: %s\n", + cache, nl_cache_name(cache), err, nl_geterror(err)); + + nl_cb_put(cb); + + return err; +} + +static int pickup_cb(struct nl_object *c, struct nl_parser_param *p) +{ + struct nl_cache *cache = (struct nl_cache *)p->pp_arg; + struct nl_object *old; + + old = nl_cache_search(cache, c); + if (old) { + if (nl_object_update(old, c) == 0) { + nl_object_put(old); + return 0; + } + + nl_cache_remove(old); + nl_object_put(old); + } + + return nl_cache_add(cache, c); +} + +/** + * Pickup a netlink dump response and put it into a cache. + * @arg sk Netlink socket. + * @arg cache Cache to put items into. + * + * Waits for netlink messages to arrive, parses them and puts them into + * the specified cache. If an old object with same key attributes is + * present in the cache, it is replaced with the new object. + * If the old object type supports an update operation, an update is + * attempted before a replace. + * + * @return 0 on success or a negative error code. + */ +int nl_cache_pickup(struct nl_sock *sk, struct nl_cache *cache) +{ + struct nl_parser_param p = { + .pp_cb = pickup_cb, + .pp_arg = cache, + }; + + return __cache_pickup(sk, cache, &p); +} + +static int cache_include(struct nl_cache *cache, struct nl_object *obj, + struct nl_msgtype *type, change_func_t cb, void *data) +{ + struct nl_object *old; + + switch (type->mt_act) { + case NL_ACT_NEW: + case NL_ACT_DEL: + old = nl_cache_search(cache, obj); + if (old) { + /* + * Some objects types might support merging the new + * object with the old existing cache object. + * Handle them first. + */ + if (nl_object_update(old, obj) == 0) { + if (cb) + cb(cache, old, NL_ACT_CHANGE, data); + nl_object_put(old); + return 0; + } + + nl_cache_remove(old); + if (type->mt_act == NL_ACT_DEL) { + if (cb) + cb(cache, old, NL_ACT_DEL, data); + nl_object_put(old); + } + } + + if (type->mt_act == NL_ACT_NEW) { + nl_cache_move(cache, obj); + if (old == NULL && cb) + cb(cache, obj, NL_ACT_NEW, data); + else if (old) { + if (nl_object_diff(old, obj) && cb) + cb(cache, obj, NL_ACT_CHANGE, data); + + nl_object_put(old); + } + } + break; + default: + NL_DBG(2, "Unknown action associated to object %p\n", obj); + return 0; + } + + return 0; +} + +int nl_cache_include(struct nl_cache *cache, struct nl_object *obj, + change_func_t change_cb, void *data) +{ + struct nl_cache_ops *ops = cache->c_ops; + int i; + + if (ops->co_obj_ops != obj->ce_ops) + return -NLE_OBJ_MISMATCH; + + for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) + if (ops->co_msgtypes[i].mt_id == obj->ce_msgtype) + return cache_include(cache, obj, &ops->co_msgtypes[i], + change_cb, data); + + NL_DBG(3, "Object %p does not seem to belong to cache %p <%s>\n", + obj, cache, nl_cache_name(cache)); + + return -NLE_MSGTYPE_NOSUPPORT; +} + +static int resync_cb(struct nl_object *c, struct nl_parser_param *p) +{ + struct nl_cache_assoc *ca = p->pp_arg; + + return nl_cache_include(ca->ca_cache, c, ca->ca_change, ca->ca_change_data); +} + +int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache, + change_func_t change_cb, void *data) +{ + struct nl_object *obj, *next; + struct nl_af_group *grp; + struct nl_cache_assoc ca = { + .ca_cache = cache, + .ca_change = change_cb, + .ca_change_data = data, + }; + struct nl_parser_param p = { + .pp_cb = resync_cb, + .pp_arg = &ca, + }; + int err; + + NL_DBG(1, "Resyncing cache %p <%s>...\n", cache, nl_cache_name(cache)); + + /* Mark all objects so we can see if some of them are obsolete */ + nl_cache_mark_all(cache); + + grp = cache->c_ops->co_groups; + do { + if (grp && grp->ag_group && + (cache->c_flags & NL_CACHE_AF_ITER)) + nl_cache_set_arg1(cache, grp->ag_family); + +restart: + err = nl_cache_request_full_dump(sk, cache); + if (err < 0) + goto errout; + + err = __cache_pickup(sk, cache, &p); + if (err == -NLE_DUMP_INTR) + goto restart; + else if (err < 0) + goto errout; + + if (grp) + grp++; + } while (grp && grp->ag_group && + (cache->c_flags & NL_CACHE_AF_ITER)); + + nl_list_for_each_entry_safe(obj, next, &cache->c_items, ce_list) { + if (nl_object_is_marked(obj)) { + nl_object_get(obj); + nl_cache_remove(obj); + if (change_cb) + change_cb(cache, obj, NL_ACT_DEL, data); + nl_object_put(obj); + } + } + + NL_DBG(1, "Finished resyncing %p <%s>\n", cache, nl_cache_name(cache)); + + err = 0; +errout: + return err; +} + +/** @} */ + +/** + * @name Parsing + * @{ + */ + +/** @cond SKIP */ +int nl_cache_parse(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *nlh, struct nl_parser_param *params) +{ + int i, err; + + if (!nlmsg_valid_hdr(nlh, ops->co_hdrsize)) + return -NLE_MSG_TOOSHORT; + + for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) { + if (ops->co_msgtypes[i].mt_id == nlh->nlmsg_type) { + err = ops->co_msg_parser(ops, who, nlh, params); + if (err != -NLE_OPNOTSUPP) + goto errout; + } + } + + + err = -NLE_MSGTYPE_NOSUPPORT; +errout: + return err; +} +/** @endcond */ + +/** + * Parse a netlink message and add it to the cache. + * @arg cache cache to add element to + * @arg msg netlink message + * + * Parses a netlink message by calling the cache specific message parser + * and adds the new element to the cache. If an old object with same key + * attributes is present in the cache, it is replaced with the new object. + * If the old object type supports an update operation, an update is + * attempted before a replace. + * + * @return 0 or a negative error code. + */ +int nl_cache_parse_and_add(struct nl_cache *cache, struct nl_msg *msg) +{ + struct nl_parser_param p = { + .pp_cb = pickup_cb, + .pp_arg = cache, + }; + + return nl_cache_parse(cache->c_ops, NULL, nlmsg_hdr(msg), &p); +} + +/** + * (Re)fill a cache with the contents in the kernel. + * @arg sk Netlink socket. + * @arg cache cache to update + * + * Clears the specified cache and fills it with the current state in + * the kernel. + * + * @return 0 or a negative error code. + */ +int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache) +{ + struct nl_af_group *grp; + int err; + + nl_cache_clear(cache); + grp = cache->c_ops->co_groups; + do { + if (grp && grp->ag_group && + (cache->c_flags & NL_CACHE_AF_ITER)) + nl_cache_set_arg1(cache, grp->ag_family); + +restart: + err = nl_cache_request_full_dump(sk, cache); + if (err < 0) + return err; + + NL_DBG(2, "Updating cache %p <%s> for family %u, request sent, waiting for reply\n", + cache, nl_cache_name(cache), grp ? grp->ag_family : AF_UNSPEC); + + err = nl_cache_pickup(sk, cache); + if (err == -NLE_DUMP_INTR) { + NL_DBG(2, "Dump interrupted, restarting!\n"); + goto restart; + } else if (err < 0) + break; + + if (grp) + grp++; + } while (grp && grp->ag_group && + (cache->c_flags & NL_CACHE_AF_ITER)); + + return err; +} + +/** @} */ + +/** + * @name Utillities + * @{ + */ +static struct nl_object *__cache_fast_lookup(struct nl_cache *cache, + struct nl_object *needle) +{ + struct nl_object *obj; + + obj = nl_hash_table_lookup(cache->hashtable, needle); + if (obj) { + nl_object_get(obj); + return obj; + } + + return NULL; +} + +/** + * Search object in cache + * @arg cache Cache + * @arg needle Object to look for. + * + * Searches the cache for an object which matches the object \p needle. + * The function nl_object_identical() is used to determine if the + * objects match. If a matching object is found, the reference counter + * is incremented and the object is returned. + * + * Therefore, if an object is returned, the reference to the object + * must be returned by calling nl_object_put() after usage. + * + * @return Reference to object or NULL if not found. + */ +struct nl_object *nl_cache_search(struct nl_cache *cache, + struct nl_object *needle) +{ + struct nl_object *obj; + + if (cache->hashtable) + return __cache_fast_lookup(cache, needle); + + nl_list_for_each_entry(obj, &cache->c_items, ce_list) { + if (nl_object_identical(obj, needle)) { + nl_object_get(obj); + return obj; + } + } + + return NULL; +} + +/** + * Find object in cache + * @arg cache Cache + * @arg filter object acting as a filter + * + * Searches the cache for an object which matches the object filter. + * If the filter attributes matches the object type id attributes, + * and the cache supports hash lookups, a faster hashtable lookup + * is used to return the object. Else, function nl_object_match_filter() is + * used to determine if the objects match. If a matching object is + * found, the reference counter is incremented and the object is returned. + * + * Therefore, if an object is returned, the reference to the object + * must be returned by calling nl_object_put() after usage. + * + * @return Reference to object or NULL if not found. + */ +struct nl_object *nl_cache_find(struct nl_cache *cache, + struct nl_object *filter) +{ + struct nl_object *obj; + + if (cache->c_ops == NULL) + BUG(); + + if ((nl_object_get_id_attrs(filter) == filter->ce_mask) + && cache->hashtable) + return __cache_fast_lookup(cache, filter); + + nl_list_for_each_entry(obj, &cache->c_items, ce_list) { + if (nl_object_match_filter(obj, filter)) { + nl_object_get(obj); + return obj; + } + } + + return NULL; +} + +/** + * Mark all objects of a cache + * @arg cache Cache + * + * Marks all objects of a cache by calling nl_object_mark() on each + * object associated with the cache. + */ +void nl_cache_mark_all(struct nl_cache *cache) +{ + struct nl_object *obj; + + NL_DBG(2, "Marking all objects in cache %p <%s>\n", + cache, nl_cache_name(cache)); + + nl_list_for_each_entry(obj, &cache->c_items, ce_list) + nl_object_mark(obj); +} + +/** @} */ + +/** + * @name Dumping + * @{ + */ + +/** + * Dump all elements of a cache. + * @arg cache cache to dump + * @arg params dumping parameters + * + * Dumps all elements of the \a cache to the file descriptor \a fd. + */ +void nl_cache_dump(struct nl_cache *cache, struct nl_dump_params *params) +{ + nl_cache_dump_filter(cache, params, NULL); +} + +/** + * Dump all elements of a cache (filtered). + * @arg cache cache to dump + * @arg params dumping parameters (optional) + * @arg filter filter object + * + * Dumps all elements of the \a cache to the file descriptor \a fd + * given they match the given filter \a filter. + */ +void nl_cache_dump_filter(struct nl_cache *cache, + struct nl_dump_params *params, + struct nl_object *filter) +{ + int type = params ? params->dp_type : NL_DUMP_DETAILS; + struct nl_object_ops *ops; + struct nl_object *obj; + + NL_DBG(2, "Dumping cache %p <%s> with filter %p\n", + cache, nl_cache_name(cache), filter); + + if (type > NL_DUMP_MAX || type < 0) + BUG(); + + if (cache->c_ops == NULL) + BUG(); + + ops = cache->c_ops->co_obj_ops; + if (!ops->oo_dump[type]) + return; + + if (params->dp_buf) + memset(params->dp_buf, 0, params->dp_buflen); + + nl_list_for_each_entry(obj, &cache->c_items, ce_list) { + if (filter && !nl_object_match_filter(obj, filter)) + continue; + + NL_DBG(4, "Dumping object %p...\n", obj); + dump_from_ops(obj, params); + } +} + +/** @} */ + +/** + * @name Iterators + * @{ + */ + +/** + * Call a callback on each element of the cache. + * @arg cache cache to iterate on + * @arg cb callback function + * @arg arg argument passed to callback function + * + * Calls a callback function \a cb on each element of the \a cache. + * The argument \a arg is passed on the callback function. + */ +void nl_cache_foreach(struct nl_cache *cache, + void (*cb)(struct nl_object *, void *), void *arg) +{ + nl_cache_foreach_filter(cache, NULL, cb, arg); +} + +/** + * Call a callback on each element of the cache (filtered). + * @arg cache cache to iterate on + * @arg filter filter object + * @arg cb callback function + * @arg arg argument passed to callback function + * + * Calls a callback function \a cb on each element of the \a cache + * that matches the \a filter. The argument \a arg is passed on + * to the callback function. + */ +void nl_cache_foreach_filter(struct nl_cache *cache, struct nl_object *filter, + void (*cb)(struct nl_object *, void *), void *arg) +{ + struct nl_object *obj, *tmp; + + if (cache->c_ops == NULL) + BUG(); + + nl_list_for_each_entry_safe(obj, tmp, &cache->c_items, ce_list) { + if (filter) { + int diff = nl_object_match_filter(obj, filter); + + NL_DBG(3, "%p<->%p object difference: %x\n", + obj, filter, diff); + + if (!diff) + continue; + } + + /* Caller may hold obj for a long time */ + nl_object_get(obj); + + cb(obj, arg); + + nl_object_put(obj); + } +} + +/** @} */ + +/** @} */ diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c new file mode 100644 index 0000000..f8a65e3 --- /dev/null +++ b/lib/cache_mngr.c @@ -0,0 +1,523 @@ +/* + * lib/cache_mngr.c Cache Manager + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +/** + * @ingroup cache_mngt + * @defgroup cache_mngr Manager + * @brief Manager keeping caches up to date automatically. + * + * The cache manager keeps caches up to date automatically by listening to + * netlink notifications and integrating the received information into the + * existing cache. + * + * @note This functionality is still considered experimental. + * + * Related sections in the development guide: + * - @core_doc{_cache_manager,Cache Manager} + * + * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ + */ + +#include +#include +#include +#include + +/** @cond SKIP */ +#define NASSOC_INIT 16 +#define NASSOC_EXPAND 8 +/** @endcond */ + +static int include_cb(struct nl_object *obj, struct nl_parser_param *p) +{ + struct nl_cache_assoc *ca = p->pp_arg; + struct nl_cache_ops *ops = ca->ca_cache->c_ops; + + NL_DBG(2, "Including object %p into cache %p\n", obj, ca->ca_cache); +#ifdef NL_DEBUG + if (nl_debug >= 4) + nl_object_dump(obj, &nl_debug_dp); +#endif + + if (ops->co_event_filter) + if (ops->co_event_filter(ca->ca_cache, obj) != NL_OK) + return 0; + + if (ops->co_include_event) + return ops->co_include_event(ca->ca_cache, obj, ca->ca_change, + ca->ca_change_data); + else + return nl_cache_include(ca->ca_cache, obj, ca->ca_change, ca->ca_change_data); +} + +static int event_input(struct nl_msg *msg, void *arg) +{ + struct nl_cache_mngr *mngr = arg; + int protocol = nlmsg_get_proto(msg); + int type = nlmsg_hdr(msg)->nlmsg_type; + struct nl_cache_ops *ops; + int i, n; + struct nl_parser_param p = { + .pp_cb = include_cb, + }; + + NL_DBG(2, "Cache manager %p, handling new message %p as event\n", + mngr, msg); +#ifdef NL_DEBUG + if (nl_debug >= 4) + nl_msg_dump(msg, stderr); +#endif + + if (mngr->cm_protocol != protocol) + BUG(); + + for (i = 0; i < mngr->cm_nassocs; i++) { + if (mngr->cm_assocs[i].ca_cache) { + ops = mngr->cm_assocs[i].ca_cache->c_ops; + for (n = 0; ops->co_msgtypes[n].mt_id >= 0; n++) + if (ops->co_msgtypes[n].mt_id == type) + goto found; + } + } + + return NL_SKIP; + +found: + NL_DBG(2, "Associated message %p to cache %p\n", + msg, mngr->cm_assocs[i].ca_cache); + p.pp_arg = &mngr->cm_assocs[i]; + + return nl_cache_parse(ops, NULL, nlmsg_hdr(msg), &p); +} + +/** + * Allocate new cache manager + * @arg sk Netlink socket or NULL to auto allocate + * @arg protocol Netlink protocol this manager is used for + * @arg flags Flags (\c NL_AUTO_PROVIDE) + * @arg result Result pointer + * + * Allocates a new cache manager for the specified netlink protocol. + * + * 1. If sk is not specified (\c NULL) a netlink socket matching the + * specified protocol will be automatically allocated. + * + * 2. The socket will be put in non-blocking mode and sequence checking + * will be disabled regardless of whether the socket was provided by + * the caller or automatically allocated. + * + * 3. The socket will be connected. + * + * If the flag \c NL_AUTO_PROVIDE is specified, any cache added to the + * manager will automatically be made available to other users using + * nl_cache_mngt_provide(). + * + * @note If the socket is provided by the caller, it is NOT recommended + * to use the socket for anything else besides receiving netlink + * notifications. + * + * @return 0 on success or a negative error code. + */ +int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags, + struct nl_cache_mngr **result) +{ + struct nl_cache_mngr *mngr; + int err = -NLE_NOMEM; + + /* Catch abuse of flags */ + if (flags & NL_ALLOCATED_SOCK) + BUG(); + + mngr = calloc(1, sizeof(*mngr)); + if (!mngr) + return -NLE_NOMEM; + + if (!sk) { + if (!(sk = nl_socket_alloc())) + goto errout; + + flags |= NL_ALLOCATED_SOCK; + } + + mngr->cm_sock = sk; + mngr->cm_nassocs = NASSOC_INIT; + mngr->cm_protocol = protocol; + mngr->cm_flags = flags; + mngr->cm_assocs = calloc(mngr->cm_nassocs, + sizeof(struct nl_cache_assoc)); + if (!mngr->cm_assocs) + goto errout; + + /* Required to receive async event notifications */ + nl_socket_disable_seq_check(mngr->cm_sock); + + if ((err = nl_connect(mngr->cm_sock, protocol) < 0)) + goto errout; + + if ((err = nl_socket_set_nonblocking(mngr->cm_sock) < 0)) + goto errout; + + /* Create and allocate socket for sync cache fills */ + mngr->cm_sync_sock = nl_socket_alloc(); + if (!mngr->cm_sync_sock) + goto errout; + if ((err = nl_connect(mngr->cm_sync_sock, protocol)) < 0) + goto errout_free_sync_sock; + + NL_DBG(1, "Allocated cache manager %p, protocol %d, %d caches\n", + mngr, protocol, mngr->cm_nassocs); + + *result = mngr; + return 0; + +errout_free_sync_sock: + nl_socket_free(mngr->cm_sync_sock); +errout: + nl_cache_mngr_free(mngr); + return err; +} + +/** + * Add cache to cache manager + * @arg mngr Cache manager. + * @arg cache Cache to be added to cache manager + * @arg cb Function to be called upon changes. + * @arg data Argument passed on to change callback + * + * Adds cache to the manager. The operation will trigger a full + * dump request from the kernel to initially fill the contents + * of the cache. The manager will subscribe to the notification group + * of the cache and keep track of any further changes. + * + * The user is responsible for calling nl_cache_mngr_poll() or monitor + * the socket and call nl_cache_mngr_data_ready() to allow the library + * to process netlink notification events. + * + * @see nl_cache_mngr_poll() + * @see nl_cache_mngr_data_ready() + * + * @return 0 on success or a negative error code. + * @return -NLE_PROTO_MISMATCH Protocol mismatch between cache manager and + * cache type + * @return -NLE_OPNOTSUPP Cache type does not support updates + * @return -NLE_EXIST Cache of this type already being managed + */ +int nl_cache_mngr_add_cache(struct nl_cache_mngr *mngr, struct nl_cache *cache, + change_func_t cb, void *data) +{ + struct nl_cache_ops *ops; + struct nl_af_group *grp; + int err, i; + + ops = cache->c_ops; + if (!ops) + return -NLE_INVAL; + + if (ops->co_protocol != mngr->cm_protocol) + return -NLE_PROTO_MISMATCH; + + if (ops->co_groups == NULL) + return -NLE_OPNOTSUPP; + + for (i = 0; i < mngr->cm_nassocs; i++) + if (mngr->cm_assocs[i].ca_cache && + mngr->cm_assocs[i].ca_cache->c_ops == ops) + return -NLE_EXIST; + +retry: + for (i = 0; i < mngr->cm_nassocs; i++) + if (!mngr->cm_assocs[i].ca_cache) + break; + + if (i >= mngr->cm_nassocs) { + mngr->cm_nassocs += NASSOC_EXPAND; + mngr->cm_assocs = realloc(mngr->cm_assocs, + mngr->cm_nassocs * + sizeof(struct nl_cache_assoc)); + if (mngr->cm_assocs == NULL) + return -NLE_NOMEM; + + memset(mngr->cm_assocs + (mngr->cm_nassocs - NASSOC_EXPAND), 0, + NASSOC_EXPAND * sizeof(struct nl_cache_assoc)); + + NL_DBG(1, "Increased capacity of cache manager %p " \ + "to %d\n", mngr, mngr->cm_nassocs); + goto retry; + } + + for (grp = ops->co_groups; grp->ag_group; grp++) { + err = nl_socket_add_membership(mngr->cm_sock, grp->ag_group); + if (err < 0) + return err; + } + + err = nl_cache_refill(mngr->cm_sync_sock, cache); + if (err < 0) + goto errout_drop_membership; + + mngr->cm_assocs[i].ca_cache = cache; + mngr->cm_assocs[i].ca_change = cb; + mngr->cm_assocs[i].ca_change_data = data; + + if (mngr->cm_flags & NL_AUTO_PROVIDE) + nl_cache_mngt_provide(cache); + + NL_DBG(1, "Added cache %p <%s> to cache manager %p\n", + cache, nl_cache_name(cache), mngr); + + return 0; + +errout_drop_membership: + for (grp = ops->co_groups; grp->ag_group; grp++) + nl_socket_drop_membership(mngr->cm_sock, grp->ag_group); + + return err; +} + +/** + * Add cache to cache manager + * @arg mngr Cache manager. + * @arg name Name of cache to keep track of + * @arg cb Function to be called upon changes. + * @arg data Argument passed on to change callback + * @arg result Pointer to store added cache (optional) + * + * Allocates a new cache of the specified type and adds it to the manager. + * The operation will trigger a full dump request from the kernel to + * initially fill the contents of the cache. The manager will subscribe + * to the notification group of the cache and keep track of any further + * changes. + * + * The user is responsible for calling nl_cache_mngr_poll() or monitor + * the socket and call nl_cache_mngr_data_ready() to allow the library + * to process netlink notification events. + * + * @see nl_cache_mngr_poll() + * @see nl_cache_mngr_data_ready() + * + * @return 0 on success or a negative error code. + * @return -NLE_NOCACHE Unknown cache type + * @return -NLE_PROTO_MISMATCH Protocol mismatch between cache manager and + * cache type + * @return -NLE_OPNOTSUPP Cache type does not support updates + * @return -NLE_EXIST Cache of this type already being managed + */ +int nl_cache_mngr_add(struct nl_cache_mngr *mngr, const char *name, + change_func_t cb, void *data, struct nl_cache **result) +{ + struct nl_cache_ops *ops; + struct nl_cache *cache; + int err; + + ops = nl_cache_ops_lookup_safe(name); + if (!ops) + return -NLE_NOCACHE; + + cache = nl_cache_alloc(ops); + nl_cache_ops_put(ops); + if (!cache) + return -NLE_NOMEM; + + err = nl_cache_mngr_add_cache(mngr, cache, cb, data); + if (err < 0) + goto errout_free_cache; + + *result = cache; + return 0; + +errout_free_cache: + nl_cache_free(cache); + + return err; +} + +/** + * Get socket file descriptor + * @arg mngr Cache Manager + * + * Get the file descriptor of the socket associated with the manager. + * + * @note Do not use the socket for anything besides receiving + * notifications. + */ +int nl_cache_mngr_get_fd(struct nl_cache_mngr *mngr) +{ + return nl_socket_get_fd(mngr->cm_sock); +} + +/** + * Check for event notifications + * @arg mngr Cache Manager + * @arg timeout Upper limit poll() will block, in milliseconds. + * + * Causes poll() to be called to check for new event notifications + * being available. Calls nl_cache_mngr_data_ready() to process + * available data. + * + * This functionally is ideally called regularly during an idle + * period. + * + * A timeout can be specified in milliseconds to limit the time the + * function will wait for updates. + * + * @see nl_cache_mngr_data_ready() + * + * @return The number of messages processed or a negative error code. + */ +int nl_cache_mngr_poll(struct nl_cache_mngr *mngr, int timeout) +{ + int ret; + struct pollfd fds = { + .fd = nl_socket_get_fd(mngr->cm_sock), + .events = POLLIN, + }; + + NL_DBG(3, "Cache manager %p, poll() fd %d\n", mngr, fds.fd); + ret = poll(&fds, 1, timeout); + NL_DBG(3, "Cache manager %p, poll() returned %d\n", mngr, ret); + if (ret < 0) + return -nl_syserr2nlerr(errno); + + /* No events, return */ + if (ret == 0) + return 0; + + return nl_cache_mngr_data_ready(mngr); +} + +/** + * Receive available event notifications + * @arg mngr Cache manager + * + * This function can be called if the socket associated to the manager + * contains updates to be received. This function should only be used + * if nl_cache_mngr_poll() is not used. + * + * The function will process messages until there is no more data to + * be read from the socket. + * + * @see nl_cache_mngr_poll() + * + * @return The number of messages processed or a negative error code. + */ +int nl_cache_mngr_data_ready(struct nl_cache_mngr *mngr) +{ + int err, nread = 0; + struct nl_cb *cb; + + NL_DBG(2, "Cache manager %p, reading new data from fd %d\n", + mngr, nl_socket_get_fd(mngr->cm_sock)); + + cb = nl_cb_clone(mngr->cm_sock->s_cb); + if (cb == NULL) + return -NLE_NOMEM; + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, event_input, mngr); + + while ((err = nl_recvmsgs_report(mngr->cm_sock, cb)) > 0) { + NL_DBG(2, "Cache manager %p, recvmsgs read %d messages\n", + mngr, err); + nread += err; + } + + nl_cb_put(cb); + if (err < 0) + return err; + + return nread; +} + +/** + * Print information about cache manager + * @arg mngr Cache manager + * @arg p Dumping parameters + * + * Prints information about the cache manager including all managed caches. + * + * @note This is a debugging function. + */ +void nl_cache_mngr_info(struct nl_cache_mngr *mngr, struct nl_dump_params *p) +{ + char buf[128]; + int i; + + nl_dump_line(p, "cache-manager <%p>\n", mngr); + nl_dump_line(p, " .protocol = %s\n", + nl_nlfamily2str(mngr->cm_protocol, buf, sizeof(buf))); + nl_dump_line(p, " .flags = %#x\n", mngr->cm_flags); + nl_dump_line(p, " .nassocs = %u\n", mngr->cm_nassocs); + nl_dump_line(p, " .sock = <%p>\n", mngr->cm_sock); + + for (i = 0; i < mngr->cm_nassocs; i++) { + struct nl_cache_assoc *assoc = &mngr->cm_assocs[i]; + + if (assoc->ca_cache) { + nl_dump_line(p, " .cache[%d] = <%p> {\n", i, assoc->ca_cache); + nl_dump_line(p, " .name = %s\n", assoc->ca_cache->c_ops->co_name); + nl_dump_line(p, " .change_func = <%p>\n", assoc->ca_change); + nl_dump_line(p, " .change_data = <%p>\n", assoc->ca_change_data); + nl_dump_line(p, " .nitems = %u\n", nl_cache_nitems(assoc->ca_cache)); + nl_dump_line(p, " .objects = {\n"); + + p->dp_prefix += 6; + nl_cache_dump(assoc->ca_cache, p); + p->dp_prefix -= 6; + + nl_dump_line(p, " }\n"); + nl_dump_line(p, " }\n"); + } + } +} + +/** + * Free cache manager and all caches. + * @arg mngr Cache manager. + * + * Release all resources held by a cache manager. + */ +void nl_cache_mngr_free(struct nl_cache_mngr *mngr) +{ + int i; + + if (!mngr) + return; + + if (mngr->cm_sock) + nl_close(mngr->cm_sock); + + if (mngr->cm_sync_sock) { + nl_close(mngr->cm_sync_sock); + nl_socket_free(mngr->cm_sync_sock); + } + + if (mngr->cm_flags & NL_ALLOCATED_SOCK) + nl_socket_free(mngr->cm_sock); + + for (i = 0; i < mngr->cm_nassocs; i++) { + if (mngr->cm_assocs[i].ca_cache) { + nl_cache_mngt_unprovide(mngr->cm_assocs[i].ca_cache); + nl_cache_free(mngr->cm_assocs[i].ca_cache); + } + } + + free(mngr->cm_assocs); + free(mngr); + + NL_DBG(1, "Cache manager %p freed\n", mngr); +} + +/** @} */ diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c new file mode 100644 index 0000000..4d3d6ff --- /dev/null +++ b/lib/cache_mngt.c @@ -0,0 +1,439 @@ +/* + * lib/cache_mngt.c Cache Management + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +/** + * @ingroup core + * @defgroup cache_mngt Caching System + * + * Related sections in the development guide: + * - @core_doc{core_cache, Caching System} + * + * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ + */ + +#include +#include +#include +#include + +static struct nl_cache_ops *cache_ops; +static NL_RW_LOCK(cache_ops_lock); + +/** + * @name Cache Operations Sets + * @{ + */ + +struct nl_cache_ops *__nl_cache_ops_lookup(const char *name) +{ + struct nl_cache_ops *ops; + + for (ops = cache_ops; ops; ops = ops->co_next) + if (!strcmp(ops->co_name, name)) + return ops; + + return NULL; +} + +/** + * Increment reference counter + * @arg ops Cache operations + */ +void nl_cache_ops_get(struct nl_cache_ops *ops) +{ + ops->co_refcnt++; +} + +/** + * Decrement reference counter + * @arg ops Cache operations + */ +void nl_cache_ops_put(struct nl_cache_ops *ops) +{ + ops->co_refcnt--; +} + +/** + * Lookup cache operations by name + * @arg name name of the cache type + * + * @attention This function is not safe, it does not increment the reference + * counter. Please use nl_cache_ops_lookup_safe(). + * + * @return The cache operations or NULL if not found. + */ +struct nl_cache_ops *nl_cache_ops_lookup(const char *name) +{ + struct nl_cache_ops *ops; + + nl_read_lock(&cache_ops_lock); + ops = __nl_cache_ops_lookup(name); + nl_read_unlock(&cache_ops_lock); + + return ops; +} + +/** + * Lookup cache operations by name + * @arg name name of the cache type + * + * @note The reference counter of the returned cache operation is incremented + * and must be decremented after use with nl_cache_ops_put(). + * + * @return The cache operations or NULL if not found. + */ +struct nl_cache_ops *nl_cache_ops_lookup_safe(const char *name) +{ + struct nl_cache_ops *ops; + + nl_write_lock(&cache_ops_lock); + if ((ops = __nl_cache_ops_lookup(name))) + nl_cache_ops_get(ops); + nl_write_unlock(&cache_ops_lock); + + return ops; +} + +static struct nl_cache_ops *__cache_ops_associate(int protocol, int msgtype) +{ + int i; + struct nl_cache_ops *ops; + + for (ops = cache_ops; ops; ops = ops->co_next) { + if (ops->co_protocol != protocol) + continue; + + for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) + if (ops->co_msgtypes[i].mt_id == msgtype) + return ops; + } + + return NULL; +} + +/** + * Associate protocol and message type to cache operations + * @arg protocol netlink protocol + * @arg msgtype netlink message type + * + * @attention This function is not safe, it does not increment the reference + * counter. Please use nl_cache_ops_associate_safe(). + * + * @see nl_cache_ops_associate_safe() + * + * @return The cache operations or NULL if no match found. + */ +struct nl_cache_ops *nl_cache_ops_associate(int protocol, int msgtype) +{ + struct nl_cache_ops *ops; + + nl_read_lock(&cache_ops_lock); + ops = __cache_ops_associate(protocol, msgtype); + nl_read_unlock(&cache_ops_lock); + + return ops; +} + +/** + * Associate protocol and message type to cache operations + * @arg protocol netlink protocol + * @arg msgtype netlink message type + * + * Searches the registered cache operations for a matching protocol + * and message type. + * + * @note The reference counter of the returned cache operation is incremented + * and must be decremented after use with nl_cache_ops_put(). + * + * @return The cache operations or NULL if no no match was found. + */ +struct nl_cache_ops *nl_cache_ops_associate_safe(int protocol, int msgtype) +{ + struct nl_cache_ops *ops; + + nl_write_lock(&cache_ops_lock); + if ((ops = __cache_ops_associate(protocol, msgtype))) + nl_cache_ops_get(ops); + nl_write_unlock(&cache_ops_lock); + + return ops; +} + +/** + * Lookup message type cache association + * @arg ops cache operations + * @arg msgtype netlink message type + * + * Searches for a matching message type association ing the specified + * cache operations. + * + * @attention The guranteed lifetime of the returned message type is bound + * to the lifetime of the underlying cache operations. + * + * @return A message type association or NULL. + */ +struct nl_msgtype *nl_msgtype_lookup(struct nl_cache_ops *ops, int msgtype) +{ + int i; + + for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) + if (ops->co_msgtypes[i].mt_id == msgtype) + return &ops->co_msgtypes[i]; + + return NULL; +} + +/* Must hold cache_ops_lock */ +static struct nl_cache_ops *cache_ops_lookup_for_obj(struct nl_object_ops *obj_ops) +{ + struct nl_cache_ops *ops; + + for (ops = cache_ops; ops; ops = ops->co_next) + if (ops->co_obj_ops == obj_ops) + return ops; + + return NULL; + +} + +/** + * Call a function for each registered cache operation + * @arg cb Callback function to be called + * @arg arg User specific argument. + */ +void nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *arg) +{ + struct nl_cache_ops *ops; + + nl_read_lock(&cache_ops_lock); + for (ops = cache_ops; ops; ops = ops->co_next) + cb(ops, arg); + nl_read_unlock(&cache_ops_lock); +} + +/** + * Set default flags for caches of this type + * @arg ops Cache ops + * @arg flags Flags to set + * + * The cache operation flags will be derived to all caches allocates + * based on this set of cache operations. + */ +void nl_cache_ops_set_flags(struct nl_cache_ops *ops, unsigned int flags) +{ + nl_write_lock(&cache_ops_lock); + ops->co_flags |= flags; + nl_write_unlock(&cache_ops_lock); +} + +/** + * Register a set of cache operations + * @arg ops cache operations + * + * Called by users of caches to announce the avaibility of + * a certain cache type. + * + * @return 0 on success or a negative error code. + */ +int nl_cache_mngt_register(struct nl_cache_ops *ops) +{ + if (!ops->co_name || !ops->co_obj_ops) + return -NLE_INVAL; + + nl_write_lock(&cache_ops_lock); + if (__nl_cache_ops_lookup(ops->co_name)) { + nl_write_unlock(&cache_ops_lock); + return -NLE_EXIST; + } + + ops->co_refcnt = 0; + ops->co_next = cache_ops; + cache_ops = ops; + nl_write_unlock(&cache_ops_lock); + + NL_DBG(1, "Registered cache operations %s\n", ops->co_name); + + return 0; +} + +/** + * Unregister a set of cache operations + * @arg ops cache operations + * + * Called by users of caches to announce a set of + * cache operations is no longer available. The + * specified cache operations must have been registered + * previously using nl_cache_mngt_register() + * + * @return 0 on success or a negative error code + */ +int nl_cache_mngt_unregister(struct nl_cache_ops *ops) +{ + struct nl_cache_ops *t, **tp; + int err = 0; + + nl_write_lock(&cache_ops_lock); + + if (ops->co_refcnt > 0) { + err = -NLE_BUSY; + goto errout; + } + + for (tp = &cache_ops; (t=*tp) != NULL; tp = &t->co_next) + if (t == ops) + break; + + if (!t) { + err = -NLE_NOCACHE; + goto errout; + } + + NL_DBG(1, "Unregistered cache operations %s\n", ops->co_name); + + *tp = t->co_next; +errout: + nl_write_unlock(&cache_ops_lock); + + return err; +} + +/** @} */ + +/** + * @name Global Cache Provisioning/Requiring + * @{ + */ + +/** + * Provide a cache for global use + * @arg cache cache to provide + * + * Offers the specified cache to be used by other modules. + * Only one cache per type may be shared at a time, + * a previsouly provided caches will be overwritten. + */ +void nl_cache_mngt_provide(struct nl_cache *cache) +{ + struct nl_cache_ops *ops; + + nl_write_lock(&cache_ops_lock); + + ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops); + if (!ops) + BUG(); + else { + nl_cache_get(cache); + + /* + * Hold a reference to the cache operations to ensure the + * ops don't go away while we use it to store the cache pointer. + */ + if (!ops->co_major_cache) + nl_cache_ops_get(ops); + + ops->co_major_cache = cache; + } + + nl_write_unlock(&cache_ops_lock); +} + +/** + * Unprovide a cache for global use + * @arg cache cache to unprovide + * + * Cancels the offer to use a cache globally. The + * cache will no longer be returned via lookups but + * may still be in use. + */ +void nl_cache_mngt_unprovide(struct nl_cache *cache) +{ + struct nl_cache_ops *ops; + + nl_write_lock(&cache_ops_lock); + + ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops); + if (!ops) + BUG(); + else if (ops->co_major_cache == cache) { + nl_cache_free(ops->co_major_cache); + nl_cache_ops_put(ops); + ops->co_major_cache = NULL; + } + + nl_write_unlock(&cache_ops_lock); +} + +struct nl_cache *__nl_cache_mngt_require(const char *name) +{ + struct nl_cache_ops *ops; + struct nl_cache *cache = NULL; + + ops = nl_cache_ops_lookup_safe(name); + if (ops) { + cache = ops->co_major_cache; + nl_cache_ops_put(ops); + } + + return cache; +} + +/** + * Return cache previously provided via nl_cache_mngt_provide() + * @arg name Name of cache to lookup + * + * @attention This function is not safe, it does not increment the reference + * counter. Please use nl_cache_mngt_require_safe(). + * + * @see nl_cache_mngt_require_safe() + * + * @return Pointer to cache or NULL if none registered + */ +struct nl_cache *nl_cache_mngt_require(const char *name) +{ + struct nl_cache *cache; + + if (!(cache = __nl_cache_mngt_require(name))) + NL_DBG(1, "Application BUG: Your application must " + "call nl_cache_mngt_provide() and\nprovide a valid " + "%s cache to be used for internal lookups.\nSee the " + " API documentation for more details.\n", name); + + return cache; +} + +/** + * Return cache previously provided via nl_cache_mngt_provide() + * @arg name Name of cache to lookup + * + * @note The reference counter of the returned cache is incremented + * and must be decremented after use with nl_cache_put(). + * + * @return Pointer to cache or NULL if none registered + */ +struct nl_cache *nl_cache_mngt_require_safe(const char *name) +{ + struct nl_cache *cache; + + if ((cache = nl_cache_mngt_require(name))) + nl_cache_get(cache); + + return cache; +} + +/** @} */ + +/** @} */ diff --git a/lib/cli/cls/basic.c b/lib/cli/cls/basic.c new file mode 100644 index 0000000..1939988 --- /dev/null +++ b/lib/cli/cls/basic.c @@ -0,0 +1,93 @@ +/* + * lib/cli/cls/basic.c basic classifier module for CLI lib + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2010-2011 Thomas Graf + */ + +#include +#include +#include +#include + +static void print_usage(void) +{ + printf( +"Usage: nl-cls-add [...] basic [OPTIONS]...\n" +"\n" +"OPTIONS\n" +" -h, --help Show this help text.\n" +" -t, --target=ID Target class to send matching packets to\n" +" -e, --ematch=EXPR Ematch expression\n" +"\n" +"EXAMPLE" +" # Create a \"catch-all\" classifier, attached to \"q_root\", classyfing\n" +" # all not yet classified packets to class \"c_default\"\n" +" nl-cls-add --dev=eth0 --parent=q_root basic --target=c_default\n"); +} + +static void parse_argv(struct rtnl_tc *tc, int argc, char **argv) +{ + struct rtnl_cls *cls = (struct rtnl_cls *) tc; + struct rtnl_ematch_tree *tree; + uint32_t target; + int err; + + for (;;) { + int c, optidx = 0; + enum { + ARG_TARGET = 257, + ARG_DEFAULT = 258, + }; + static struct option long_opts[] = { + { "help", 0, 0, 'h' }, + { "target", 1, 0, 't' }, + { "ematch", 1, 0, 'e' }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "ht:e:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'h': + print_usage(); + exit(0); + + case 't': + if ((err = rtnl_tc_str2handle(optarg, &target)) < 0) + nl_cli_fatal(err, "Unable to parse target \"%s\":", + optarg, nl_geterror(err)); + + rtnl_basic_set_target(cls, target); + break; + + case 'e': + tree = nl_cli_cls_parse_ematch(cls, optarg); + rtnl_basic_set_ematch(cls, tree); + break; + } + } +} + +static struct nl_cli_tc_module basic_module = +{ + .tm_name = "basic", + .tm_type = RTNL_TC_TYPE_CLS, + .tm_parse_argv = parse_argv, +}; + +static void __init basic_init(void) +{ + nl_cli_tc_register(&basic_module); +} + +static void __exit basic_exit(void) +{ + nl_cli_tc_unregister(&basic_module); +} diff --git a/lib/cli/cls/cgroup.c b/lib/cli/cls/cgroup.c new file mode 100644 index 0000000..fae6208 --- /dev/null +++ b/lib/cli/cls/cgroup.c @@ -0,0 +1,75 @@ +/* + * lib/cli/cls/cgroup.c cgroup classifier module for CLI lib + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2010-2011 Thomas Graf + */ + +#include +#include +#include +#include + +static void print_usage(void) +{ + printf( +"Usage: nl-cls-add [...] cgroup [OPTIONS]...\n" +"\n" +"OPTIONS\n" +" -h, --help Show this help text.\n" +" -e, --ematch=EXPR Ematch expression\n" +"\n" +"EXAMPLE" +" nl-cls-add --dev=eth0 --parent=q_root cgroup\n"); +} + +static void parse_argv(struct rtnl_tc *tc, int argc, char **argv) +{ + struct rtnl_cls *cls = (struct rtnl_cls *) tc; + struct rtnl_ematch_tree *tree; + + for (;;) { + int c, optidx = 0; + static struct option long_opts[] = { + { "help", 0, 0, 'h' }, + { "ematch", 1, 0, 'e' }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "he:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'h': + print_usage(); + exit(0); + + case 'e': + tree = nl_cli_cls_parse_ematch(cls, optarg); + rtnl_cgroup_set_ematch(cls, tree); + break; + } + } +} + +static struct nl_cli_tc_module cgroup_module = +{ + .tm_name = "cgroup", + .tm_type = RTNL_TC_TYPE_CLS, + .tm_parse_argv = parse_argv, +}; + +static void __init cgroup_init(void) +{ + nl_cli_tc_register(&cgroup_module); +} + +static void __exit cgroup_exit(void) +{ + nl_cli_tc_unregister(&cgroup_module); +} diff --git a/lib/cli/qdisc/bfifo.c b/lib/cli/qdisc/bfifo.c new file mode 100644 index 0000000..1ee4777 --- /dev/null +++ b/lib/cli/qdisc/bfifo.c @@ -0,0 +1,83 @@ +/* + * src/lib/bfifo.c bfifo module for CLI lib + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2010-2011 Thomas Graf + */ + +#include +#include +#include + +static void print_usage(void) +{ + printf( +"Usage: nl-qdisc-add [...] bfifo [OPTIONS]...\n" +"\n" +"OPTIONS\n" +" --help Show this help text.\n" +" --limit=LIMIT Maximum queue length in number of bytes.\n" +"\n" +"EXAMPLE" +" # Attach bfifo with a 4KB bytes limit to eth1\n" +" nl-qdisc-add --dev=eth1 --parent=root bfifo --limit=4096\n"); +} + +static void bfifo_parse_argv(struct rtnl_tc *tc, int argc, char **argv) +{ + struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc; + int limit; + + for (;;) { + int c, optidx = 0; + enum { + ARG_LIMIT = 257, + }; + static struct option long_opts[] = { + { "help", 0, 0, 'h' }, + { "limit", 1, 0, ARG_LIMIT }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "h", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'h': + print_usage(); + return; + + case ARG_LIMIT: + limit = nl_size2int(optarg); + if (limit < 0) { + nl_cli_fatal(limit, "Unable to parse bfifo limit " + "\"%s\": Invalid format.", optarg); + } + + rtnl_qdisc_fifo_set_limit(qdisc, limit); + break; + } + } +} + +static struct nl_cli_tc_module bfifo_module = +{ + .tm_name = "bfifo", + .tm_type = RTNL_TC_TYPE_QDISC, + .tm_parse_argv = bfifo_parse_argv, +}; + +static void __init bfifo_init(void) +{ + nl_cli_tc_register(&bfifo_module); +} + +static void __exit bfifo_exit(void) +{ + nl_cli_tc_unregister(&bfifo_module); +} diff --git a/lib/cli/qdisc/blackhole.c b/lib/cli/qdisc/blackhole.c new file mode 100644 index 0000000..af9dc6d --- /dev/null +++ b/lib/cli/qdisc/blackhole.c @@ -0,0 +1,64 @@ +/* + * src/lib/blackhole.c Blackhole module for CLI lib + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2010-2011 Thomas Graf + */ + +#include +#include + +static void print_usage(void) +{ + printf( +"Usage: nl-qdisc-add [...] blackhole [OPTIONS]...\n" +"\n" +"OPTIONS\n" +" --help Show this help text.\n" +"\n" +"EXAMPLE" +" # Drop all outgoing packets on eth1\n" +" nl-qdisc-add --dev=eth1 --parent=root blackhole\n"); +} + +static void blackhole_parse_argv(struct rtnl_tc *tc, int argc, char **argv) +{ + for (;;) { + int c, optidx = 0; + static struct option long_opts[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "h", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'h': + print_usage(); + return; + } + } +} + +static struct nl_cli_tc_module blackhole_module = +{ + .tm_name = "blackhole", + .tm_type = RTNL_TC_TYPE_QDISC, + .tm_parse_argv = blackhole_parse_argv, +}; + +static void __init blackhole_init(void) +{ + nl_cli_tc_register(&blackhole_module); +} + +static void __exit blackhole_exit(void) +{ + nl_cli_tc_unregister(&blackhole_module); +} diff --git a/lib/cli/qdisc/htb.c b/lib/cli/qdisc/htb.c new file mode 100644 index 0000000..1751595 --- /dev/null +++ b/lib/cli/qdisc/htb.c @@ -0,0 +1,203 @@ +/* + * src/lib/htb.c HTB module for CLI lib + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2010-2011 Thomas Graf + */ + +#include +#include +#include + +static void print_qdisc_usage(void) +{ + printf( +"Usage: nl-qdisc-add [...] htb [OPTIONS]...\n" +"\n" +"OPTIONS\n" +" --help Show this help text.\n" +" --r2q=DIV Rate to quantum divisor (default: 10)\n" +" --default=ID Default class for unclassified traffic.\n" +"\n" +"EXAMPLE" +" # Create htb root qdisc 1: and direct unclassified traffic to class 1:10\n" +" nl-qdisc-add --dev=eth1 --parent=root --handle=1: htb --default=10\n"); +} + +static void htb_parse_qdisc_argv(struct rtnl_tc *tc, int argc, char **argv) +{ + struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc; + + for (;;) { + int c, optidx = 0; + enum { + ARG_R2Q = 257, + ARG_DEFAULT = 258, + }; + static struct option long_opts[] = { + { "help", 0, 0, 'h' }, + { "r2q", 1, 0, ARG_R2Q }, + { "default", 1, 0, ARG_DEFAULT }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "hv", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'h': + print_qdisc_usage(); + return; + + case ARG_R2Q: + rtnl_htb_set_rate2quantum(qdisc, nl_cli_parse_u32(optarg)); + break; + + case ARG_DEFAULT: + rtnl_htb_set_defcls(qdisc, nl_cli_parse_u32(optarg)); + break; + } + } +} + +static void print_class_usage(void) +{ + printf( +"Usage: nl-class-add [...] htb [OPTIONS]...\n" +"\n" +"OPTIONS\n" +" --help Show this help text.\n" +" --rate=RATE Rate limit.\n" +" --ceil=RATE Rate limit while borrowing (default: equal to --rate).\n" +" --prio=PRIO Priority, lower is served first (default: 0).\n" +" --quantum=SIZE Amount of bytes to serve at once (default: rate/r2q).\n" +" --burst=SIZE Max charge size of rate burst buffer (default: auto).\n" +" --cburst=SIZE Max charge size of ceil rate burst buffer (default: auto)\n" +"\n" +"EXAMPLE" +" # Attach class 1:1 to htb qdisc 1: and rate limit it to 20mbit\n" +" nl-class-add --dev=eth1 --parent=1: --classid=1:1 htb --rate=20mbit\n"); +} + +static void htb_parse_class_argv(struct rtnl_tc *tc, int argc, char **argv) +{ + struct rtnl_class *class = (struct rtnl_class *) tc; + long rate; + + for (;;) { + int c, optidx = 0; + enum { + ARG_RATE = 257, + ARG_QUANTUM = 258, + ARG_CEIL, + ARG_PRIO, + ARG_BURST, + ARG_CBURST, + }; + static struct option long_opts[] = { + { "help", 0, 0, 'h' }, + { "rate", 1, 0, ARG_RATE }, + { "quantum", 1, 0, ARG_QUANTUM }, + { "ceil", 1, 0, ARG_CEIL }, + { "prio", 1, 0, ARG_PRIO }, + { "burst", 1, 0, ARG_BURST }, + { "cburst", 1, 0, ARG_CBURST }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "h", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'h': + print_class_usage(); + return; + + case ARG_RATE: + rate = nl_size2int(optarg); + if (rate < 0) { + nl_cli_fatal(rate, "Unable to parse htb rate " + "\"%s\": Invalid format.", optarg); + } + + rtnl_htb_set_rate(class, rate); + break; + + case ARG_CEIL: + rate = nl_size2int(optarg); + if (rate < 0) { + nl_cli_fatal(rate, "Unable to parse htb ceil rate " + "\"%s\": Invalid format.", optarg); + } + + rtnl_htb_set_ceil(class, rate); + break; + + case ARG_PRIO: + rtnl_htb_set_prio(class, nl_cli_parse_u32(optarg)); + break; + + case ARG_QUANTUM: + rate = nl_size2int(optarg); + if (rate < 0) { + nl_cli_fatal(rate, "Unable to parse quantum " + "\"%s\": Invalid format.", optarg); + } + + rtnl_htb_set_quantum(class, rate); + break; + + case ARG_BURST: + rate = nl_size2int(optarg); + if (rate < 0) { + nl_cli_fatal(rate, "Unable to parse burst " + "\"%s\": Invalid format.", optarg); + } + + rtnl_htb_set_rbuffer(class, rate); + break; + + case ARG_CBURST: + rate = nl_size2int(optarg); + if (rate < 0) { + nl_cli_fatal(rate, "Unable to parse cburst " + "\"%s\": Invalid format.", optarg); + } + + rtnl_htb_set_cbuffer(class, rate); + break; + } + } +} + +static struct nl_cli_tc_module htb_qdisc_module = +{ + .tm_name = "htb", + .tm_type = RTNL_TC_TYPE_QDISC, + .tm_parse_argv = htb_parse_qdisc_argv, +}; + +static struct nl_cli_tc_module htb_class_module = +{ + .tm_name = "htb", + .tm_type = RTNL_TC_TYPE_CLASS, + .tm_parse_argv = htb_parse_class_argv, +}; + +static void __init htb_init(void) +{ + nl_cli_tc_register(&htb_qdisc_module); + nl_cli_tc_register(&htb_class_module); +} + +static void __exit htb_exit(void) +{ + nl_cli_tc_unregister(&htb_class_module); + nl_cli_tc_unregister(&htb_qdisc_module); +} diff --git a/lib/cli/qdisc/pfifo.c b/lib/cli/qdisc/pfifo.c new file mode 100644 index 0000000..02c4d22 --- /dev/null +++ b/lib/cli/qdisc/pfifo.c @@ -0,0 +1,77 @@ + +/* + * src/lib/pfifo.c pfifo module for CLI lib + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2010-2011 Thomas Graf + */ + +#include +#include +#include + +static void print_usage(void) +{ + printf( +"Usage: nl-qdisc-add [...] pfifo [OPTIONS]...\n" +"\n" +"OPTIONS\n" +" --help Show this help text.\n" +" --limit=LIMIT Maximum queue length in number of packets.\n" +"\n" +"EXAMPLE" +" # Attach pfifo with a 32 packet limit to eth1\n" +" nl-qdisc-add --dev=eth1 --parent=root pfifo --limit=32\n"); +} + +static void pfifo_parse_argv(struct rtnl_tc *tc, int argc, char **argv) +{ + struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc; + + for (;;) { + int c, optidx = 0; + enum { + ARG_LIMIT = 257, + }; + static struct option long_opts[] = { + { "help", 0, 0, 'h' }, + { "limit", 1, 0, ARG_LIMIT }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "h", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'h': + print_usage(); + return; + + case ARG_LIMIT: + rtnl_qdisc_fifo_set_limit(qdisc, nl_cli_parse_u32(optarg)); + break; + } + } +} + +static struct nl_cli_tc_module pfifo_module = +{ + .tm_name = "pfifo", + .tm_type = RTNL_TC_TYPE_QDISC, + .tm_parse_argv = pfifo_parse_argv, +}; + +static void __init pfifo_init(void) +{ + nl_cli_tc_register(&pfifo_module); +} + +static void __exit pfifo_exit(void) +{ + nl_cli_tc_unregister(&pfifo_module); +} diff --git a/lib/cli/qdisc/plug.c b/lib/cli/qdisc/plug.c new file mode 100644 index 0000000..2b8d5d6 --- /dev/null +++ b/lib/cli/qdisc/plug.c @@ -0,0 +1,113 @@ + +/* + * src/lib/cli/qdisc/plug.c plug module for CLI lib + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2012 Shriram Rajagopalan + */ + +#include +#include +#include + +static void print_usage(void) +{ + printf( +"Usage: nl-qdisc-add [...] plug [OPTIONS]...\n" +"\n" +"OPTIONS\n" +" --help Show this help text.\n" +" --limit Maximum queue length in bytes.\n" +" --buffer create a new buffer(plug) and queue incoming traffic into it.\n" +" --release-one release traffic from previous buffer.\n" +" --release-indefinite stop buffering and release all (buffered and new) packets.\n" +"\n" +"EXAMPLE" +" # Attach plug qdisc with 32KB queue size to ifb0\n" +" nl-qdisc-add --dev=ifb0 --parent=root plug --limit=32768\n" +" # Plug network traffic arriving at ifb0\n" +" nl-qdisc-add --dev=ifb0 --parent=root --update plug --buffer\n" +" # Unplug traffic arriving at ifb0 indefinitely\n" +" nl-qdisc-add --dev=ifb0 --parent=root --update plug --release-indefinite\n\n" +" # If operating in output buffering mode:\n" +" # at time t=t0, create a new output buffer b0 to hold network output\n" +" nl-qdisc-add --dev=ifb0 --parent=root --update plug --buffer\n\n" +" # at time t=t1, take a checkpoint c0, create a new output buffer b1\n" +" nl-qdisc-add --dev=ifb0 --parent=root --update plug --buffer\n" +" # at time t=t1+r, after c0 is committed, release b0\n" +" nl-qdisc-add --dev=ifb0 --parent=root --update plug --release-one\n\n" +" # at time t=t2, take a checkpoint c1, create a new output buffer b2\n" +" nl-qdisc-add --dev=ifb0 --parent=root --update plug --buffer\n" +" # at time t=t2+r, after c1 is committed, release b1\n" +" nl-qdisc-add --dev=ifb0 --parent=root --update plug --release-one\n"); +} + +static void plug_parse_argv(struct rtnl_tc *tc, int argc, char **argv) +{ + struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc; + + for (;;) { + int c, optidx = 0; + enum { + ARG_LIMIT = 257, + ARG_BUFFER = 258, + ARG_RELEASE_ONE = 259, + ARG_RELEASE_INDEFINITE = 260, + }; + static struct option long_opts[] = { + { "help", 0, 0, 'h' }, + { "limit", 1, 0, ARG_LIMIT }, + { "buffer", 0, 0, ARG_BUFFER }, + { "release-one", 0, 0, ARG_RELEASE_ONE }, + { "release-indefinite", 0, 0, ARG_RELEASE_INDEFINITE }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "h", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'h': + print_usage(); + return; + + case ARG_LIMIT: + rtnl_qdisc_plug_set_limit(qdisc, nl_cli_parse_u32(optarg)); + break; + + case ARG_BUFFER: + rtnl_qdisc_plug_buffer(qdisc); + break; + + case ARG_RELEASE_ONE: + rtnl_qdisc_plug_release_one(qdisc); + break; + + case ARG_RELEASE_INDEFINITE: + rtnl_qdisc_plug_release_indefinite(qdisc); + break; + } + } +} + +static struct nl_cli_tc_module plug_module = +{ + .tm_name = "plug", + .tm_type = RTNL_TC_TYPE_QDISC, + .tm_parse_argv = plug_parse_argv, +}; + +static void __init plug_init(void) +{ + nl_cli_tc_register(&plug_module); +} + +static void __exit plug_exit(void) +{ + nl_cli_tc_unregister(&plug_module); +} diff --git a/lib/data.c b/lib/data.c new file mode 100644 index 0000000..1a3a3fb --- /dev/null +++ b/lib/data.c @@ -0,0 +1,195 @@ +/* + * lib/data.c Abstract Data + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +/** + * @ingroup core_types + * @defgroup data Abstract Data + * + * Abstract data type representing a binary data blob. + * + * Related sections in the development guide: + * - @core_doc{_abstract_data, Abstract Data} + * + * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ + */ + +#include +#include +#include +#include + +/** + * @name General + * @{ + */ + +/** + * Allocate a new abstract data object. + * @arg buf Data buffer containing the actual data. + * @arg size Size of data buffer. + * + * Allocates a new abstract data and copies the specified data + * buffer into the new handle. + * + * @return Newly allocated data handle or NULL + */ +struct nl_data *nl_data_alloc(void *buf, size_t size) +{ + struct nl_data *data; + + data = calloc(1, sizeof(*data)); + if (!data) + goto errout; + + data->d_data = calloc(1, size); + if (!data->d_data) { + free(data); + goto errout; + } + + data->d_size = size; + + if (buf) + memcpy(data->d_data, buf, size); + + return data; +errout: + return NULL; +} + +/** + * Allocate abstract data object based on netlink attribute. + * @arg nla Netlink attribute of unspecific type. + * + * Allocates a new abstract data and copies the payload of the + * attribute to the abstract data object. + * + * @see nla_data_alloc + * @return Newly allocated data handle or NULL + */ +struct nl_data *nl_data_alloc_attr(struct nlattr *nla) +{ + return nl_data_alloc(nla_data(nla), nla_len(nla)); +} + +/** + * Clone an abstract data object. + * @arg src Abstract data object + * + * @return Cloned object or NULL + */ +struct nl_data *nl_data_clone(struct nl_data *src) +{ + return nl_data_alloc(src->d_data, src->d_size); +} + +/** + * Append data to an abstract data object. + * @arg data Abstract data object. + * @arg buf Data buffer containing the data to be appended. + * @arg size Size of data to be apppended. + * + * Reallocates an abstract data and copies the specified data + * buffer into the new handle. + * + * @return 0 on success or a negative error code + */ +int nl_data_append(struct nl_data *data, void *buf, size_t size) +{ + if (size > 0) { + data->d_data = realloc(data->d_data, data->d_size + size); + if (!data->d_data) + return -NLE_NOMEM; + + if (buf) + memcpy(data->d_data + data->d_size, buf, size); + else + memset(data->d_data + data->d_size, 0, size); + + data->d_size += size; + } + + return 0; +} + +/** + * Free an abstract data object. + * @arg data Abstract data object. + */ +void nl_data_free(struct nl_data *data) +{ + if (data) + free(data->d_data); + + free(data); +} + +/** @} */ + +/** + * @name Attribute Access + * @{ + */ + +/** + * Get data buffer of abstract data object. + * @arg data Abstract data object. + * @return Data buffer or NULL if empty. + */ +void *nl_data_get(struct nl_data *data) +{ + return data->d_size > 0 ? data->d_data : NULL; +} + +/** + * Get size of data buffer of abstract data object. + * @arg data Abstract data object. + * @return Size of data buffer. + */ +size_t nl_data_get_size(struct nl_data *data) +{ + return data->d_size; +} + +/** @} */ + +/** + * @name Misc + * @{ + */ + +/** + * Compare two abstract data objects. + * @arg a Abstract data object. + * @arg b Another abstract data object. + * @return An integer less than, equal to, or greater than zero if + * a is found, respectively, to be less than, to match, or + * be greater than b. + */ +int nl_data_cmp(struct nl_data *a, struct nl_data *b) +{ + void *a_ = nl_data_get(a); + void *b_ = nl_data_get(b); + + if (a_ && b_) + return memcmp(a_, b_, nl_data_get_size(a)); + else + return -1; +} + +/** @} */ +/** @} */ diff --git a/lib/defs.h.in b/lib/defs.h.in new file mode 100644 index 0000000..62785cb --- /dev/null +++ b/lib/defs.h.in @@ -0,0 +1,86 @@ +/* lib/defs.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 to disable pthreads */ +#undef DISABLE_PTHREADS + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `m' library (-lm). */ +#undef HAVE_LIBM + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#undef HAVE_LIBPTHREAD + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Define to 1 to enable debugging */ +#undef NL_DEBUG + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +#undef NO_MINUS_C_MINUS_O + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif diff --git a/lib/error.c b/lib/error.c new file mode 100644 index 0000000..f30b9a5 --- /dev/null +++ b/lib/error.c @@ -0,0 +1,116 @@ +/* + * lib/error.c Error Handling + * + * 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 Thomas Graf + */ + +#include +#include + +static const char *errmsg[NLE_MAX+1] = { +[NLE_SUCCESS] = "Success", +[NLE_FAILURE] = "Unspecific failure", +[NLE_INTR] = "Interrupted system call", +[NLE_BAD_SOCK] = "Bad socket", +[NLE_AGAIN] = "Try again", +[NLE_NOMEM] = "Out of memory", +[NLE_EXIST] = "Object exists", +[NLE_INVAL] = "Invalid input data or parameter", +[NLE_RANGE] = "Input data out of range", +[NLE_MSGSIZE] = "Message size not sufficient", +[NLE_OPNOTSUPP] = "Operation not supported", +[NLE_AF_NOSUPPORT] = "Address family not supported", +[NLE_OBJ_NOTFOUND] = "Object not found", +[NLE_NOATTR] = "Attribute not available", +[NLE_MISSING_ATTR] = "Missing attribute", +[NLE_AF_MISMATCH] = "Address family mismatch", +[NLE_SEQ_MISMATCH] = "Message sequence number mismatch", +[NLE_MSG_OVERFLOW] = "Kernel reported message overflow", +[NLE_MSG_TRUNC] = "Kernel reported truncated message", +[NLE_NOADDR] = "Invalid address for specified address family", +[NLE_SRCRT_NOSUPPORT] = "Source based routing not supported", +[NLE_MSG_TOOSHORT] = "Netlink message is too short", +[NLE_MSGTYPE_NOSUPPORT] = "Netlink message type is not supported", +[NLE_OBJ_MISMATCH] = "Object type does not match cache", +[NLE_NOCACHE] = "Unknown or invalid cache type", +[NLE_BUSY] = "Object busy", +[NLE_PROTO_MISMATCH] = "Protocol mismatch", +[NLE_NOACCESS] = "No Access", +[NLE_PERM] = "Operation not permitted", +[NLE_PKTLOC_FILE] = "Unable to open packet location file", +[NLE_PARSE_ERR] = "Unable to parse object", +[NLE_NODEV] = "No such device", +[NLE_IMMUTABLE] = "Immutable attribute", +[NLE_DUMP_INTR] = "Dump inconsistency detected, interrupted", +}; + +/** + * Return error message for an error code + * @return error message + */ +const char *nl_geterror(int error) +{ + error = abs(error); + + if (error > NLE_MAX) + error = NLE_FAILURE; + + return errmsg[error]; +} + +/** + * Print a libnl error message + * @arg s error message prefix + * + * Prints the error message of the call that failed last. + * + * If s is not NULL and *s is not a null byte the argument + * string is printed, followed by a colon and a blank. Then + * the error message and a new-line. + */ +void nl_perror(int error, const char *s) +{ + if (s && *s) + fprintf(stderr, "%s: %s\n", s, nl_geterror(error)); + else + fprintf(stderr, "%s\n", nl_geterror(error)); +} + +int nl_syserr2nlerr(int error) +{ + error = abs(error); + + switch (error) { + case EBADF: return NLE_BAD_SOCK; + case EADDRINUSE: return NLE_EXIST; + case EEXIST: return NLE_EXIST; + case EADDRNOTAVAIL: return NLE_NOADDR; + case ESRCH: /* fall through */ + case ENOENT: return NLE_OBJ_NOTFOUND; + case EINTR: return NLE_INTR; + case EAGAIN: return NLE_AGAIN; + case ENOTSOCK: return NLE_BAD_SOCK; + case ENOPROTOOPT: return NLE_INVAL; + case EFAULT: return NLE_INVAL; + case EACCES: return NLE_NOACCESS; + case EINVAL: return NLE_INVAL; + case ENOBUFS: return NLE_NOMEM; + case ENOMEM: return NLE_NOMEM; + case EAFNOSUPPORT: return NLE_AF_NOSUPPORT; + case EPROTONOSUPPORT: return NLE_PROTO_MISMATCH; + case EOPNOTSUPP: return NLE_OPNOTSUPP; + case EPERM: return NLE_PERM; + case EBUSY: return NLE_BUSY; + case ERANGE: return NLE_RANGE; + case ENODEV: return NLE_NODEV; + default: return NLE_FAILURE; + } +} + +/** @} */ + diff --git a/lib/fib_lookup/lookup.c b/lib/fib_lookup/lookup.c new file mode 100644 index 0000000..3d07317 --- /dev/null +++ b/lib/fib_lookup/lookup.c @@ -0,0 +1,349 @@ +/* + * lib/fib_lookup/lookup.c FIB Lookup + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +/** + * @ingroup rtnl + * @defgroup fib_lookup FIB Lookup + * @brief + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +static struct nl_cache_ops fib_lookup_ops; +static struct nl_object_ops result_obj_ops; + +/* not exported so far */ +struct fib_result_nl { + uint32_t fl_addr; /* To be looked up*/ + uint32_t fl_fwmark; + unsigned char fl_tos; + unsigned char fl_scope; + unsigned char tb_id_in; + + unsigned char tb_id; /* Results */ + unsigned char prefixlen; + unsigned char nh_sel; + unsigned char type; + unsigned char scope; + int err; +}; +/** @endcond */ + +static void result_free_data(struct nl_object *obj) +{ + struct flnl_result *res = nl_object_priv(obj); + + if (res && res->fr_req) + nl_object_put(OBJ_CAST(res->fr_req)); +} + +static int result_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct flnl_result *dst = nl_object_priv(_dst); + struct flnl_result *src = nl_object_priv(_src); + + if (src->fr_req) + if (!(dst->fr_req = (struct flnl_request *) + nl_object_clone(OBJ_CAST(src->fr_req)))) + return -NLE_NOMEM; + + return 0; +} + +static int result_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *n, struct nl_parser_param *pp) +{ + struct flnl_result *res; + struct fib_result_nl *fr; + struct nl_addr *addr; + int err = -NLE_INVAL; + + res = flnl_result_alloc(); + if (!res) + goto errout; + + res->ce_msgtype = n->nlmsg_type; + + res->fr_req = flnl_request_alloc(); + if (!res->fr_req) + goto errout; + + fr = nlmsg_data(n); + addr = nl_addr_build(AF_INET, &fr->fl_addr, 4); + if (!addr) + goto errout; + err = flnl_request_set_addr(res->fr_req, addr); + nl_addr_put(addr); + if (err < 0) + goto errout; + + flnl_request_set_fwmark(res->fr_req, fr->fl_fwmark); + flnl_request_set_tos(res->fr_req, fr->fl_tos); + flnl_request_set_scope(res->fr_req, fr->fl_scope); + flnl_request_set_table(res->fr_req, fr->tb_id_in); + + res->fr_table_id = fr->tb_id; + res->fr_prefixlen = fr->prefixlen; + res->fr_nh_sel = fr->nh_sel; + res->fr_type = fr->type; + res->fr_scope = fr->scope; + res->fr_error = fr->err; + + err = pp->pp_cb((struct nl_object *) res, pp); + if (err < 0) + goto errout; + + /* REAL HACK, fib_lookup doesn't support ACK nor does it + * send a DONE message, enforce end of message stream + * after just the first message */ + err = NL_STOP; + +errout: + flnl_result_put(res); + return err; +} + +static void result_dump_line(struct nl_object *obj, struct nl_dump_params *p) +{ + struct flnl_result *res = (struct flnl_result *) obj; + char buf[256]; + + nl_dump_line(p, "table %s prefixlen %u next-hop-selector %u\n", + rtnl_route_table2str(res->fr_table_id, buf, sizeof(buf)), + res->fr_prefixlen, res->fr_nh_sel); + nl_dump_line(p, "type %s ", + nl_rtntype2str(res->fr_type, buf, sizeof(buf))); + nl_dump(p, "scope %s error %s (%d)\n", + rtnl_scope2str(res->fr_scope, buf, sizeof(buf)), + strerror_r(-res->fr_error, buf, sizeof(buf)), res->fr_error); +} + +static void result_dump_details(struct nl_object *obj, struct nl_dump_params *p) +{ + result_dump_line(obj, p); +} + +static int result_compare(struct nl_object *_a, struct nl_object *_b, + uint32_t attrs, int flags) +{ + return 0; +} + +/** + * @name Allocation/Freeing + * @{ + */ + +struct flnl_result *flnl_result_alloc(void) +{ + return (struct flnl_result *) nl_object_alloc(&result_obj_ops); +} + +void flnl_result_put(struct flnl_result *res) +{ + nl_object_put((struct nl_object *) res); +} + +/** @} */ + +/** + * @name Cache Management + * @{ + */ + +/** + * Allocate lookup result cache. + * + * Allocates a new lookup result cache and initializes it properly. + * + * @note Free the memory after usage using nl_cache_destroy_and_free(). + * @return Newly allocated cache or NULL if an error occured. + */ +struct nl_cache *flnl_result_alloc_cache(void) +{ + return nl_cache_alloc(&fib_lookup_ops); +} + +/** @} */ + +/** + * @name Lookup + * @{ + */ + +/** + * Builds a netlink request message to do a lookup + * @arg req Requested match. + * @arg flags additional netlink message flags + * @arg result Result pointer + * + * Builds a new netlink message requesting a change of link attributes. + * The netlink message header isn't fully equipped with all relevant + * fields and must be sent out via nl_send_auto_complete() or + * supplemented as needed. + * \a old must point to a link currently configured in the kernel + * and \a tmpl must contain the attributes to be changed set via + * \c rtnl_link_set_* functions. + * + * @return 0 on success or a negative error code. + */ +int flnl_lookup_build_request(struct flnl_request *req, int flags, + struct nl_msg **result) +{ + struct nl_msg *msg; + struct nl_addr *addr; + uint64_t fwmark; + int tos, scope, table; + struct fib_result_nl fr = {0}; + + fwmark = flnl_request_get_fwmark(req); + tos = flnl_request_get_tos(req); + scope = flnl_request_get_scope(req); + table = flnl_request_get_table(req); + + fr.fl_fwmark = fwmark != UINT_LEAST64_MAX ? fwmark : 0; + fr.fl_tos = tos >= 0 ? tos : 0; + fr.fl_scope = scope >= 0 ? scope : RT_SCOPE_UNIVERSE; + fr.tb_id_in = table >= 0 ? table : RT_TABLE_UNSPEC; + + addr = flnl_request_get_addr(req); + if (!addr) + return -NLE_MISSING_ATTR; + + fr.fl_addr = *(uint32_t *) nl_addr_get_binary_addr(addr); + + msg = nlmsg_alloc_simple(0, flags); + if (!msg) + return -NLE_NOMEM; + + if (nlmsg_append(msg, &fr, sizeof(fr), NLMSG_ALIGNTO) < 0) + goto errout; + + *result = msg; + return 0; + +errout: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +/** + * Perform FIB Lookup + * @arg sk Netlink socket. + * @arg req Lookup request object. + * @arg cache Cache for result. + * + * Builds a netlink message to request a FIB lookup, waits for the + * reply and adds the result to the specified cache. + * + * @return 0 on success or a negative error code. + */ +int flnl_lookup(struct nl_sock *sk, struct flnl_request *req, + struct nl_cache *cache) +{ + struct nl_msg *msg; + int err; + + if ((err = flnl_lookup_build_request(req, 0, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return nl_cache_pickup(sk, cache); +} + +/** @} */ + +/** + * @name Attribute Access + * @{ + */ + +int flnl_result_get_table_id(struct flnl_result *res) +{ + return res->fr_table_id; +} + +int flnl_result_get_prefixlen(struct flnl_result *res) +{ + return res->fr_prefixlen; +} + +int flnl_result_get_nexthop_sel(struct flnl_result *res) +{ + return res->fr_nh_sel; +} + +int flnl_result_get_type(struct flnl_result *res) +{ + return res->fr_type; +} + +int flnl_result_get_scope(struct flnl_result *res) +{ + return res->fr_scope; +} + +int flnl_result_get_error(struct flnl_result *res) +{ + return res->fr_error; +} + +/** @} */ + +static struct nl_object_ops result_obj_ops = { + .oo_name = "fib_lookup/result", + .oo_size = sizeof(struct flnl_result), + .oo_free_data = result_free_data, + .oo_clone = result_clone, + .oo_dump = { + [NL_DUMP_LINE] = result_dump_line, + [NL_DUMP_DETAILS] = result_dump_details, + }, + .oo_compare = result_compare, +}; + +static struct nl_cache_ops fib_lookup_ops = { + .co_name = "fib_lookup/fib_lookup", + .co_hdrsize = sizeof(struct fib_result_nl), + .co_msgtypes = { + { 0, NL_ACT_UNSPEC, "any" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_FIB_LOOKUP, + .co_msg_parser = result_msg_parser, + .co_obj_ops = &result_obj_ops, +}; + +static void __init fib_lookup_init(void) +{ + nl_cache_mngt_register(&fib_lookup_ops); +} + +static void __exit fib_lookup_exit(void) +{ + nl_cache_mngt_unregister(&fib_lookup_ops); +} + +/** @} */ diff --git a/lib/fib_lookup/request.c b/lib/fib_lookup/request.c new file mode 100644 index 0000000..1b021b6 --- /dev/null +++ b/lib/fib_lookup/request.c @@ -0,0 +1,185 @@ +/* + * lib/fib_lookup/request.c FIB Lookup Request + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + */ + +/** + * @ingroup fib_lookup + * @defgroup flreq Request + * @brief + * @{ + */ + +#include +#include +#include +#include +#include +#include + +static struct nl_object_ops request_obj_ops; + +/** @cond SKIP */ +#define REQUEST_ATTR_ADDR 0x01 +#define REQUEST_ATTR_FWMARK 0x02 +#define REQUEST_ATTR_TOS 0x04 +#define REQUEST_ATTR_SCOPE 0x08 +#define REQUEST_ATTR_TABLE 0x10 +/** @endcond */ + +static void request_free_data(struct nl_object *obj) +{ + struct flnl_request *req = REQUEST_CAST(obj); + + if (req) + nl_addr_put(req->lr_addr); +} + +static int request_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct flnl_request *dst = nl_object_priv(_dst); + struct flnl_request *src = nl_object_priv(_src); + + if (src->lr_addr) + if (!(dst->lr_addr = nl_addr_clone(src->lr_addr))) + return -NLE_NOMEM; + + return 0; +} + +static int request_compare(struct nl_object *_a, struct nl_object *_b, + uint32_t attrs, int flags) +{ + struct flnl_request *a = (struct flnl_request *) _a; + struct flnl_request *b = (struct flnl_request *) _b; + int diff = 0; + +#define REQ_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, REQUEST_ATTR_##ATTR, a, b, EXPR) + + diff |= REQ_DIFF(FWMARK, a->lr_fwmark != b->lr_fwmark); + diff |= REQ_DIFF(TOS, a->lr_tos != b->lr_tos); + diff |= REQ_DIFF(SCOPE, a->lr_scope != b->lr_scope); + diff |= REQ_DIFF(TABLE, a->lr_table != b->lr_table); + diff |= REQ_DIFF(ADDR, nl_addr_cmp(a->lr_addr, b->lr_addr)); + +#undef REQ_DIFF + + return diff; +} + + +/** + * @name Lookup Request Creation/Deletion + * @{ + */ + +struct flnl_request *flnl_request_alloc(void) +{ + return REQUEST_CAST(nl_object_alloc(&request_obj_ops)); +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ + +void flnl_request_set_fwmark(struct flnl_request *req, uint64_t fwmark) +{ + req->lr_fwmark = fwmark; + req->ce_mask |= REQUEST_ATTR_FWMARK; +} + +uint64_t flnl_request_get_fwmark(struct flnl_request *req) +{ + if (req->ce_mask & REQUEST_ATTR_FWMARK) + return req->lr_fwmark; + else + return UINT_LEAST64_MAX; +} + +void flnl_request_set_tos(struct flnl_request *req, int tos) +{ + req->lr_tos = tos; + req->ce_mask |= REQUEST_ATTR_TOS; +} + +int flnl_request_get_tos(struct flnl_request *req) +{ + if (req->ce_mask & REQUEST_ATTR_TOS) + return req->lr_tos; + else + return -1; +} + +void flnl_request_set_scope(struct flnl_request *req, int scope) +{ + req->lr_scope = scope; + req->ce_mask |= REQUEST_ATTR_SCOPE; +} + +int flnl_request_get_scope(struct flnl_request *req) +{ + if (req->ce_mask & REQUEST_ATTR_SCOPE) + return req->lr_scope; + else + return -1; +} + +void flnl_request_set_table(struct flnl_request *req, int table) +{ + req->lr_table = table; + req->ce_mask |= REQUEST_ATTR_TABLE; +} + +int flnl_request_get_table(struct flnl_request *req) +{ + if (req->ce_mask & REQUEST_ATTR_TABLE) + return req->lr_table; + else + return -1; +} + +int flnl_request_set_addr(struct flnl_request *req, struct nl_addr *addr) +{ + if (addr->a_family != AF_INET) + return -NLE_AF_NOSUPPORT; + + if (req->lr_addr) + nl_addr_put(req->lr_addr); + + nl_addr_get(addr); + req->lr_addr = addr; + + req->ce_mask |= REQUEST_ATTR_ADDR; + + return 0; +} + +struct nl_addr *flnl_request_get_addr(struct flnl_request *req) +{ + if (req->ce_mask & REQUEST_ATTR_ADDR) + return req->lr_addr; + else + return NULL; +} + +/** @} */ + +static struct nl_object_ops request_obj_ops = { + .oo_name = "fib_lookup/request", + .oo_size = sizeof(struct flnl_request), + .oo_free_data = request_free_data, + .oo_clone = request_clone, + .oo_compare = request_compare, + .oo_id_attrs = ~0, +}; + +/** @} */ diff --git a/lib/genl/ctrl.c b/lib/genl/ctrl.c new file mode 100644 index 0000000..ce07f1d --- /dev/null +++ b/lib/genl/ctrl.c @@ -0,0 +1,547 @@ +/* + * lib/genl/ctrl.c Generic Netlink Controller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +/** + * @ingroup genl + * @defgroup genl_ctrl Controller (Resolver) + * + * Resolves Generic Netlink family names to numeric identifiers. + * + * The controller is a component in the kernel that resolves Generic Netlink + * family names to their numeric identifiers. This module provides functions + * to query the controller to access the resolving functionality. + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define CTRL_VERSION 0x0001 + +static struct nl_cache_ops genl_ctrl_ops; + +static int ctrl_request_update(struct nl_cache *c, struct nl_sock *h) +{ + return genl_send_simple(h, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, + CTRL_VERSION, NLM_F_DUMP); +} + +static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = { + [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 }, + [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_STRING, + .maxlen = GENL_NAMSIZ }, + [CTRL_ATTR_VERSION] = { .type = NLA_U32 }, + [CTRL_ATTR_HDRSIZE] = { .type = NLA_U32 }, + [CTRL_ATTR_MAXATTR] = { .type = NLA_U32 }, + [CTRL_ATTR_OPS] = { .type = NLA_NESTED }, + [CTRL_ATTR_MCAST_GROUPS] = { .type = NLA_NESTED }, +}; + +static struct nla_policy family_op_policy[CTRL_ATTR_OP_MAX+1] = { + [CTRL_ATTR_OP_ID] = { .type = NLA_U32 }, + [CTRL_ATTR_OP_FLAGS] = { .type = NLA_U32 }, +}; + +static struct nla_policy family_grp_policy[CTRL_ATTR_MCAST_GRP_MAX+1] = { + [CTRL_ATTR_MCAST_GRP_NAME] = { .type = NLA_STRING }, + [CTRL_ATTR_MCAST_GRP_ID] = { .type = NLA_U32 }, +}; + +static int parse_mcast_grps(struct genl_family *family, struct nlattr *grp_attr) +{ + struct nlattr *nla; + int remaining, err; + + if (!grp_attr) + BUG(); + + nla_for_each_nested(nla, grp_attr, remaining) { + struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX+1]; + int id; + const char * name; + + err = nla_parse_nested(tb, CTRL_ATTR_MCAST_GRP_MAX, nla, + family_grp_policy); + if (err < 0) + goto errout; + + if (tb[CTRL_ATTR_MCAST_GRP_ID] == NULL) { + err = -NLE_MISSING_ATTR; + goto errout; + } + id = nla_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID]); + + if (tb[CTRL_ATTR_MCAST_GRP_NAME] == NULL) { + err = -NLE_MISSING_ATTR; + goto errout; + } + name = nla_get_string(tb[CTRL_ATTR_MCAST_GRP_NAME]); + + err = genl_family_add_grp(family, id, name); + if (err < 0) + goto errout; + } + + err = 0; + +errout: + return err; +} + +static int ctrl_msg_parser(struct nl_cache_ops *ops, struct genl_cmd *cmd, + struct genl_info *info, void *arg) +{ + struct genl_family *family; + struct nl_parser_param *pp = arg; + int err; + + family = genl_family_alloc(); + if (family == NULL) { + err = -NLE_NOMEM; + goto errout; + } + + if (info->attrs[CTRL_ATTR_FAMILY_NAME] == NULL) { + err = -NLE_MISSING_ATTR; + goto errout; + } + + if (info->attrs[CTRL_ATTR_FAMILY_ID] == NULL) { + err = -NLE_MISSING_ATTR; + goto errout; + } + + family->ce_msgtype = info->nlh->nlmsg_type; + genl_family_set_id(family, + nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID])); + genl_family_set_name(family, + nla_get_string(info->attrs[CTRL_ATTR_FAMILY_NAME])); + + if (info->attrs[CTRL_ATTR_VERSION]) { + uint32_t version = nla_get_u32(info->attrs[CTRL_ATTR_VERSION]); + genl_family_set_version(family, version); + } + + if (info->attrs[CTRL_ATTR_HDRSIZE]) { + uint32_t hdrsize = nla_get_u32(info->attrs[CTRL_ATTR_HDRSIZE]); + genl_family_set_hdrsize(family, hdrsize); + } + + if (info->attrs[CTRL_ATTR_MAXATTR]) { + uint32_t maxattr = nla_get_u32(info->attrs[CTRL_ATTR_MAXATTR]); + genl_family_set_maxattr(family, maxattr); + } + + if (info->attrs[CTRL_ATTR_OPS]) { + struct nlattr *nla, *nla_ops; + int remaining; + + nla_ops = info->attrs[CTRL_ATTR_OPS]; + nla_for_each_nested(nla, nla_ops, remaining) { + struct nlattr *tb[CTRL_ATTR_OP_MAX+1]; + int flags = 0, id; + + err = nla_parse_nested(tb, CTRL_ATTR_OP_MAX, nla, + family_op_policy); + if (err < 0) + goto errout; + + if (tb[CTRL_ATTR_OP_ID] == NULL) { + err = -NLE_MISSING_ATTR; + goto errout; + } + + id = nla_get_u32(tb[CTRL_ATTR_OP_ID]); + + if (tb[CTRL_ATTR_OP_FLAGS]) + flags = nla_get_u32(tb[CTRL_ATTR_OP_FLAGS]); + + err = genl_family_add_op(family, id, flags); + if (err < 0) + goto errout; + + } + } + + if (info->attrs[CTRL_ATTR_MCAST_GROUPS]) { + err = parse_mcast_grps(family, info->attrs[CTRL_ATTR_MCAST_GROUPS]); + if (err < 0) + goto errout; + } + + err = pp->pp_cb((struct nl_object *) family, pp); +errout: + genl_family_put(family); + return err; +} + +/** + * process responses from from the query sent by genl_ctrl_probe_by_name + * @arg nl_msg Returned message. + * @arg name genl_family structure to fill out. + * + * Process returned messages, filling out the missing informatino in the + * genl_family structure + * + * @return Indicator to keep processing frames or not + * + */ +static int probe_response(struct nl_msg *msg, void *arg) +{ + struct nlattr *tb[CTRL_ATTR_MAX+1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct genl_family *ret = (struct genl_family *)arg; + + if (genlmsg_parse(nlh, 0, tb, CTRL_ATTR_MAX, ctrl_policy)) + return NL_SKIP; + + if (tb[CTRL_ATTR_FAMILY_ID]) + genl_family_set_id(ret, nla_get_u16(tb[CTRL_ATTR_FAMILY_ID])); + + if (tb[CTRL_ATTR_MCAST_GROUPS]) + if (parse_mcast_grps(ret, tb[CTRL_ATTR_MCAST_GROUPS]) < 0) + return NL_SKIP; + + return NL_STOP; +} + +/** + * Look up generic netlink family by family name querying the kernel directly + * @arg sk Socket. + * @arg name Family name. + * + * Directly query's the kernel for a given family name. The caller will own a + * reference on the returned object which needsd to be given back after usage + * using genl_family_put. + * + * Note: This API call differs from genl_ctrl_search_by_name in that it querys + * the kernel directly, alowing for module autoload to take place to resolve the + * family request. Using an nl_cache prevents that operation + * + * @return Generic netlink family object or NULL if no match was found. + */ +static struct genl_family *genl_ctrl_probe_by_name(struct nl_sock *sk, + const char *name) +{ + struct nl_msg *msg; + struct genl_family *ret; + struct nl_cb *cb, *orig; + int rc; + + ret = genl_family_alloc(); + if (!ret) + goto out; + + genl_family_set_name(ret, name); + + msg = nlmsg_alloc(); + if (!msg) + goto out_fam_free; + + if (!(orig = nl_socket_get_cb(sk))) + goto out_msg_free; + + cb = nl_cb_clone(orig); + nl_cb_put(orig); + if (!cb) + goto out_msg_free; + + if (!genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, + 0, 0, CTRL_CMD_GETFAMILY, 1)) { + BUG(); + goto out_cb_free; + } + + if (nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, name) < 0) + goto out_cb_free; + + rc = nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, probe_response, + (void *) ret); + if (rc < 0) + goto out_cb_free; + + rc = nl_send_auto_complete(sk, msg); + if (rc < 0) + goto out_cb_free; + + rc = nl_recvmsgs(sk, cb); + if (rc < 0) + goto out_cb_free; + + /* If search was successful, request may be ACKed after data */ + rc = wait_for_ack(sk); + if (rc < 0) + goto out_cb_free; + + if (genl_family_get_id(ret) != 0) { + nlmsg_free(msg); + nl_cb_put(cb); + return ret; + } + +out_cb_free: + nl_cb_put(cb); +out_msg_free: + nlmsg_free(msg); +out_fam_free: + genl_family_put(ret); + ret = NULL; +out: + return ret; +} + + +/** @endcond */ + +/** + * @name Controller Cache + * + * The controller cache allows to keep a local copy of the list of all + * kernel side registered Generic Netlink families to quickly resolve + * multiple Generic Netlink family names without requiring to communicate + * with the kernel for each resolving iteration. + * + * @{ + */ + +/** + * Allocate a new controller cache + * @arg sk Generic Netlink socket + * @arg result Pointer to store resulting cache + * + * Allocates a new cache mirroring the state of the controller and stores it + * in \c *result. The allocated cache will contain a list of all currently + * registered kernel side Generic Netlink families. The cache is meant to be + * used to resolve family names locally. + * + * @return 0 on success or a negative error code. + */ +int genl_ctrl_alloc_cache(struct nl_sock *sk, struct nl_cache **result) +{ + return nl_cache_alloc_and_fill(&genl_ctrl_ops, sk, result); +} + +/** + * Search controller cache for a numeric address match + * @arg cache Controller cache + * @arg id Numeric family identifier. + * + * Searches a previously allocated controller cache and looks for an entry + * that matches the specified numeric family identifier \c id. If a match + * is found successfully, the reference count of the matching object is + * increased by one before the objet is returned. + * + * @see genl_ctrl_alloc_cache() + * @see genl_ctrl_search_by_name() + * @see genl_family_put() + * + * @return Generic Netlink family object or NULL if no match was found. + */ +struct genl_family *genl_ctrl_search(struct nl_cache *cache, int id) +{ + struct genl_family *fam; + + if (cache->c_ops != &genl_ctrl_ops) + BUG(); + + nl_list_for_each_entry(fam, &cache->c_items, ce_list) { + if (fam->gf_id == id) { + nl_object_get((struct nl_object *) fam); + return fam; + } + } + + return NULL; +} + +/** + * Search controller cache for a family name match + * @arg cache Controller cache + * @arg name Name of Generic Netlink family + * + * Searches a previously allocated controller cache and looks for an entry + * that matches the specified family \c name. If a match is found successfully, + * the reference count of the matching object is increased by one before the + * objet is returned. + * + * @see genl_ctrl_alloc_cache() + * @see genl_ctrl_search() + * @see genl_family_put() + * + * @return Generic Netlink family object or NULL if no match was found. + */ +struct genl_family *genl_ctrl_search_by_name(struct nl_cache *cache, + const char *name) +{ + struct genl_family *fam; + + if (cache->c_ops != &genl_ctrl_ops) + BUG(); + + nl_list_for_each_entry(fam, &cache->c_items, ce_list) { + if (!strcmp(name, fam->gf_name)) { + nl_object_get((struct nl_object *) fam); + return fam; + } + } + + return NULL; +} + +/** @} */ + +/** + * @name Direct Resolvers + * + * These functions communicate directly with the kernel and do not require + * a cache to be kept up to date. + * + * @{ + */ + +/** + * Resolve Generic Netlink family name to numeric identifier + * @arg sk Generic Netlink socket. + * @arg name Name of Generic Netlink family + * + * Resolves the Generic Netlink family name to the corresponding numeric + * family identifier. This function queries the kernel directly, use + * genl_ctrl_search_by_name() if you need to resolve multiple names. + * + * @see genl_ctrl_search_by_name() + * + * @return The numeric family identifier or a negative error code. + */ +int genl_ctrl_resolve(struct nl_sock *sk, const char *name) +{ + struct genl_family *family; + int err; + + family = genl_ctrl_probe_by_name(sk, name); + if (family == NULL) { + err = -NLE_OBJ_NOTFOUND; + goto errout; + } + + err = genl_family_get_id(family); + genl_family_put(family); +errout: + return err; +} + +static int genl_ctrl_grp_by_name(const struct genl_family *family, + const char *grp_name) +{ + struct genl_family_grp *grp; + + nl_list_for_each_entry(grp, &family->gf_mc_grps, list) { + if (!strcmp(grp->name, grp_name)) { + return grp->id; + } + } + + return -NLE_OBJ_NOTFOUND; +} + +/** + * Resolve Generic Netlink family group name + * @arg sk Generic Netlink socket + * @arg family_name Name of Generic Netlink family + * @arg grp_name Name of group to resolve + * + * Looks up the family object and resolves the group name to the numeric + * group identifier. + * + * @return Numeric group identifier or a negative error code. + */ +int genl_ctrl_resolve_grp(struct nl_sock *sk, const char *family_name, + const char *grp_name) +{ + + struct genl_family *family; + int err; + + family = genl_ctrl_probe_by_name(sk, family_name); + if (family == NULL) { + err = -NLE_OBJ_NOTFOUND; + goto errout; + } + + err = genl_ctrl_grp_by_name(family, grp_name); + genl_family_put(family); +errout: + return err; +} + +/** @} */ + +/** @cond SKIP */ +static struct genl_cmd genl_cmds[] = { + { + .c_id = CTRL_CMD_NEWFAMILY, + .c_name = "NEWFAMILY" , + .c_maxattr = CTRL_ATTR_MAX, + .c_attr_policy = ctrl_policy, + .c_msg_parser = ctrl_msg_parser, + }, + { + .c_id = CTRL_CMD_DELFAMILY, + .c_name = "DELFAMILY" , + }, + { + .c_id = CTRL_CMD_GETFAMILY, + .c_name = "GETFAMILY" , + }, + { + .c_id = CTRL_CMD_NEWOPS, + .c_name = "NEWOPS" , + }, + { + .c_id = CTRL_CMD_DELOPS, + .c_name = "DELOPS" , + }, +}; + +static struct genl_ops genl_ops = { + .o_cmds = genl_cmds, + .o_ncmds = ARRAY_SIZE(genl_cmds), +}; + +extern struct nl_object_ops genl_family_ops; + +static struct nl_cache_ops genl_ctrl_ops = { + .co_name = "genl/family", + .co_hdrsize = GENL_HDRSIZE(0), + .co_msgtypes = GENL_FAMILY(GENL_ID_CTRL, "nlctrl"), + .co_genl = &genl_ops, + .co_protocol = NETLINK_GENERIC, + .co_request_update = ctrl_request_update, + .co_obj_ops = &genl_family_ops, +}; + +static void __init ctrl_init(void) +{ + genl_register(&genl_ctrl_ops); +} + +static void __exit ctrl_exit(void) +{ + genl_unregister(&genl_ctrl_ops); +} +/** @endcond */ + +/** @} */ diff --git a/lib/genl/family.c b/lib/genl/family.c new file mode 100644 index 0000000..897c809 --- /dev/null +++ b/lib/genl/family.c @@ -0,0 +1,402 @@ +/* + * lib/genl/family.c Generic Netlink Family + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +/** + * @ingroup genl_ctrl + * @defgroup genl_family Generic Netlink Family Object + * + * Object representing a kernel side registered Generic Netlink family + * + * @{ + */ + +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define FAMILY_ATTR_ID 0x01 +#define FAMILY_ATTR_NAME 0x02 +#define FAMILY_ATTR_VERSION 0x04 +#define FAMILY_ATTR_HDRSIZE 0x08 +#define FAMILY_ATTR_MAXATTR 0x10 +#define FAMILY_ATTR_OPS 0x20 + +struct nl_object_ops genl_family_ops; + +static void family_constructor(struct nl_object *c) +{ + struct genl_family *family = (struct genl_family *) c; + + nl_init_list_head(&family->gf_ops); + nl_init_list_head(&family->gf_mc_grps); +} + +static void family_free_data(struct nl_object *c) +{ + struct genl_family *family = (struct genl_family *) c; + struct genl_family_op *ops, *tmp; + struct genl_family_grp *grp, *t_grp; + + if (family == NULL) + return; + + nl_list_for_each_entry_safe(ops, tmp, &family->gf_ops, o_list) { + nl_list_del(&ops->o_list); + free(ops); + } + + nl_list_for_each_entry_safe(grp, t_grp, &family->gf_mc_grps, list) { + nl_list_del(&grp->list); + free(grp); + } + +} + +static int family_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct genl_family *dst = nl_object_priv(_dst); + struct genl_family *src = nl_object_priv(_src); + struct genl_family_op *ops; + struct genl_family_grp *grp; + int err; + + nl_list_for_each_entry(ops, &src->gf_ops, o_list) { + err = genl_family_add_op(dst, ops->o_id, ops->o_flags); + if (err < 0) + return err; + } + + nl_list_for_each_entry(grp, &src->gf_mc_grps, list) { + err = genl_family_add_grp(dst, grp->id, grp->name); + if (err < 0) + return err; + } + + + return 0; +} + +static void family_dump_line(struct nl_object *obj, struct nl_dump_params *p) +{ + struct genl_family *family = (struct genl_family *) obj; + + nl_dump(p, "0x%04x %s version %u\n", + family->gf_id, family->gf_name, family->gf_version); +} + +static const struct trans_tbl ops_flags[] = { + __ADD(GENL_ADMIN_PERM, admin_perm) + __ADD(GENL_CMD_CAP_DO, has_doit) + __ADD(GENL_CMD_CAP_DUMP, has_dump) + __ADD(GENL_CMD_CAP_HASPOL, has_policy) +}; + +static char *ops_flags2str(int flags, char *buf, size_t len) +{ + return __flags2str(flags, buf, len, ops_flags, ARRAY_SIZE(ops_flags)); +} + +static void family_dump_details(struct nl_object *obj, struct nl_dump_params *p) +{ + struct genl_family_grp *grp; + struct genl_family *family = (struct genl_family *) obj; + + family_dump_line(obj, p); + nl_dump_line(p, " hdrsize %u maxattr %u\n", + family->gf_hdrsize, family->gf_maxattr); + + if (family->ce_mask & FAMILY_ATTR_OPS) { + struct genl_family_op *op; + char buf[64]; + + nl_list_for_each_entry(op, &family->gf_ops, o_list) { + ops_flags2str(op->o_flags, buf, sizeof(buf)); + + genl_op2name(family->gf_id, op->o_id, buf, sizeof(buf)); + + nl_dump_line(p, " op %s (0x%02x)", buf, op->o_id); + + if (op->o_flags) + nl_dump(p, " <%s>", + ops_flags2str(op->o_flags, buf, + sizeof(buf))); + + nl_dump(p, "\n"); + } + } + + nl_list_for_each_entry(grp, &family->gf_mc_grps, list) { + nl_dump_line(p, " grp %s (0x%02x)\n", grp->name, grp->id); + } + +} + +static void family_dump_stats(struct nl_object *obj, struct nl_dump_params *p) +{ + family_dump_details(obj, p); +} + +static int family_compare(struct nl_object *_a, struct nl_object *_b, + uint32_t attrs, int flags) +{ + struct genl_family *a = (struct genl_family *) _a; + struct genl_family *b = (struct genl_family *) _b; + int diff = 0; + +#define FAM_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, FAMILY_ATTR_##ATTR, a, b, EXPR) + + diff |= FAM_DIFF(ID, a->gf_id != b->gf_id); + diff |= FAM_DIFF(VERSION, a->gf_version != b->gf_version); + diff |= FAM_DIFF(HDRSIZE, a->gf_hdrsize != b->gf_hdrsize); + diff |= FAM_DIFF(MAXATTR, a->gf_maxattr != b->gf_maxattr); + diff |= FAM_DIFF(NAME, strcmp(a->gf_name, b->gf_name)); + +#undef FAM_DIFF + + return diff; +} +/** @endcond */ + +/** + * @name Object Allocation + * @{ + */ + +/** + * Allocate new Generic Netlink family object + * + * @return Newly allocated Generic Netlink family object or NULL. + */ +struct genl_family *genl_family_alloc(void) +{ + return (struct genl_family *) nl_object_alloc(&genl_family_ops); +} + +/** + * Release reference on Generic Netlink family object + * @arg family Generic Netlink family object + * + * Reduces the reference counter of a Generic Netlink family object by one. + * The object is freed after the last user has returned its reference. + * + * @see nl_object_put() + */ +void genl_family_put(struct genl_family *family) +{ + nl_object_put((struct nl_object *) family); +} + +/** @} */ + +/** + * @name Numeric Identifier + * @{ + */ + +/** + * Return numeric identifier + * @arg family Generic Netlink family object + * + * @return Numeric identifier or 0 if not available. + */ +unsigned int genl_family_get_id(struct genl_family *family) +{ + if (family->ce_mask & FAMILY_ATTR_ID) + return family->gf_id; + else + return GENL_ID_GENERATE; +} + +/** + * Set the numeric identifier + * @arg family Generic Netlink family object + * @arg id New numeric identifier + */ +void genl_family_set_id(struct genl_family *family, unsigned int id) +{ + family->gf_id = id; + family->ce_mask |= FAMILY_ATTR_ID; +} + +/** @} */ + +/** + * @name Human Readable Name + * @{ + */ + +/** + * Return human readable name + * @arg family Generic Netlink family object + * + * @return Name of family or NULL if not available + */ +char *genl_family_get_name(struct genl_family *family) +{ + if (family->ce_mask & FAMILY_ATTR_NAME) + return family->gf_name; + else + return NULL; +} + +/** + * Set human readable name + * @arg family Generic Netlink family object + * @arg name New human readable name + */ +void genl_family_set_name(struct genl_family *family, const char *name) +{ + strncpy(family->gf_name, name, GENL_NAMSIZ-1); + family->ce_mask |= FAMILY_ATTR_NAME; +} + +/** + * @name Interface Version + * @{ + */ + +/** + * Return interface version + * @arg family Generic Netlink family object + * + * @return Interface version or 0 if not available. + */ +uint8_t genl_family_get_version(struct genl_family *family) +{ + if (family->ce_mask & FAMILY_ATTR_VERSION) + return family->gf_version; + else + return 0; +} + +/** + * Set interface version + * @arg family Generic Netlink family object + * @arg version New interface version + */ +void genl_family_set_version(struct genl_family *family, uint8_t version) +{ + family->gf_version = version; + family->ce_mask |= FAMILY_ATTR_VERSION; +} + +/** @} */ + +/** + * @name Header Size + * @{ + */ + +/** + * Return user header size expected by kernel component + * @arg family Generic Netlink family object + * + * @return Expected header length or 0 if not available. + */ +uint32_t genl_family_get_hdrsize(struct genl_family *family) +{ + if (family->ce_mask & FAMILY_ATTR_HDRSIZE) + return family->gf_hdrsize; + else + return 0; +} + +void genl_family_set_hdrsize(struct genl_family *family, uint32_t hdrsize) +{ + family->gf_hdrsize = hdrsize; + family->ce_mask |= FAMILY_ATTR_HDRSIZE; +} + +/** @} */ + +/** + * @name Maximum Expected Attribute + * @{ + */ + +uint32_t genl_family_get_maxattr(struct genl_family *family) +{ + if (family->ce_mask & FAMILY_ATTR_MAXATTR) + return family->gf_maxattr; + else + return family->gf_maxattr; +} + +void genl_family_set_maxattr(struct genl_family *family, uint32_t maxattr) +{ + family->gf_maxattr = maxattr; + family->ce_mask |= FAMILY_ATTR_MAXATTR; +} + +/** @} */ + +/** + * @name Operations + * @{ + */ + +int genl_family_add_op(struct genl_family *family, int id, int flags) +{ + struct genl_family_op *op; + + op = calloc(1, sizeof(*op)); + if (op == NULL) + return -NLE_NOMEM; + + op->o_id = id; + op->o_flags = flags; + + nl_list_add_tail(&op->o_list, &family->gf_ops); + family->ce_mask |= FAMILY_ATTR_OPS; + + return 0; +} + +int genl_family_add_grp(struct genl_family *family, uint32_t id, + const char *name) +{ + struct genl_family_grp *grp; + + grp = calloc(1, sizeof(*grp)); + if (grp == NULL) + return -NLE_NOMEM; + + grp->id = id; + strncpy(grp->name, name, GENL_NAMSIZ - 1); + + nl_list_add_tail(&grp->list, &family->gf_mc_grps); + + return 0; +} + +/** @} */ + +/** @cond SKIP */ +struct nl_object_ops genl_family_ops = { + .oo_name = "genl/family", + .oo_size = sizeof(struct genl_family), + .oo_constructor = family_constructor, + .oo_free_data = family_free_data, + .oo_clone = family_clone, + .oo_dump = { + [NL_DUMP_LINE] = family_dump_line, + [NL_DUMP_DETAILS] = family_dump_details, + [NL_DUMP_STATS] = family_dump_stats, + }, + .oo_compare = family_compare, + .oo_id_attrs = FAMILY_ATTR_ID, +}; +/** @endcond */ + +/** @} */ diff --git a/lib/genl/genl.c b/lib/genl/genl.c new file mode 100644 index 0000000..0c9b11e --- /dev/null +++ b/lib/genl/genl.c @@ -0,0 +1,391 @@ +/* + * lib/genl/genl.c Generic Netlink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +/** + * @defgroup genl Generic Netlink Library (libnl-genl) + * + * @{ + */ + +#include +#include +#include +#include + +/** + * @name Generic Netlink Socket + * @{ + */ + +/** + * Connect a Generic Netlink socket + * @arg sk Unconnected Netlink socket + * + * This function expects a struct nl_socket object previously allocated via + * nl_socket_alloc(). It calls nl_connect() to create the local socket file + * descriptor and binds the socket to the \c NETLINK_GENERIC Netlink protocol. + * + * Using this function is equivalent to: + * @code + * nl_connect(sk, NETLINK_GENERIC); + * @endcode + * + * @see nl_connect() + * + * @return 0 on success or a negative error code. + */ +int genl_connect(struct nl_sock *sk) +{ + return nl_connect(sk, NETLINK_GENERIC); +} + +/** @} */ + +/** + * @name Sending Data + * @{ + */ + +/** + * Send a Generic Netlink message consisting only of a header + * @arg sk Generic Netlink socket + * @arg family Numeric family identifier + * @arg cmd Numeric command identifier + * @arg version Interface version + * @arg flags Additional Netlink message flags (optional) + * + * This function is a shortcut for sending a Generic Netlink message without + * any message payload. The message will only consist of the Netlink and + * Generic Netlink headers. The header is constructed based on the specified + * parameters and passed on to nl_send_simple() to send it on the specified + * socket. + * + * @par Example: + * @code + * #include + * #include + * + * err = genl_send_simple(sk, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, CTRL_VERSION, + * NLM_F_DUMP); + * @endcode + * + * @see nl_send_simple() + * + * @return 0 on success or a negative error code. + */ +int genl_send_simple(struct nl_sock *sk, int family, int cmd, + int version, int flags) +{ + struct genlmsghdr hdr = { + .cmd = cmd, + .version = version, + }; + + return nl_send_simple(sk, family, flags, &hdr, sizeof(hdr)); +} + +/** @} */ + +/** + * @name Message Parsing + * @{ + */ + +/** + * Validate Generic Netlink message headers + * @arg nlh Pointer to Netlink message header + * @arg hdrlen Length of user header + * + * Verifies the integrity of the Netlink and Generic Netlink headers by + * enforcing the following requirements: + * - Valid Netlink message header (nlmsg_valid_hdr()) + * - Presence of a complete Generic Netlink header + * - At least \c hdrlen bytes of payload included after the generic + * netlink header. + * + * @return A positive integer (true) if the headers are valid or + * 0 (false) if not. + */ +int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen) +{ + struct genlmsghdr *ghdr; + + if (!nlmsg_valid_hdr(nlh, GENL_HDRLEN)) + return 0; + + ghdr = nlmsg_data(nlh); + if (genlmsg_len(ghdr) < NLMSG_ALIGN(hdrlen)) + return 0; + + return 1; +} + +/** + * Validate Generic Netlink message including attributes + * @arg nlh Pointer to Netlink message header + * @arg hdrlen Length of user header + * @arg maxtype Maximum attribtue id expected + * @arg policy Attribute validation policy + * + * Verifies the validity of the Netlink and Generic Netlink headers using + * genlmsg_valid_hdr() and calls nla_validate() on the message payload to + * verify the integrity of eventual attributes. + * + * @note You may call genlmsg_parse() directly to perform validation and + * parsing in a single step. + * + * @see genlmsg_valid_hdr() + * @see nla_validate() + * @see genlmsg_parse() + * + * @return 0 on success or a negative error code. + */ +int genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype, + struct nla_policy *policy) +{ + struct genlmsghdr *ghdr; + + if (!genlmsg_valid_hdr(nlh, hdrlen)) + return -NLE_MSG_TOOSHORT; + + ghdr = nlmsg_data(nlh); + return nla_validate(genlmsg_attrdata(ghdr, hdrlen), + genlmsg_attrlen(ghdr, hdrlen), maxtype, policy); +} + +/** + * Parse Generic Netlink message including attributes + * @arg nlh Pointer to Netlink message header + * @arg hdrlen Length of user header + * @arg tb Array to store parsed attributes + * @arg maxtype Maximum attribute id expected + * @arg policy Attribute validation policy + * + * Verifies the validity of the Netlink and Generic Netlink headers using + * genlmsg_valid_hdr() and calls nla_parse() on the message payload to + * parse eventual attributes. + * + * @par Example: + * @code + * struct nlattr *attrs[MY_TYPE_MAX+1]; + * + * if ((err = genlsmg_parse(nlmsg_nlh(msg), sizeof(struct my_hdr), attrs, + * MY_TYPE_MAX, attr_policy)) < 0) + * // ERROR + * @endcode + * + * @see genlmsg_valid_hdr() + * @see genlmsg_validate() + * @see nla_parse() + * + * @return 0 on success or a negative error code. + */ +int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], + int maxtype, struct nla_policy *policy) +{ + struct genlmsghdr *ghdr; + + if (!genlmsg_valid_hdr(nlh, hdrlen)) + return -NLE_MSG_TOOSHORT; + + ghdr = nlmsg_data(nlh); + return nla_parse(tb, maxtype, genlmsg_attrdata(ghdr, hdrlen), + genlmsg_attrlen(ghdr, hdrlen), policy); +} + +/** + * Return pointer to Generic Netlink header + * @arg nlh Netlink message header + * + * @return Pointer to Generic Netlink message header + */ +struct genlmsghdr *genlmsg_hdr(struct nlmsghdr *nlh) +{ + return nlmsg_data(nlh); +} + +/** + * Return length of message payload including user header + * @arg gnlh Generic Netlink message header + * + * @see genlmsg_data() + * + * @return Length of user payload including an eventual user header in + * number of bytes. + */ +int genlmsg_len(const struct genlmsghdr *gnlh) +{ + const struct nlmsghdr *nlh; + + nlh = (const struct nlmsghdr *)((const unsigned char *) gnlh - NLMSG_HDRLEN); + return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN); +} + + +/** + * Return pointer to user header + * @arg gnlh Generic Netlink message header + * + * Calculates the pointer to the user header based on the pointer to + * the Generic Netlink message header. + * + * @return Pointer to the user header + */ +void *genlmsg_user_hdr(const struct genlmsghdr *gnlh) +{ + return genlmsg_data(gnlh); +} + +/** + * Return pointer to user data + * @arg gnlh Generic netlink message header + * @arg hdrlen Length of user header + * + * Calculates the pointer to the user data based on the pointer to + * the Generic Netlink message header. + * + * @see genlmsg_user_datalen() + * + * @return Pointer to the user data + */ +void *genlmsg_user_data(const struct genlmsghdr *gnlh, const int hdrlen) +{ + return genlmsg_user_hdr(gnlh) + NLMSG_ALIGN(hdrlen); +} + +/** + * Return length of user data + * @arg gnlh Generic Netlink message header + * @arg hdrlen Length of user header + * + * @see genlmsg_user_data() + * + * @return Length of user data in bytes + */ +int genlmsg_user_datalen(const struct genlmsghdr *gnlh, const int hdrlen) +{ + return genlmsg_len(gnlh) - NLMSG_ALIGN(hdrlen); +} + +/** + * Return pointer to message attributes + * @arg gnlh Generic Netlink message header + * @arg hdrlen Length of user header + * + * @see genlmsg_attrlen() + * + * @return Pointer to the start of the message's attributes section. + */ +struct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen) +{ + return genlmsg_user_data(gnlh, hdrlen); +} + +/** + * Return length of message attributes + * @arg gnlh Generic Netlink message header + * @arg hdrlen Length of user header + * + * @see genlmsg_attrdata() + * + * @return Length of the message section containing attributes in number + * of bytes. + */ +int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen) +{ + return genlmsg_len(gnlh) - NLMSG_ALIGN(hdrlen); +} + +/** @} */ + +/** + * @name Message Construction + * @{ + */ + +/** + * Add Generic Netlink headers to Netlink message + * @arg msg Netlink message object + * @arg port Netlink port or NL_AUTO_PORT + * @arg seq Sequence number of message or NL_AUTO_SEQ + * @arg family Numeric family identifier + * @arg hdrlen Length of user header + * @arg flags Additional Netlink message flags (optional) + * @arg cmd Numeric command identifier + * @arg version Interface version + * + * Calls nlmsg_put() on the specified message object to reserve space for + * the Netlink header, the Generic Netlink header, and a user header of + * specified length. Fills out the header fields with the specified + * parameters. + * + * @par Example: + * @code + * struct nl_msg *msg; + * struct my_hdr *user_hdr; + * + * if (!(msg = nlmsg_alloc())) + * // ERROR + * + * user_hdr = genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, family_id, + * sizeof(struct my_hdr), 0, MY_CMD_FOO, 0); + * if (!user_hdr) + * // ERROR + * @endcode + * + * @see nlmsg_put() + * + * Returns Pointer to user header or NULL if an error occurred. + */ +void *genlmsg_put(struct nl_msg *msg, uint32_t port, uint32_t seq, int family, + int hdrlen, int flags, uint8_t cmd, uint8_t version) +{ + struct nlmsghdr *nlh; + struct genlmsghdr hdr = { + .cmd = cmd, + .version = version, + }; + + nlh = nlmsg_put(msg, port, seq, family, GENL_HDRLEN + hdrlen, flags); + if (nlh == NULL) + return NULL; + + memcpy(nlmsg_data(nlh), &hdr, sizeof(hdr)); + NL_DBG(2, "msg %p: Added generic netlink header cmd=%d version=%d\n", + msg, cmd, version); + + return nlmsg_data(nlh) + GENL_HDRLEN; +} + +/** @} */ + +/** + * @name Deprecated + * @{ + */ + +/** + * Return pointer to message payload + * @arg gnlh Generic Netlink message header + * + * @deprecated This function has been deprecated due to inability to specify + * the length of the user header. Use genlmsg_user_hdr() + * respectively genlmsg_user_data(). + * + * @return Pointer to payload section + */ +void *genlmsg_data(const struct genlmsghdr *gnlh) +{ + return ((unsigned char *) gnlh + GENL_HDRLEN); +} + +/** @} */ +/** @} */ diff --git a/lib/genl/mngt.c b/lib/genl/mngt.c new file mode 100644 index 0000000..3648663 --- /dev/null +++ b/lib/genl/mngt.c @@ -0,0 +1,399 @@ +/* + * lib/genl/mngt.c Generic Netlink Management + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +/** + * @ingroup genl + * @defgroup genl_mngt Family and Command Registration + * + * Registering Generic Netlink Families and Commands + * + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ + +static NL_LIST_HEAD(genl_ops_list); + +static struct genl_cmd *lookup_cmd(struct genl_ops *ops, int cmd_id) +{ + struct genl_cmd *cmd; + int i; + + for (i = 0; i < ops->o_ncmds; i++) { + cmd = &ops->o_cmds[i]; + if (cmd->c_id == cmd_id) + return cmd; + } + + return NULL; +} + +static int cmd_msg_parser(struct sockaddr_nl *who, struct nlmsghdr *nlh, + struct genl_ops *ops, struct nl_cache_ops *cache_ops, void *arg) +{ + int err; + struct genlmsghdr *ghdr; + struct genl_cmd *cmd; + + ghdr = genlmsg_hdr(nlh); + + if (!(cmd = lookup_cmd(ops, ghdr->cmd))) { + err = -NLE_MSGTYPE_NOSUPPORT; + goto errout; + } + + if (cmd->c_msg_parser == NULL) + err = -NLE_OPNOTSUPP; + else { + struct nlattr *tb[cmd->c_maxattr + 1]; + struct genl_info info = { + .who = who, + .nlh = nlh, + .genlhdr = ghdr, + .userhdr = genlmsg_user_hdr(ghdr), + .attrs = tb, + }; + + err = nlmsg_parse(nlh, GENL_HDRSIZE(ops->o_hdrsize), tb, cmd->c_maxattr, + cmd->c_attr_policy); + if (err < 0) + goto errout; + + err = cmd->c_msg_parser(cache_ops, cmd, &info, arg); + } +errout: + return err; + +} + +static int genl_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *nlh, struct nl_parser_param *pp) +{ + if (ops->co_genl == NULL) + BUG(); + + return cmd_msg_parser(who, nlh, ops->co_genl, ops, pp); +} + +static struct genl_ops *lookup_family(int family) +{ + struct genl_ops *ops; + + nl_list_for_each_entry(ops, &genl_ops_list, o_list) { + if (ops->o_id == family) + return ops; + } + + return NULL; +} + +static struct genl_ops *lookup_family_by_name(const char *name) +{ + struct genl_ops *ops; + + nl_list_for_each_entry(ops, &genl_ops_list, o_list) { + if (!strcmp(ops->o_name, name)) + return ops; + } + + return NULL; +} + +char *genl_op2name(int family, int op, char *buf, size_t len) +{ + struct genl_ops *ops; + int i; + + if ((ops = lookup_family(family))) { + for (i = 0; i < ops->o_ncmds; i++) { + struct genl_cmd *cmd; + cmd = &ops->o_cmds[i]; + + if (cmd->c_id == op) { + strncpy(buf, cmd->c_name, len - 1); + return buf; + } + } + } + + strncpy(buf, "unknown", len - 1); + return NULL; +} + +/** @endcond */ + +/** + * @name Registration + * @{ + */ + +/** + * Register Generic Netlink family and associated commands + * @arg ops Generic Netlink family definition + * + * Registers the specified Generic Netlink family definition together with + * all associated commands. After registration, received Generic Netlink + * messages can be passed to genl_handle_msg() which will validate the + * messages, look for a matching command and call the respective callback + * function automatically. + * + * @note Consider using genl_register() if the family is used to implement a + * cacheable type. + * + * @see genl_unregister_family(); + * @see genl_register(); + * + * @return 0 on success or a negative error code. + */ +int genl_register_family(struct genl_ops *ops) +{ + if (!ops->o_name) + return -NLE_INVAL; + + if (ops->o_cmds && ops->o_ncmds <= 0) + return -NLE_INVAL; + + if (ops->o_id && lookup_family(ops->o_id)) + return -NLE_EXIST; + + if (lookup_family_by_name(ops->o_name)) + return -NLE_EXIST; + + nl_list_add_tail(&ops->o_list, &genl_ops_list); + + return 0; +} + +/** + * Unregister Generic Netlink family + * @arg ops Generic Netlink family definition + * + * Unregisters a family and all associated commands that were previously + * registered using genl_register_family(). + * + * @see genl_register_family() + * + * @return 0 on success or a negative error code. + */ +int genl_unregister_family(struct genl_ops *ops) +{ + nl_list_del(&ops->o_list); + + return 0; +} + +/** + * Run a received message through the demultiplexer + * @arg msg Generic Netlink message + * @arg arg Argument passed on to the message handler callback + * + * @return 0 on success or a negative error code. + */ +int genl_handle_msg(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct genl_ops *ops; + + if (!genlmsg_valid_hdr(nlh, 0)) + return -NLE_INVAL; + + if (!(ops = lookup_family(nlh->nlmsg_type))) + return -NLE_MSGTYPE_NOSUPPORT; + + return cmd_msg_parser(nlmsg_get_src(msg), nlh, ops, NULL, arg); +} + +/** @} */ + +/** + * @name Registration of Cache Operations + * @{ + */ + +/** + * Register Generic Netlink family backed cache + * @arg ops Cache operations definition + * + * Same as genl_register_family() but additionally registers the specified + * cache operations using nl_cache_mngt_register() and associates it with + * the Generic Netlink family. + * + * @see genl_register_family() + * + * @return 0 on success or a negative error code. + */ +int genl_register(struct nl_cache_ops *ops) +{ + int err; + + if (ops->co_protocol != NETLINK_GENERIC) { + err = -NLE_PROTO_MISMATCH; + goto errout; + } + + if (ops->co_hdrsize < GENL_HDRSIZE(0)) { + err = -NLE_INVAL; + goto errout; + } + + if (ops->co_genl == NULL) { + err = -NLE_INVAL; + goto errout; + } + + ops->co_genl->o_cache_ops = ops; + ops->co_genl->o_hdrsize = ops->co_hdrsize - GENL_HDRLEN; + ops->co_genl->o_name = ops->co_msgtypes[0].mt_name; + ops->co_genl->o_id = ops->co_msgtypes[0].mt_id; + ops->co_msg_parser = genl_msg_parser; + + if ((err = genl_register_family(ops->co_genl)) < 0) + goto errout; + + err = nl_cache_mngt_register(ops); +errout: + return err; +} + +/** + * Unregister cache based Generic Netlink family + * @arg ops Cache operations definition + */ +void genl_unregister(struct nl_cache_ops *ops) +{ + if (!ops) + return; + + nl_cache_mngt_unregister(ops); + + genl_unregister_family(ops->co_genl); +} + +/** @} */ + +/** @cond SKIP */ +static int __genl_ops_resolve(struct nl_cache *ctrl, struct genl_ops *ops) +{ + struct genl_family *family; + + family = genl_ctrl_search_by_name(ctrl, ops->o_name); + if (family != NULL) { + ops->o_id = genl_family_get_id(family); + + if (ops->o_cache_ops) + ops->o_cache_ops->co_msgtypes[0].mt_id = ops->o_id; + + genl_family_put(family); + + return 0; + } + + return -NLE_OBJ_NOTFOUND; +} + +int genl_resolve_id(struct genl_ops *ops) +{ + struct nl_sock *sk; + int err = 0; + + /* Check if resolved already */ + if (ops->o_id != GENL_ID_GENERATE) + return 0; + + if (!ops->o_name) + return -NLE_INVAL; + + if (!(sk = nl_socket_alloc())) + return -NLE_NOMEM; + + if ((err = genl_connect(sk)) < 0) + goto errout_free; + + err = genl_ops_resolve(sk, ops); + +errout_free: + nl_socket_free(sk); + + return err; +} +/** @endcond */ + +/** + * @name Resolving the name of registered families + * @{ + */ + +/** + * Resolve a single Generic Netlink family + * @arg sk Generic Netlink socket + * @arg ops Generic Netlink family definition + * + * Resolves the family name to its numeric identifier. + * + * @return 0 on success or a negative error code. + */ +int genl_ops_resolve(struct nl_sock *sk, struct genl_ops *ops) +{ + struct nl_cache *ctrl; + int err; + + if ((err = genl_ctrl_alloc_cache(sk, &ctrl)) < 0) + goto errout; + + err = __genl_ops_resolve(ctrl, ops); + + nl_cache_free(ctrl); +errout: + return err; +} + +/** + * Resolve all registered Generic Netlink families + * @arg sk Generic Netlink socket + * + * Walks through all local Generic Netlink families that have been registered + * using genl_register() and resolves the name of each family to the + * corresponding numeric identifier. + * + * @see genl_register() + * @see genl_ops_resolve() + * + * @return 0 on success or a negative error code. + */ +int genl_mngt_resolve(struct nl_sock *sk) +{ + struct nl_cache *ctrl; + struct genl_ops *ops; + int err = 0; + + if ((err = genl_ctrl_alloc_cache(sk, &ctrl)) < 0) + goto errout; + + nl_list_for_each_entry(ops, &genl_ops_list, o_list) { + err = __genl_ops_resolve(ctrl, ops); + } + + nl_cache_free(ctrl); +errout: + return err; +} + +/** @} */ + +/** @} */ diff --git a/lib/handlers.c b/lib/handlers.c new file mode 100644 index 0000000..e52c850 --- /dev/null +++ b/lib/handlers.c @@ -0,0 +1,391 @@ +/* + * lib/handlers.c default netlink message handlers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + */ + +/** + * @ingroup core + * @defgroup cb Callbacks/Customization + * + * Related sections in the development guide: + * - @core_doc{core_cb, Callback Configuration} + * + * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ + */ + +#include +#include +#include +#include +#include + +static void print_header_content(FILE *ofd, struct nlmsghdr *n) +{ + char flags[128]; + char type[32]; + + fprintf(ofd, "type=%s length=%u flags=<%s> sequence-nr=%u pid=%u", + nl_nlmsgtype2str(n->nlmsg_type, type, sizeof(type)), + n->nlmsg_len, nl_nlmsg_flags2str(n->nlmsg_flags, flags, + sizeof(flags)), n->nlmsg_seq, n->nlmsg_pid); +} + +static int nl_valid_handler_verbose(struct nl_msg *msg, void *arg) +{ + FILE *ofd = arg ? arg : stdout; + + fprintf(ofd, "-- Warning: unhandled valid message: "); + print_header_content(ofd, nlmsg_hdr(msg)); + fprintf(ofd, "\n"); + + return NL_OK; +} + +static int nl_invalid_handler_verbose(struct nl_msg *msg, void *arg) +{ + FILE *ofd = arg ? arg : stderr; + + fprintf(ofd, "-- Error: Invalid message: "); + print_header_content(ofd, nlmsg_hdr(msg)); + fprintf(ofd, "\n"); + + return NL_STOP; +} + +static int nl_overrun_handler_verbose(struct nl_msg *msg, void *arg) +{ + FILE *ofd = arg ? arg : stderr; + + fprintf(ofd, "-- Error: Netlink Overrun: "); + print_header_content(ofd, nlmsg_hdr(msg)); + fprintf(ofd, "\n"); + + return NL_STOP; +} + +static int nl_error_handler_verbose(struct sockaddr_nl *who, + struct nlmsgerr *e, void *arg) +{ + FILE *ofd = arg ? arg : stderr; + char buf[256]; + + fprintf(ofd, "-- Error received: %s\n-- Original message: ", + strerror_r(-e->error, buf, sizeof(buf))); + print_header_content(ofd, &e->msg); + fprintf(ofd, "\n"); + + return -nl_syserr2nlerr(e->error); +} + +static int nl_valid_handler_debug(struct nl_msg *msg, void *arg) +{ + FILE *ofd = arg ? arg : stderr; + + fprintf(ofd, "-- Debug: Unhandled Valid message: "); + print_header_content(ofd, nlmsg_hdr(msg)); + fprintf(ofd, "\n"); + + return NL_OK; +} + +static int nl_finish_handler_debug(struct nl_msg *msg, void *arg) +{ + FILE *ofd = arg ? arg : stderr; + + fprintf(ofd, "-- Debug: End of multipart message block: "); + print_header_content(ofd, nlmsg_hdr(msg)); + fprintf(ofd, "\n"); + + return NL_STOP; +} + +static int nl_msg_in_handler_debug(struct nl_msg *msg, void *arg) +{ + FILE *ofd = arg ? arg : stderr; + + fprintf(ofd, "-- Debug: Received Message:\n"); + nl_msg_dump(msg, ofd); + + return NL_OK; +} + +static int nl_msg_out_handler_debug(struct nl_msg *msg, void *arg) +{ + FILE *ofd = arg ? arg : stderr; + + fprintf(ofd, "-- Debug: Sent Message:\n"); + nl_msg_dump(msg, ofd); + + return NL_OK; +} + +static int nl_skipped_handler_debug(struct nl_msg *msg, void *arg) +{ + FILE *ofd = arg ? arg : stderr; + + fprintf(ofd, "-- Debug: Skipped message: "); + print_header_content(ofd, nlmsg_hdr(msg)); + fprintf(ofd, "\n"); + + return NL_SKIP; +} + +static int nl_ack_handler_debug(struct nl_msg *msg, void *arg) +{ + FILE *ofd = arg ? arg : stderr; + + fprintf(ofd, "-- Debug: ACK: "); + print_header_content(ofd, nlmsg_hdr(msg)); + fprintf(ofd, "\n"); + + return NL_STOP; +} + +static nl_recvmsg_msg_cb_t cb_def[NL_CB_TYPE_MAX+1][NL_CB_KIND_MAX+1] = { + [NL_CB_VALID] = { + [NL_CB_VERBOSE] = nl_valid_handler_verbose, + [NL_CB_DEBUG] = nl_valid_handler_debug, + }, + [NL_CB_FINISH] = { + [NL_CB_DEBUG] = nl_finish_handler_debug, + }, + [NL_CB_INVALID] = { + [NL_CB_VERBOSE] = nl_invalid_handler_verbose, + [NL_CB_DEBUG] = nl_invalid_handler_verbose, + }, + [NL_CB_MSG_IN] = { + [NL_CB_DEBUG] = nl_msg_in_handler_debug, + }, + [NL_CB_MSG_OUT] = { + [NL_CB_DEBUG] = nl_msg_out_handler_debug, + }, + [NL_CB_OVERRUN] = { + [NL_CB_VERBOSE] = nl_overrun_handler_verbose, + [NL_CB_DEBUG] = nl_overrun_handler_verbose, + }, + [NL_CB_SKIPPED] = { + [NL_CB_DEBUG] = nl_skipped_handler_debug, + }, + [NL_CB_ACK] = { + [NL_CB_DEBUG] = nl_ack_handler_debug, + }, +}; + +static nl_recvmsg_err_cb_t cb_err_def[NL_CB_KIND_MAX+1] = { + [NL_CB_VERBOSE] = nl_error_handler_verbose, + [NL_CB_DEBUG] = nl_error_handler_verbose, +}; + +/** + * @name Callback Handle Management + * @{ + */ + +/** + * Allocate a new callback handle + * @arg kind callback kind to be used for initialization + * @return Newly allocated callback handle or NULL + */ +struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind) +{ + int i; + struct nl_cb *cb; + + if (kind < 0 || kind > NL_CB_KIND_MAX) + return NULL; + + cb = calloc(1, sizeof(*cb)); + if (!cb) + return NULL; + + cb->cb_refcnt = 1; + + for (i = 0; i <= NL_CB_TYPE_MAX; i++) + nl_cb_set(cb, i, kind, NULL, NULL); + + nl_cb_err(cb, kind, NULL, NULL); + + return cb; +} + +/** + * Clone an existing callback handle + * @arg orig original callback handle + * @return Newly allocated callback handle being a duplicate of + * orig or NULL + */ +struct nl_cb *nl_cb_clone(struct nl_cb *orig) +{ + struct nl_cb *cb; + + cb = nl_cb_alloc(NL_CB_DEFAULT); + if (!cb) + return NULL; + + memcpy(cb, orig, sizeof(*orig)); + cb->cb_refcnt = 1; + + return cb; +} + +struct nl_cb *nl_cb_get(struct nl_cb *cb) +{ + cb->cb_refcnt++; + + return cb; +} + +void nl_cb_put(struct nl_cb *cb) +{ + if (!cb) + return; + + cb->cb_refcnt--; + + if (cb->cb_refcnt < 0) + BUG(); + + if (cb->cb_refcnt <= 0) + free(cb); +} + +/** @} */ + +/** + * @name Callback Setup + * @{ + */ + +/** + * Set up a callback + * @arg cb callback set + * @arg type callback to modify + * @arg kind kind of implementation + * @arg func callback function (NL_CB_CUSTOM) + * @arg arg argument passed to callback + * + * @return 0 on success or a negative error code + */ +int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind, + nl_recvmsg_msg_cb_t func, void *arg) +{ + if (type < 0 || type > NL_CB_TYPE_MAX) + return -NLE_RANGE; + + if (kind < 0 || kind > NL_CB_KIND_MAX) + return -NLE_RANGE; + + if (kind == NL_CB_CUSTOM) { + cb->cb_set[type] = func; + cb->cb_args[type] = arg; + } else { + cb->cb_set[type] = cb_def[type][kind]; + cb->cb_args[type] = arg; + } + + return 0; +} + +/** + * Set up a all callbacks + * @arg cb callback set + * @arg kind kind of callback + * @arg func callback function + * @arg arg argument to be passwd to callback function + * + * @return 0 on success or a negative error code + */ +int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind, + nl_recvmsg_msg_cb_t func, void *arg) +{ + int i, err; + + for (i = 0; i <= NL_CB_TYPE_MAX; i++) { + err = nl_cb_set(cb, i, kind, func, arg); + if (err < 0) + return err; + } + + return 0; +} + +/** + * Set up an error callback + * @arg cb callback set + * @arg kind kind of callback + * @arg func callback function + * @arg arg argument to be passed to callback function + */ +int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind, + nl_recvmsg_err_cb_t func, void *arg) +{ + if (kind < 0 || kind > NL_CB_KIND_MAX) + return -NLE_RANGE; + + if (kind == NL_CB_CUSTOM) { + cb->cb_err = func; + cb->cb_err_arg = arg; + } else { + cb->cb_err = cb_err_def[kind]; + cb->cb_err_arg = arg; + } + + return 0; +} + +/** @} */ + +/** + * @name Overwriting + * @{ + */ + +/** + * Overwrite internal calls to nl_recvmsgs() + * @arg cb callback set + * @arg func replacement callback for nl_recvmsgs() + */ +void nl_cb_overwrite_recvmsgs(struct nl_cb *cb, + int (*func)(struct nl_sock *, struct nl_cb *)) +{ + cb->cb_recvmsgs_ow = func; +} + +/** + * Overwrite internal calls to nl_recv() + * @arg cb callback set + * @arg func replacement callback for nl_recv() + */ +void nl_cb_overwrite_recv(struct nl_cb *cb, + int (*func)(struct nl_sock *, struct sockaddr_nl *, + unsigned char **, struct ucred **)) +{ + cb->cb_recv_ow = func; +} + +/** + * Overwrite internal calls to nl_send() + * @arg cb callback set + * @arg func replacement callback for nl_send() + */ +void nl_cb_overwrite_send(struct nl_cb *cb, + int (*func)(struct nl_sock *, struct nl_msg *)) +{ + cb->cb_send_ow = func; +} + +/** @} */ + +/** @} */ diff --git a/lib/hash.c b/lib/hash.c new file mode 100644 index 0000000..47c938b --- /dev/null +++ b/lib/hash.c @@ -0,0 +1,482 @@ +/* + * This code was taken from http://ccodearchive.net/info/hash.html + * The original file was modified to remove unwanted code + * and some changes to fit the current build environment + */ +/* +------------------------------------------------------------------------------- +lookup3.c, by Bob Jenkins, May 2006, Public Domain. + +These are functions for producing 32-bit hashes for hash table lookup. +hash_word(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() +are externally useful functions. Routines to test the hash are included +if SELF_TEST is defined. You can use this free for any purpose. It's in +the public domain. It has no warranty. + +You probably want to use hashlittle(). hashlittle() and hashbig() +hash byte arrays. hashlittle() is is faster than hashbig() on +little-endian machines. Intel and AMD are little-endian machines. +On second thought, you probably want hashlittle2(), which is identical to +hashlittle() except it returns two 32-bit hashes for the price of one. +You could implement hashbig2() if you wanted but I haven't bothered here. + +If you want to find a hash of, say, exactly 7 integers, do + a = i1; b = i2; c = i3; + mix(a,b,c); + a += i4; b += i5; c += i6; + mix(a,b,c); + a += i7; + final(a,b,c); +then use c as the hash value. If you have a variable length array of +4-byte integers to hash, use hash_word(). If you have a byte array (like +a character string), use hashlittle(). If you have several byte arrays, or +a mix of things, see the comments above hashlittle(). + +Why is this so big? I read 12 bytes at a time into 3 4-byte integers, +then mix those integers. This is fast (you can do a lot more thorough +mixing with 12*3 instructions on 3 integers than you can with 3 instructions +on 1 byte), but shoehorning those bytes into integers efficiently is messy. +------------------------------------------------------------------------------- +*/ +#include + +#if HAVE_LITTLE_ENDIAN +#define HASH_LITTLE_ENDIAN 1 +#define HASH_BIG_ENDIAN 0 +#elif HAVE_BIG_ENDIAN +#define HASH_LITTLE_ENDIAN 0 +#define HASH_BIG_ENDIAN 1 +#else +#error Unknown endian +#endif + +#define hashsize(n) ((uint32_t)1<<(n)) +#define hashmask(n) (hashsize(n)-1) +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) + +/* +------------------------------------------------------------------------------- +mix -- mix 3 32-bit values reversibly. + +This is reversible, so any information in (a,b,c) before mix() is +still in (a,b,c) after mix(). + +If four pairs of (a,b,c) inputs are run through mix(), or through +mix() in reverse, there are at least 32 bits of the output that +are sometimes the same for one pair and different for another pair. +This was tested for: +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that +satisfy this are + 4 6 8 16 19 4 + 9 15 3 18 27 15 + 14 9 3 7 17 3 +Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing +for "differ" defined as + with a one-bit base and a two-bit delta. I +used http://burtleburtle.net/bob/hash/avalanche.html to choose +the operations, constants, and arrangements of the variables. + +This does not achieve avalanche. There are input bits of (a,b,c) +that fail to affect some output bits of (a,b,c), especially of a. The +most thoroughly mixed value is c, but it doesn't really even achieve +avalanche in c. + +This allows some parallelism. Read-after-writes are good at doubling +the number of bits affected, so the goal of mixing pulls in the opposite +direction as the goal of parallelism. I did what I could. Rotates +seem to cost as much as shifts on every machine I could lay my hands +on, and rotates are much kinder to the top and bottom bits, so I used +rotates. +------------------------------------------------------------------------------- +*/ +#define mix(a,b,c) \ +{ \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ +} + +/* +------------------------------------------------------------------------------- +final -- final mixing of 3 32-bit values (a,b,c) into c + +Pairs of (a,b,c) values differing in only a few bits will usually +produce values of c that look totally different. This was tested for +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +These constants passed: + 14 11 25 16 4 14 24 + 12 14 25 16 4 14 24 +and these came close: + 4 8 15 26 3 22 24 + 10 8 15 26 3 22 24 + 11 8 15 26 3 22 24 +------------------------------------------------------------------------------- +*/ +#define final(a,b,c) \ +{ \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c,4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ +} + +/* +------------------------------------------------------------------------------- +hashlittle() -- hash a variable-length key into a 32-bit value + k : the key (the unaligned variable-length array of bytes) + length : the length of the key, counting by bytes + val2 : IN: can be any 4-byte value OUT: second 32 bit hash. +Returns a 32-bit value. Every bit of the key affects every bit of +the return value. Two keys differing by one or two bits will have +totally different hash values. Note that the return value is better +mixed than val2, so use that first. + +The best hash table sizes are powers of 2. There is no need to do +mod a prime (mod is sooo slow!). If you need less than 32 bits, +use a bitmask. For example, if you need only 10 bits, do + h = (h & hashmask(10)); +In which case, the hash table should have hashsize(10) elements. + +If you are hashing n strings (uint8_t **)k, do it like this: + for (i=0, h=0; i 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]&0xffffff" actually reads beyond the end of the string, but + * then masks off the part it's not allowed to read. Because the + * string is aligned, the masked-off tail is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticably faster for short strings (like English words). + * + * Not on my testing with gcc 4.5 on an intel i5 CPU, at least --RR. + */ +#if 0 + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff; a+=k[0]; break; + case 6 : b+=k[1]&0xffff; a+=k[0]; break; + case 5 : b+=k[1]&0xff; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff; break; + case 2 : a+=k[0]&0xffff; break; + case 1 : a+=k[0]&0xff; break; + case 0 : return c; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]; break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ + case 1 : a+=k8[0]; break; + case 0 : return c; + } + +#endif /* !valgrind */ + + } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { + const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ + const uint8_t *k8; + + /*--------------- all but last block: aligned reads and different mixing */ + while (length > 12) + { + a += k[0] + (((uint32_t)k[1])<<16); + b += k[2] + (((uint32_t)k[3])<<16); + c += k[4] + (((uint32_t)k[5])<<16); + mix(a,b,c); + length -= 12; + k += 6; + } + + /*----------------------------- handle the last (probably partial) block */ + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[4]+(((uint32_t)k[5])<<16); + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=k[4]; + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=k[2]; + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=k[0]; + break; + case 1 : a+=k8[0]; + break; + case 0 : return c; /* zero length requires no mixing */ + } + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + a += ((uint32_t)k[1])<<8; + a += ((uint32_t)k[2])<<16; + a += ((uint32_t)k[3])<<24; + b += k[4]; + b += ((uint32_t)k[5])<<8; + b += ((uint32_t)k[6])<<16; + b += ((uint32_t)k[7])<<24; + c += k[8]; + c += ((uint32_t)k[9])<<8; + c += ((uint32_t)k[10])<<16; + c += ((uint32_t)k[11])<<24; + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) /* all the case statements fall through */ + { + case 12: c+=((uint32_t)k[11])<<24; + case 11: c+=((uint32_t)k[10])<<16; + case 10: c+=((uint32_t)k[9])<<8; + case 9 : c+=k[8]; + case 8 : b+=((uint32_t)k[7])<<24; + case 7 : b+=((uint32_t)k[6])<<16; + case 6 : b+=((uint32_t)k[5])<<8; + case 5 : b+=k[4]; + case 4 : a+=((uint32_t)k[3])<<24; + case 3 : a+=((uint32_t)k[2])<<16; + case 2 : a+=((uint32_t)k[1])<<8; + case 1 : a+=k[0]; + break; + case 0 : return c; + } + } + + final(a,b,c); + *val2 = b; + return c; +} + +/* + * hashbig(): + * This is the same as hash_word() on big-endian machines. It is different + * from hashlittle() on all machines. hashbig() takes advantage of + * big-endian byte ordering. + */ +static uint32_t hashbig( const void *key, size_t length, uint32_t *val2) +{ + uint32_t a,b,c; + union { const void *ptr; size_t i; } u; /* to cast key to (size_t) happily */ + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + ((uint32_t)length) + *val2; + + u.ptr = key; + if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) { + const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ + const uint8_t *k8; + + /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]<<8" actually reads beyond the end of the string, but + * then shifts out the part it's not allowed to read. Because the + * string is aligned, the illegal read is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticably faster for short strings (like English words). + * + * Not on my testing with gcc 4.5 on an intel i5 CPU, at least --RR. + */ +#if 0 + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff00; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff0000; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff000000; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff00; a+=k[0]; break; + case 6 : b+=k[1]&0xffff0000; a+=k[0]; break; + case 5 : b+=k[1]&0xff000000; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff00; break; + case 2 : a+=k[0]&0xffff0000; break; + case 1 : a+=k[0]&0xff000000; break; + case 0 : return c; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + + k8 = (const uint8_t *)k; + switch(length) /* all the case statements fall through */ + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((uint32_t)k8[10])<<8; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<16; /* fall through */ + case 9 : c+=((uint32_t)k8[8])<<24; /* fall through */ + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((uint32_t)k8[6])<<8; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<16; /* fall through */ + case 5 : b+=((uint32_t)k8[4])<<24; /* fall through */ + case 4 : a+=k[0]; break; + case 3 : a+=((uint32_t)k8[2])<<8; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<16; /* fall through */ + case 1 : a+=((uint32_t)k8[0])<<24; break; + case 0 : return c; + } + +#endif /* !VALGRIND */ + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += ((uint32_t)k[0])<<24; + a += ((uint32_t)k[1])<<16; + a += ((uint32_t)k[2])<<8; + a += ((uint32_t)k[3]); + b += ((uint32_t)k[4])<<24; + b += ((uint32_t)k[5])<<16; + b += ((uint32_t)k[6])<<8; + b += ((uint32_t)k[7]); + c += ((uint32_t)k[8])<<24; + c += ((uint32_t)k[9])<<16; + c += ((uint32_t)k[10])<<8; + c += ((uint32_t)k[11]); + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) /* all the case statements fall through */ + { + case 12: c+=k[11]; + case 11: c+=((uint32_t)k[10])<<8; + case 10: c+=((uint32_t)k[9])<<16; + case 9 : c+=((uint32_t)k[8])<<24; + case 8 : b+=k[7]; + case 7 : b+=((uint32_t)k[6])<<8; + case 6 : b+=((uint32_t)k[5])<<16; + case 5 : b+=((uint32_t)k[4])<<24; + case 4 : a+=k[3]; + case 3 : a+=((uint32_t)k[2])<<8; + case 2 : a+=((uint32_t)k[1])<<16; + case 1 : a+=((uint32_t)k[0])<<24; + break; + case 0 : return c; + } + } + + final(a,b,c); + *val2 = b; + return c; +} + +uint32_t nl_hash_any(const void *key, size_t length, uint32_t base) +{ + if (HASH_BIG_ENDIAN) + return hashbig(key, length, &base); + else + return hashlittle(key, length, &base); +} diff --git a/lib/hashtable.c b/lib/hashtable.c new file mode 100644 index 0000000..8b15925 --- /dev/null +++ b/lib/hashtable.c @@ -0,0 +1,197 @@ +/* + * netlink/hashtable.c Netlink hashtable Utilities + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2012 Cumulus Networks, Inc + */ +#include +#include +#include +#include +#include + +/** + * @ingroup core_types + * @defgroup hashtable Hashtable + * @{ + */ + +/** + * Allocate hashtable + * @arg size Size of hashtable in number of elements + * + * @return Allocated hashtable or NULL. + */ +nl_hash_table_t *nl_hash_table_alloc(int size) +{ + nl_hash_table_t *ht; + + ht = calloc(1, sizeof (*ht)); + if (!ht) + goto errout; + + ht->nodes = calloc(size, sizeof (*ht->nodes)); + if (!ht->nodes) { + free(ht); + goto errout; + } + + ht->size = size; + + return ht; +errout: + return NULL; +} + +/** + * Free hashtable including all nodes + * @arg ht Hashtable + * + * @note Reference counter of all objects in the hashtable will be decremented. + */ +void nl_hash_table_free(nl_hash_table_t *ht) +{ + int i; + + for(i = 0; i < ht->size; i++) { + nl_hash_node_t *node = ht->nodes[i]; + nl_hash_node_t *saved_node; + + while (node) { + saved_node = node; + node = node->next; + nl_object_put(saved_node->obj); + free(saved_node); + } + } + + free(ht->nodes); + free(ht); +} + +/** + * Lookup identical object in hashtable + * @arg ht Hashtable + * @arg obj Object to lookup + * + * Generates hashkey for `obj` and traverses the corresponding chain calling + * `nl_object_identical()` on each trying to find a match. + * + * @return Pointer to object if match was found or NULL. + */ +struct nl_object* nl_hash_table_lookup(nl_hash_table_t *ht, + struct nl_object *obj) +{ + nl_hash_node_t *node; + uint32_t key_hash; + + nl_object_keygen(obj, &key_hash, ht->size); + node = ht->nodes[key_hash]; + + while (node) { + if (nl_object_identical(node->obj, obj)) + return node->obj; + node = node->next; + } + + return NULL; +} + +/** + * Add object to hashtable + * @arg ht Hashtable + * @arg obj Object to add + * + * Adds `obj` to the hashtable. Object type must support hashing, otherwise all + * objects will be added to the chain `0`. + * + * @note The reference counter of the object is incremented. + * + * @return 0 on success or a negative error code + * @retval -NLE_EXIST Identical object already present in hashtable + */ +int nl_hash_table_add(nl_hash_table_t *ht, struct nl_object *obj) +{ + nl_hash_node_t *node; + uint32_t key_hash; + + nl_object_keygen(obj, &key_hash, ht->size); + node = ht->nodes[key_hash]; + + while (node) { + if (nl_object_identical(node->obj, obj)) { + NL_DBG(2, "Warning: Add to hashtable found duplicate...\n"); + return -NLE_EXIST; + } + node = node->next; + } + + NL_DBG (5, "adding cache entry of obj %p in table %p, with hash 0x%x\n", + obj, ht, key_hash); + + node = malloc(sizeof(nl_hash_node_t)); + if (!node) + return -NLE_NOMEM; + nl_object_get(obj); + node->obj = obj; + node->key = key_hash; + node->key_size = sizeof(uint32_t); + node->next = ht->nodes[key_hash]; + ht->nodes[key_hash] = node; + + return 0; +} + +/** + * Remove object from hashtable + * @arg ht Hashtable + * @arg obj Object to remove + * + * Remove `obj` from hashtable if it exists. + * + * @note Reference counter of object will be decremented. + * + * @return 0 on success or a negative error code. + * @retval -NLE_OBJ_NOTFOUND Object not present in hashtable. + */ +int nl_hash_table_del(nl_hash_table_t *ht, struct nl_object *obj) +{ + nl_hash_node_t *node, *prev; + uint32_t key_hash; + + nl_object_keygen(obj, &key_hash, ht->size); + prev = node = ht->nodes[key_hash]; + + while (node) { + if (nl_object_identical(node->obj, obj)) { + nl_object_put(obj); + + NL_DBG (5, "deleting cache entry of obj %p in table %p, with" + " hash 0x%x\n", obj, ht, key_hash); + + if (node == ht->nodes[key_hash]) + ht->nodes[key_hash] = node->next; + else + prev->next = node->next; + + free(node); + + return 0; + } + prev = node; + node = node->next; + } + + return -NLE_OBJ_NOTFOUND; +} + +uint32_t nl_hash(void *k, size_t length, uint32_t initval) +{ + return(__nl_hash(k, length, initval)); +} + +/** @} */ diff --git a/lib/msg.c b/lib/msg.c new file mode 100644 index 0000000..6478507 --- /dev/null +++ b/lib/msg.c @@ -0,0 +1,996 @@ +/* + * lib/msg.c Netlink Messages Interface + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +/** + * @ingroup core + * @defgroup msg Message Construction & Parsing + * Netlink Message Construction/Parsing Interface + * + * Related sections in the development guide: + * - @core_doc{_message_parsing_amp_construction,Message Parsing & Construction} + * + * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ + */ + +#include +#include +#include +#include +#include +#include + +static size_t default_msg_size; + +static void __init init_msg_size(void) +{ + default_msg_size = getpagesize(); +} + +/** + * @name Size Calculations + * @{ + */ + +/** + * Calculates size of netlink message based on payload length. + * @arg payload Length of payload + * + * @return size of netlink message without padding. + */ +int nlmsg_size(int payload) +{ + return NLMSG_HDRLEN + payload; +} + +static int nlmsg_msg_size(int payload) +{ + return nlmsg_size(payload); +} + +/** + * Calculates size of netlink message including padding based on payload length + * @arg payload Length of payload + * + * This function is idential to nlmsg_size() + nlmsg_padlen(). + * + * @return Size of netlink message including padding. + */ +int nlmsg_total_size(int payload) +{ + return NLMSG_ALIGN(nlmsg_msg_size(payload)); +} + +/** + * Size of padding that needs to be added at end of message + * @arg payload Length of payload + * + * Calculates the number of bytes of padding which is required to be added to + * the end of the message to ensure that the next netlink message header begins + * properly aligned to NLMSG_ALIGNTO. + * + * @return Number of bytes of padding needed. + */ +int nlmsg_padlen(int payload) +{ + return nlmsg_total_size(payload) - nlmsg_msg_size(payload); +} + +/** @} */ + +/** + * @name Access to Message Payload + * @{ + */ + +/** + * Return pointer to message payload + * @arg nlh Netlink message header + * + * @return Pointer to start of message payload. + */ +void *nlmsg_data(const struct nlmsghdr *nlh) +{ + return (unsigned char *) nlh + NLMSG_HDRLEN; +} + +void *nlmsg_tail(const struct nlmsghdr *nlh) +{ + return (unsigned char *) nlh + NLMSG_ALIGN(nlh->nlmsg_len); +} + +/** + * Return length of message payload + * @arg nlh Netlink message header + * + * @return Length of message payload in bytes. + */ +int nlmsg_datalen(const struct nlmsghdr *nlh) +{ + return nlh->nlmsg_len - NLMSG_HDRLEN; +} + +static int nlmsg_len(const struct nlmsghdr *nlh) +{ + return nlmsg_datalen(nlh); +} + +/** @} */ + +/** + * @name Attribute Access + * @{ + */ + +/** + * head of attributes data + * @arg nlh netlink message header + * @arg hdrlen length of family specific header + */ +struct nlattr *nlmsg_attrdata(const struct nlmsghdr *nlh, int hdrlen) +{ + unsigned char *data = nlmsg_data(nlh); + return (struct nlattr *) (data + NLMSG_ALIGN(hdrlen)); +} + +/** + * length of attributes data + * @arg nlh netlink message header + * @arg hdrlen length of family specific header + */ +int nlmsg_attrlen(const struct nlmsghdr *nlh, int hdrlen) +{ + return nlmsg_len(nlh) - NLMSG_ALIGN(hdrlen); +} + +/** @} */ + +/** + * @name Message Parsing + * @{ + */ + +int nlmsg_valid_hdr(const struct nlmsghdr *nlh, int hdrlen) +{ + if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen)) + return 0; + + return 1; +} + +/** + * check if the netlink message fits into the remaining bytes + * @arg nlh netlink message header + * @arg remaining number of bytes remaining in message stream + */ +int nlmsg_ok(const struct nlmsghdr *nlh, int remaining) +{ + return (remaining >= (int)sizeof(struct nlmsghdr) && + nlh->nlmsg_len >= sizeof(struct nlmsghdr) && + nlh->nlmsg_len <= remaining); +} + +/** + * next netlink message in message stream + * @arg nlh netlink message header + * @arg remaining number of bytes remaining in message stream + * + * @returns the next netlink message in the message stream and + * decrements remaining by the size of the current message. + */ +struct nlmsghdr *nlmsg_next(struct nlmsghdr *nlh, int *remaining) +{ + int totlen = NLMSG_ALIGN(nlh->nlmsg_len); + + *remaining -= totlen; + + return (struct nlmsghdr *) ((unsigned char *) nlh + totlen); +} + +/** + * parse attributes of a netlink message + * @arg nlh netlink message header + * @arg hdrlen length of family specific header + * @arg tb destination array with maxtype+1 elements + * @arg maxtype maximum attribute type to be expected + * @arg policy validation policy + * + * See nla_parse() + */ +int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], + int maxtype, struct nla_policy *policy) +{ + if (!nlmsg_valid_hdr(nlh, hdrlen)) + return -NLE_MSG_TOOSHORT; + + return nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen), + nlmsg_attrlen(nlh, hdrlen), policy); +} + +/** + * nlmsg_find_attr - find a specific attribute in a netlink message + * @arg nlh netlink message header + * @arg hdrlen length of familiy specific header + * @arg attrtype type of attribute to look for + * + * Returns the first attribute which matches the specified type. + */ +struct nlattr *nlmsg_find_attr(struct nlmsghdr *nlh, int hdrlen, int attrtype) +{ + return nla_find(nlmsg_attrdata(nlh, hdrlen), + nlmsg_attrlen(nlh, hdrlen), attrtype); +} + +/** + * nlmsg_validate - validate a netlink message including attributes + * @arg nlh netlinket message header + * @arg hdrlen length of familiy specific header + * @arg maxtype maximum attribute type to be expected + * @arg policy validation policy + */ +int nlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype, + struct nla_policy *policy) +{ + if (!nlmsg_valid_hdr(nlh, hdrlen)) + return -NLE_MSG_TOOSHORT; + + return nla_validate(nlmsg_attrdata(nlh, hdrlen), + nlmsg_attrlen(nlh, hdrlen), maxtype, policy); +} + +/** @} */ + +/** + * @name Message Building/Access + * @{ + */ + +static struct nl_msg *__nlmsg_alloc(size_t len) +{ + struct nl_msg *nm; + + if (len < sizeof(struct nlmsghdr)) + len = sizeof(struct nlmsghdr); + + nm = calloc(1, sizeof(*nm)); + if (!nm) + goto errout; + + nm->nm_refcnt = 1; + + nm->nm_nlh = calloc(1, len); + if (!nm->nm_nlh) + goto errout; + + memset(nm->nm_nlh, 0, sizeof(struct nlmsghdr)); + + nm->nm_protocol = -1; + nm->nm_size = len; + nm->nm_nlh->nlmsg_len = nlmsg_total_size(0); + + NL_DBG(2, "msg %p: Allocated new message, maxlen=%zu\n", nm, len); + + return nm; +errout: + free(nm); + return NULL; +} + +/** + * Allocate a new netlink message with the default maximum payload size. + * + * Allocates a new netlink message without any further payload. The + * maximum payload size defaults to PAGESIZE or as otherwise specified + * with nlmsg_set_default_size(). + * + * @return Newly allocated netlink message or NULL. + */ +struct nl_msg *nlmsg_alloc(void) +{ + return __nlmsg_alloc(default_msg_size); +} + +/** + * Allocate a new netlink message with maximum payload size specified. + */ +struct nl_msg *nlmsg_alloc_size(size_t max) +{ + return __nlmsg_alloc(max); +} + +/** + * Allocate a new netlink message and inherit netlink message header + * @arg hdr Netlink message header template + * + * Allocates a new netlink message and inherits the original message + * header. If \a hdr is not NULL it will be used as a template for + * the netlink message header, otherwise the header is left blank. + * + * @return Newly allocated netlink message or NULL + */ +struct nl_msg *nlmsg_inherit(struct nlmsghdr *hdr) +{ + struct nl_msg *nm; + + nm = nlmsg_alloc(); + if (nm && hdr) { + struct nlmsghdr *new = nm->nm_nlh; + + new->nlmsg_type = hdr->nlmsg_type; + new->nlmsg_flags = hdr->nlmsg_flags; + new->nlmsg_seq = hdr->nlmsg_seq; + new->nlmsg_pid = hdr->nlmsg_pid; + } + + return nm; +} + +/** + * Allocate a new netlink message + * @arg nlmsgtype Netlink message type + * @arg flags Message flags. + * + * @return Newly allocated netlink message or NULL. + */ +struct nl_msg *nlmsg_alloc_simple(int nlmsgtype, int flags) +{ + struct nl_msg *msg; + struct nlmsghdr nlh = { + .nlmsg_type = nlmsgtype, + .nlmsg_flags = flags, + }; + + msg = nlmsg_inherit(&nlh); + if (msg) + NL_DBG(2, "msg %p: Allocated new simple message\n", msg); + + return msg; +} + +/** + * Set the default maximum message payload size for allocated messages + * @arg max Size of payload in bytes. + */ +void nlmsg_set_default_size(size_t max) +{ + if (max < nlmsg_total_size(0)) + max = nlmsg_total_size(0); + + default_msg_size = max; +} + +/** + * Convert a netlink message received from a netlink socket to a nl_msg + * @arg hdr Netlink message received from netlink socket. + * + * Allocates a new netlink message and copies all of the data pointed to + * by \a hdr into the new message object. + * + * @return Newly allocated netlink message or NULL. + */ +struct nl_msg *nlmsg_convert(struct nlmsghdr *hdr) +{ + struct nl_msg *nm; + + nm = __nlmsg_alloc(NLMSG_ALIGN(hdr->nlmsg_len)); + if (!nm) + goto errout; + + memcpy(nm->nm_nlh, hdr, hdr->nlmsg_len); + + return nm; +errout: + nlmsg_free(nm); + return NULL; +} + +/** + * Reserve room for additional data in a netlink message + * @arg n netlink message + * @arg len length of additional data to reserve room for + * @arg pad number of bytes to align data to + * + * Reserves room for additional data at the tail of the an + * existing netlink message. Eventual padding required will + * be zeroed out. + * + * @return Pointer to start of additional data tailroom or NULL. + */ +void *nlmsg_reserve(struct nl_msg *n, size_t len, int pad) +{ + void *buf = n->nm_nlh; + size_t nlmsg_len = n->nm_nlh->nlmsg_len; + size_t tlen; + + tlen = pad ? ((len + (pad - 1)) & ~(pad - 1)) : len; + + if ((tlen + nlmsg_len) > n->nm_size) + return NULL; + + buf += nlmsg_len; + n->nm_nlh->nlmsg_len += tlen; + + if (tlen > len) + memset(buf + len, 0, tlen - len); + + NL_DBG(2, "msg %p: Reserved %zu (%zu) bytes, pad=%d, nlmsg_len=%d\n", + n, tlen, len, pad, n->nm_nlh->nlmsg_len); + + return buf; +} + +/** + * Append data to tail of a netlink message + * @arg n netlink message + * @arg data data to add + * @arg len length of data + * @arg pad Number of bytes to align data to. + * + * Extends the netlink message as needed and appends the data of given + * length to the message. + * + * @return 0 on success or a negative error code + */ +int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad) +{ + void *tmp; + + tmp = nlmsg_reserve(n, len, pad); + if (tmp == NULL) + return -NLE_NOMEM; + + memcpy(tmp, data, len); + NL_DBG(2, "msg %p: Appended %zu bytes with padding %d\n", n, len, pad); + + return 0; +} + +/** + * Expand maximum payload size of a netlink message + * @arg n Netlink message. + * @arg newlen New maximum payload size. + * + * Reallocates the payload section of a netlink message and increases + * the maximum payload size of the message. + * + * @note Any pointers pointing to old payload block will be stale and + * need to be refetched. Therfore, do not expand while constructing + * nested attributes or while reserved data blocks are held. + * + * @return 0 on success or a negative error code. + */ +int nlmsg_expand(struct nl_msg *n, size_t newlen) +{ + void *tmp; + + if (newlen <= n->nm_size) + return -NLE_INVAL; + + tmp = realloc(n->nm_nlh, newlen); + if (tmp == NULL) + return -NLE_NOMEM; + + n->nm_nlh = tmp; + n->nm_size = newlen; + + return 0; +} + +/** + * Add a netlink message header to a netlink message + * @arg n netlink message + * @arg pid netlink process id or NL_AUTO_PID + * @arg seq sequence number of message or NL_AUTO_SEQ + * @arg type message type + * @arg payload length of message payload + * @arg flags message flags + * + * Adds or overwrites the netlink message header in an existing message + * object. If \a payload is greater-than zero additional room will be + * reserved, f.e. for family specific headers. It can be accesed via + * nlmsg_data(). + * + * @return A pointer to the netlink message header or NULL. + */ +struct nlmsghdr *nlmsg_put(struct nl_msg *n, uint32_t pid, uint32_t seq, + int type, int payload, int flags) +{ + struct nlmsghdr *nlh; + + if (n->nm_nlh->nlmsg_len < NLMSG_HDRLEN) + BUG(); + + nlh = (struct nlmsghdr *) n->nm_nlh; + nlh->nlmsg_type = type; + nlh->nlmsg_flags = flags; + nlh->nlmsg_pid = pid; + nlh->nlmsg_seq = seq; + + NL_DBG(2, "msg %p: Added netlink header type=%d, flags=%d, pid=%d, " + "seq=%d\n", n, type, flags, pid, seq); + + if (payload > 0 && + nlmsg_reserve(n, payload, NLMSG_ALIGNTO) == NULL) + return NULL; + + return nlh; +} + +/** + * Return actual netlink message + * @arg n netlink message + * + * Returns the actual netlink message casted to the type of the netlink + * message header. + * + * @return A pointer to the netlink message. + */ +struct nlmsghdr *nlmsg_hdr(struct nl_msg *n) +{ + return n->nm_nlh; +} + +/** + * Acquire a reference on a netlink message + * @arg msg message to acquire reference from + */ +void nlmsg_get(struct nl_msg *msg) +{ + msg->nm_refcnt++; + NL_DBG(4, "New reference to message %p, total %d\n", + msg, msg->nm_refcnt); +} + +/** + * Release a reference from an netlink message + * @arg msg message to release reference from + * + * Frees memory after the last reference has been released. + */ +void nlmsg_free(struct nl_msg *msg) +{ + if (!msg) + return; + + msg->nm_refcnt--; + NL_DBG(4, "Returned message reference %p, %d remaining\n", + msg, msg->nm_refcnt); + + if (msg->nm_refcnt < 0) + BUG(); + + if (msg->nm_refcnt <= 0) { + free(msg->nm_nlh); + free(msg); + NL_DBG(2, "msg %p: Freed\n", msg); + } +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ + +void nlmsg_set_proto(struct nl_msg *msg, int protocol) +{ + msg->nm_protocol = protocol; +} + +int nlmsg_get_proto(struct nl_msg *msg) +{ + return msg->nm_protocol; +} + +size_t nlmsg_get_max_size(struct nl_msg *msg) +{ + return msg->nm_size; +} + +void nlmsg_set_src(struct nl_msg *msg, struct sockaddr_nl *addr) +{ + memcpy(&msg->nm_src, addr, sizeof(*addr)); +} + +struct sockaddr_nl *nlmsg_get_src(struct nl_msg *msg) +{ + return &msg->nm_src; +} + +void nlmsg_set_dst(struct nl_msg *msg, struct sockaddr_nl *addr) +{ + memcpy(&msg->nm_dst, addr, sizeof(*addr)); +} + +struct sockaddr_nl *nlmsg_get_dst(struct nl_msg *msg) +{ + return &msg->nm_dst; +} + +void nlmsg_set_creds(struct nl_msg *msg, struct ucred *creds) +{ + memcpy(&msg->nm_creds, creds, sizeof(*creds)); + msg->nm_flags |= NL_MSG_CRED_PRESENT; +} + +struct ucred *nlmsg_get_creds(struct nl_msg *msg) +{ + if (msg->nm_flags & NL_MSG_CRED_PRESENT) + return &msg->nm_creds; + return NULL; +} + +/** @} */ + +/** + * @name Netlink Message Type Translations + * @{ + */ + +static const struct trans_tbl nl_msgtypes[] = { + __ADD(NLMSG_NOOP,NOOP) + __ADD(NLMSG_ERROR,ERROR) + __ADD(NLMSG_DONE,DONE) + __ADD(NLMSG_OVERRUN,OVERRUN) +}; + +char *nl_nlmsgtype2str(int type, char *buf, size_t size) +{ + return __type2str(type, buf, size, nl_msgtypes, + ARRAY_SIZE(nl_msgtypes)); +} + +int nl_str2nlmsgtype(const char *name) +{ + return __str2type(name, nl_msgtypes, ARRAY_SIZE(nl_msgtypes)); +} + +/** @} */ + +/** + * @name Netlink Message Flags Translations + * @{ + */ + +char *nl_nlmsg_flags2str(int flags, char *buf, size_t len) +{ + memset(buf, 0, len); + +#define PRINT_FLAG(f) \ + if (flags & NLM_F_##f) { \ + flags &= ~NLM_F_##f; \ + strncat(buf, #f, len - strlen(buf) - 1); \ + if (flags) \ + strncat(buf, ",", len - strlen(buf) - 1); \ + } + + PRINT_FLAG(REQUEST); + PRINT_FLAG(MULTI); + PRINT_FLAG(ACK); + PRINT_FLAG(ECHO); + PRINT_FLAG(ROOT); + PRINT_FLAG(MATCH); + PRINT_FLAG(ATOMIC); + PRINT_FLAG(REPLACE); + PRINT_FLAG(EXCL); + PRINT_FLAG(CREATE); + PRINT_FLAG(APPEND); + + if (flags) { + char s[32]; + snprintf(s, sizeof(s), "0x%x", flags); + strncat(buf, s, len - strlen(buf) - 1); + } +#undef PRINT_FLAG + + return buf; +} + +/** @} */ + +/** + * @name Direct Parsing + * @{ + */ + +/** @cond SKIP */ +struct dp_xdata { + void (*cb)(struct nl_object *, void *); + void *arg; +}; +/** @endcond */ + +static int parse_cb(struct nl_object *obj, struct nl_parser_param *p) +{ + struct dp_xdata *x = p->pp_arg; + + x->cb(obj, x->arg); + return 0; +} + +int nl_msg_parse(struct nl_msg *msg, void (*cb)(struct nl_object *, void *), + void *arg) +{ + struct nl_cache_ops *ops; + struct nl_parser_param p = { + .pp_cb = parse_cb + }; + struct dp_xdata x = { + .cb = cb, + .arg = arg, + }; + int err; + + ops = nl_cache_ops_associate_safe(nlmsg_get_proto(msg), + nlmsg_hdr(msg)->nlmsg_type); + if (ops == NULL) + return -NLE_MSGTYPE_NOSUPPORT; + p.pp_arg = &x; + + err = nl_cache_parse(ops, NULL, nlmsg_hdr(msg), &p); + nl_cache_ops_put(ops); + + return err; +} + +/** @} */ + +/** + * @name Dumping + * @{ + */ + +static void prefix_line(FILE *ofd, int prefix) +{ + int i; + + for (i = 0; i < prefix; i++) + fprintf(ofd, " "); +} + +static inline void dump_hex(FILE *ofd, char *start, int len, int prefix) +{ + int i, a, c, limit; + char ascii[21] = {0}; + + limit = 16 - (prefix * 2); + prefix_line(ofd, prefix); + fprintf(ofd, " "); + + for (i = 0, a = 0, c = 0; i < len; i++) { + int v = *(uint8_t *) (start + i); + + fprintf(ofd, "%02x ", v); + ascii[a++] = isprint(v) ? v : '.'; + + if (++c >= limit) { + fprintf(ofd, "%s\n", ascii); + if (i < (len - 1)) { + prefix_line(ofd, prefix); + fprintf(ofd, " "); + } + a = c = 0; + memset(ascii, 0, sizeof(ascii)); + } + } + + if (c != 0) { + for (i = 0; i < (limit - c); i++) + fprintf(ofd, " "); + fprintf(ofd, "%s\n", ascii); + } +} + +static void print_hdr(FILE *ofd, struct nl_msg *msg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct nl_cache_ops *ops; + struct nl_msgtype *mt; + char buf[128]; + + fprintf(ofd, " .nlmsg_len = %d\n", nlh->nlmsg_len); + + ops = nl_cache_ops_associate_safe(nlmsg_get_proto(msg), nlh->nlmsg_type); + if (ops) { + mt = nl_msgtype_lookup(ops, nlh->nlmsg_type); + if (!mt) + BUG(); + + snprintf(buf, sizeof(buf), "%s::%s", ops->co_name, mt->mt_name); + nl_cache_ops_put(ops); + } else + nl_nlmsgtype2str(nlh->nlmsg_type, buf, sizeof(buf)); + + fprintf(ofd, " .type = %d <%s>\n", nlh->nlmsg_type, buf); + fprintf(ofd, " .flags = %d <%s>\n", nlh->nlmsg_flags, + nl_nlmsg_flags2str(nlh->nlmsg_flags, buf, sizeof(buf))); + fprintf(ofd, " .seq = %d\n", nlh->nlmsg_seq); + fprintf(ofd, " .port = %d\n", nlh->nlmsg_pid); + +} + +static void print_genl_hdr(FILE *ofd, void *start) +{ + struct genlmsghdr *ghdr = start; + + fprintf(ofd, " [GENERIC NETLINK HEADER] %zu octets\n", GENL_HDRLEN); + fprintf(ofd, " .cmd = %u\n", ghdr->cmd); + fprintf(ofd, " .version = %u\n", ghdr->version); + fprintf(ofd, " .unused = %#x\n", ghdr->reserved); +} + +static void *print_genl_msg(struct nl_msg *msg, FILE *ofd, struct nlmsghdr *hdr, + struct nl_cache_ops *ops, int *payloadlen) +{ + void *data = nlmsg_data(hdr); + + if (*payloadlen < GENL_HDRLEN) + return data; + + print_genl_hdr(ofd, data); + + *payloadlen -= GENL_HDRLEN; + data += GENL_HDRLEN; + + if (ops) { + int hdrsize = ops->co_hdrsize - GENL_HDRLEN; + + if (hdrsize > 0) { + if (*payloadlen < hdrsize) + return data; + + fprintf(ofd, " [HEADER] %d octets\n", hdrsize); + dump_hex(ofd, data, hdrsize, 0); + + *payloadlen -= hdrsize; + data += hdrsize; + } + } + + return data; +} + +static void dump_attr(FILE *ofd, struct nlattr *attr, int prefix) +{ + int len = nla_len(attr); + + dump_hex(ofd, nla_data(attr), len, prefix); +} + +static void dump_attrs(FILE *ofd, struct nlattr *attrs, int attrlen, + int prefix) +{ + int rem; + struct nlattr *nla; + + nla_for_each_attr(nla, attrs, attrlen, rem) { + int padlen, alen = nla_len(nla); + + prefix_line(ofd, prefix); + + if (nla->nla_type == 0) + fprintf(ofd, " [ATTR PADDING] %d octets\n", alen); + else + fprintf(ofd, " [ATTR %02d%s] %d octets\n", nla_type(nla), + nla_is_nested(nla) ? " NESTED" : "", + alen); + + if (nla_is_nested(nla)) + dump_attrs(ofd, nla_data(nla), alen, prefix+1); + else + dump_attr(ofd, nla, prefix); + + padlen = nla_padlen(alen); + if (padlen > 0) { + prefix_line(ofd, prefix); + fprintf(ofd, " [PADDING] %d octets\n", + padlen); + dump_hex(ofd, nla_data(nla) + alen, + padlen, prefix); + } + } + + if (rem) { + prefix_line(ofd, prefix); + fprintf(ofd, " [LEFTOVER] %d octets\n", rem); + } +} + +static void dump_error_msg(struct nl_msg *msg, FILE *ofd) +{ + struct nlmsghdr *hdr = nlmsg_hdr(msg); + struct nlmsgerr *err = nlmsg_data(hdr); + + fprintf(ofd, " [ERRORMSG] %zu octets\n", sizeof(*err)); + + if (nlmsg_len(hdr) >= sizeof(*err)) { + char buf[256]; + struct nl_msg *errmsg; + + fprintf(ofd, " .error = %d \"%s\"\n", err->error, + strerror_r(-err->error, buf, sizeof(buf))); + fprintf(ofd, " [ORIGINAL MESSAGE] %zu octets\n", sizeof(*hdr)); + + errmsg = nlmsg_inherit(&err->msg); + print_hdr(ofd, errmsg); + nlmsg_free(errmsg); + } +} + +static void print_msg(struct nl_msg *msg, FILE *ofd, struct nlmsghdr *hdr) +{ + struct nl_cache_ops *ops; + int payloadlen = nlmsg_len(hdr); + int attrlen = 0; + void *data; + + data = nlmsg_data(hdr); + ops = nl_cache_ops_associate_safe(nlmsg_get_proto(msg), + hdr->nlmsg_type); + if (ops) { + attrlen = nlmsg_attrlen(hdr, ops->co_hdrsize); + payloadlen -= attrlen; + } + + if (msg->nm_protocol == NETLINK_GENERIC) + data = print_genl_msg(msg, ofd, hdr, ops, &payloadlen); + + if (payloadlen) { + fprintf(ofd, " [PAYLOAD] %d octets\n", payloadlen); + dump_hex(ofd, data, payloadlen, 0); + } + + if (attrlen) { + struct nlattr *attrs; + int attrlen; + + attrs = nlmsg_attrdata(hdr, ops->co_hdrsize); + attrlen = nlmsg_attrlen(hdr, ops->co_hdrsize); + dump_attrs(ofd, attrs, attrlen, 0); + } + + if (ops) + nl_cache_ops_put(ops); +} + +/** + * Dump message in human readable format to file descriptor + * @arg msg Message to print + * @arg ofd File descriptor. + */ +void nl_msg_dump(struct nl_msg *msg, FILE *ofd) +{ + struct nlmsghdr *hdr = nlmsg_hdr(msg); + + fprintf(ofd, + "-------------------------- BEGIN NETLINK MESSAGE ---------------------------\n"); + + fprintf(ofd, " [NETLINK HEADER] %zu octets\n", sizeof(struct nlmsghdr)); + print_hdr(ofd, msg); + + if (hdr->nlmsg_type == NLMSG_ERROR) + dump_error_msg(msg, ofd); + else if (nlmsg_len(hdr) > 0) + print_msg(msg, ofd, hdr); + + fprintf(ofd, + "--------------------------- END NETLINK MESSAGE ---------------------------\n"); +} + +/** @} */ + +/** @} */ diff --git a/lib/netfilter/ct.c b/lib/netfilter/ct.c new file mode 100644 index 0000000..794932f --- /dev/null +++ b/lib/netfilter/ct.c @@ -0,0 +1,628 @@ +/* + * lib/netfilter/ct.c Conntrack + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c= 2008 Patrick McHardy + */ + +/** + * @ingroup nfnl + * @defgroup ct Conntrack + * @brief + * @{ + */ + +#include +#include +#include + +#include +#include +#include +#include + +static struct nl_cache_ops nfnl_ct_ops; + +#if __BYTE_ORDER == __BIG_ENDIAN +static uint64_t ntohll(uint64_t x) +{ + return x; +} +#elif __BYTE_ORDER == __LITTLE_ENDIAN +static uint64_t ntohll(uint64_t x) +{ + return bswap_64(x); +} +#endif + +static struct nla_policy ct_policy[CTA_MAX+1] = { + [CTA_TUPLE_ORIG] = { .type = NLA_NESTED }, + [CTA_TUPLE_REPLY] = { .type = NLA_NESTED }, + [CTA_STATUS] = { .type = NLA_U32 }, + [CTA_PROTOINFO] = { .type = NLA_NESTED }, + //[CTA_HELP] + //[CTA_NAT_SRC] + [CTA_TIMEOUT] = { .type = NLA_U32 }, + [CTA_MARK] = { .type = NLA_U32 }, + [CTA_COUNTERS_ORIG] = { .type = NLA_NESTED }, + [CTA_COUNTERS_REPLY] = { .type = NLA_NESTED }, + [CTA_USE] = { .type = NLA_U32 }, + [CTA_ID] = { .type = NLA_U32 }, + //[CTA_NAT_DST] +}; + +static struct nla_policy ct_tuple_policy[CTA_TUPLE_MAX+1] = { + [CTA_TUPLE_IP] = { .type = NLA_NESTED }, + [CTA_TUPLE_PROTO] = { .type = NLA_NESTED }, +}; + +static struct nla_policy ct_ip_policy[CTA_IP_MAX+1] = { + [CTA_IP_V4_SRC] = { .type = NLA_U32 }, + [CTA_IP_V4_DST] = { .type = NLA_U32 }, + [CTA_IP_V6_SRC] = { .minlen = 16 }, + [CTA_IP_V6_DST] = { .minlen = 16 }, +}; + +static struct nla_policy ct_proto_policy[CTA_PROTO_MAX+1] = { + [CTA_PROTO_NUM] = { .type = NLA_U8 }, + [CTA_PROTO_SRC_PORT] = { .type = NLA_U16 }, + [CTA_PROTO_DST_PORT] = { .type = NLA_U16 }, + [CTA_PROTO_ICMP_ID] = { .type = NLA_U16 }, + [CTA_PROTO_ICMP_TYPE] = { .type = NLA_U8 }, + [CTA_PROTO_ICMP_CODE] = { .type = NLA_U8 }, + [CTA_PROTO_ICMPV6_ID] = { .type = NLA_U16 }, + [CTA_PROTO_ICMPV6_TYPE] = { .type = NLA_U8 }, + [CTA_PROTO_ICMPV6_CODE] = { .type = NLA_U8 }, +}; + +static struct nla_policy ct_protoinfo_policy[CTA_PROTOINFO_MAX+1] = { + [CTA_PROTOINFO_TCP] = { .type = NLA_NESTED }, +}; + +static struct nla_policy ct_protoinfo_tcp_policy[CTA_PROTOINFO_TCP_MAX+1] = { + [CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 }, + [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 }, + [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 }, + [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .minlen = 2 }, + [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .minlen = 2 }, + +}; + +static struct nla_policy ct_counters_policy[CTA_COUNTERS_MAX+1] = { + [CTA_COUNTERS_PACKETS] = { .type = NLA_U64 }, + [CTA_COUNTERS_BYTES] = { .type = NLA_U64 }, + [CTA_COUNTERS32_PACKETS]= { .type = NLA_U32 }, + [CTA_COUNTERS32_BYTES] = { .type = NLA_U32 }, +}; + +static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr) +{ + struct nlattr *tb[CTA_IP_MAX+1]; + struct nl_addr *addr; + int err; + + err = nla_parse_nested(tb, CTA_IP_MAX, attr, ct_ip_policy); + if (err < 0) + goto errout; + + if (tb[CTA_IP_V4_SRC]) { + addr = nl_addr_alloc_attr(tb[CTA_IP_V4_SRC], AF_INET); + if (addr == NULL) + goto errout_enomem; + err = nfnl_ct_set_src(ct, repl, addr); + nl_addr_put(addr); + if (err < 0) + goto errout; + } + if (tb[CTA_IP_V4_DST]) { + addr = nl_addr_alloc_attr(tb[CTA_IP_V4_DST], AF_INET); + if (addr == NULL) + goto errout_enomem; + err = nfnl_ct_set_dst(ct, repl, addr); + nl_addr_put(addr); + if (err < 0) + goto errout; + } + if (tb[CTA_IP_V6_SRC]) { + addr = nl_addr_alloc_attr(tb[CTA_IP_V6_SRC], AF_INET6); + if (addr == NULL) + goto errout_enomem; + err = nfnl_ct_set_src(ct, repl, addr); + nl_addr_put(addr); + if (err < 0) + goto errout; + } + if (tb[CTA_IP_V6_DST]) { + addr = nl_addr_alloc_attr(tb[CTA_IP_V6_DST], AF_INET6); + if (addr == NULL) + goto errout_enomem; + err = nfnl_ct_set_dst(ct, repl, addr); + nl_addr_put(addr); + if (err < 0) + goto errout; + } + + return 0; + +errout_enomem: + err = -NLE_NOMEM; +errout: + return err; +} + +static int ct_parse_proto(struct nfnl_ct *ct, int repl, struct nlattr *attr) +{ + struct nlattr *tb[CTA_PROTO_MAX+1]; + int err; + + err = nla_parse_nested(tb, CTA_PROTO_MAX, attr, ct_proto_policy); + if (err < 0) + return err; + + if (!repl && tb[CTA_PROTO_NUM]) + nfnl_ct_set_proto(ct, nla_get_u8(tb[CTA_PROTO_NUM])); + if (tb[CTA_PROTO_SRC_PORT]) + nfnl_ct_set_src_port(ct, repl, + ntohs(nla_get_u16(tb[CTA_PROTO_SRC_PORT]))); + if (tb[CTA_PROTO_DST_PORT]) + nfnl_ct_set_dst_port(ct, repl, + ntohs(nla_get_u16(tb[CTA_PROTO_DST_PORT]))); + + if (ct->ct_family == AF_INET) { + if (tb[CTA_PROTO_ICMP_ID]) + nfnl_ct_set_icmp_id(ct, repl, + ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID]))); + if (tb[CTA_PROTO_ICMP_TYPE]) + nfnl_ct_set_icmp_type(ct, repl, + nla_get_u8(tb[CTA_PROTO_ICMP_TYPE])); + if (tb[CTA_PROTO_ICMP_CODE]) + nfnl_ct_set_icmp_code(ct, repl, + nla_get_u8(tb[CTA_PROTO_ICMP_CODE])); + } else if (ct->ct_family == AF_INET6) { + if (tb[CTA_PROTO_ICMPV6_ID]) + nfnl_ct_set_icmp_id(ct, repl, + ntohs(nla_get_u16(tb[CTA_PROTO_ICMPV6_ID]))); + if (tb[CTA_PROTO_ICMPV6_TYPE]) + nfnl_ct_set_icmp_type(ct, repl, + nla_get_u8(tb[CTA_PROTO_ICMPV6_TYPE])); + if (tb[CTA_PROTO_ICMPV6_CODE]) + nfnl_ct_set_icmp_code(ct, repl, + nla_get_u8(tb[CTA_PROTO_ICMPV6_CODE])); + } + + return 0; +} + +static int ct_parse_tuple(struct nfnl_ct *ct, int repl, struct nlattr *attr) +{ + struct nlattr *tb[CTA_TUPLE_MAX+1]; + int err; + + err = nla_parse_nested(tb, CTA_TUPLE_MAX, attr, ct_tuple_policy); + if (err < 0) + return err; + + if (tb[CTA_TUPLE_IP]) { + err = ct_parse_ip(ct, repl, tb[CTA_TUPLE_IP]); + if (err < 0) + return err; + } + + if (tb[CTA_TUPLE_PROTO]) { + err = ct_parse_proto(ct, repl, tb[CTA_TUPLE_PROTO]); + if (err < 0) + return err; + } + + return 0; +} + +static int ct_parse_protoinfo_tcp(struct nfnl_ct *ct, struct nlattr *attr) +{ + struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1]; + int err; + + err = nla_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr, + ct_protoinfo_tcp_policy); + if (err < 0) + return err; + + if (tb[CTA_PROTOINFO_TCP_STATE]) + nfnl_ct_set_tcp_state(ct, + nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE])); + + return 0; +} + +static int ct_parse_protoinfo(struct nfnl_ct *ct, struct nlattr *attr) +{ + struct nlattr *tb[CTA_PROTOINFO_MAX+1]; + int err; + + err = nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, + ct_protoinfo_policy); + if (err < 0) + return err; + + if (tb[CTA_PROTOINFO_TCP]) { + err = ct_parse_protoinfo_tcp(ct, tb[CTA_PROTOINFO_TCP]); + if (err < 0) + return err; + } + + return 0; +} + +static int ct_parse_counters(struct nfnl_ct *ct, int repl, struct nlattr *attr) +{ + struct nlattr *tb[CTA_COUNTERS_MAX+1]; + int err; + + err = nla_parse_nested(tb, CTA_COUNTERS_MAX, attr, ct_counters_policy); + if (err < 0) + return err; + + if (tb[CTA_COUNTERS_PACKETS]) + nfnl_ct_set_packets(ct, repl, + ntohll(nla_get_u64(tb[CTA_COUNTERS_PACKETS]))); + if (tb[CTA_COUNTERS32_PACKETS]) + nfnl_ct_set_packets(ct, repl, + ntohl(nla_get_u32(tb[CTA_COUNTERS32_PACKETS]))); + if (tb[CTA_COUNTERS_BYTES]) + nfnl_ct_set_bytes(ct, repl, + ntohll(nla_get_u64(tb[CTA_COUNTERS_BYTES]))); + if (tb[CTA_COUNTERS32_BYTES]) + nfnl_ct_set_bytes(ct, repl, + ntohl(nla_get_u32(tb[CTA_COUNTERS32_BYTES]))); + + return 0; +} + +int nfnlmsg_ct_group(struct nlmsghdr *nlh) +{ + switch (nfnlmsg_subtype(nlh)) { + case IPCTNL_MSG_CT_NEW: + if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL)) + return NFNLGRP_CONNTRACK_NEW; + else + return NFNLGRP_CONNTRACK_UPDATE; + case IPCTNL_MSG_CT_DELETE: + return NFNLGRP_CONNTRACK_DESTROY; + default: + return NFNLGRP_NONE; + } +} + +int nfnlmsg_ct_parse(struct nlmsghdr *nlh, struct nfnl_ct **result) +{ + struct nfnl_ct *ct; + struct nlattr *tb[CTA_MAX+1]; + int err; + + ct = nfnl_ct_alloc(); + if (!ct) + return -NLE_NOMEM; + + ct->ce_msgtype = nlh->nlmsg_type; + + err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_MAX, + ct_policy); + if (err < 0) + goto errout; + + nfnl_ct_set_family(ct, nfnlmsg_family(nlh)); + + if (tb[CTA_TUPLE_ORIG]) { + err = ct_parse_tuple(ct, 0, tb[CTA_TUPLE_ORIG]); + if (err < 0) + goto errout; + } + if (tb[CTA_TUPLE_REPLY]) { + err = ct_parse_tuple(ct, 1, tb[CTA_TUPLE_REPLY]); + if (err < 0) + goto errout; + } + + if (tb[CTA_PROTOINFO]) { + err = ct_parse_protoinfo(ct, tb[CTA_PROTOINFO]); + if (err < 0) + goto errout; + } + + if (tb[CTA_STATUS]) + nfnl_ct_set_status(ct, ntohl(nla_get_u32(tb[CTA_STATUS]))); + if (tb[CTA_TIMEOUT]) + nfnl_ct_set_timeout(ct, ntohl(nla_get_u32(tb[CTA_TIMEOUT]))); + if (tb[CTA_MARK]) + nfnl_ct_set_mark(ct, ntohl(nla_get_u32(tb[CTA_MARK]))); + if (tb[CTA_USE]) + nfnl_ct_set_use(ct, ntohl(nla_get_u32(tb[CTA_USE]))); + if (tb[CTA_ID]) + nfnl_ct_set_id(ct, ntohl(nla_get_u32(tb[CTA_ID]))); + + if (tb[CTA_COUNTERS_ORIG]) { + err = ct_parse_counters(ct, 0, tb[CTA_COUNTERS_ORIG]); + if (err < 0) + goto errout; + } + + if (tb[CTA_COUNTERS_REPLY]) { + err = ct_parse_counters(ct, 1, tb[CTA_COUNTERS_REPLY]); + if (err < 0) + goto errout; + } + + *result = ct; + return 0; + +errout: + nfnl_ct_put(ct); + return err; +} + +static int ct_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *nlh, struct nl_parser_param *pp) +{ + struct nfnl_ct *ct; + int err; + + if ((err = nfnlmsg_ct_parse(nlh, &ct)) < 0) + goto errout; + + err = pp->pp_cb((struct nl_object *) ct, pp); +errout: + nfnl_ct_put(ct); + return err; +} + +int nfnl_ct_dump_request(struct nl_sock *sk) +{ + return nfnl_send_simple(sk, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET, + NLM_F_DUMP, AF_UNSPEC, 0); +} + +static int ct_request_update(struct nl_cache *cache, struct nl_sock *sk) +{ + return nfnl_ct_dump_request(sk); +} + +static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct, + int repl) +{ + struct nlattr *tuple, *ip, *proto; + struct nl_addr *addr; + int family; + + family = nfnl_ct_get_family(ct); + + tuple = nla_nest_start(msg, repl ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG); + if (!tuple) + goto nla_put_failure; + + ip = nla_nest_start(msg, CTA_TUPLE_IP); + if (!ip) + goto nla_put_failure; + + addr = nfnl_ct_get_src(ct, repl); + if (addr) + NLA_PUT_ADDR(msg, + family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC, + addr); + + addr = nfnl_ct_get_dst(ct, repl); + if (addr) + NLA_PUT_ADDR(msg, + family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST, + addr); + + nla_nest_end(msg, ip); + + proto = nla_nest_start(msg, CTA_TUPLE_PROTO); + if (!proto) + goto nla_put_failure; + + if (nfnl_ct_test_proto(ct)) + NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_ct_get_proto(ct)); + + if (nfnl_ct_test_src_port(ct, repl)) + NLA_PUT_U16(msg, CTA_PROTO_SRC_PORT, + htons(nfnl_ct_get_src_port(ct, repl))); + + if (nfnl_ct_test_dst_port(ct, repl)) + NLA_PUT_U16(msg, CTA_PROTO_DST_PORT, + htons(nfnl_ct_get_dst_port(ct, repl))); + + if (family == AF_INET) { + if (nfnl_ct_test_icmp_id(ct, repl)) + NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID, + htons(nfnl_ct_get_icmp_id(ct, repl))); + + if (nfnl_ct_test_icmp_type(ct, repl)) + NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE, + nfnl_ct_get_icmp_type(ct, repl)); + + if (nfnl_ct_test_icmp_code(ct, repl)) + NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE, + nfnl_ct_get_icmp_code(ct, repl)); + } else if (family == AF_INET6) { + if (nfnl_ct_test_icmp_id(ct, repl)) + NLA_PUT_U16(msg, CTA_PROTO_ICMPV6_ID, + htons(nfnl_ct_get_icmp_id(ct, repl))); + + if (nfnl_ct_test_icmp_type(ct, repl)) + NLA_PUT_U8(msg, CTA_PROTO_ICMPV6_TYPE, + nfnl_ct_get_icmp_type(ct, repl)); + + if (nfnl_ct_test_icmp_code(ct, repl)) + NLA_PUT_U8(msg, CTA_PROTO_ICMPV6_CODE, + nfnl_ct_get_icmp_code(ct, repl)); + } + + nla_nest_end(msg, proto); + + nla_nest_end(msg, tuple); + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +static int nfnl_ct_build_message(const struct nfnl_ct *ct, int cmd, int flags, + struct nl_msg **result) +{ + struct nl_msg *msg; + int err; + + msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK, cmd, flags, + nfnl_ct_get_family(ct), 0); + if (msg == NULL) + return -NLE_NOMEM; + + if ((err = nfnl_ct_build_tuple(msg, ct, 0)) < 0) + goto err_out; + + *result = msg; + return 0; + +err_out: + nlmsg_free(msg); + return err; +} + +int nfnl_ct_build_add_request(const struct nfnl_ct *ct, int flags, + struct nl_msg **result) +{ + return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_NEW, flags, result); +} + +int nfnl_ct_add(struct nl_sock *sk, const struct nfnl_ct *ct, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_ct_build_add_request(ct, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +int nfnl_ct_build_delete_request(const struct nfnl_ct *ct, int flags, + struct nl_msg **result) +{ + return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_DELETE, flags, result); +} + +int nfnl_ct_del(struct nl_sock *sk, const struct nfnl_ct *ct, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_ct_build_delete_request(ct, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +int nfnl_ct_build_query_request(const struct nfnl_ct *ct, int flags, + struct nl_msg **result) +{ + return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_GET, flags, result); +} + +int nfnl_ct_query(struct nl_sock *sk, const struct nfnl_ct *ct, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_ct_build_query_request(ct, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +/** + * @name Cache Management + * @{ + */ + +/** + * Build a conntrack cache holding all conntrack currently in the kernel + * @arg sk Netlink socket. + * @arg result Pointer to store resulting cache. + * + * Allocates a new cache, initializes it properly and updates it to + * contain all conntracks currently in the kernel. + * + * @return 0 on success or a negative error code. + */ +int nfnl_ct_alloc_cache(struct nl_sock *sk, struct nl_cache **result) +{ + return nl_cache_alloc_and_fill(&nfnl_ct_ops, sk, result); +} + +/** @} */ + +/** + * @name Conntrack Addition + * @{ + */ + +/** @} */ + +static struct nl_af_group ct_groups[] = { + { AF_UNSPEC, NFNLGRP_CONNTRACK_NEW }, + { AF_UNSPEC, NFNLGRP_CONNTRACK_UPDATE }, + { AF_UNSPEC, NFNLGRP_CONNTRACK_DESTROY }, + { END_OF_GROUP_LIST }, +}; + +#define NFNLMSG_CT_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK, (type)) +static struct nl_cache_ops nfnl_ct_ops = { + .co_name = "netfilter/ct", + .co_hdrsize = NFNL_HDRLEN, + .co_msgtypes = { + { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_NEW), NL_ACT_NEW, "new" }, + { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_GET), NL_ACT_GET, "get" }, + { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_DELETE), NL_ACT_DEL, "del" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_NETFILTER, + .co_groups = ct_groups, + .co_request_update = ct_request_update, + .co_msg_parser = ct_msg_parser, + .co_obj_ops = &ct_obj_ops, +}; + +static void __init ct_init(void) +{ + nl_cache_mngt_register(&nfnl_ct_ops); +} + +static void __exit ct_exit(void) +{ + nl_cache_mngt_unregister(&nfnl_ct_ops); +} + +/** @} */ diff --git a/lib/netfilter/ct_obj.c b/lib/netfilter/ct_obj.c new file mode 100644 index 0000000..bac775b --- /dev/null +++ b/lib/netfilter/ct_obj.c @@ -0,0 +1,796 @@ +/* + * lib/netfilter/ct_obj.c Conntrack Object + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + */ + +#include +#include +#include +#include + +#include +#include +#include + +/** @cond SKIP */ +#define CT_ATTR_FAMILY (1UL << 0) +#define CT_ATTR_PROTO (1UL << 1) + +#define CT_ATTR_TCP_STATE (1UL << 2) + +#define CT_ATTR_STATUS (1UL << 3) +#define CT_ATTR_TIMEOUT (1UL << 4) +#define CT_ATTR_MARK (1UL << 5) +#define CT_ATTR_USE (1UL << 6) +#define CT_ATTR_ID (1UL << 7) + +#define CT_ATTR_ORIG_SRC (1UL << 8) +#define CT_ATTR_ORIG_DST (1UL << 9) +#define CT_ATTR_ORIG_SRC_PORT (1UL << 10) +#define CT_ATTR_ORIG_DST_PORT (1UL << 11) +#define CT_ATTR_ORIG_ICMP_ID (1UL << 12) +#define CT_ATTR_ORIG_ICMP_TYPE (1UL << 13) +#define CT_ATTR_ORIG_ICMP_CODE (1UL << 14) +#define CT_ATTR_ORIG_PACKETS (1UL << 15) +#define CT_ATTR_ORIG_BYTES (1UL << 16) + +#define CT_ATTR_REPL_SRC (1UL << 17) +#define CT_ATTR_REPL_DST (1UL << 18) +#define CT_ATTR_REPL_SRC_PORT (1UL << 19) +#define CT_ATTR_REPL_DST_PORT (1UL << 20) +#define CT_ATTR_REPL_ICMP_ID (1UL << 21) +#define CT_ATTR_REPL_ICMP_TYPE (1UL << 22) +#define CT_ATTR_REPL_ICMP_CODE (1UL << 23) +#define CT_ATTR_REPL_PACKETS (1UL << 24) +#define CT_ATTR_REPL_BYTES (1UL << 25) +/** @endcond */ + +static void ct_free_data(struct nl_object *c) +{ + struct nfnl_ct *ct = (struct nfnl_ct *) c; + + if (ct == NULL) + return; + + nl_addr_put(ct->ct_orig.src); + nl_addr_put(ct->ct_orig.dst); + nl_addr_put(ct->ct_repl.src); + nl_addr_put(ct->ct_repl.dst); +} + +static int ct_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct nfnl_ct *dst = (struct nfnl_ct *) _dst; + struct nfnl_ct *src = (struct nfnl_ct *) _src; + struct nl_addr *addr; + + if (src->ct_orig.src) { + addr = nl_addr_clone(src->ct_orig.src); + if (!addr) + return -NLE_NOMEM; + dst->ct_orig.src = addr; + } + + if (src->ct_orig.dst) { + addr = nl_addr_clone(src->ct_orig.dst); + if (!addr) + return -NLE_NOMEM; + dst->ct_orig.dst = addr; + } + + if (src->ct_repl.src) { + addr = nl_addr_clone(src->ct_repl.src); + if (!addr) + return -NLE_NOMEM; + dst->ct_repl.src = addr; + } + + if (src->ct_repl.dst) { + addr = nl_addr_clone(src->ct_repl.dst); + if (!addr) + return -NLE_NOMEM; + dst->ct_repl.dst = addr; + } + + return 0; +} + +static void dump_addr(struct nl_dump_params *p, struct nl_addr *addr, int port) +{ + char buf[64]; + + if (addr) + nl_dump(p, "%s", nl_addr2str(addr, buf, sizeof(buf))); + + if (port) + nl_dump(p, ":%u ", port); + else if (addr) + nl_dump(p, " "); +} + +static void dump_icmp(struct nl_dump_params *p, struct nfnl_ct *ct, int reply) +{ + if (nfnl_ct_test_icmp_type(ct, reply)) + nl_dump(p, "icmp type %d ", nfnl_ct_get_icmp_type(ct, reply)); + + if (nfnl_ct_test_icmp_code(ct, reply)) + nl_dump(p, "code %d ", nfnl_ct_get_icmp_code(ct, reply)); + + if (nfnl_ct_test_icmp_id(ct, reply)) + nl_dump(p, "id %d ", nfnl_ct_get_icmp_id(ct, reply)); +} + +static void ct_dump_tuples(struct nfnl_ct *ct, struct nl_dump_params *p) +{ + struct nl_addr *orig_src, *orig_dst, *reply_src, *reply_dst; + int orig_sport = 0, orig_dport = 0, reply_sport = 0, reply_dport = 0; + int sync = 0; + + orig_src = nfnl_ct_get_src(ct, 0); + orig_dst = nfnl_ct_get_dst(ct, 0); + reply_src = nfnl_ct_get_src(ct, 1); + reply_dst = nfnl_ct_get_dst(ct, 1); + + if (nfnl_ct_test_src_port(ct, 0)) + orig_sport = nfnl_ct_get_src_port(ct, 0); + + if (nfnl_ct_test_dst_port(ct, 0)) + orig_dport = nfnl_ct_get_dst_port(ct, 0); + + if (nfnl_ct_test_src_port(ct, 1)) + reply_sport = nfnl_ct_get_src_port(ct, 1); + + if (nfnl_ct_test_dst_port(ct, 1)) + reply_dport = nfnl_ct_get_dst_port(ct, 1); + + if (orig_src && orig_dst && reply_src && reply_dst && + orig_sport == reply_dport && orig_dport == reply_sport && + !nl_addr_cmp(orig_src, reply_dst) && + !nl_addr_cmp(orig_dst, reply_src)) + sync = 1; + + dump_addr(p, orig_src, orig_sport); + nl_dump(p, sync ? "<-> " : "-> "); + dump_addr(p, orig_dst, orig_dport); + dump_icmp(p, ct, 0); + + if (!sync) { + dump_addr(p, reply_src, reply_sport); + nl_dump(p, "<- "); + dump_addr(p, reply_dst, reply_dport); + dump_icmp(p, ct, 1); + } +} + +/* Compatible with /proc/net/nf_conntrack */ +static void ct_dump_line(struct nl_object *a, struct nl_dump_params *p) +{ + struct nfnl_ct *ct = (struct nfnl_ct *) a; + char buf[64]; + + nl_new_line(p); + + if (nfnl_ct_test_proto(ct)) + nl_dump(p, "%s ", + nl_ip_proto2str(nfnl_ct_get_proto(ct), buf, sizeof(buf))); + + if (nfnl_ct_test_tcp_state(ct)) + nl_dump(p, "%s ", + nfnl_ct_tcp_state2str(nfnl_ct_get_tcp_state(ct), + buf, sizeof(buf))); + + ct_dump_tuples(ct, p); + + if (nfnl_ct_test_mark(ct) && nfnl_ct_get_mark(ct)) + nl_dump(p, "mark %u ", nfnl_ct_get_mark(ct)); + + nl_dump(p, "\n"); +} + +static void ct_dump_details(struct nl_object *a, struct nl_dump_params *p) +{ + struct nfnl_ct *ct = (struct nfnl_ct *) a; + char buf[64]; + int fp = 0; + + ct_dump_line(a, p); + + nl_dump(p, " id 0x%x ", ct->ct_id); + nl_dump_line(p, "family %s ", + nl_af2str(ct->ct_family, buf, sizeof(buf))); + + if (nfnl_ct_test_use(ct)) + nl_dump(p, "refcnt %u ", nfnl_ct_get_use(ct)); + + if (nfnl_ct_test_timeout(ct)) { + uint64_t timeout_ms = nfnl_ct_get_timeout(ct) * 1000UL; + nl_dump(p, "timeout %s ", + nl_msec2str(timeout_ms, buf, sizeof(buf))); + } + + if (ct->ct_status) + nl_dump(p, "<"); + +#define PRINT_FLAG(str) \ + { nl_dump(p, "%s%s", fp++ ? "," : "", (str)); } + + if (ct->ct_status & IPS_EXPECTED) + PRINT_FLAG("EXPECTED"); + if (!(ct->ct_status & IPS_SEEN_REPLY)) + PRINT_FLAG("NOREPLY"); + if (ct->ct_status & IPS_ASSURED) + PRINT_FLAG("ASSURED"); + if (!(ct->ct_status & IPS_CONFIRMED)) + PRINT_FLAG("NOTSENT"); + if (ct->ct_status & IPS_SRC_NAT) + PRINT_FLAG("SNAT"); + if (ct->ct_status & IPS_DST_NAT) + PRINT_FLAG("DNAT"); + if (ct->ct_status & IPS_SEQ_ADJUST) + PRINT_FLAG("SEQADJUST"); + if (!(ct->ct_status & IPS_SRC_NAT_DONE)) + PRINT_FLAG("SNAT_INIT"); + if (!(ct->ct_status & IPS_DST_NAT_DONE)) + PRINT_FLAG("DNAT_INIT"); + if (ct->ct_status & IPS_DYING) + PRINT_FLAG("DYING"); + if (ct->ct_status & IPS_FIXED_TIMEOUT) + PRINT_FLAG("FIXED_TIMEOUT"); +#undef PRINT_FLAG + + if (ct->ct_status) + nl_dump(p, ">"); + nl_dump(p, "\n"); +} + +static void ct_dump_stats(struct nl_object *a, struct nl_dump_params *p) +{ + struct nfnl_ct *ct = (struct nfnl_ct *) a; + double res; + char *unit; + uint64_t packets; + const char * const names[] = {"rx", "tx"}; + int i; + + ct_dump_details(a, p); + + if (!nfnl_ct_test_bytes(ct, 0) || + !nfnl_ct_test_packets(ct, 0) || + !nfnl_ct_test_bytes(ct, 1) || + !nfnl_ct_test_packets(ct, 1)) + { + nl_dump_line(p, " Statistics are not available.\n"); + nl_dump_line(p, " Please set sysctl net.netfilter.nf_conntrack_acct=1\n"); + nl_dump_line(p, " (Require kernel 2.6.27)\n"); + return; + } + + nl_dump_line(p, " # packets volume\n"); + for (i=0; i<=1; i++) { + res = nl_cancel_down_bytes(nfnl_ct_get_bytes(ct, i), &unit); + packets = nfnl_ct_get_packets(ct, i); + nl_dump_line(p, " %s %10" PRIu64 " %7.2f %s\n", names[i], packets, res, unit); + } +} + +static int ct_compare(struct nl_object *_a, struct nl_object *_b, + uint32_t attrs, int flags) +{ + struct nfnl_ct *a = (struct nfnl_ct *) _a; + struct nfnl_ct *b = (struct nfnl_ct *) _b; + int diff = 0; + +#define CT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, CT_ATTR_##ATTR, a, b, EXPR) +#define CT_DIFF_VAL(ATTR, FIELD) CT_DIFF(ATTR, a->FIELD != b->FIELD) +#define CT_DIFF_ADDR(ATTR, FIELD) \ + ((flags & LOOSE_COMPARISON) \ + ? CT_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \ + : CT_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD))) + + diff |= CT_DIFF_VAL(FAMILY, ct_family); + diff |= CT_DIFF_VAL(PROTO, ct_proto); + diff |= CT_DIFF_VAL(TCP_STATE, ct_protoinfo.tcp.state); + diff |= CT_DIFF_VAL(TIMEOUT, ct_timeout); + diff |= CT_DIFF_VAL(MARK, ct_mark); + diff |= CT_DIFF_VAL(USE, ct_use); + diff |= CT_DIFF_VAL(ID, ct_id); + diff |= CT_DIFF_ADDR(ORIG_SRC, ct_orig.src); + diff |= CT_DIFF_ADDR(ORIG_DST, ct_orig.dst); + diff |= CT_DIFF_VAL(ORIG_SRC_PORT, ct_orig.proto.port.src); + diff |= CT_DIFF_VAL(ORIG_DST_PORT, ct_orig.proto.port.dst); + diff |= CT_DIFF_VAL(ORIG_ICMP_ID, ct_orig.proto.icmp.id); + diff |= CT_DIFF_VAL(ORIG_ICMP_TYPE, ct_orig.proto.icmp.type); + diff |= CT_DIFF_VAL(ORIG_ICMP_CODE, ct_orig.proto.icmp.code); + diff |= CT_DIFF_VAL(ORIG_PACKETS, ct_orig.packets); + diff |= CT_DIFF_VAL(ORIG_BYTES, ct_orig.bytes); + diff |= CT_DIFF_ADDR(REPL_SRC, ct_repl.src); + diff |= CT_DIFF_ADDR(REPL_DST, ct_repl.dst); + diff |= CT_DIFF_VAL(REPL_SRC_PORT, ct_repl.proto.port.src); + diff |= CT_DIFF_VAL(REPL_DST_PORT, ct_repl.proto.port.dst); + diff |= CT_DIFF_VAL(REPL_ICMP_ID, ct_repl.proto.icmp.id); + diff |= CT_DIFF_VAL(REPL_ICMP_TYPE, ct_repl.proto.icmp.type); + diff |= CT_DIFF_VAL(REPL_ICMP_CODE, ct_repl.proto.icmp.code); + diff |= CT_DIFF_VAL(REPL_PACKETS, ct_repl.packets); + diff |= CT_DIFF_VAL(REPL_BYTES, ct_repl.bytes); + + if (flags & LOOSE_COMPARISON) + diff |= CT_DIFF(STATUS, (a->ct_status ^ b->ct_status) & + b->ct_status_mask); + else + diff |= CT_DIFF(STATUS, a->ct_status != b->ct_status); + +#undef CT_DIFF +#undef CT_DIFF_VAL +#undef CT_DIFF_ADDR + + return diff; +} + +static const struct trans_tbl ct_attrs[] = { + __ADD(CT_ATTR_FAMILY, family) + __ADD(CT_ATTR_PROTO, proto) + __ADD(CT_ATTR_TCP_STATE, tcpstate) + __ADD(CT_ATTR_STATUS, status) + __ADD(CT_ATTR_TIMEOUT, timeout) + __ADD(CT_ATTR_MARK, mark) + __ADD(CT_ATTR_USE, use) + __ADD(CT_ATTR_ID, id) + __ADD(CT_ATTR_ORIG_SRC, origsrc) + __ADD(CT_ATTR_ORIG_DST, origdst) + __ADD(CT_ATTR_ORIG_SRC_PORT, origsrcport) + __ADD(CT_ATTR_ORIG_DST_PORT, origdstport) + __ADD(CT_ATTR_ORIG_ICMP_ID, origicmpid) + __ADD(CT_ATTR_ORIG_ICMP_TYPE, origicmptype) + __ADD(CT_ATTR_ORIG_ICMP_CODE, origicmpcode) + __ADD(CT_ATTR_ORIG_PACKETS, origpackets) + __ADD(CT_ATTR_ORIG_BYTES, origbytes) + __ADD(CT_ATTR_REPL_SRC, replysrc) + __ADD(CT_ATTR_REPL_DST, replydst) + __ADD(CT_ATTR_REPL_SRC_PORT, replysrcport) + __ADD(CT_ATTR_REPL_DST_PORT, replydstport) + __ADD(CT_ATTR_REPL_ICMP_ID, replyicmpid) + __ADD(CT_ATTR_REPL_ICMP_TYPE, replyicmptype) + __ADD(CT_ATTR_REPL_ICMP_CODE, replyicmpcode) + __ADD(CT_ATTR_REPL_PACKETS, replypackets) + __ADD(CT_ATTR_REPL_BYTES, replybytes) +}; + +static char *ct_attrs2str(int attrs, char *buf, size_t len) +{ + return __flags2str(attrs, buf, len, ct_attrs, ARRAY_SIZE(ct_attrs)); +} + +/** + * @name Allocation/Freeing + * @{ + */ + +struct nfnl_ct *nfnl_ct_alloc(void) +{ + return (struct nfnl_ct *) nl_object_alloc(&ct_obj_ops); +} + +void nfnl_ct_get(struct nfnl_ct *ct) +{ + nl_object_get((struct nl_object *) ct); +} + +void nfnl_ct_put(struct nfnl_ct *ct) +{ + nl_object_put((struct nl_object *) ct); +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ + +void nfnl_ct_set_family(struct nfnl_ct *ct, uint8_t family) +{ + ct->ct_family = family; + ct->ce_mask |= CT_ATTR_FAMILY; +} + +uint8_t nfnl_ct_get_family(const struct nfnl_ct *ct) +{ + if (ct->ce_mask & CT_ATTR_FAMILY) + return ct->ct_family; + else + return AF_UNSPEC; +} + +void nfnl_ct_set_proto(struct nfnl_ct *ct, uint8_t proto) +{ + ct->ct_proto = proto; + ct->ce_mask |= CT_ATTR_PROTO; +} + +int nfnl_ct_test_proto(const struct nfnl_ct *ct) +{ + return !!(ct->ce_mask & CT_ATTR_PROTO); +} + +uint8_t nfnl_ct_get_proto(const struct nfnl_ct *ct) +{ + return ct->ct_proto; +} + +void nfnl_ct_set_tcp_state(struct nfnl_ct *ct, uint8_t state) +{ + ct->ct_protoinfo.tcp.state = state; + ct->ce_mask |= CT_ATTR_TCP_STATE; +} + +int nfnl_ct_test_tcp_state(const struct nfnl_ct *ct) +{ + return !!(ct->ce_mask & CT_ATTR_TCP_STATE); +} + +uint8_t nfnl_ct_get_tcp_state(const struct nfnl_ct *ct) +{ + return ct->ct_protoinfo.tcp.state; +} + +static const struct trans_tbl tcp_states[] = { + __ADD(TCP_CONNTRACK_NONE,NONE) + __ADD(TCP_CONNTRACK_SYN_SENT,SYN_SENT) + __ADD(TCP_CONNTRACK_SYN_RECV,SYN_RECV) + __ADD(TCP_CONNTRACK_ESTABLISHED,ESTABLISHED) + __ADD(TCP_CONNTRACK_FIN_WAIT,FIN_WAIT) + __ADD(TCP_CONNTRACK_CLOSE_WAIT,CLOSE_WAIT) + __ADD(TCP_CONNTRACK_LAST_ACK,LAST_ACK) + __ADD(TCP_CONNTRACK_TIME_WAIT,TIME_WAIT) + __ADD(TCP_CONNTRACK_CLOSE,CLOSE) + __ADD(TCP_CONNTRACK_LISTEN,LISTEN) +}; + +char *nfnl_ct_tcp_state2str(uint8_t state, char *buf, size_t len) +{ + return __type2str(state, buf, len, tcp_states, ARRAY_SIZE(tcp_states)); +} + +int nfnl_ct_str2tcp_state(const char *name) +{ + return __str2type(name, tcp_states, ARRAY_SIZE(tcp_states)); +} + +void nfnl_ct_set_status(struct nfnl_ct *ct, uint32_t status) +{ + ct->ct_status_mask |= status; + ct->ct_status |= status; + ct->ce_mask |= CT_ATTR_STATUS; +} + +void nfnl_ct_unset_status(struct nfnl_ct *ct, uint32_t status) +{ + ct->ct_status_mask |= status; + ct->ct_status &= ~status; + ct->ce_mask |= CT_ATTR_STATUS; +} + +uint32_t nfnl_ct_get_status(const struct nfnl_ct *ct) +{ + return ct->ct_status; +} + +static const struct trans_tbl status_flags[] = { + __ADD(IPS_EXPECTED, expected) + __ADD(IPS_SEEN_REPLY, seen_reply) + __ADD(IPS_ASSURED, assured) + __ADD(IPS_CONFIRMED, confirmed) + __ADD(IPS_SRC_NAT, snat) + __ADD(IPS_DST_NAT, dnat) + __ADD(IPS_SEQ_ADJUST, seqadjust) + __ADD(IPS_SRC_NAT_DONE, snat_done) + __ADD(IPS_DST_NAT_DONE, dnat_done) + __ADD(IPS_DYING, dying) + __ADD(IPS_FIXED_TIMEOUT, fixed_timeout) +}; + +char * nfnl_ct_status2str(int flags, char *buf, size_t len) +{ + return __flags2str(flags, buf, len, status_flags, + ARRAY_SIZE(status_flags)); +} + +int nfnl_ct_str2status(const char *name) +{ + return __str2flags(name, status_flags, ARRAY_SIZE(status_flags)); +} + +void nfnl_ct_set_timeout(struct nfnl_ct *ct, uint32_t timeout) +{ + ct->ct_timeout = timeout; + ct->ce_mask |= CT_ATTR_TIMEOUT; +} + +int nfnl_ct_test_timeout(const struct nfnl_ct *ct) +{ + return !!(ct->ce_mask & CT_ATTR_TIMEOUT); +} + +uint32_t nfnl_ct_get_timeout(const struct nfnl_ct *ct) +{ + return ct->ct_timeout; +} + +void nfnl_ct_set_mark(struct nfnl_ct *ct, uint32_t mark) +{ + ct->ct_mark = mark; + ct->ce_mask |= CT_ATTR_MARK; +} + +int nfnl_ct_test_mark(const struct nfnl_ct *ct) +{ + return !!(ct->ce_mask & CT_ATTR_MARK); +} + +uint32_t nfnl_ct_get_mark(const struct nfnl_ct *ct) +{ + return ct->ct_mark; +} + +void nfnl_ct_set_use(struct nfnl_ct *ct, uint32_t use) +{ + ct->ct_use = use; + ct->ce_mask |= CT_ATTR_USE; +} + +int nfnl_ct_test_use(const struct nfnl_ct *ct) +{ + return !!(ct->ce_mask & CT_ATTR_USE); +} + +uint32_t nfnl_ct_get_use(const struct nfnl_ct *ct) +{ + return ct->ct_use; +} + +void nfnl_ct_set_id(struct nfnl_ct *ct, uint32_t id) +{ + ct->ct_id = id; + ct->ce_mask |= CT_ATTR_ID; +} + +int nfnl_ct_test_id(const struct nfnl_ct *ct) +{ + return !!(ct->ce_mask & CT_ATTR_ID); +} + +uint32_t nfnl_ct_get_id(const struct nfnl_ct *ct) +{ + return ct->ct_id; +} + +static int ct_set_addr(struct nfnl_ct *ct, struct nl_addr *addr, + int attr, struct nl_addr ** ct_addr) +{ + if (ct->ce_mask & CT_ATTR_FAMILY) { + if (addr->a_family != ct->ct_family) + return -NLE_AF_MISMATCH; + } else + nfnl_ct_set_family(ct, addr->a_family); + + if (*ct_addr) + nl_addr_put(*ct_addr); + + nl_addr_get(addr); + *ct_addr = addr; + ct->ce_mask |= attr; + + return 0; +} + +int nfnl_ct_set_src(struct nfnl_ct *ct, int repl, struct nl_addr *addr) +{ + struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC; + return ct_set_addr(ct, addr, attr, &dir->src); +} + +int nfnl_ct_set_dst(struct nfnl_ct *ct, int repl, struct nl_addr *addr) +{ + struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST; + return ct_set_addr(ct, addr, attr, &dir->dst); +} + +struct nl_addr *nfnl_ct_get_src(const struct nfnl_ct *ct, int repl) +{ + const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC; + if (!(ct->ce_mask & attr)) + return NULL; + return dir->src; +} + +struct nl_addr *nfnl_ct_get_dst(const struct nfnl_ct *ct, int repl) +{ + const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST; + if (!(ct->ce_mask & attr)) + return NULL; + return dir->dst; +} + +void nfnl_ct_set_src_port(struct nfnl_ct *ct, int repl, uint16_t port) +{ + struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT; + + dir->proto.port.src = port; + ct->ce_mask |= attr; +} + +int nfnl_ct_test_src_port(const struct nfnl_ct *ct, int repl) +{ + int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT; + return !!(ct->ce_mask & attr); +} + +uint16_t nfnl_ct_get_src_port(const struct nfnl_ct *ct, int repl) +{ + const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + + return dir->proto.port.src; +} + +void nfnl_ct_set_dst_port(struct nfnl_ct *ct, int repl, uint16_t port) +{ + struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT; + + dir->proto.port.dst = port; + ct->ce_mask |= attr; +} + +int nfnl_ct_test_dst_port(const struct nfnl_ct *ct, int repl) +{ + int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT; + return !!(ct->ce_mask & attr); +} + +uint16_t nfnl_ct_get_dst_port(const struct nfnl_ct *ct, int repl) +{ + const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + + return dir->proto.port.dst; +} + +void nfnl_ct_set_icmp_id(struct nfnl_ct *ct, int repl, uint16_t id) +{ + struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID; + + dir->proto.icmp.id = id; + ct->ce_mask |= attr; +} + +int nfnl_ct_test_icmp_id(const struct nfnl_ct *ct, int repl) +{ + int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID; + return !!(ct->ce_mask & attr); +} + +uint16_t nfnl_ct_get_icmp_id(const struct nfnl_ct *ct, int repl) +{ + const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + + return dir->proto.icmp.id; +} + +void nfnl_ct_set_icmp_type(struct nfnl_ct *ct, int repl, uint8_t type) +{ + struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_ICMP_TYPE : CT_ATTR_ORIG_ICMP_TYPE; + + dir->proto.icmp.type = type; + ct->ce_mask |= attr; +} + +int nfnl_ct_test_icmp_type(const struct nfnl_ct *ct, int repl) +{ + int attr = repl ? CT_ATTR_REPL_ICMP_TYPE : CT_ATTR_ORIG_ICMP_TYPE; + return !!(ct->ce_mask & attr); +} + +uint8_t nfnl_ct_get_icmp_type(const struct nfnl_ct *ct, int repl) +{ + const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + + return dir->proto.icmp.type; +} + +void nfnl_ct_set_icmp_code(struct nfnl_ct *ct, int repl, uint8_t code) +{ + struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_ICMP_CODE : CT_ATTR_ORIG_ICMP_CODE; + + dir->proto.icmp.code = code; + ct->ce_mask |= attr; +} + +int nfnl_ct_test_icmp_code(const struct nfnl_ct *ct, int repl) +{ + int attr = repl ? CT_ATTR_REPL_ICMP_CODE : CT_ATTR_ORIG_ICMP_CODE; + return !!(ct->ce_mask & attr); +} + +uint8_t nfnl_ct_get_icmp_code(const struct nfnl_ct *ct, int repl) +{ + const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + + return dir->proto.icmp.code; +} + +void nfnl_ct_set_packets(struct nfnl_ct *ct, int repl, uint64_t packets) +{ + struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_PACKETS : CT_ATTR_ORIG_PACKETS; + + dir->packets = packets; + ct->ce_mask |= attr; +} + +int nfnl_ct_test_packets(const struct nfnl_ct *ct, int repl) +{ + int attr = repl ? CT_ATTR_REPL_PACKETS : CT_ATTR_ORIG_PACKETS; + return !!(ct->ce_mask & attr); +} + +uint64_t nfnl_ct_get_packets(const struct nfnl_ct *ct, int repl) +{ + const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + + return dir->packets; +} + +void nfnl_ct_set_bytes(struct nfnl_ct *ct, int repl, uint64_t bytes) +{ + struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + int attr = repl ? CT_ATTR_REPL_BYTES : CT_ATTR_ORIG_BYTES; + + dir->bytes = bytes; + ct->ce_mask |= attr; +} + +int nfnl_ct_test_bytes(const struct nfnl_ct *ct, int repl) +{ + int attr = repl ? CT_ATTR_REPL_BYTES : CT_ATTR_ORIG_BYTES; + return !!(ct->ce_mask & attr); +} + +uint64_t nfnl_ct_get_bytes(const struct nfnl_ct *ct, int repl) +{ + const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + + return dir->bytes; +} + +/** @} */ + +struct nl_object_ops ct_obj_ops = { + .oo_name = "netfilter/ct", + .oo_size = sizeof(struct nfnl_ct), + .oo_free_data = ct_free_data, + .oo_clone = ct_clone, + .oo_dump = { + [NL_DUMP_LINE] = ct_dump_line, + [NL_DUMP_DETAILS] = ct_dump_details, + [NL_DUMP_STATS] = ct_dump_stats, + }, + .oo_compare = ct_compare, + .oo_attrs2str = ct_attrs2str, +}; + +/** @} */ diff --git a/lib/netfilter/exp.c b/lib/netfilter/exp.c new file mode 100644 index 0000000..86ed8d1 --- /dev/null +++ b/lib/netfilter/exp.c @@ -0,0 +1,621 @@ +/* + * lib/netfilter/exp.c Conntrack Expectation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c= 2008 Patrick McHardy + * Copyright (c) 2012 Rich Fought + */ + +/** + * @ingroup nfnl + * @defgroup exp Expectation + * @brief + * @{ + */ + +#include +#include +#include + +#include +#include +#include +#include + +static struct nl_cache_ops nfnl_exp_ops; + +static struct nla_policy exp_policy[CTA_EXPECT_MAX+1] = { + [CTA_EXPECT_MASTER] = { .type = NLA_NESTED }, + [CTA_EXPECT_TUPLE] = { .type = NLA_NESTED }, + [CTA_EXPECT_MASK] = { .type = NLA_NESTED }, + [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 }, + [CTA_EXPECT_ID] = { .type = NLA_U32 }, + [CTA_EXPECT_HELP_NAME] = { .type = NLA_STRING }, + [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, + [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, // Added in kernel 2.6.37 + [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, // Added in kernel 3.5 + [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, // Added in kernel 3.5 + [CTA_EXPECT_FN] = { .type = NLA_STRING }, // Added in kernel 3.5 +}; + +static struct nla_policy exp_tuple_policy[CTA_TUPLE_MAX+1] = { + [CTA_TUPLE_IP] = { .type = NLA_NESTED }, + [CTA_TUPLE_PROTO] = { .type = NLA_NESTED }, +}; + +static struct nla_policy exp_ip_policy[CTA_IP_MAX+1] = { + [CTA_IP_V4_SRC] = { .type = NLA_U32 }, + [CTA_IP_V4_DST] = { .type = NLA_U32 }, + [CTA_IP_V6_SRC] = { .minlen = 16 }, + [CTA_IP_V6_DST] = { .minlen = 16 }, +}; + +static struct nla_policy exp_proto_policy[CTA_PROTO_MAX+1] = { + [CTA_PROTO_NUM] = { .type = NLA_U8 }, + [CTA_PROTO_SRC_PORT] = { .type = NLA_U16 }, + [CTA_PROTO_DST_PORT] = { .type = NLA_U16 }, + [CTA_PROTO_ICMP_ID] = { .type = NLA_U16 }, + [CTA_PROTO_ICMP_TYPE] = { .type = NLA_U8 }, + [CTA_PROTO_ICMP_CODE] = { .type = NLA_U8 }, + [CTA_PROTO_ICMPV6_ID] = { .type = NLA_U16 }, + [CTA_PROTO_ICMPV6_TYPE] = { .type = NLA_U8 }, + [CTA_PROTO_ICMPV6_CODE] = { .type = NLA_U8 }, +}; + +static struct nla_policy exp_nat_policy[CTA_EXPECT_NAT_MAX+1] = { + [CTA_EXPECT_NAT_DIR] = { .type = NLA_U32 }, + [CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED }, +}; + +static int exp_parse_ip(struct nfnl_exp *exp, int tuple, struct nlattr *attr) +{ + struct nlattr *tb[CTA_IP_MAX+1]; + struct nl_addr *addr; + int err; + + err = nla_parse_nested(tb, CTA_IP_MAX, attr, exp_ip_policy); + if (err < 0) + goto errout; + + if (tb[CTA_IP_V4_SRC]) { + addr = nl_addr_alloc_attr(tb[CTA_IP_V4_SRC], AF_INET); + if (addr == NULL) + goto errout_enomem; + err = nfnl_exp_set_src(exp, tuple, addr); + nl_addr_put(addr); + if (err < 0) + goto errout; + } + if (tb[CTA_IP_V4_DST]) { + addr = nl_addr_alloc_attr(tb[CTA_IP_V4_DST], AF_INET); + if (addr == NULL) + goto errout_enomem; + err = nfnl_exp_set_dst(exp, tuple, addr); + nl_addr_put(addr); + if (err < 0) + goto errout; + } + if (tb[CTA_IP_V6_SRC]) { + addr = nl_addr_alloc_attr(tb[CTA_IP_V6_SRC], AF_INET6); + if (addr == NULL) + goto errout_enomem; + err = nfnl_exp_set_src(exp, tuple, addr); + nl_addr_put(addr); + if (err < 0) + goto errout; + } + if (tb[CTA_IP_V6_DST]) { + addr = nl_addr_alloc_attr(tb[CTA_IP_V6_DST], AF_INET6); + if (addr == NULL) + goto errout_enomem; + err = nfnl_exp_set_dst(exp, tuple, addr); + nl_addr_put(addr); + if (err < 0) + goto errout; + } + + return 0; + +errout_enomem: + err = -NLE_NOMEM; +errout: + return err; +} + +static int exp_parse_proto(struct nfnl_exp *exp, int tuple, struct nlattr *attr) +{ + struct nlattr *tb[CTA_PROTO_MAX+1]; + int err; + uint16_t srcport = 0, dstport = 0, icmpid = 0; + uint8_t icmptype = 0, icmpcode = 0; + + err = nla_parse_nested(tb, CTA_PROTO_MAX, attr, exp_proto_policy); + if (err < 0) + return err; + + if (tb[CTA_PROTO_NUM]) + nfnl_exp_set_l4protonum(exp, tuple, nla_get_u8(tb[CTA_PROTO_NUM])); + + if (tb[CTA_PROTO_SRC_PORT]) + srcport = ntohs(nla_get_u16(tb[CTA_PROTO_SRC_PORT])); + if (tb[CTA_PROTO_DST_PORT]) + dstport = ntohs(nla_get_u16(tb[CTA_PROTO_DST_PORT])); + if (tb[CTA_PROTO_SRC_PORT] || tb[CTA_PROTO_DST_PORT]) + nfnl_exp_set_ports(exp, tuple, srcport, dstport); + + if (tb[CTA_PROTO_ICMP_ID]) + icmpid = ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID])); + if (tb[CTA_PROTO_ICMP_TYPE]) + icmptype = nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]); + if (tb[CTA_PROTO_ICMP_CODE]) + icmpcode = nla_get_u8(tb[CTA_PROTO_ICMP_CODE]); + if (tb[CTA_PROTO_ICMP_ID] || tb[CTA_PROTO_ICMP_TYPE] || tb[CTA_PROTO_ICMP_CODE]) + nfnl_exp_set_icmp(exp, tuple, icmpid, icmptype, icmpcode); + return 0; +} + +static int exp_parse_tuple(struct nfnl_exp *exp, int tuple, struct nlattr *attr) +{ + struct nlattr *tb[CTA_TUPLE_MAX+1]; + int err; + + err = nla_parse_nested(tb, CTA_TUPLE_MAX, attr, exp_tuple_policy); + if (err < 0) + return err; + + if (tb[CTA_TUPLE_IP]) { + err = exp_parse_ip(exp, tuple, tb[CTA_TUPLE_IP]); + if (err < 0) + return err; + } + + if (tb[CTA_TUPLE_PROTO]) { + err = exp_parse_proto(exp, tuple, tb[CTA_TUPLE_PROTO]); + if (err < 0) + return err; + } + + return 0; +} + +static int exp_parse_nat(struct nfnl_exp *exp, struct nlattr *attr) +{ + struct nlattr *tb[CTA_EXPECT_NAT_MAX+1]; + int err; + + err = nla_parse_nested(tb, CTA_EXPECT_NAT_MAX, attr, exp_nat_policy); + if (err < 0) + return err; + + if (tb[CTA_EXPECT_NAT_DIR]) + nfnl_exp_set_nat_dir(exp, nla_get_u32(tb[CTA_EXPECT_NAT_DIR])); + + if (tb[CTA_EXPECT_NAT_TUPLE]) { + err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_NAT, tb[CTA_EXPECT_NAT_TUPLE]); + if (err < 0) + return err; + } + + return 0; +} + +int nfnlmsg_exp_group(struct nlmsghdr *nlh) +{ + switch (nfnlmsg_subtype(nlh)) { + case IPCTNL_MSG_EXP_NEW: + if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL)) + return NFNLGRP_CONNTRACK_EXP_NEW; + else + return NFNLGRP_CONNTRACK_EXP_UPDATE; + case IPCTNL_MSG_EXP_DELETE: + return NFNLGRP_CONNTRACK_EXP_DESTROY; + default: + return NFNLGRP_NONE; + } +} + +int nfnlmsg_exp_parse(struct nlmsghdr *nlh, struct nfnl_exp **result) +{ + struct nfnl_exp *exp; + struct nlattr *tb[CTA_MAX+1]; + int err; + + exp = nfnl_exp_alloc(); + if (!exp) + return -NLE_NOMEM; + + exp->ce_msgtype = nlh->nlmsg_type; + + err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_EXPECT_MAX, + exp_policy); + if (err < 0) + goto errout; + + nfnl_exp_set_family(exp, nfnlmsg_family(nlh)); + + if (tb[CTA_EXPECT_TUPLE]) { + err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_EXPECT, tb[CTA_EXPECT_TUPLE]); + if (err < 0) + goto errout; + } + if (tb[CTA_EXPECT_MASTER]) { + err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_MASTER, tb[CTA_EXPECT_MASTER]); + if (err < 0) + goto errout; + } + if (tb[CTA_EXPECT_MASK]) { + err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_MASK, tb[CTA_EXPECT_MASK]); + if (err < 0) + goto errout; + } + + if (tb[CTA_EXPECT_NAT]) { + err = exp_parse_nat(exp, tb[CTA_EXPECT_MASK]); + if (err < 0) + goto errout; + } + + if (tb[CTA_EXPECT_CLASS]) + nfnl_exp_set_class(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_CLASS]))); + + if (tb[CTA_EXPECT_FN]) + nfnl_exp_set_fn(exp, nla_data(tb[CTA_EXPECT_FN])); + + if (tb[CTA_EXPECT_TIMEOUT]) + nfnl_exp_set_timeout(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_TIMEOUT]))); + + if (tb[CTA_EXPECT_ID]) + nfnl_exp_set_id(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_ID]))); + + if (tb[CTA_EXPECT_HELP_NAME]) + nfnl_exp_set_helper_name(exp, nla_data(tb[CTA_EXPECT_HELP_NAME])); + + if (tb[CTA_EXPECT_ZONE]) + nfnl_exp_set_zone(exp, ntohs(nla_get_u16(tb[CTA_EXPECT_ZONE]))); + + if (tb[CTA_EXPECT_FLAGS]) + nfnl_exp_set_flags(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_FLAGS]))); + + *result = exp; + return 0; + +errout: + nfnl_exp_put(exp); + return err; +} + +static int exp_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *nlh, struct nl_parser_param *pp) +{ + struct nfnl_exp *exp; + int err; + + if ((err = nfnlmsg_exp_parse(nlh, &exp)) < 0) + goto errout; + + err = pp->pp_cb((struct nl_object *) exp, pp); +errout: + nfnl_exp_put(exp); + return err; +} + +int nfnl_exp_dump_request(struct nl_sock *sk) +{ + return nfnl_send_simple(sk, NFNL_SUBSYS_CTNETLINK_EXP, IPCTNL_MSG_EXP_GET, + NLM_F_DUMP, AF_UNSPEC, 0); +} + +static int exp_request_update(struct nl_cache *cache, struct nl_sock *sk) +{ + return nfnl_exp_dump_request(sk); +} + +static int exp_get_tuple_attr(int tuple) +{ + int attr = 0; + + switch (tuple) { + case CTA_EXPECT_MASTER: + attr = NFNL_EXP_TUPLE_MASTER; + break; + case CTA_EXPECT_MASK: + attr = NFNL_EXP_TUPLE_MASK; + break; + case CTA_EXPECT_NAT: + attr = NFNL_EXP_TUPLE_NAT; + break; + case CTA_EXPECT_TUPLE: + default : + attr = NFNL_EXP_TUPLE_EXPECT; + break; + } + + return attr; +} + +static int nfnl_exp_build_tuple(struct nl_msg *msg, const struct nfnl_exp *exp, + int cta) +{ + struct nlattr *tuple, *ip, *proto; + struct nl_addr *addr; + int family; + + family = nfnl_exp_get_family(exp); + + int type = exp_get_tuple_attr(cta); + + if (cta == CTA_EXPECT_NAT) + tuple = nla_nest_start(msg, CTA_EXPECT_NAT_TUPLE); + else + tuple = nla_nest_start(msg, cta); + + if (!tuple) + goto nla_put_failure; + + ip = nla_nest_start(msg, CTA_TUPLE_IP); + if (!ip) + goto nla_put_failure; + + addr = nfnl_exp_get_src(exp, type); + if (addr) + NLA_PUT_ADDR(msg, + family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC, + addr); + + addr = nfnl_exp_get_dst(exp, type); + if (addr) + NLA_PUT_ADDR(msg, + family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST, + addr); + + nla_nest_end(msg, ip); + + proto = nla_nest_start(msg, CTA_TUPLE_PROTO); + if (!proto) + goto nla_put_failure; + + if (nfnl_exp_test_l4protonum(exp, type)) + NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_exp_get_l4protonum(exp, type)); + + if (nfnl_exp_test_ports(exp, type)) { + NLA_PUT_U16(msg, CTA_PROTO_SRC_PORT, + htons(nfnl_exp_get_src_port(exp, type))); + + NLA_PUT_U16(msg, CTA_PROTO_DST_PORT, + htons(nfnl_exp_get_dst_port(exp, type))); + } + + if (nfnl_exp_test_icmp(exp, type)) { + NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID, + htons(nfnl_exp_get_icmp_id(exp, type))); + + NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE, + nfnl_exp_get_icmp_type(exp, type)); + + NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE, + nfnl_exp_get_icmp_code(exp, type)); + } + + nla_nest_end(msg, proto); + + nla_nest_end(msg, tuple); + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +static int nfnl_exp_build_nat(struct nl_msg *msg, const struct nfnl_exp *exp) +{ + struct nlattr *nat; + int err; + + nat = nla_nest_start(msg, CTA_EXPECT_NAT); + + if (nfnl_exp_test_nat_dir(exp)) { + NLA_PUT_U32(msg, CTA_EXPECT_NAT_DIR, + nfnl_exp_get_nat_dir(exp)); + } + + if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_NAT)) < 0) + goto nla_put_failure; + + nla_nest_end(msg, nat); + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags, + struct nl_msg **result) +{ + struct nl_msg *msg; + int err; + + msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK_EXP, cmd, flags, + nfnl_exp_get_family(exp), 0); + if (msg == NULL) + return -NLE_NOMEM; + + if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_TUPLE)) < 0) + goto err_out; + + if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASTER)) < 0) + goto err_out; + + if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASK)) < 0) + goto err_out; + + if (nfnl_exp_test_src(exp, NFNL_EXP_TUPLE_NAT)) { + if ((err = nfnl_exp_build_nat(msg, exp)) < 0) + goto err_out; + } + + if (nfnl_exp_test_class(exp)) + NLA_PUT_U32(msg, CTA_EXPECT_CLASS, htonl(nfnl_exp_get_class(exp))); + + if (nfnl_exp_test_fn(exp)) + NLA_PUT_STRING(msg, CTA_EXPECT_FN, nfnl_exp_get_fn(exp)); + + if (nfnl_exp_test_id(exp)) + NLA_PUT_U32(msg, CTA_EXPECT_ID, htonl(nfnl_exp_get_id(exp))); + + if (nfnl_exp_test_timeout(exp)) + NLA_PUT_U32(msg, CTA_EXPECT_TIMEOUT, htonl(nfnl_exp_get_timeout(exp))); + + if (nfnl_exp_test_helper_name(exp)) + NLA_PUT_STRING(msg, CTA_EXPECT_HELP_NAME, nfnl_exp_get_helper_name(exp)); + + if (nfnl_exp_test_zone(exp)) + NLA_PUT_U16(msg, CTA_EXPECT_ZONE, htons(nfnl_exp_get_zone(exp))); + + if (nfnl_exp_test_flags(exp)) + NLA_PUT_U32(msg, CTA_EXPECT_FLAGS, htonl(nfnl_exp_get_flags(exp))); + + *result = msg; + return 0; + +nla_put_failure: +err_out: + nlmsg_free(msg); + return err; +} + +int nfnl_exp_build_add_request(const struct nfnl_exp *exp, int flags, + struct nl_msg **result) +{ + return nfnl_exp_build_message(exp, IPCTNL_MSG_EXP_NEW, flags, result); +} + +int nfnl_exp_add(struct nl_sock *sk, const struct nfnl_exp *exp, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_exp_build_add_request(exp, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +int nfnl_exp_build_delete_request(const struct nfnl_exp *exp, int flags, + struct nl_msg **result) +{ + return nfnl_exp_build_message(exp, IPCTNL_MSG_EXP_DELETE, flags, result); +} + +int nfnl_exp_del(struct nl_sock *sk, const struct nfnl_exp *exp, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_exp_build_delete_request(exp, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +int nfnl_exp_build_query_request(const struct nfnl_exp *exp, int flags, + struct nl_msg **result) +{ + return nfnl_exp_build_message(exp, IPCTNL_MSG_EXP_GET, flags, result); +} + +int nfnl_exp_query(struct nl_sock *sk, const struct nfnl_exp *exp, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_exp_build_query_request(exp, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +/** + * @name Cache Management + * @{ + */ + +/** + * Build a expectation cache holding all expectations currently in the kernel + * @arg sk Netlink socket. + * @arg result Pointer to store resulting cache. + * + * Allocates a new cache, initializes it properly and updates it to + * contain all expectations currently in the kernel. + * + * @return 0 on success or a negative error code. + */ +int nfnl_exp_alloc_cache(struct nl_sock *sk, struct nl_cache **result) +{ + return nl_cache_alloc_and_fill(&nfnl_exp_ops, sk, result); +} + +/** @} */ + +/** + * @name Expectation Addition + * @{ + */ + +/** @} */ + +static struct nl_af_group exp_groups[] = { + { AF_UNSPEC, NFNLGRP_CONNTRACK_EXP_NEW }, + { AF_UNSPEC, NFNLGRP_CONNTRACK_EXP_UPDATE }, + { AF_UNSPEC, NFNLGRP_CONNTRACK_EXP_DESTROY }, + { END_OF_GROUP_LIST }, +}; + +#define NFNLMSG_EXP_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK_EXP, (type)) +static struct nl_cache_ops nfnl_exp_ops = { + .co_name = "netfilter/exp", + .co_hdrsize = NFNL_HDRLEN, + .co_msgtypes = { + { NFNLMSG_EXP_TYPE(IPCTNL_MSG_EXP_NEW), NL_ACT_NEW, "new" }, + { NFNLMSG_EXP_TYPE(IPCTNL_MSG_EXP_GET), NL_ACT_GET, "get" }, + { NFNLMSG_EXP_TYPE(IPCTNL_MSG_EXP_DELETE), NL_ACT_DEL, "del" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_NETFILTER, + .co_groups = exp_groups, + .co_request_update = exp_request_update, + .co_msg_parser = exp_msg_parser, + .co_obj_ops = &exp_obj_ops, +}; + +static void __init exp_init(void) +{ + nl_cache_mngt_register(&nfnl_exp_ops); +} + +static void __exit exp_exit(void) +{ + nl_cache_mngt_unregister(&nfnl_exp_ops); +} + +/** @} */ diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c new file mode 100644 index 0000000..69b4dd3 --- /dev/null +++ b/lib/netfilter/exp_obj.c @@ -0,0 +1,888 @@ +/* + * lib/netfilter/exp_obj.c Conntrack Expectation Object + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c) 2012 Rich Fought + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +// The 32-bit attribute mask in the common object header isn't +// big enough to handle all attributes of an expectation. So +// we'll for sure specify optional attributes + parent attributes +// that are required for valid object comparison. Comparison of +// these parent attributes will include nested attributes. + +/** @cond SKIP */ +#define EXP_ATTR_FAMILY (1UL << 0) // 8-bit +#define EXP_ATTR_TIMEOUT (1UL << 1) // 32-bit +#define EXP_ATTR_ID (1UL << 2) // 32-bit +#define EXP_ATTR_HELPER_NAME (1UL << 3) // string +#define EXP_ATTR_ZONE (1UL << 4) // 16-bit +#define EXP_ATTR_FLAGS (1UL << 5) // 32-bit +#define EXP_ATTR_CLASS (1UL << 6) // 32-bit +#define EXP_ATTR_FN (1UL << 7) // String +// Tuples +#define EXP_ATTR_EXPECT_IP_SRC (1UL << 8) +#define EXP_ATTR_EXPECT_IP_DST (1UL << 9) +#define EXP_ATTR_EXPECT_L4PROTO_NUM (1UL << 10) +#define EXP_ATTR_EXPECT_L4PROTO_PORTS (1UL << 11) +#define EXP_ATTR_EXPECT_L4PROTO_ICMP (1UL << 12) +#define EXP_ATTR_MASTER_IP_SRC (1UL << 13) +#define EXP_ATTR_MASTER_IP_DST (1UL << 14) +#define EXP_ATTR_MASTER_L4PROTO_NUM (1UL << 15) +#define EXP_ATTR_MASTER_L4PROTO_PORTS (1UL << 16) +#define EXP_ATTR_MASTER_L4PROTO_ICMP (1UL << 17) +#define EXP_ATTR_MASK_IP_SRC (1UL << 18) +#define EXP_ATTR_MASK_IP_DST (1UL << 19) +#define EXP_ATTR_MASK_L4PROTO_NUM (1UL << 20) +#define EXP_ATTR_MASK_L4PROTO_PORTS (1UL << 21) +#define EXP_ATTR_MASK_L4PROTO_ICMP (1UL << 22) +#define EXP_ATTR_NAT_IP_SRC (1UL << 23) +#define EXP_ATTR_NAT_IP_DST (1UL << 24) +#define EXP_ATTR_NAT_L4PROTO_NUM (1UL << 25) +#define EXP_ATTR_NAT_L4PROTO_PORTS (1UL << 26) +#define EXP_ATTR_NAT_L4PROTO_ICMP (1UL << 27) +#define EXP_ATTR_NAT_DIR (1UL << 28) +/** @endcond */ + +static void exp_free_data(struct nl_object *c) +{ + struct nfnl_exp *exp = (struct nfnl_exp *) c; + + if (exp == NULL) + return; + + nl_addr_put(exp->exp_expect.src); + nl_addr_put(exp->exp_expect.dst); + nl_addr_put(exp->exp_master.src); + nl_addr_put(exp->exp_master.dst); + nl_addr_put(exp->exp_mask.src); + nl_addr_put(exp->exp_mask.dst); + nl_addr_put(exp->exp_nat.src); + nl_addr_put(exp->exp_nat.dst); + + free(exp->exp_fn); + free(exp->exp_helper_name); +} + +static int exp_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct nfnl_exp *dst = (struct nfnl_exp *) _dst; + struct nfnl_exp *src = (struct nfnl_exp *) _src; + struct nl_addr *addr; + + // Expectation + if (src->exp_expect.src) { + addr = nl_addr_clone(src->exp_expect.src); + if (!addr) + return -NLE_NOMEM; + dst->exp_expect.src = addr; + } + + if (src->exp_expect.dst) { + addr = nl_addr_clone(src->exp_expect.dst); + if (!addr) + return -NLE_NOMEM; + dst->exp_expect.dst = addr; + } + + // Master CT + if (src->exp_master.src) { + addr = nl_addr_clone(src->exp_master.src); + if (!addr) + return -NLE_NOMEM; + dst->exp_master.src = addr; + } + + if (src->exp_master.dst) { + addr = nl_addr_clone(src->exp_master.dst); + if (!addr) + return -NLE_NOMEM; + dst->exp_master.dst = addr; + } + + // Mask + if (src->exp_mask.src) { + addr = nl_addr_clone(src->exp_mask.src); + if (!addr) + return -NLE_NOMEM; + dst->exp_mask.src = addr; + } + + if (src->exp_mask.dst) { + addr = nl_addr_clone(src->exp_mask.dst); + if (!addr) + return -NLE_NOMEM; + dst->exp_mask.dst = addr; + } + + // NAT + if (src->exp_nat.src) { + addr = nl_addr_clone(src->exp_nat.src); + if (!addr) + return -NLE_NOMEM; + dst->exp_nat.src = addr; + } + + if (src->exp_nat.dst) { + addr = nl_addr_clone(src->exp_nat.dst); + if (!addr) + return -NLE_NOMEM; + dst->exp_nat.dst = addr; + } + + if (src->exp_fn) + dst->exp_fn = strdup(src->exp_fn); + + if (src->exp_helper_name) + dst->exp_helper_name = strdup(src->exp_helper_name); + + return 0; +} + +static void dump_addr(struct nl_dump_params *p, struct nl_addr *addr, int port) +{ + char buf[64]; + + if (addr) + nl_dump(p, "%s", nl_addr2str(addr, buf, sizeof(buf))); + + if (port) + nl_dump(p, ":%u ", port); + else if (addr) + nl_dump(p, " "); +} + +static void dump_icmp(struct nl_dump_params *p, struct nfnl_exp *exp, int tuple) +{ + if (nfnl_exp_test_icmp(exp, tuple)) { + + nl_dump(p, "icmp type %d ", nfnl_exp_get_icmp_type(exp, tuple)); + + nl_dump(p, "code %d ", nfnl_exp_get_icmp_code(exp, tuple)); + + nl_dump(p, "id %d ", nfnl_exp_get_icmp_id(exp, tuple)); + } +} + +static void exp_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) +{ + struct nl_addr *tuple_src, *tuple_dst; + int tuple_sport, tuple_dport; + int i = 0; + char buf[64]; + + for (i = NFNL_EXP_TUPLE_EXPECT; i < NFNL_EXP_TUPLE_MAX; i++) { + tuple_src = NULL; + tuple_dst = NULL; + tuple_sport = 0; + tuple_dport = 0; + + // Test needed for NAT case + if (nfnl_exp_test_src(exp, i)) + tuple_src = nfnl_exp_get_src(exp, i); + if (nfnl_exp_test_dst(exp, i)) + tuple_dst = nfnl_exp_get_dst(exp, i); + + // Don't have tests for individual ports/types/codes/ids, + if (nfnl_exp_test_l4protonum(exp, i)) { + nl_dump(p, "%s ", + nl_ip_proto2str(nfnl_exp_get_l4protonum(exp, i), buf, sizeof(buf))); + } + + if (nfnl_exp_test_ports(exp, i)) { + tuple_sport = nfnl_exp_get_src_port(exp, i); + tuple_dport = nfnl_exp_get_dst_port(exp, i); + } + + dump_addr(p, tuple_src, tuple_sport); + dump_addr(p, tuple_dst, tuple_dport); + dump_icmp(p, exp, 0); + } + + if (nfnl_exp_test_nat_dir(exp)) + nl_dump(p, "nat dir %s ", exp->exp_nat_dir); + +} + +/* FIXME Compatible with /proc/net/nf_conntrack */ +static void exp_dump_line(struct nl_object *a, struct nl_dump_params *p) +{ + struct nfnl_exp *exp = (struct nfnl_exp *) a; + + nl_new_line(p); + + exp_dump_tuples(exp, p); + + nl_dump(p, "\n"); +} + +static void exp_dump_details(struct nl_object *a, struct nl_dump_params *p) +{ + struct nfnl_exp *exp = (struct nfnl_exp *) a; + char buf[64]; + int fp = 0; + + exp_dump_line(a, p); + + nl_dump(p, " id 0x%x ", exp->exp_id); + nl_dump_line(p, "family %s ", + nl_af2str(exp->exp_family, buf, sizeof(buf))); + + if (nfnl_exp_test_timeout(exp)) { + uint64_t timeout_ms = nfnl_exp_get_timeout(exp) * 1000UL; + nl_dump(p, "timeout %s ", + nl_msec2str(timeout_ms, buf, sizeof(buf))); + } + + if (nfnl_exp_test_helper_name(exp)) + nl_dump(p, "helper %s ", exp->exp_helper_name); + + if (nfnl_exp_test_fn(exp)) + nl_dump(p, "fn %s ", exp->exp_fn); + + if (nfnl_exp_test_class(exp)) + nl_dump(p, "class %u ", nfnl_exp_get_class(exp)); + + if (nfnl_exp_test_zone(exp)) + nl_dump(p, "zone %u ", nfnl_exp_get_zone(exp)); + + if (nfnl_exp_test_flags(exp)) + nl_dump(p, "<"); +#define PRINT_FLAG(str) \ + { nl_dump(p, "%s%s", fp++ ? "," : "", (str)); } + + if (exp->exp_flags & NF_CT_EXPECT_PERMANENT) + PRINT_FLAG("PERMANENT"); + if (exp->exp_flags & NF_CT_EXPECT_INACTIVE) + PRINT_FLAG("INACTIVE"); + if (exp->exp_flags & NF_CT_EXPECT_USERSPACE) + PRINT_FLAG("USERSPACE"); +#undef PRINT_FLAG + + if (nfnl_exp_test_flags(exp)) + nl_dump(p, ">"); + + nl_dump(p, "\n"); +} + +static int exp_cmp_l4proto_ports (union nfnl_exp_protodata *a, union nfnl_exp_protodata *b) { + // Must return 0 for match, 1 for mismatch + int d = 0; + d = ( (a->port.src != b->port.src) || + (a->port.dst != b->port.dst) ); + + return d; +} + +static int exp_cmp_l4proto_icmp (union nfnl_exp_protodata *a, union nfnl_exp_protodata *b) { + // Must return 0 for match, 1 for mismatch + int d = 0; + d = ( (a->icmp.code != b->icmp.code) || + (a->icmp.type != b->icmp.type) || + (a->icmp.id != b->icmp.id) ); + + return d; +} + +static int exp_compare(struct nl_object *_a, struct nl_object *_b, + uint32_t attrs, int flags) +{ + struct nfnl_exp *a = (struct nfnl_exp *) _a; + struct nfnl_exp *b = (struct nfnl_exp *) _b; + int diff = 0; + +#define EXP_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, EXP_ATTR_##ATTR, a, b, EXPR) +#define EXP_DIFF_VAL(ATTR, FIELD) EXP_DIFF(ATTR, a->FIELD != b->FIELD) +#define EXP_DIFF_STRING(ATTR, FIELD) EXP_DIFF(ATTR, (strcmp(a->FIELD, b->FIELD) != 0)) +#define EXP_DIFF_ADDR(ATTR, FIELD) \ + ((flags & LOOSE_COMPARISON) \ + ? EXP_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \ + : EXP_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD))) +#define EXP_DIFF_L4PROTO_PORTS(ATTR, FIELD) \ + EXP_DIFF(ATTR, exp_cmp_l4proto_ports(&(a->FIELD), &(b->FIELD))) +#define EXP_DIFF_L4PROTO_ICMP(ATTR, FIELD) \ + EXP_DIFF(ATTR, exp_cmp_l4proto_icmp(&(a->FIELD), &(b->FIELD))) + + diff |= EXP_DIFF_VAL(FAMILY, exp_family); + diff |= EXP_DIFF_VAL(TIMEOUT, exp_timeout); + diff |= EXP_DIFF_VAL(ID, exp_id); + diff |= EXP_DIFF_VAL(ZONE, exp_zone); + diff |= EXP_DIFF_VAL(CLASS, exp_class); + diff |= EXP_DIFF_VAL(FLAGS, exp_flags); + diff |= EXP_DIFF_VAL(NAT_DIR, exp_nat_dir); + + diff |= EXP_DIFF_STRING(FN, exp_fn); + diff |= EXP_DIFF_STRING(HELPER_NAME, exp_helper_name); + + diff |= EXP_DIFF_ADDR(EXPECT_IP_SRC, exp_expect.src); + diff |= EXP_DIFF_ADDR(EXPECT_IP_DST, exp_expect.dst); + diff |= EXP_DIFF_VAL(EXPECT_L4PROTO_NUM, exp_expect.proto.l4protonum); + diff |= EXP_DIFF_L4PROTO_PORTS(EXPECT_L4PROTO_PORTS, exp_expect.proto.l4protodata); + diff |= EXP_DIFF_L4PROTO_ICMP(EXPECT_L4PROTO_ICMP, exp_expect.proto.l4protodata); + + diff |= EXP_DIFF_ADDR(MASTER_IP_SRC, exp_master.src); + diff |= EXP_DIFF_ADDR(MASTER_IP_DST, exp_master.dst); + diff |= EXP_DIFF_VAL(MASTER_L4PROTO_NUM, exp_master.proto.l4protonum); + diff |= EXP_DIFF_L4PROTO_PORTS(MASTER_L4PROTO_PORTS, exp_master.proto.l4protodata); + diff |= EXP_DIFF_L4PROTO_ICMP(MASTER_L4PROTO_ICMP, exp_master.proto.l4protodata); + + diff |= EXP_DIFF_ADDR(MASK_IP_SRC, exp_mask.src); + diff |= EXP_DIFF_ADDR(MASK_IP_DST, exp_mask.dst); + diff |= EXP_DIFF_VAL(MASK_L4PROTO_NUM, exp_mask.proto.l4protonum); + diff |= EXP_DIFF_L4PROTO_PORTS(MASK_L4PROTO_PORTS, exp_mask.proto.l4protodata); + diff |= EXP_DIFF_L4PROTO_ICMP(MASK_L4PROTO_ICMP, exp_mask.proto.l4protodata); + + diff |= EXP_DIFF_ADDR(NAT_IP_SRC, exp_nat.src); + diff |= EXP_DIFF_ADDR(NAT_IP_DST, exp_nat.dst); + diff |= EXP_DIFF_VAL(NAT_L4PROTO_NUM, exp_nat.proto.l4protonum); + diff |= EXP_DIFF_L4PROTO_PORTS(NAT_L4PROTO_PORTS, exp_nat.proto.l4protodata); + diff |= EXP_DIFF_L4PROTO_ICMP(NAT_L4PROTO_ICMP, exp_nat.proto.l4protodata); + +#undef EXP_DIFF +#undef EXP_DIFF_VAL +#undef EXP_DIFF_STRING +#undef EXP_DIFF_ADDR +#undef EXP_DIFF_L4PROTO_PORTS +#undef EXP_DIFF_L4PROTO_ICMP + + return diff; +} + +// CLI arguments? +static const struct trans_tbl exp_attrs[] = { + __ADD(EXP_ATTR_FAMILY, family) + __ADD(EXP_ATTR_TIMEOUT, timeout) + __ADD(EXP_ATTR_ID, id) + __ADD(EXP_ATTR_HELPER_NAME, helpername) + __ADD(EXP_ATTR_ZONE, zone) + __ADD(EXP_ATTR_CLASS, class) + __ADD(EXP_ATTR_FLAGS, flags) + __ADD(EXP_ATTR_FN, function) + __ADD(EXP_ATTR_EXPECT_IP_SRC, expectipsrc) + __ADD(EXP_ATTR_EXPECT_IP_DST, expectipdst) + __ADD(EXP_ATTR_EXPECT_L4PROTO_NUM, expectprotonum) + __ADD(EXP_ATTR_EXPECT_L4PROTO_PORTS, expectports) + __ADD(EXP_ATTR_EXPECT_L4PROTO_ICMP, expecticmp) + __ADD(EXP_ATTR_MASTER_IP_SRC, masteripsrc) + __ADD(EXP_ATTR_MASTER_IP_DST, masteripdst) + __ADD(EXP_ATTR_MASTER_L4PROTO_NUM, masterprotonum) + __ADD(EXP_ATTR_MASTER_L4PROTO_PORTS, masterports) + __ADD(EXP_ATTR_MASTER_L4PROTO_ICMP, mastericmp) + __ADD(EXP_ATTR_MASK_IP_SRC, maskipsrc) + __ADD(EXP_ATTR_MASK_IP_DST, maskipdst) + __ADD(EXP_ATTR_MASK_L4PROTO_NUM, maskprotonum) + __ADD(EXP_ATTR_MASK_L4PROTO_PORTS, maskports) + __ADD(EXP_ATTR_MASK_L4PROTO_ICMP, maskicmp) + __ADD(EXP_ATTR_NAT_IP_SRC, natipsrc) + __ADD(EXP_ATTR_NAT_IP_DST, natipdst) + __ADD(EXP_ATTR_NAT_L4PROTO_NUM, natprotonum) + __ADD(EXP_ATTR_NAT_L4PROTO_PORTS, natports) + __ADD(EXP_ATTR_NAT_L4PROTO_ICMP, naticmp) + __ADD(EXP_ATTR_NAT_DIR, natdir) +}; + +static char *exp_attrs2str(int attrs, char *buf, size_t len) +{ + return __flags2str(attrs, buf, len, exp_attrs, ARRAY_SIZE(exp_attrs)); +} + +/** + * @name Allocation/Freeing + * @{ + */ + +struct nfnl_exp *nfnl_exp_alloc(void) +{ + return (struct nfnl_exp *) nl_object_alloc(&exp_obj_ops); +} + +void nfnl_exp_get(struct nfnl_exp *exp) +{ + nl_object_get((struct nl_object *) exp); +} + +void nfnl_exp_put(struct nfnl_exp *exp) +{ + nl_object_put((struct nl_object *) exp); +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ + +void nfnl_exp_set_family(struct nfnl_exp *exp, uint8_t family) +{ + exp->exp_family = family; + exp->ce_mask |= EXP_ATTR_FAMILY; +} + +uint8_t nfnl_exp_get_family(const struct nfnl_exp *exp) +{ + if (exp->ce_mask & EXP_ATTR_FAMILY) + return exp->exp_family; + else + return AF_UNSPEC; +} + +void nfnl_exp_set_flags(struct nfnl_exp *exp, uint32_t flags) +{ + exp->exp_flags |= flags; + exp->ce_mask |= EXP_ATTR_FLAGS; +} + +int nfnl_exp_test_flags(const struct nfnl_exp *exp) +{ + return !!(exp->ce_mask & EXP_ATTR_FLAGS); +} + +void nfnl_exp_unset_flags(struct nfnl_exp *exp, uint32_t flags) +{ + exp->exp_flags &= ~flags; + exp->ce_mask |= EXP_ATTR_FLAGS; +} + +uint32_t nfnl_exp_get_flags(const struct nfnl_exp *exp) +{ + return exp->exp_flags; +} + +static const struct trans_tbl flag_table[] = { + __ADD(IPS_EXPECTED, expected) + __ADD(IPS_SEEN_REPLY, seen_reply) + __ADD(IPS_ASSURED, assured) +}; + +char * nfnl_exp_flags2str(int flags, char *buf, size_t len) +{ + return __flags2str(flags, buf, len, flag_table, + ARRAY_SIZE(flag_table)); +} + +int nfnl_exp_str2flags(const char *name) +{ + return __str2flags(name, flag_table, ARRAY_SIZE(flag_table)); +} + +void nfnl_exp_set_timeout(struct nfnl_exp *exp, uint32_t timeout) +{ + exp->exp_timeout = timeout; + exp->ce_mask |= EXP_ATTR_TIMEOUT; +} + +int nfnl_exp_test_timeout(const struct nfnl_exp *exp) +{ + return !!(exp->ce_mask & EXP_ATTR_TIMEOUT); +} + +uint32_t nfnl_exp_get_timeout(const struct nfnl_exp *exp) +{ + return exp->exp_timeout; +} + +void nfnl_exp_set_id(struct nfnl_exp *exp, uint32_t id) +{ + exp->exp_id = id; + exp->ce_mask |= EXP_ATTR_ID; +} + +int nfnl_exp_test_id(const struct nfnl_exp *exp) +{ + return !!(exp->ce_mask & EXP_ATTR_ID); +} + +uint32_t nfnl_exp_get_id(const struct nfnl_exp *exp) +{ + return exp->exp_id; +} + +int nfnl_exp_set_helper_name(struct nfnl_exp *exp, void *name) +{ + free(exp->exp_helper_name); + exp->exp_helper_name = strdup(name); + if (!exp->exp_helper_name) + return -NLE_NOMEM; + + exp->ce_mask |= EXP_ATTR_HELPER_NAME; + return 0; +} + +int nfnl_exp_test_helper_name(const struct nfnl_exp *exp) +{ + return !!(exp->ce_mask & EXP_ATTR_HELPER_NAME); +} + +const char * nfnl_exp_get_helper_name(const struct nfnl_exp *exp) +{ + return exp->exp_helper_name; +} + +void nfnl_exp_set_zone(struct nfnl_exp *exp, uint16_t zone) +{ + exp->exp_zone = zone; + exp->ce_mask |= EXP_ATTR_ZONE; +} + +int nfnl_exp_test_zone(const struct nfnl_exp *exp) +{ + return !!(exp->ce_mask & EXP_ATTR_ZONE); +} + +uint16_t nfnl_exp_get_zone(const struct nfnl_exp *exp) +{ + return exp->exp_zone; +} + +void nfnl_exp_set_class(struct nfnl_exp *exp, uint32_t class) +{ + exp->exp_class = class; + exp->ce_mask |= EXP_ATTR_CLASS; +} + +int nfnl_exp_test_class(const struct nfnl_exp *exp) +{ + return !!(exp->ce_mask & EXP_ATTR_CLASS); +} + +uint32_t nfnl_exp_get_class(const struct nfnl_exp *exp) +{ + return exp->exp_class; +} + +int nfnl_exp_set_fn(struct nfnl_exp *exp, void *fn) +{ + free(exp->exp_fn); + exp->exp_fn = strdup(fn); + if (!exp->exp_fn) + return -NLE_NOMEM; + + exp->ce_mask |= EXP_ATTR_FN; + return 0; +} + +int nfnl_exp_test_fn(const struct nfnl_exp *exp) +{ + return !!(exp->ce_mask & EXP_ATTR_FN); +} + +const char * nfnl_exp_get_fn(const struct nfnl_exp *exp) +{ + return exp->exp_fn; +} + +void nfnl_exp_set_nat_dir(struct nfnl_exp *exp, uint8_t nat_dir) +{ + exp->exp_nat_dir = nat_dir; + exp->ce_mask |= EXP_ATTR_NAT_DIR; +} + +int nfnl_exp_test_nat_dir(const struct nfnl_exp *exp) +{ + return !!(exp->ce_mask & EXP_ATTR_NAT_DIR); +} + +uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *exp) +{ + return exp->exp_nat_dir; +} + +#define EXP_GET_TUPLE(e, t) \ + (t == NFNL_EXP_TUPLE_MASTER) ? \ + &(e->exp_master) : \ + (t == NFNL_EXP_TUPLE_MASK) ? \ + &(e->exp_mask) : \ + (t == NFNL_EXP_TUPLE_NAT) ? \ + &(e->exp_nat) : &(exp->exp_expect) + +static int exp_get_src_attr(int tuple) +{ + int attr = 0; + + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_IP_SRC; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_IP_SRC; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_IP_SRC; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_IP_SRC; + } + + return attr; +} + +static int exp_get_dst_attr(int tuple) +{ + int attr = 0; + + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_IP_DST; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_IP_DST; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_IP_DST; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_IP_DST; + } + + return attr; +} + + +static int exp_set_addr(struct nfnl_exp *exp, struct nl_addr *addr, + int attr, struct nl_addr ** exp_addr) +{ + if (exp->ce_mask & EXP_ATTR_FAMILY) { + if (addr->a_family != exp->exp_family) + return -NLE_AF_MISMATCH; + } else + nfnl_exp_set_family(exp, addr->a_family); + + if (*exp_addr) + nl_addr_put(*exp_addr); + + nl_addr_get(addr); + *exp_addr = addr; + exp->ce_mask |= attr; + + return 0; +} + +int nfnl_exp_set_src(struct nfnl_exp *exp, int tuple, struct nl_addr *addr) +{ + struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + + return exp_set_addr(exp, addr, exp_get_src_attr(tuple), &dir->src); +} + +int nfnl_exp_set_dst(struct nfnl_exp *exp, int tuple, struct nl_addr *addr) +{ + struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + + return exp_set_addr(exp, addr, exp_get_dst_attr(tuple), &dir->dst); +} + +int nfnl_exp_test_src(const struct nfnl_exp *exp, int tuple) +{ + return !!(exp->ce_mask & exp_get_src_attr(tuple)); +} + +int nfnl_exp_test_dst(const struct nfnl_exp *exp, int tuple) +{ + return !!(exp->ce_mask & exp_get_dst_attr(tuple)); +} + +struct nl_addr *nfnl_exp_get_src(const struct nfnl_exp *exp, int tuple) +{ + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + + if (!(exp->ce_mask & exp_get_src_attr(tuple))) + return NULL; + return dir->src; +} + +struct nl_addr *nfnl_exp_get_dst(const struct nfnl_exp *exp, int tuple) +{ + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + + if (!(exp->ce_mask & exp_get_dst_attr(tuple))) + return NULL; + return dir->dst; +} + +static int exp_get_l4protonum_attr(int tuple) +{ + int attr = 0; + + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_L4PROTO_NUM; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_L4PROTO_NUM; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_L4PROTO_NUM; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_L4PROTO_NUM; + } + + return attr; +} + +void nfnl_exp_set_l4protonum(struct nfnl_exp *exp, int tuple, uint8_t l4protonum) +{ + struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + + dir->proto.l4protonum = l4protonum; + exp->ce_mask |= exp_get_l4protonum_attr(tuple); +} + +int nfnl_exp_test_l4protonum(const struct nfnl_exp *exp, int tuple) +{ + return !!(exp->ce_mask & exp_get_l4protonum_attr(tuple)); +} + +uint8_t nfnl_exp_get_l4protonum(const struct nfnl_exp *exp, int tuple) +{ + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + return dir->proto.l4protonum; +} + +static int exp_get_l4ports_attr(int tuple) +{ + int attr = 0; + + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_L4PROTO_PORTS; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_L4PROTO_PORTS; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_L4PROTO_PORTS; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_L4PROTO_PORTS; + } + + return attr; +} + +void nfnl_exp_set_ports(struct nfnl_exp *exp, int tuple, uint16_t srcport, uint16_t dstport) +{ + struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + + dir->proto.l4protodata.port.src = srcport; + dir->proto.l4protodata.port.dst = dstport; + + exp->ce_mask |= exp_get_l4ports_attr(tuple); +} + +int nfnl_exp_test_ports(const struct nfnl_exp *exp, int tuple) +{ + return !!(exp->ce_mask & exp_get_l4ports_attr(tuple)); +} + +uint16_t nfnl_exp_get_src_port(const struct nfnl_exp *exp, int tuple) +{ + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + return dir->proto.l4protodata.port.src; +} + +uint16_t nfnl_exp_get_dst_port(const struct nfnl_exp *exp, int tuple) +{ + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + + return dir->proto.l4protodata.port.dst; +} + +static int exp_get_l4icmp_attr(int tuple) +{ + int attr = 0; + + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_L4PROTO_ICMP; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_L4PROTO_ICMP; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_L4PROTO_ICMP; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_L4PROTO_ICMP; + } + + return attr; +} + +void nfnl_exp_set_icmp(struct nfnl_exp *exp, int tuple, uint16_t id, uint8_t type, uint8_t code) +{ + struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + + dir->proto.l4protodata.icmp.id = id; + dir->proto.l4protodata.icmp.type = type; + dir->proto.l4protodata.icmp.code = code; + + exp->ce_mask |= exp_get_l4icmp_attr(tuple); +} + +int nfnl_exp_test_icmp(const struct nfnl_exp *exp, int tuple) +{ + int attr = exp_get_l4icmp_attr(tuple); + return !!(exp->ce_mask & attr); +} + +uint16_t nfnl_exp_get_icmp_id(const struct nfnl_exp *exp, int tuple) +{ + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + + return dir->proto.l4protodata.icmp.id; +} + +uint8_t nfnl_exp_get_icmp_type(const struct nfnl_exp *exp, int tuple) +{ + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + + return dir->proto.l4protodata.icmp.type; +} + +uint8_t nfnl_exp_get_icmp_code(const struct nfnl_exp *exp, int tuple) +{ + const struct nfnl_exp_dir *dir = EXP_GET_TUPLE(exp, tuple); + + return dir->proto.l4protodata.icmp.code; +} + +/** @} */ + +struct nl_object_ops exp_obj_ops = { + .oo_name = "netfilter/exp", + .oo_size = sizeof(struct nfnl_exp), + .oo_free_data = exp_free_data, + .oo_clone = exp_clone, + .oo_dump = { + [NL_DUMP_LINE] = exp_dump_line, + [NL_DUMP_DETAILS] = exp_dump_details, + }, + .oo_compare = exp_compare, + .oo_attrs2str = exp_attrs2str, +}; + +/** @} */ diff --git a/lib/netfilter/log.c b/lib/netfilter/log.c new file mode 100644 index 0000000..1bab9b6 --- /dev/null +++ b/lib/netfilter/log.c @@ -0,0 +1,251 @@ +/* + * lib/netfilter/log.c Netfilter Log + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + */ + +/** + * @ingroup nfnl + * @defgroup log Log + * @brief + * @{ + */ + +#include +#include + +#include +#include +#include +#include + +/** + * @name Log Commands + * @{ + */ + +static int build_log_cmd_request(uint8_t family, uint16_t queuenum, + uint8_t command, struct nl_msg **result) +{ + struct nl_msg *msg; + struct nfulnl_msg_config_cmd cmd; + + msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_ULOG, NFULNL_MSG_CONFIG, 0, + family, queuenum); + if (msg == NULL) + return -NLE_NOMEM; + + cmd.command = command; + if (nla_put(msg, NFULA_CFG_CMD, sizeof(cmd), &cmd) < 0) + goto nla_put_failure; + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +static int send_log_request(struct nl_sock *sk, struct nl_msg *msg) +{ + int err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +int nfnl_log_build_pf_bind(uint8_t pf, struct nl_msg **result) +{ + return build_log_cmd_request(pf, 0, NFULNL_CFG_CMD_PF_BIND, result); +} + +int nfnl_log_pf_bind(struct nl_sock *nlh, uint8_t pf) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_log_build_pf_bind(pf, &msg)) < 0) + return err; + + return send_log_request(nlh, msg); +} + +int nfnl_log_build_pf_unbind(uint8_t pf, struct nl_msg **result) +{ + return build_log_cmd_request(pf, 0, NFULNL_CFG_CMD_PF_UNBIND, result); +} + +int nfnl_log_pf_unbind(struct nl_sock *nlh, uint8_t pf) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_log_build_pf_unbind(pf, &msg)) < 0) + return err; + + return send_log_request(nlh, msg); +} + +static int nfnl_log_build_request(const struct nfnl_log *log, + struct nl_msg **result) +{ + struct nl_msg *msg; + + if (!nfnl_log_test_group(log)) + return -NLE_MISSING_ATTR; + + msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_ULOG, NFULNL_MSG_CONFIG, 0, + 0, nfnl_log_get_group(log)); + if (msg == NULL) + return -NLE_NOMEM; + + /* This sucks. The nfnetlink_log interface always expects both + * parameters to be present. Needs to be done properly. + */ + if (nfnl_log_test_copy_mode(log)) { + struct nfulnl_msg_config_mode mode; + + switch (nfnl_log_get_copy_mode(log)) { + case NFNL_LOG_COPY_NONE: + mode.copy_mode = NFULNL_COPY_NONE; + break; + case NFNL_LOG_COPY_META: + mode.copy_mode = NFULNL_COPY_META; + break; + case NFNL_LOG_COPY_PACKET: + mode.copy_mode = NFULNL_COPY_PACKET; + break; + } + mode.copy_range = htonl(nfnl_log_get_copy_range(log)); + mode._pad = 0; + + if (nla_put(msg, NFULA_CFG_MODE, sizeof(mode), &mode) < 0) + goto nla_put_failure; + } + + if (nfnl_log_test_flush_timeout(log) && + nla_put_u32(msg, NFULA_CFG_TIMEOUT, + htonl(nfnl_log_get_flush_timeout(log))) < 0) + goto nla_put_failure; + + if (nfnl_log_test_alloc_size(log) && + nla_put_u32(msg, NFULA_CFG_NLBUFSIZ, + htonl(nfnl_log_get_alloc_size(log))) < 0) + goto nla_put_failure; + + if (nfnl_log_test_queue_threshold(log) && + nla_put_u32(msg, NFULA_CFG_QTHRESH, + htonl(nfnl_log_get_queue_threshold(log))) < 0) + goto nla_put_failure; + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +int nfnl_log_build_create_request(const struct nfnl_log *log, + struct nl_msg **result) +{ + struct nfulnl_msg_config_cmd cmd; + int err; + + if ((err = nfnl_log_build_request(log, result)) < 0) + return err; + + cmd.command = NFULNL_CFG_CMD_BIND; + + if (nla_put(*result, NFULA_CFG_CMD, sizeof(cmd), &cmd) < 0) + goto nla_put_failure; + + return 0; + +nla_put_failure: + nlmsg_free(*result); + return -NLE_MSGSIZE; +} + +int nfnl_log_create(struct nl_sock *nlh, const struct nfnl_log *log) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_log_build_create_request(log, &msg)) < 0) + return err; + + return send_log_request(nlh, msg); +} + +int nfnl_log_build_change_request(const struct nfnl_log *log, + struct nl_msg **result) +{ + return nfnl_log_build_request(log, result); +} + +int nfnl_log_change(struct nl_sock *nlh, const struct nfnl_log *log) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_log_build_change_request(log, &msg)) < 0) + return err; + + return send_log_request(nlh, msg); +} + +int nfnl_log_build_delete_request(const struct nfnl_log *log, + struct nl_msg **result) +{ + if (!nfnl_log_test_group(log)) + return -NLE_MISSING_ATTR; + + return build_log_cmd_request(0, nfnl_log_get_group(log), + NFULNL_CFG_CMD_UNBIND, result); +} + +int nfnl_log_delete(struct nl_sock *nlh, const struct nfnl_log *log) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_log_build_delete_request(log, &msg)) < 0) + return err; + + return send_log_request(nlh, msg); +} + +/** @} */ + +static struct nl_cache_ops nfnl_log_ops = { + .co_name = "netfilter/log", + .co_obj_ops = &log_obj_ops, + .co_msgtypes = { + END_OF_MSGTYPES_LIST, + }, +}; + +static void __init log_init(void) +{ + nl_cache_mngt_register(&nfnl_log_ops); +} + +static void __exit log_exit(void) +{ + nl_cache_mngt_unregister(&nfnl_log_ops); +} + +/** @} */ diff --git a/lib/netfilter/log_msg.c b/lib/netfilter/log_msg.c new file mode 100644 index 0000000..6e09da2 --- /dev/null +++ b/lib/netfilter/log_msg.c @@ -0,0 +1,210 @@ +/* + * lib/netfilter/log_msg.c Netfilter Log Message + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c) 2008 Patrick McHardy + */ + +/** + * @ingroup nfnl + * @defgroup log Log + * @brief + * @{ + */ + +#include +#include + +#include +#include +#include +#include +#include + +#if __BYTE_ORDER == __BIG_ENDIAN +static uint64_t ntohll(uint64_t x) +{ + return x; +} +#elif __BYTE_ORDER == __LITTLE_ENDIAN +static uint64_t ntohll(uint64_t x) +{ + return bswap_64(x); +} +#endif + +static struct nla_policy log_msg_policy[NFULA_MAX+1] = { + [NFULA_PACKET_HDR] = { + .minlen = sizeof(struct nfulnl_msg_packet_hdr) + }, + [NFULA_MARK] = { .type = NLA_U32 }, + [NFULA_TIMESTAMP] = { + .minlen = sizeof(struct nfulnl_msg_packet_timestamp) + }, + [NFULA_IFINDEX_INDEV] = { .type = NLA_U32 }, + [NFULA_IFINDEX_OUTDEV] = { .type = NLA_U32 }, + [NFULA_IFINDEX_PHYSINDEV] = { .type = NLA_U32 }, + [NFULA_IFINDEX_PHYSOUTDEV] = { .type = NLA_U32 }, + [NFULA_HWADDR] = { + .minlen = sizeof(struct nfulnl_msg_packet_hw) + }, + //[NFULA_PAYLOAD] + [NFULA_PREFIX] = { .type = NLA_STRING, }, + [NFULA_UID] = { .type = NLA_U32 }, + [NFULA_GID] = { .type = NLA_U32 }, + [NFULA_SEQ] = { .type = NLA_U32 }, + [NFULA_SEQ_GLOBAL] = { .type = NLA_U32 }, +}; + +int nfnlmsg_log_msg_parse(struct nlmsghdr *nlh, struct nfnl_log_msg **result) +{ + struct nfnl_log_msg *msg; + struct nlattr *tb[NFULA_MAX+1]; + struct nlattr *attr; + int err; + + msg = nfnl_log_msg_alloc(); + if (!msg) + return -NLE_NOMEM; + + msg->ce_msgtype = nlh->nlmsg_type; + + err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, NFULA_MAX, + log_msg_policy); + if (err < 0) + goto errout; + + nfnl_log_msg_set_family(msg, nfnlmsg_family(nlh)); + + attr = tb[NFULA_PACKET_HDR]; + if (attr) { + struct nfulnl_msg_packet_hdr *hdr = nla_data(attr); + + if (hdr->hw_protocol) + nfnl_log_msg_set_hwproto(msg, hdr->hw_protocol); + nfnl_log_msg_set_hook(msg, hdr->hook); + } + + attr = tb[NFULA_MARK]; + if (attr) + nfnl_log_msg_set_mark(msg, ntohl(nla_get_u32(attr))); + + attr = tb[NFULA_TIMESTAMP]; + if (attr) { + struct nfulnl_msg_packet_timestamp *timestamp = nla_data(attr); + struct timeval tv; + + tv.tv_sec = ntohll(timestamp->sec); + tv.tv_usec = ntohll(timestamp->usec); + nfnl_log_msg_set_timestamp(msg, &tv); + } + + attr = tb[NFULA_IFINDEX_INDEV]; + if (attr) + nfnl_log_msg_set_indev(msg, ntohl(nla_get_u32(attr))); + + attr = tb[NFULA_IFINDEX_OUTDEV]; + if (attr) + nfnl_log_msg_set_outdev(msg, ntohl(nla_get_u32(attr))); + + attr = tb[NFULA_IFINDEX_PHYSINDEV]; + if (attr) + nfnl_log_msg_set_physindev(msg, ntohl(nla_get_u32(attr))); + + attr = tb[NFULA_IFINDEX_PHYSOUTDEV]; + if (attr) + nfnl_log_msg_set_physoutdev(msg, ntohl(nla_get_u32(attr))); + + attr = tb[NFULA_HWADDR]; + if (attr) { + struct nfulnl_msg_packet_hw *hw = nla_data(attr); + + nfnl_log_msg_set_hwaddr(msg, hw->hw_addr, ntohs(hw->hw_addrlen)); + } + + attr = tb[NFULA_PAYLOAD]; + if (attr) { + err = nfnl_log_msg_set_payload(msg, nla_data(attr), nla_len(attr)); + if (err < 0) + goto errout; + } + + attr = tb[NFULA_PREFIX]; + if (attr) { + err = nfnl_log_msg_set_prefix(msg, nla_data(attr)); + if (err < 0) + goto errout; + } + + attr = tb[NFULA_UID]; + if (attr) + nfnl_log_msg_set_uid(msg, ntohl(nla_get_u32(attr))); + + attr = tb[NFULA_GID]; + if (attr) + nfnl_log_msg_set_gid(msg, ntohl(nla_get_u32(attr))); + + attr = tb[NFULA_SEQ]; + if (attr) + nfnl_log_msg_set_seq(msg, ntohl(nla_get_u32(attr))); + + attr = tb[NFULA_SEQ_GLOBAL]; + if (attr) + nfnl_log_msg_set_seq_global(msg, ntohl(nla_get_u32(attr))); + + *result = msg; + return 0; + +errout: + nfnl_log_msg_put(msg); + return err; +} + +static int log_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *nlh, struct nl_parser_param *pp) +{ + struct nfnl_log_msg *msg; + int err; + + if ((err = nfnlmsg_log_msg_parse(nlh, &msg)) < 0) + goto errout; + + err = pp->pp_cb((struct nl_object *) msg, pp); +errout: + nfnl_log_msg_put(msg); + return err; +} + +/** @} */ + +#define NFNLMSG_LOG_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_ULOG, (type)) +static struct nl_cache_ops nfnl_log_msg_ops = { + .co_name = "netfilter/log_msg", + .co_hdrsize = NFNL_HDRLEN, + .co_msgtypes = { + { NFNLMSG_LOG_TYPE(NFULNL_MSG_PACKET), NL_ACT_NEW, "new" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_NETFILTER, + .co_msg_parser = log_msg_parser, + .co_obj_ops = &log_msg_obj_ops, +}; + +static void __init log_msg_init(void) +{ + nl_cache_mngt_register(&nfnl_log_msg_ops); +} + +static void __exit log_msg_exit(void) +{ + nl_cache_mngt_unregister(&nfnl_log_msg_ops); +} + +/** @} */ diff --git a/lib/netfilter/log_msg_obj.c b/lib/netfilter/log_msg_obj.c new file mode 100644 index 0000000..57db9d4 --- /dev/null +++ b/lib/netfilter/log_msg_obj.c @@ -0,0 +1,461 @@ +/* + * lib/netfilter/log_msg_obj.c Netfilter Log Object + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + */ + +#include +#include +#include +#include + +/** @cond SKIP */ +#define LOG_MSG_ATTR_FAMILY (1UL << 0) +#define LOG_MSG_ATTR_HWPROTO (1UL << 1) +#define LOG_MSG_ATTR_HOOK (1UL << 2) +#define LOG_MSG_ATTR_MARK (1UL << 3) +#define LOG_MSG_ATTR_TIMESTAMP (1UL << 4) +#define LOG_MSG_ATTR_INDEV (1UL << 5) +#define LOG_MSG_ATTR_OUTDEV (1UL << 6) +#define LOG_MSG_ATTR_PHYSINDEV (1UL << 7) +#define LOG_MSG_ATTR_PHYSOUTDEV (1UL << 8) +#define LOG_MSG_ATTR_HWADDR (1UL << 9) +#define LOG_MSG_ATTR_PAYLOAD (1UL << 10) +#define LOG_MSG_ATTR_PREFIX (1UL << 11) +#define LOG_MSG_ATTR_UID (1UL << 12) +#define LOG_MSG_ATTR_GID (1UL << 13) +#define LOG_MSG_ATTR_SEQ (1UL << 14) +#define LOG_MSG_ATTR_SEQ_GLOBAL (1UL << 15) +/** @endcond */ + +static void log_msg_free_data(struct nl_object *c) +{ + struct nfnl_log_msg *msg = (struct nfnl_log_msg *) c; + + if (msg == NULL) + return; + + free(msg->log_msg_payload); + free(msg->log_msg_prefix); +} + +static int log_msg_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct nfnl_log_msg *dst = (struct nfnl_log_msg *) _dst; + struct nfnl_log_msg *src = (struct nfnl_log_msg *) _src; + int err; + + if (src->log_msg_payload) { + err = nfnl_log_msg_set_payload(dst, src->log_msg_payload, + src->log_msg_payload_len); + if (err < 0) + goto errout; + } + + if (src->log_msg_prefix) { + err = nfnl_log_msg_set_prefix(dst, src->log_msg_prefix); + if (err < 0) + goto errout; + } + + return 0; +errout: + return err; +} + +static void log_msg_dump(struct nl_object *a, struct nl_dump_params *p) +{ + struct nfnl_log_msg *msg = (struct nfnl_log_msg *) a; + struct nl_cache *link_cache; + char buf[64]; + + link_cache = nl_cache_mngt_require_safe("route/link"); + + nl_new_line(p); + + if (msg->ce_mask & LOG_MSG_ATTR_PREFIX) + nl_dump(p, "%s", msg->log_msg_prefix); + + if (msg->ce_mask & LOG_MSG_ATTR_INDEV) { + if (link_cache) + nl_dump(p, "IN=%s ", + rtnl_link_i2name(link_cache, + msg->log_msg_indev, + buf, sizeof(buf))); + else + nl_dump(p, "IN=%d ", msg->log_msg_indev); + } + + if (msg->ce_mask & LOG_MSG_ATTR_PHYSINDEV) { + if (link_cache) + nl_dump(p, "PHYSIN=%s ", + rtnl_link_i2name(link_cache, + msg->log_msg_physindev, + buf, sizeof(buf))); + else + nl_dump(p, "IN=%d ", msg->log_msg_physindev); + } + + if (msg->ce_mask & LOG_MSG_ATTR_OUTDEV) { + if (link_cache) + nl_dump(p, "OUT=%s ", + rtnl_link_i2name(link_cache, + msg->log_msg_outdev, + buf, sizeof(buf))); + else + nl_dump(p, "OUT=%d ", msg->log_msg_outdev); + } + + if (msg->ce_mask & LOG_MSG_ATTR_PHYSOUTDEV) { + if (link_cache) + nl_dump(p, "PHYSOUT=%s ", + rtnl_link_i2name(link_cache, + msg->log_msg_physoutdev, + buf, sizeof(buf))); + else + nl_dump(p, "PHYSOUT=%d ", msg->log_msg_physoutdev); + } + + if (msg->ce_mask & LOG_MSG_ATTR_HWADDR) { + int i; + + nl_dump(p, "MAC"); + for (i = 0; i < msg->log_msg_hwaddr_len; i++) + nl_dump(p, "%c%02x", i?':':'=', msg->log_msg_hwaddr[i]); + nl_dump(p, " "); + } + + /* FIXME: parse the payload to get iptables LOG compatible format */ + + if (msg->ce_mask & LOG_MSG_ATTR_FAMILY) + nl_dump(p, "FAMILY=%s ", + nl_af2str(msg->log_msg_family, buf, sizeof(buf))); + + if (msg->ce_mask & LOG_MSG_ATTR_HWPROTO) + nl_dump(p, "HWPROTO=%s ", + nl_ether_proto2str(ntohs(msg->log_msg_hwproto), + buf, sizeof(buf))); + + if (msg->ce_mask & LOG_MSG_ATTR_HOOK) + nl_dump(p, "HOOK=%s ", + nfnl_inet_hook2str(msg->log_msg_hook, + buf, sizeof(buf))); + + if (msg->ce_mask & LOG_MSG_ATTR_MARK) + nl_dump(p, "MARK=%u ", msg->log_msg_mark); + + if (msg->ce_mask & LOG_MSG_ATTR_PAYLOAD) + nl_dump(p, "PAYLOADLEN=%d ", msg->log_msg_payload_len); + + if (msg->ce_mask & LOG_MSG_ATTR_UID) + nl_dump(p, "UID=%u ", msg->log_msg_uid); + + if (msg->ce_mask & LOG_MSG_ATTR_GID) + nl_dump(p, "GID=%u ", msg->log_msg_gid); + + if (msg->ce_mask & LOG_MSG_ATTR_SEQ) + nl_dump(p, "SEQ=%d ", msg->log_msg_seq); + + if (msg->ce_mask & LOG_MSG_ATTR_SEQ_GLOBAL) + nl_dump(p, "SEQGLOBAL=%d ", msg->log_msg_seq_global); + + nl_dump(p, "\n"); + + if (link_cache) + nl_cache_put(link_cache); +} + +/** + * @name Allocation/Freeing + * @{ + */ + +struct nfnl_log_msg *nfnl_log_msg_alloc(void) +{ + return (struct nfnl_log_msg *) nl_object_alloc(&log_msg_obj_ops); +} + +void nfnl_log_msg_get(struct nfnl_log_msg *msg) +{ + nl_object_get((struct nl_object *) msg); +} + +void nfnl_log_msg_put(struct nfnl_log_msg *msg) +{ + nl_object_put((struct nl_object *) msg); +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ + +void nfnl_log_msg_set_family(struct nfnl_log_msg *msg, uint8_t family) +{ + msg->log_msg_family = family; + msg->ce_mask |= LOG_MSG_ATTR_FAMILY; +} + +uint8_t nfnl_log_msg_get_family(const struct nfnl_log_msg *msg) +{ + if (msg->ce_mask & LOG_MSG_ATTR_FAMILY) + return msg->log_msg_family; + else + return AF_UNSPEC; +} + +void nfnl_log_msg_set_hwproto(struct nfnl_log_msg *msg, uint16_t hwproto) +{ + msg->log_msg_hwproto = hwproto; + msg->ce_mask |= LOG_MSG_ATTR_HWPROTO; +} + +int nfnl_log_msg_test_hwproto(const struct nfnl_log_msg *msg) +{ + return !!(msg->ce_mask & LOG_MSG_ATTR_HWPROTO); +} + +uint16_t nfnl_log_msg_get_hwproto(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_hwproto; +} + +void nfnl_log_msg_set_hook(struct nfnl_log_msg *msg, uint8_t hook) +{ + msg->log_msg_hook = hook; + msg->ce_mask |= LOG_MSG_ATTR_HOOK; +} + +int nfnl_log_msg_test_hook(const struct nfnl_log_msg *msg) +{ + return !!(msg->ce_mask & LOG_MSG_ATTR_HOOK); +} + +uint8_t nfnl_log_msg_get_hook(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_hook; +} + +void nfnl_log_msg_set_mark(struct nfnl_log_msg *msg, uint32_t mark) +{ + msg->log_msg_mark = mark; + msg->ce_mask |= LOG_MSG_ATTR_MARK; +} + +int nfnl_log_msg_test_mark(const struct nfnl_log_msg *msg) +{ + return !!(msg->ce_mask & LOG_MSG_ATTR_MARK); +} + +uint32_t nfnl_log_msg_get_mark(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_mark; +} + +void nfnl_log_msg_set_timestamp(struct nfnl_log_msg *msg, struct timeval *tv) +{ + msg->log_msg_timestamp.tv_sec = tv->tv_sec; + msg->log_msg_timestamp.tv_usec = tv->tv_usec; + msg->ce_mask |= LOG_MSG_ATTR_TIMESTAMP; +} + +const struct timeval *nfnl_log_msg_get_timestamp(const struct nfnl_log_msg *msg) +{ + if (!(msg->ce_mask & LOG_MSG_ATTR_TIMESTAMP)) + return NULL; + return &msg->log_msg_timestamp; +} + +void nfnl_log_msg_set_indev(struct nfnl_log_msg *msg, uint32_t indev) +{ + msg->log_msg_indev = indev; + msg->ce_mask |= LOG_MSG_ATTR_INDEV; +} + +uint32_t nfnl_log_msg_get_indev(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_indev; +} + +void nfnl_log_msg_set_outdev(struct nfnl_log_msg *msg, uint32_t outdev) +{ + msg->log_msg_outdev = outdev; + msg->ce_mask |= LOG_MSG_ATTR_OUTDEV; +} + +uint32_t nfnl_log_msg_get_outdev(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_outdev; +} + +void nfnl_log_msg_set_physindev(struct nfnl_log_msg *msg, uint32_t physindev) +{ + msg->log_msg_physindev = physindev; + msg->ce_mask |= LOG_MSG_ATTR_PHYSINDEV; +} + +uint32_t nfnl_log_msg_get_physindev(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_physindev; +} + +void nfnl_log_msg_set_physoutdev(struct nfnl_log_msg *msg, uint32_t physoutdev) +{ + msg->log_msg_physoutdev = physoutdev; + msg->ce_mask |= LOG_MSG_ATTR_PHYSOUTDEV; +} + +uint32_t nfnl_log_msg_get_physoutdev(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_physoutdev; +} + +void nfnl_log_msg_set_hwaddr(struct nfnl_log_msg *msg, uint8_t *hwaddr, int len) +{ + if (len > sizeof(msg->log_msg_hwaddr)) + len = sizeof(msg->log_msg_hwaddr); + msg->log_msg_hwaddr_len = len; + memcpy(msg->log_msg_hwaddr, hwaddr, len); + msg->ce_mask |= LOG_MSG_ATTR_HWADDR; +} + +const uint8_t *nfnl_log_msg_get_hwaddr(const struct nfnl_log_msg *msg, int *len) +{ + if (!(msg->ce_mask & LOG_MSG_ATTR_HWADDR)) { + *len = 0; + return NULL; + } + + *len = msg->log_msg_hwaddr_len; + return msg->log_msg_hwaddr; +} + +int nfnl_log_msg_set_payload(struct nfnl_log_msg *msg, uint8_t *payload, int len) +{ + free(msg->log_msg_payload); + msg->log_msg_payload = malloc(len); + if (!msg->log_msg_payload) + return -NLE_NOMEM; + + memcpy(msg->log_msg_payload, payload, len); + msg->log_msg_payload_len = len; + msg->ce_mask |= LOG_MSG_ATTR_PAYLOAD; + return 0; +} + +const void *nfnl_log_msg_get_payload(const struct nfnl_log_msg *msg, int *len) +{ + if (!(msg->ce_mask & LOG_MSG_ATTR_PAYLOAD)) { + *len = 0; + return NULL; + } + + *len = msg->log_msg_payload_len; + return msg->log_msg_payload; +} + +int nfnl_log_msg_set_prefix(struct nfnl_log_msg *msg, void *prefix) +{ + free(msg->log_msg_prefix); + msg->log_msg_prefix = strdup(prefix); + if (!msg->log_msg_prefix) + return -NLE_NOMEM; + + msg->ce_mask |= LOG_MSG_ATTR_PREFIX; + return 0; +} + +const char *nfnl_log_msg_get_prefix(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_prefix; +} + +void nfnl_log_msg_set_uid(struct nfnl_log_msg *msg, uint32_t uid) +{ + msg->log_msg_uid = uid; + msg->ce_mask |= LOG_MSG_ATTR_UID; +} + +int nfnl_log_msg_test_uid(const struct nfnl_log_msg *msg) +{ + return !!(msg->ce_mask & LOG_MSG_ATTR_UID); +} + +uint32_t nfnl_log_msg_get_uid(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_uid; +} + +void nfnl_log_msg_set_gid(struct nfnl_log_msg *msg, uint32_t gid) +{ + msg->log_msg_gid = gid; + msg->ce_mask |= LOG_MSG_ATTR_GID; +} + +int nfnl_log_msg_test_gid(const struct nfnl_log_msg *msg) +{ + return !!(msg->ce_mask & LOG_MSG_ATTR_GID); +} + +uint32_t nfnl_log_msg_get_gid(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_gid; +} + + +void nfnl_log_msg_set_seq(struct nfnl_log_msg *msg, uint32_t seq) +{ + msg->log_msg_seq = seq; + msg->ce_mask |= LOG_MSG_ATTR_SEQ; +} + +int nfnl_log_msg_test_seq(const struct nfnl_log_msg *msg) +{ + return !!(msg->ce_mask & LOG_MSG_ATTR_SEQ); +} + +uint32_t nfnl_log_msg_get_seq(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_seq; +} + +void nfnl_log_msg_set_seq_global(struct nfnl_log_msg *msg, uint32_t seq_global) +{ + msg->log_msg_seq_global = seq_global; + msg->ce_mask |= LOG_MSG_ATTR_SEQ_GLOBAL; +} + +int nfnl_log_msg_test_seq_global(const struct nfnl_log_msg *msg) +{ + return !!(msg->ce_mask & LOG_MSG_ATTR_SEQ_GLOBAL); +} + +uint32_t nfnl_log_msg_get_seq_global(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_seq_global; +} + +/** @} */ + +struct nl_object_ops log_msg_obj_ops = { + .oo_name = "netfilter/log_msg", + .oo_size = sizeof(struct nfnl_log_msg), + .oo_free_data = log_msg_free_data, + .oo_clone = log_msg_clone, + .oo_dump = { + [NL_DUMP_LINE] = log_msg_dump, + [NL_DUMP_DETAILS] = log_msg_dump, + [NL_DUMP_STATS] = log_msg_dump, + }, +}; + +/** @} */ diff --git a/lib/netfilter/log_obj.c b/lib/netfilter/log_obj.c new file mode 100644 index 0000000..2b11414 --- /dev/null +++ b/lib/netfilter/log_obj.c @@ -0,0 +1,287 @@ +/* + * lib/netfilter/log_obj.c Netfilter Log Object + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c) 2008 Patrick McHardy + */ + +#include +#include +#include + +/** @cond SKIP */ +#define LOG_ATTR_GROUP (1UL << 0) +#define LOG_ATTR_COPY_MODE (1UL << 1) +#define LOG_ATTR_COPY_RANGE (1UL << 3) +#define LOG_ATTR_FLUSH_TIMEOUT (1UL << 4) +#define LOG_ATTR_ALLOC_SIZE (1UL << 5) +#define LOG_ATTR_QUEUE_THRESHOLD (1UL << 6) + +/** @endcond */ + +static void nfnl_log_dump(struct nl_object *a, struct nl_dump_params *p) +{ + struct nfnl_log *log = (struct nfnl_log *) a; + char buf[64]; + + nl_new_line(p); + + if (log->ce_mask & LOG_ATTR_GROUP) + nl_dump(p, "group=%u ", log->log_group); + + if (log->ce_mask & LOG_ATTR_COPY_MODE) + nl_dump(p, "copy_mode=%s ", + nfnl_log_copy_mode2str(log->log_copy_mode, + buf, sizeof(buf))); + + if (log->ce_mask & LOG_ATTR_COPY_RANGE) + nl_dump(p, "copy_range=%u ", log->log_copy_range); + + if (log->ce_mask & LOG_ATTR_FLUSH_TIMEOUT) + nl_dump(p, "flush_timeout=%u ", log->log_flush_timeout); + + if (log->ce_mask & LOG_ATTR_ALLOC_SIZE) + nl_dump(p, "alloc_size=%u ", log->log_alloc_size); + + if (log->ce_mask & LOG_ATTR_QUEUE_THRESHOLD) + nl_dump(p, "queue_threshold=%u ", log->log_queue_threshold); + + nl_dump(p, "\n"); +} + +static const struct trans_tbl copy_modes[] = { + __ADD(NFNL_LOG_COPY_NONE, none) + __ADD(NFNL_LOG_COPY_META, meta) + __ADD(NFNL_LOG_COPY_PACKET, packet) +}; + +char *nfnl_log_copy_mode2str(enum nfnl_log_copy_mode copy_mode, char *buf, + size_t len) +{ + return __type2str(copy_mode, buf, len, copy_modes, + ARRAY_SIZE(copy_modes)); +} + +enum nfnl_log_copy_mode nfnl_log_str2copy_mode(const char *name) +{ + return __str2type(name, copy_modes, ARRAY_SIZE(copy_modes)); +} + +/** + * @name Allocation/Freeing + * @{ + */ + +struct nfnl_log *nfnl_log_alloc(void) +{ + return (struct nfnl_log *) nl_object_alloc(&log_obj_ops); +} + +void nfnl_log_get(struct nfnl_log *log) +{ + nl_object_get((struct nl_object *) log); +} + +void nfnl_log_put(struct nfnl_log *log) +{ + nl_object_put((struct nl_object *) log); +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ + +void nfnl_log_set_group(struct nfnl_log *log, uint16_t group) +{ + log->log_group = group; + log->ce_mask |= LOG_ATTR_GROUP; +} + +int nfnl_log_test_group(const struct nfnl_log *log) +{ + return !!(log->ce_mask & LOG_ATTR_GROUP); +} + +uint16_t nfnl_log_get_group(const struct nfnl_log *log) +{ + return log->log_group; +} + +void nfnl_log_set_copy_mode(struct nfnl_log *log, enum nfnl_log_copy_mode mode) +{ + log->log_copy_mode = mode; + log->ce_mask |= LOG_ATTR_COPY_MODE; +} + +int nfnl_log_test_copy_mode(const struct nfnl_log *log) +{ + return !!(log->ce_mask & LOG_ATTR_COPY_MODE); +} + +enum nfnl_log_copy_mode nfnl_log_get_copy_mode(const struct nfnl_log *log) +{ + return log->log_copy_mode; +} + +void nfnl_log_set_copy_range(struct nfnl_log *log, uint32_t copy_range) +{ + log->log_copy_range = copy_range; + log->ce_mask |= LOG_ATTR_COPY_RANGE; +} + +int nfnl_log_test_copy_range(const struct nfnl_log *log) +{ + return !!(log->ce_mask & LOG_ATTR_COPY_RANGE); +} + +uint32_t nfnl_log_get_copy_range(const struct nfnl_log *log) +{ + return log->log_copy_range; +} + +void nfnl_log_set_flush_timeout(struct nfnl_log *log, uint32_t timeout) +{ + log->log_flush_timeout = timeout; + log->ce_mask |= LOG_ATTR_FLUSH_TIMEOUT; +} + +int nfnl_log_test_flush_timeout(const struct nfnl_log *log) +{ + return !!(log->ce_mask & LOG_ATTR_FLUSH_TIMEOUT); +} + +uint32_t nfnl_log_get_flush_timeout(const struct nfnl_log *log) +{ + return log->log_flush_timeout; +} + +void nfnl_log_set_alloc_size(struct nfnl_log *log, uint32_t alloc_size) +{ + log->log_alloc_size = alloc_size; + log->ce_mask |= LOG_ATTR_ALLOC_SIZE; +} + +int nfnl_log_test_alloc_size(const struct nfnl_log *log) +{ + return !!(log->ce_mask & LOG_ATTR_ALLOC_SIZE); +} + +uint32_t nfnl_log_get_alloc_size(const struct nfnl_log *log) +{ + return log->log_alloc_size; +} + +void nfnl_log_set_queue_threshold(struct nfnl_log *log, uint32_t threshold) +{ + log->log_queue_threshold = threshold; + log->ce_mask |= LOG_ATTR_QUEUE_THRESHOLD; +} + +int nfnl_log_test_queue_threshold(const struct nfnl_log *log) +{ + return !!(log->ce_mask & LOG_ATTR_QUEUE_THRESHOLD); +} + +uint32_t nfnl_log_get_queue_threshold(const struct nfnl_log *log) +{ + return log->log_queue_threshold; +} + +/* We don't actually use the flags for anything yet since the + * nfnetlog_log interface truly sucks - it only contains the + * flag value, but not mask, so we would have to make assumptions + * about the supported flags. + */ +void nfnl_log_set_flags(struct nfnl_log *log, unsigned int flags) +{ + log->log_flags |= flags; + log->log_flag_mask |= flags; +} + +void nfnl_log_unset_flags(struct nfnl_log *log, unsigned int flags) +{ + log->log_flags &= ~flags; + log->log_flag_mask |= flags; +} + +static const struct trans_tbl log_flags[] = { + __ADD(NFNL_LOG_FLAG_SEQ, seq) + __ADD(NFNL_LOG_FLAG_SEQ_GLOBAL, seq_global) +}; + +char *nfnl_log_flags2str(unsigned int flags, char *buf, size_t len) +{ + return __flags2str(flags, buf, len, log_flags, ARRAY_SIZE(log_flags)); +} + +unsigned int nfnl_log_str2flags(const char *name) +{ + return __str2flags(name, log_flags, ARRAY_SIZE(log_flags)); +} + +static int nfnl_log_compare(struct nl_object *_a, struct nl_object *_b, + uint32_t attrs, int flags) +{ + struct nfnl_log *a = (struct nfnl_log *) _a; + struct nfnl_log *b = (struct nfnl_log *) _b; + int diff = 0; + +#define NFNL_LOG_DIFF(ATTR, EXPR) \ + ATTR_DIFF(attrs, LOG_ATTR_##ATTR, a, b, EXPR) +#define NFNL_LOG_DIFF_VAL(ATTR, FIELD) \ + NFNL_LOG_DIFF(ATTR, a->FIELD != b->FIELD) + + diff |= NFNL_LOG_DIFF_VAL(GROUP, log_group); + diff |= NFNL_LOG_DIFF_VAL(COPY_MODE, log_copy_mode); + diff |= NFNL_LOG_DIFF_VAL(COPY_RANGE, log_copy_range); + diff |= NFNL_LOG_DIFF_VAL(FLUSH_TIMEOUT, log_flush_timeout); + diff |= NFNL_LOG_DIFF_VAL(ALLOC_SIZE, log_alloc_size); + diff |= NFNL_LOG_DIFF_VAL(QUEUE_THRESHOLD, log_queue_threshold); + +#undef NFNL_LOG_DIFF +#undef NFNL_LOG_DIFF_VAL + + return diff; +} + +static const struct trans_tbl nfnl_log_attrs[] = { + __ADD(LOG_ATTR_GROUP, group) + __ADD(LOG_ATTR_COPY_MODE, copy_mode) + __ADD(LOG_ATTR_COPY_RANGE, copy_range) + __ADD(LOG_ATTR_FLUSH_TIMEOUT, flush_timeout) + __ADD(LOG_ATTR_ALLOC_SIZE, alloc_size) + __ADD(LOG_ATTR_QUEUE_THRESHOLD, queue_threshold) +}; + +static char *nfnl_log_attrs2str(int attrs, char *buf, size_t len) +{ + return __flags2str(attrs, buf, len, nfnl_log_attrs, + ARRAY_SIZE(nfnl_log_attrs)); +} + +/** @} */ + +struct nl_object_ops log_obj_ops = { + .oo_name = "netfilter/log", + .oo_size = sizeof(struct nfnl_log), + .oo_dump = { + [NL_DUMP_LINE] = nfnl_log_dump, + [NL_DUMP_DETAILS] = nfnl_log_dump, + [NL_DUMP_STATS] = nfnl_log_dump, + }, + .oo_compare = nfnl_log_compare, + .oo_attrs2str = nfnl_log_attrs2str, + .oo_id_attrs = LOG_ATTR_GROUP, +}; + +/** @} */ diff --git a/lib/netfilter/netfilter.c b/lib/netfilter/netfilter.c new file mode 100644 index 0000000..0062994 --- /dev/null +++ b/lib/netfilter/netfilter.c @@ -0,0 +1,53 @@ +/* + * lib/netfilter/netfilter.c Netfilter Generic Functions + * + * 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 Patrick McHardy + */ + +#include +#include +#include + +static const struct trans_tbl nfnl_verdicts[] = { + __ADD(NF_DROP, NF_DROP) + __ADD(NF_ACCEPT, NF_ACCEPT) + __ADD(NF_STOLEN, NF_STOLEN) + __ADD(NF_QUEUE, NF_QUEUE) + __ADD(NF_REPEAT, NF_REPEAT) + __ADD(NF_STOP, NF_STOP) +}; + +char *nfnl_verdict2str(unsigned int verdict, char *buf, size_t len) +{ + return __type2str(verdict, buf, len, nfnl_verdicts, + ARRAY_SIZE(nfnl_verdicts)); +} + +unsigned int nfnl_str2verdict(const char *name) +{ + return __str2type(name, nfnl_verdicts, ARRAY_SIZE(nfnl_verdicts)); +} + +static const struct trans_tbl nfnl_inet_hooks[] = { + __ADD(NF_INET_PRE_ROUTING, NF_INET_PREROUTING) + __ADD(NF_INET_LOCAL_IN, NF_INET_LOCAL_IN) + __ADD(NF_INET_FORWARD, NF_INET_FORWARD) + __ADD(NF_INET_LOCAL_OUT, NF_INET_LOCAL_OUT) + __ADD(NF_INET_POST_ROUTING, NF_INET_POST_ROUTING) +}; + +char *nfnl_inet_hook2str(unsigned int hook, char *buf, size_t len) +{ + return __type2str(hook, buf, len, nfnl_inet_hooks, + ARRAY_SIZE(nfnl_inet_hooks)); +} + +unsigned int nfnl_str2inet_hook(const char *name) +{ + return __str2type(name, nfnl_inet_hooks, ARRAY_SIZE(nfnl_inet_hooks)); +} diff --git a/lib/netfilter/nfnl.c b/lib/netfilter/nfnl.c new file mode 100644 index 0000000..f028a85 --- /dev/null +++ b/lib/netfilter/nfnl.c @@ -0,0 +1,245 @@ +/* + * lib/netfilter/nfnl.c Netfilter Netlink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + */ + +/** + * @defgroup nfnl Netfilter Library (libnl-nf) + * + * @par Message Format + * @code + * <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) ---> + * +----------------------------+- - -+- - - - - - - - - - -+- - -+ + * | Header | Pad | Payload | Pad | + * | struct nlmsghdr | | | | + * +----------------------------+- - -+- - - - - - - - - - -+- - -+ + * @endcode + * @code + * <-------- NFNL_HDRLEN ---------> + * +--------------------------+- - -+------------+ + * | Netfilter Netlink Header | Pad | Attributes | + * | struct nfgenmsg | | | + * +--------------------------+- - -+------------+ + * nfnlmsg_attrdata(nfg, hdrlen)-----^ + * @endcode + * + * @par 1) Creating a new netfilter netlink message + * @code + * struct nl_msg *msg; + * + * // Create a new empty netlink message + * msg = nlmsg_alloc(); + * + * // Append the netlink and netfilter netlink message header + * hdr = nfnlmsg_put(msg, PID, SEQ, SUBSYS, TYPE, NLM_F_ECHO, + * FAMILY, RES_ID); + * + * // Append the attributes. + * nla_put_u32(msg, 1, 0x10); + * + * // Message is ready to be sent. + * nl_send_auto_complete(sk, msg); + * + * // All done? Free the message. + * nlmsg_free(msg); + * @endcode + * + * @par 2) Sending of trivial messages + * @code + * // For trivial messages not requiring any subsys specific header or + * // attributes, nfnl_send_simple() may be used to send messages directly. + * nfnl_send_simple(sk, SUBSYS, TYPE, 0, FAMILY, RES_ID); + * @endcode + * @{ + */ + +#include +#include +#include + +/** + * @name Socket Creating + * @{ + */ + +/** + * Create and connect netfilter netlink socket. + * @arg sk Netlink socket. + * + * Creates a NETLINK_NETFILTER netlink socket, binds the socket and + * issues a connection attempt. + * + * @see nl_connect() + * + * @return 0 on success or a negative error code. + */ +int nfnl_connect(struct nl_sock *sk) +{ + return nl_connect(sk, NETLINK_NETFILTER); +} + +/** @} */ + +/** + * @name Sending + * @{ + */ + +/** + * Send trivial netfilter netlink message + * @arg sk Netlink socket. + * @arg subsys_id nfnetlink subsystem + * @arg type nfnetlink message type + * @arg flags message flags + * @arg family nfnetlink address family + * @arg res_id nfnetlink resource id + * + * @return Newly allocated netlink message or NULL. + */ +int nfnl_send_simple(struct nl_sock *sk, uint8_t subsys_id, uint8_t type, + int flags, uint8_t family, uint16_t res_id) +{ + struct nfgenmsg hdr = { + .nfgen_family = family, + .version = NFNETLINK_V0, + .res_id = htons(res_id), + }; + + return nl_send_simple(sk, NFNLMSG_TYPE(subsys_id, type), flags, + &hdr, sizeof(hdr)); +} + +/** @} */ + +/** + * @name Message Parsing + * @{ + */ + +/** + * Get netfilter subsystem id from message + * @arg nlh netlink messsage header + */ +uint8_t nfnlmsg_subsys(struct nlmsghdr *nlh) +{ + return NFNL_SUBSYS_ID(nlh->nlmsg_type); +} + +/** + * Get netfilter message type from message + * @arg nlh netlink messsage header + */ +uint8_t nfnlmsg_subtype(struct nlmsghdr *nlh) +{ + return NFNL_MSG_TYPE(nlh->nlmsg_type); +} + +/** + * Get netfilter family from message + * @arg nlh netlink messsage header + */ +uint8_t nfnlmsg_family(struct nlmsghdr *nlh) +{ + struct nfgenmsg *nfg = nlmsg_data(nlh); + + return nfg->nfgen_family; +} + +/** + * Get netfilter resource id from message + * @arg nlh netlink messsage header + */ +uint16_t nfnlmsg_res_id(struct nlmsghdr *nlh) +{ + struct nfgenmsg *nfg = nlmsg_data(nlh); + + return ntohs(nfg->res_id); +} + +/** @} */ + +/** + * @name Message Building + * @{ + */ + +static int nfnlmsg_append(struct nl_msg *msg, uint8_t family, uint16_t res_id) +{ + struct nfgenmsg *nfg; + + nfg = nlmsg_reserve(msg, sizeof(*nfg), NLMSG_ALIGNTO); + if (nfg == NULL) + return -NLE_NOMEM; + + nfg->nfgen_family = family; + nfg->version = NFNETLINK_V0; + nfg->res_id = htons(res_id); + NL_DBG(2, "msg %p: Added nfnetlink header family=%d res_id=%d\n", + msg, family, res_id); + return 0; +} + +/** + * Allocate a new netfilter netlink message + * @arg subsys_id nfnetlink subsystem + * @arg type nfnetlink message type + * @arg flags message flags + * @arg family nfnetlink address family + * @arg res_id nfnetlink resource id + * + * @return Newly allocated netlink message or NULL. + */ +struct nl_msg *nfnlmsg_alloc_simple(uint8_t subsys_id, uint8_t type, int flags, + uint8_t family, uint16_t res_id) +{ + struct nl_msg *msg; + + msg = nlmsg_alloc_simple(NFNLMSG_TYPE(subsys_id, type), flags); + if (msg == NULL) + return NULL; + + if (nfnlmsg_append(msg, family, res_id) < 0) + goto nla_put_failure; + + return msg; + +nla_put_failure: + nlmsg_free(msg); + return NULL; +} + +/** + * Add netlink and netfilter netlink headers to netlink message + * @arg msg netlink message + * @arg pid netlink process id + * @arg seq sequence number of message + * @arg subsys_id nfnetlink subsystem + * @arg type nfnetlink message type + * @arg flags message flags + * @arg family nfnetlink address family + * @arg res_id nfnetlink resource id + */ +int nfnlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, + uint8_t subsys_id, uint8_t type, int flags, uint8_t family, + uint16_t res_id) +{ + struct nlmsghdr *nlh; + + nlh = nlmsg_put(msg, pid, seq, NFNLMSG_TYPE(subsys_id, type), 0, flags); + if (nlh == NULL) + return -NLE_MSGSIZE; + + return nfnlmsg_append(msg, family, res_id); +} + +/** @} */ + +/** @} */ diff --git a/lib/netfilter/queue.c b/lib/netfilter/queue.c new file mode 100644 index 0000000..5655647 --- /dev/null +++ b/lib/netfilter/queue.c @@ -0,0 +1,251 @@ +/* + * lib/netfilter/queue.c Netfilter Queue + * + * 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) 2007, 2008 Patrick McHardy + */ + +/** + * @ingroup nfnl + * @defgroup queue Queue + * @brief + * @{ + */ + +#include +#include + +#include +#include +#include +#include + +struct nl_sock *nfnl_queue_socket_alloc(void) +{ + struct nl_sock *nlsk; + + nlsk = nl_socket_alloc(); + if (nlsk) + nl_socket_disable_auto_ack(nlsk); + return nlsk; +} + +static int send_queue_request(struct nl_sock *sk, struct nl_msg *msg) +{ + int err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +/** + * @name Queue Commands + * @{ + */ + +static int build_queue_cmd_request(uint8_t family, uint16_t queuenum, + uint8_t command, struct nl_msg **result) +{ + struct nl_msg *msg; + struct nfqnl_msg_config_cmd cmd; + + msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_QUEUE, NFQNL_MSG_CONFIG, 0, + family, queuenum); + if (msg == NULL) + return -NLE_NOMEM; + + cmd.pf = htons(family); + cmd._pad = 0; + cmd.command = command; + if (nla_put(msg, NFQA_CFG_CMD, sizeof(cmd), &cmd) < 0) + goto nla_put_failure; + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +int nfnl_queue_build_pf_bind(uint8_t pf, struct nl_msg **result) +{ + return build_queue_cmd_request(pf, 0, NFQNL_CFG_CMD_PF_BIND, result); +} + +int nfnl_queue_pf_bind(struct nl_sock *nlh, uint8_t pf) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_queue_build_pf_bind(pf, &msg)) < 0) + return err; + + return send_queue_request(nlh, msg); +} + +int nfnl_queue_build_pf_unbind(uint8_t pf, struct nl_msg **result) +{ + return build_queue_cmd_request(pf, 0, NFQNL_CFG_CMD_PF_UNBIND, result); +} + +int nfnl_queue_pf_unbind(struct nl_sock *nlh, uint8_t pf) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_queue_build_pf_unbind(pf, &msg)) < 0) + return err; + + return send_queue_request(nlh, msg); +} + +static int nfnl_queue_build_request(const struct nfnl_queue *queue, + struct nl_msg **result) +{ + struct nl_msg *msg; + + if (!nfnl_queue_test_group(queue)) + return -NLE_MISSING_ATTR; + + msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_QUEUE, NFQNL_MSG_CONFIG, 0, + 0, nfnl_queue_get_group(queue)); + if (msg == NULL) + return -NLE_NOMEM; + + if (nfnl_queue_test_maxlen(queue) && + nla_put_u32(msg, NFQA_CFG_QUEUE_MAXLEN, + htonl(nfnl_queue_get_maxlen(queue))) < 0) + goto nla_put_failure; + + /* This sucks, the nfnetlink_queue interface always expects both + * parameters to be present. Needs to be done properly. + */ + if (nfnl_queue_test_copy_mode(queue)) { + struct nfqnl_msg_config_params params; + + switch (nfnl_queue_get_copy_mode(queue)) { + case NFNL_QUEUE_COPY_NONE: + params.copy_mode = NFQNL_COPY_NONE; + break; + case NFNL_QUEUE_COPY_META: + params.copy_mode = NFQNL_COPY_META; + break; + case NFNL_QUEUE_COPY_PACKET: + params.copy_mode = NFQNL_COPY_PACKET; + break; + } + params.copy_range = htonl(nfnl_queue_get_copy_range(queue)); + + if (nla_put(msg, NFQA_CFG_PARAMS, sizeof(params), ¶ms) < 0) + goto nla_put_failure; + } + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +int nfnl_queue_build_create_request(const struct nfnl_queue *queue, + struct nl_msg **result) +{ + struct nfqnl_msg_config_cmd cmd; + int err; + + if ((err = nfnl_queue_build_request(queue, result)) < 0) + return err; + + cmd.pf = 0; + cmd._pad = 0; + cmd.command = NFQNL_CFG_CMD_BIND; + + NLA_PUT(*result, NFQA_CFG_CMD, sizeof(cmd), &cmd); + + return 0; + +nla_put_failure: + nlmsg_free(*result); + return -NLE_MSGSIZE; +} + +int nfnl_queue_create(struct nl_sock *nlh, const struct nfnl_queue *queue) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_queue_build_create_request(queue, &msg)) < 0) + return err; + + return send_queue_request(nlh, msg); +} + +int nfnl_queue_build_change_request(const struct nfnl_queue *queue, + struct nl_msg **result) +{ + return nfnl_queue_build_request(queue, result); +} + +int nfnl_queue_change(struct nl_sock *nlh, const struct nfnl_queue *queue) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_queue_build_change_request(queue, &msg)) < 0) + return err; + + return send_queue_request(nlh, msg); +} + +int nfnl_queue_build_delete_request(const struct nfnl_queue *queue, + struct nl_msg **result) +{ + if (!nfnl_queue_test_group(queue)) + return -NLE_MISSING_ATTR; + + return build_queue_cmd_request(0, nfnl_queue_get_group(queue), + NFQNL_CFG_CMD_UNBIND, result); +} + +int nfnl_queue_delete(struct nl_sock *nlh, const struct nfnl_queue *queue) +{ + struct nl_msg *msg; + int err; + + if ((err = nfnl_queue_build_delete_request(queue, &msg)) < 0) + return err; + + return send_queue_request(nlh, msg); +} + +/** @} */ + +static struct nl_cache_ops nfnl_queue_ops = { + .co_name = "netfilter/queue", + .co_obj_ops = &queue_obj_ops, + .co_msgtypes = { + END_OF_MSGTYPES_LIST, + }, +}; + +static void __init nfnl_queue_init(void) +{ + nl_cache_mngt_register(&nfnl_queue_ops); +} + +static void __exit nfnl_queue_exit(void) +{ + nl_cache_mngt_unregister(&nfnl_queue_ops); +} + +/** @} */ diff --git a/lib/netfilter/queue_msg.c b/lib/netfilter/queue_msg.c new file mode 100644 index 0000000..95d8ad3 --- /dev/null +++ b/lib/netfilter/queue_msg.c @@ -0,0 +1,285 @@ +/* + * lib/netfilter/queue_msg.c Netfilter Queue Messages + * + * 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) 2007, 2008 Patrick McHardy + * Copyright (c) 2010 Karl Hiramoto + */ + +/** + * @ingroup nfnl + * @defgroup queue Queue + * @brief + * @{ + */ + +#include +#include + +#include +#include +#include +#include +#include + +static struct nl_cache_ops nfnl_queue_msg_ops; + +#if __BYTE_ORDER == __BIG_ENDIAN +static uint64_t ntohll(uint64_t x) +{ + return x; +} +#elif __BYTE_ORDER == __LITTLE_ENDIAN +static uint64_t ntohll(uint64_t x) +{ + return bswap_64(x); +} +#endif + +static struct nla_policy queue_policy[NFQA_MAX+1] = { + [NFQA_PACKET_HDR] = { + .minlen = sizeof(struct nfqnl_msg_packet_hdr), + }, + [NFQA_VERDICT_HDR] = { + .minlen = sizeof(struct nfqnl_msg_verdict_hdr), + }, + [NFQA_MARK] = { .type = NLA_U32 }, + [NFQA_TIMESTAMP] = { + .minlen = sizeof(struct nfqnl_msg_packet_timestamp), + }, + [NFQA_IFINDEX_INDEV] = { .type = NLA_U32 }, + [NFQA_IFINDEX_OUTDEV] = { .type = NLA_U32 }, + [NFQA_IFINDEX_PHYSINDEV] = { .type = NLA_U32 }, + [NFQA_IFINDEX_PHYSOUTDEV] = { .type = NLA_U32 }, + [NFQA_HWADDR] = { + .minlen = sizeof(struct nfqnl_msg_packet_hw), + }, +}; + +int nfnlmsg_queue_msg_parse(struct nlmsghdr *nlh, + struct nfnl_queue_msg **result) +{ + struct nfnl_queue_msg *msg; + struct nlattr *tb[NFQA_MAX+1]; + struct nlattr *attr; + int err; + + msg = nfnl_queue_msg_alloc(); + if (!msg) + return -NLE_NOMEM; + + msg->ce_msgtype = nlh->nlmsg_type; + + err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, NFQA_MAX, + queue_policy); + if (err < 0) + goto errout; + + nfnl_queue_msg_set_group(msg, nfnlmsg_res_id(nlh)); + nfnl_queue_msg_set_family(msg, nfnlmsg_family(nlh)); + + attr = tb[NFQA_PACKET_HDR]; + if (attr) { + struct nfqnl_msg_packet_hdr *hdr = nla_data(attr); + + nfnl_queue_msg_set_packetid(msg, ntohl(hdr->packet_id)); + if (hdr->hw_protocol) + nfnl_queue_msg_set_hwproto(msg, hdr->hw_protocol); + nfnl_queue_msg_set_hook(msg, hdr->hook); + } + + attr = tb[NFQA_MARK]; + if (attr) + nfnl_queue_msg_set_mark(msg, ntohl(nla_get_u32(attr))); + + attr = tb[NFQA_TIMESTAMP]; + if (attr) { + struct nfqnl_msg_packet_timestamp *timestamp = nla_data(attr); + struct timeval tv; + + tv.tv_sec = ntohll(timestamp->sec); + tv.tv_usec = ntohll(timestamp->usec); + nfnl_queue_msg_set_timestamp(msg, &tv); + } + + attr = tb[NFQA_IFINDEX_INDEV]; + if (attr) + nfnl_queue_msg_set_indev(msg, ntohl(nla_get_u32(attr))); + + attr = tb[NFQA_IFINDEX_OUTDEV]; + if (attr) + nfnl_queue_msg_set_outdev(msg, ntohl(nla_get_u32(attr))); + + attr = tb[NFQA_IFINDEX_PHYSINDEV]; + if (attr) + nfnl_queue_msg_set_physindev(msg, ntohl(nla_get_u32(attr))); + + attr = tb[NFQA_IFINDEX_PHYSOUTDEV]; + if (attr) + nfnl_queue_msg_set_physoutdev(msg, ntohl(nla_get_u32(attr))); + + attr = tb[NFQA_HWADDR]; + if (attr) { + struct nfqnl_msg_packet_hw *hw = nla_data(attr); + + nfnl_queue_msg_set_hwaddr(msg, hw->hw_addr, + ntohs(hw->hw_addrlen)); + } + + attr = tb[NFQA_PAYLOAD]; + if (attr) { + err = nfnl_queue_msg_set_payload(msg, nla_data(attr), + nla_len(attr)); + if (err < 0) + goto errout; + } + + *result = msg; + return 0; + +errout: + nfnl_queue_msg_put(msg); + return err; +} + +static int queue_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *nlh, struct nl_parser_param *pp) +{ + struct nfnl_queue_msg *msg; + int err; + + if ((err = nfnlmsg_queue_msg_parse(nlh, &msg)) < 0) + goto errout; + + err = pp->pp_cb((struct nl_object *) msg, pp); +errout: + nfnl_queue_msg_put(msg); + return err; +} + +/** @} */ + +struct nl_msg *nfnl_queue_msg_build_verdict(const struct nfnl_queue_msg *msg) +{ + struct nl_msg *nlmsg; + struct nfqnl_msg_verdict_hdr verdict; + + nlmsg = nfnlmsg_alloc_simple(NFNL_SUBSYS_QUEUE, NFQNL_MSG_VERDICT, 0, + nfnl_queue_msg_get_family(msg), + nfnl_queue_msg_get_group(msg)); + if (nlmsg == NULL) + return NULL; + + verdict.id = htonl(nfnl_queue_msg_get_packetid(msg)); + verdict.verdict = htonl(nfnl_queue_msg_get_verdict(msg)); + if (nla_put(nlmsg, NFQA_VERDICT_HDR, sizeof(verdict), &verdict) < 0) + goto nla_put_failure; + + if (nfnl_queue_msg_test_mark(msg) && + nla_put_u32(nlmsg, NFQA_MARK, + ntohl(nfnl_queue_msg_get_mark(msg))) < 0) + goto nla_put_failure; + + return nlmsg; + +nla_put_failure: + nlmsg_free(nlmsg); + return NULL; +} + +/** +* Send a message verdict/mark +* @arg nlh netlink messsage header +* @arg msg queue msg +* @return 0 on OK or error code +*/ +int nfnl_queue_msg_send_verdict(struct nl_sock *nlh, + const struct nfnl_queue_msg *msg) +{ + struct nl_msg *nlmsg; + int err; + + nlmsg = nfnl_queue_msg_build_verdict(msg); + if (nlmsg == NULL) + return -NLE_NOMEM; + + err = nl_send_auto_complete(nlh, nlmsg); + nlmsg_free(nlmsg); + if (err < 0) + return err; + return wait_for_ack(nlh); +} + +/** +* Send a message verdict including the payload +* @arg nlh netlink messsage header +* @arg msg queue msg +* @arg payload_data packet payload data +* @arg payload_len payload length +* @return 0 on OK or error code +*/ +int nfnl_queue_msg_send_verdict_payload(struct nl_sock *nlh, + const struct nfnl_queue_msg *msg, + const void *payload_data, unsigned payload_len) +{ + struct nl_msg *nlmsg; + int err; + struct iovec iov[3]; + struct nlattr nla; + + nlmsg = nfnl_queue_msg_build_verdict(msg); + if (nlmsg == NULL) + return -NLE_NOMEM; + + memset(iov, 0, sizeof(iov)); + + iov[0].iov_base = (void *) nlmsg_hdr(nlmsg); + iov[0].iov_len = nlmsg_hdr(nlmsg)->nlmsg_len; + + nla.nla_type = NFQA_PAYLOAD; + nla.nla_len = payload_len + sizeof(nla); + nlmsg_hdr(nlmsg)->nlmsg_len += nla.nla_len; + + iov[1].iov_base = (void *) &nla; + iov[1].iov_len = sizeof(nla); + + iov[2].iov_base = (void *) payload_data; + iov[2].iov_len = NLA_ALIGN(payload_len); + + nl_complete_msg(nlh, nlmsg); + err = nl_send_iovec(nlh, nlmsg, iov, 3); + + nlmsg_free(nlmsg); + if (err < 0) + return err; + return wait_for_ack(nlh); +} + +#define NFNLMSG_QUEUE_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_QUEUE, (type)) +static struct nl_cache_ops nfnl_queue_msg_ops = { + .co_name = "netfilter/queue_msg", + .co_hdrsize = NFNL_HDRLEN, + .co_msgtypes = { + { NFNLMSG_QUEUE_TYPE(NFQNL_MSG_PACKET), NL_ACT_NEW, "new" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_NETFILTER, + .co_msg_parser = queue_msg_parser, + .co_obj_ops = &queue_msg_obj_ops, +}; + +static void __init nfnl_msg_queue_init(void) +{ + nl_cache_mngt_register(&nfnl_queue_msg_ops); +} + +static void __exit nfnl_queue_msg_exit(void) +{ + nl_cache_mngt_unregister(&nfnl_queue_msg_ops); +} + +/** @} */ diff --git a/lib/netfilter/queue_msg_obj.c b/lib/netfilter/queue_msg_obj.c new file mode 100644 index 0000000..8085f1b --- /dev/null +++ b/lib/netfilter/queue_msg_obj.c @@ -0,0 +1,495 @@ +/* + * lib/netfilter/queue_msg_obj.c Netfilter Queue Message Object + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2007, 2008 Patrick McHardy + */ + +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define QUEUE_MSG_ATTR_GROUP (1UL << 0) +#define QUEUE_MSG_ATTR_FAMILY (1UL << 1) +#define QUEUE_MSG_ATTR_PACKETID (1UL << 2) +#define QUEUE_MSG_ATTR_HWPROTO (1UL << 3) +#define QUEUE_MSG_ATTR_HOOK (1UL << 4) +#define QUEUE_MSG_ATTR_MARK (1UL << 5) +#define QUEUE_MSG_ATTR_TIMESTAMP (1UL << 6) +#define QUEUE_MSG_ATTR_INDEV (1UL << 7) +#define QUEUE_MSG_ATTR_OUTDEV (1UL << 8) +#define QUEUE_MSG_ATTR_PHYSINDEV (1UL << 9) +#define QUEUE_MSG_ATTR_PHYSOUTDEV (1UL << 10) +#define QUEUE_MSG_ATTR_HWADDR (1UL << 11) +#define QUEUE_MSG_ATTR_PAYLOAD (1UL << 12) +#define QUEUE_MSG_ATTR_VERDICT (1UL << 13) +/** @endcond */ + +static void nfnl_queue_msg_free_data(struct nl_object *c) +{ + struct nfnl_queue_msg *msg = (struct nfnl_queue_msg *) c; + + if (msg == NULL) + return; + + free(msg->queue_msg_payload); +} + +static int nfnl_queue_msg_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct nfnl_queue_msg *dst = (struct nfnl_queue_msg *) _dst; + struct nfnl_queue_msg *src = (struct nfnl_queue_msg *) _src; + int err; + + if (src->queue_msg_payload) { + err = nfnl_queue_msg_set_payload(dst, src->queue_msg_payload, + src->queue_msg_payload_len); + if (err < 0) + goto errout; + } + + return 0; +errout: + return err; +} + +static void nfnl_queue_msg_dump(struct nl_object *a, struct nl_dump_params *p) +{ + struct nfnl_queue_msg *msg = (struct nfnl_queue_msg *) a; + struct nl_cache *link_cache; + char buf[64]; + + link_cache = nl_cache_mngt_require_safe("route/link"); + + nl_new_line(p); + + if (msg->ce_mask & QUEUE_MSG_ATTR_GROUP) + nl_dump(p, "GROUP=%u ", msg->queue_msg_group); + + if (msg->ce_mask & QUEUE_MSG_ATTR_INDEV) { + if (link_cache) + nl_dump(p, "IN=%s ", + rtnl_link_i2name(link_cache, + msg->queue_msg_indev, + buf, sizeof(buf))); + else + nl_dump(p, "IN=%d ", msg->queue_msg_indev); + } + + if (msg->ce_mask & QUEUE_MSG_ATTR_PHYSINDEV) { + if (link_cache) + nl_dump(p, "PHYSIN=%s ", + rtnl_link_i2name(link_cache, + msg->queue_msg_physindev, + buf, sizeof(buf))); + else + nl_dump(p, "IN=%d ", msg->queue_msg_physindev); + } + + if (msg->ce_mask & QUEUE_MSG_ATTR_OUTDEV) { + if (link_cache) + nl_dump(p, "OUT=%s ", + rtnl_link_i2name(link_cache, + msg->queue_msg_outdev, + buf, sizeof(buf))); + else + nl_dump(p, "OUT=%d ", msg->queue_msg_outdev); + } + + if (msg->ce_mask & QUEUE_MSG_ATTR_PHYSOUTDEV) { + if (link_cache) + nl_dump(p, "PHYSOUT=%s ", + rtnl_link_i2name(link_cache, + msg->queue_msg_physoutdev, + buf, sizeof(buf))); + else + nl_dump(p, "PHYSOUT=%d ", msg->queue_msg_physoutdev); + } + + if (msg->ce_mask & QUEUE_MSG_ATTR_HWADDR) { + int i; + + nl_dump(p, "MAC"); + for (i = 0; i < msg->queue_msg_hwaddr_len; i++) + nl_dump(p, "%c%02x", i?':':'=', + msg->queue_msg_hwaddr[i]); + nl_dump(p, " "); + } + + if (msg->ce_mask & QUEUE_MSG_ATTR_FAMILY) + nl_dump(p, "FAMILY=%s ", + nl_af2str(msg->queue_msg_family, buf, sizeof(buf))); + + if (msg->ce_mask & QUEUE_MSG_ATTR_HWPROTO) + nl_dump(p, "HWPROTO=%s ", + nl_ether_proto2str(ntohs(msg->queue_msg_hwproto), + buf, sizeof(buf))); + + if (msg->ce_mask & QUEUE_MSG_ATTR_HOOK) + nl_dump(p, "HOOK=%s ", + nfnl_inet_hook2str(msg->queue_msg_hook, + buf, sizeof(buf))); + + if (msg->ce_mask & QUEUE_MSG_ATTR_MARK) + nl_dump(p, "MARK=%d ", msg->queue_msg_mark); + + if (msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD) + nl_dump(p, "PAYLOADLEN=%d ", msg->queue_msg_payload_len); + + if (msg->ce_mask & QUEUE_MSG_ATTR_PACKETID) + nl_dump(p, "PACKETID=%u ", msg->queue_msg_packetid); + + if (msg->ce_mask & QUEUE_MSG_ATTR_VERDICT) + nl_dump(p, "VERDICT=%s ", + nfnl_verdict2str(msg->queue_msg_verdict, + buf, sizeof(buf))); + + nl_dump(p, "\n"); + + if (link_cache) + nl_cache_put(link_cache); +} + +/** + * @name Allocation/Freeing + * @{ + */ + +struct nfnl_queue_msg *nfnl_queue_msg_alloc(void) +{ + return (struct nfnl_queue_msg *) nl_object_alloc(&queue_msg_obj_ops); +} + +void nfnl_queue_msg_get(struct nfnl_queue_msg *msg) +{ + nl_object_get((struct nl_object *) msg); +} + +void nfnl_queue_msg_put(struct nfnl_queue_msg *msg) +{ + nl_object_put((struct nl_object *) msg); +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ + +void nfnl_queue_msg_set_group(struct nfnl_queue_msg *msg, uint16_t group) +{ + msg->queue_msg_group = group; + msg->ce_mask |= QUEUE_MSG_ATTR_GROUP; +} + +int nfnl_queue_msg_test_group(const struct nfnl_queue_msg *msg) +{ + return !!(msg->ce_mask & QUEUE_MSG_ATTR_GROUP); +} + +uint16_t nfnl_queue_msg_get_group(const struct nfnl_queue_msg *msg) +{ + return msg->queue_msg_group; +} + +/** +* Set the protocol family +* @arg msg NF queue message +* @arg family AF_XXX address family example: AF_INET, AF_UNIX, etc +*/ +void nfnl_queue_msg_set_family(struct nfnl_queue_msg *msg, uint8_t family) +{ + msg->queue_msg_family = family; + msg->ce_mask |= QUEUE_MSG_ATTR_FAMILY; +} + +int nfnl_queue_msg_test_family(const struct nfnl_queue_msg *msg) +{ + return !!(msg->ce_mask & QUEUE_MSG_ATTR_FAMILY); +} + +uint8_t nfnl_queue_msg_get_family(const struct nfnl_queue_msg *msg) +{ + if (msg->ce_mask & QUEUE_MSG_ATTR_FAMILY) + return msg->queue_msg_family; + else + return AF_UNSPEC; +} + +void nfnl_queue_msg_set_packetid(struct nfnl_queue_msg *msg, uint32_t packetid) +{ + msg->queue_msg_packetid = packetid; + msg->ce_mask |= QUEUE_MSG_ATTR_PACKETID; +} + +int nfnl_queue_msg_test_packetid(const struct nfnl_queue_msg *msg) +{ + return !!(msg->ce_mask & QUEUE_MSG_ATTR_PACKETID); +} + +uint32_t nfnl_queue_msg_get_packetid(const struct nfnl_queue_msg *msg) +{ + return msg->queue_msg_packetid; +} + +void nfnl_queue_msg_set_hwproto(struct nfnl_queue_msg *msg, uint16_t hwproto) +{ + msg->queue_msg_hwproto = hwproto; + msg->ce_mask |= QUEUE_MSG_ATTR_HWPROTO; +} + +int nfnl_queue_msg_test_hwproto(const struct nfnl_queue_msg *msg) +{ + return !!(msg->ce_mask & QUEUE_MSG_ATTR_HWPROTO); +} + +uint16_t nfnl_queue_msg_get_hwproto(const struct nfnl_queue_msg *msg) +{ + return msg->queue_msg_hwproto; +} + +void nfnl_queue_msg_set_hook(struct nfnl_queue_msg *msg, uint8_t hook) +{ + msg->queue_msg_hook = hook; + msg->ce_mask |= QUEUE_MSG_ATTR_HOOK; +} + +int nfnl_queue_msg_test_hook(const struct nfnl_queue_msg *msg) +{ + return !!(msg->ce_mask & QUEUE_MSG_ATTR_HOOK); +} + +uint8_t nfnl_queue_msg_get_hook(const struct nfnl_queue_msg *msg) +{ + return msg->queue_msg_hook; +} + +void nfnl_queue_msg_set_mark(struct nfnl_queue_msg *msg, uint32_t mark) +{ + msg->queue_msg_mark = mark; + msg->ce_mask |= QUEUE_MSG_ATTR_MARK; +} + +int nfnl_queue_msg_test_mark(const struct nfnl_queue_msg *msg) +{ + return !!(msg->ce_mask & QUEUE_MSG_ATTR_MARK); +} + +uint32_t nfnl_queue_msg_get_mark(const struct nfnl_queue_msg *msg) +{ + return msg->queue_msg_mark; +} + +void nfnl_queue_msg_set_timestamp(struct nfnl_queue_msg *msg, + struct timeval *tv) +{ + msg->queue_msg_timestamp.tv_sec = tv->tv_sec; + msg->queue_msg_timestamp.tv_usec = tv->tv_usec; + msg->ce_mask |= QUEUE_MSG_ATTR_TIMESTAMP; +} + +int nfnl_queue_msg_test_timestamp(const struct nfnl_queue_msg *msg) +{ + return !!(msg->ce_mask & QUEUE_MSG_ATTR_TIMESTAMP); +} + +const struct timeval *nfnl_queue_msg_get_timestamp(const struct nfnl_queue_msg *msg) +{ + if (!(msg->ce_mask & QUEUE_MSG_ATTR_TIMESTAMP)) + return NULL; + return &msg->queue_msg_timestamp; +} + +void nfnl_queue_msg_set_indev(struct nfnl_queue_msg *msg, uint32_t indev) +{ + msg->queue_msg_indev = indev; + msg->ce_mask |= QUEUE_MSG_ATTR_INDEV; +} + +int nfnl_queue_msg_test_indev(const struct nfnl_queue_msg *msg) +{ + return !!(msg->ce_mask & QUEUE_MSG_ATTR_INDEV); +} + +uint32_t nfnl_queue_msg_get_indev(const struct nfnl_queue_msg *msg) +{ + return msg->queue_msg_indev; +} + +void nfnl_queue_msg_set_outdev(struct nfnl_queue_msg *msg, uint32_t outdev) +{ + msg->queue_msg_outdev = outdev; + msg->ce_mask |= QUEUE_MSG_ATTR_OUTDEV; +} + +int nfnl_queue_msg_test_outdev(const struct nfnl_queue_msg *msg) +{ + return !!(msg->ce_mask & QUEUE_MSG_ATTR_OUTDEV); +} + +uint32_t nfnl_queue_msg_get_outdev(const struct nfnl_queue_msg *msg) +{ + return msg->queue_msg_outdev; +} + +void nfnl_queue_msg_set_physindev(struct nfnl_queue_msg *msg, + uint32_t physindev) +{ + msg->queue_msg_physindev = physindev; + msg->ce_mask |= QUEUE_MSG_ATTR_PHYSINDEV; +} + +int nfnl_queue_msg_test_physindev(const struct nfnl_queue_msg *msg) +{ + return !!(msg->ce_mask & QUEUE_MSG_ATTR_PHYSINDEV); +} + +uint32_t nfnl_queue_msg_get_physindev(const struct nfnl_queue_msg *msg) +{ + return msg->queue_msg_physindev; +} + +void nfnl_queue_msg_set_physoutdev(struct nfnl_queue_msg *msg, + uint32_t physoutdev) +{ + msg->queue_msg_physoutdev = physoutdev; + msg->ce_mask |= QUEUE_MSG_ATTR_PHYSOUTDEV; +} + +int nfnl_queue_msg_test_physoutdev(const struct nfnl_queue_msg *msg) +{ + return !!(msg->ce_mask & QUEUE_MSG_ATTR_PHYSOUTDEV); +} + +uint32_t nfnl_queue_msg_get_physoutdev(const struct nfnl_queue_msg *msg) +{ + return msg->queue_msg_physoutdev; +} + +void nfnl_queue_msg_set_hwaddr(struct nfnl_queue_msg *msg, uint8_t *hwaddr, + int len) +{ + if (len > sizeof(msg->queue_msg_hwaddr)) + len = sizeof(msg->queue_msg_hwaddr); + + msg->queue_msg_hwaddr_len = len; + memcpy(msg->queue_msg_hwaddr, hwaddr, len); + msg->ce_mask |= QUEUE_MSG_ATTR_HWADDR; +} + +int nfnl_queue_msg_test_hwaddr(const struct nfnl_queue_msg *msg) +{ + return !!(msg->ce_mask & QUEUE_MSG_ATTR_HWADDR); +} + +const uint8_t *nfnl_queue_msg_get_hwaddr(const struct nfnl_queue_msg *msg, + int *len) +{ + if (!(msg->ce_mask & QUEUE_MSG_ATTR_HWADDR)) { + *len = 0; + return NULL; + } + + *len = msg->queue_msg_hwaddr_len; + return msg->queue_msg_hwaddr; +} + +int nfnl_queue_msg_set_payload(struct nfnl_queue_msg *msg, uint8_t *payload, + int len) +{ + free(msg->queue_msg_payload); + msg->queue_msg_payload = malloc(len); + if (!msg->queue_msg_payload) + return -NLE_NOMEM; + + memcpy(msg->queue_msg_payload, payload, len); + msg->queue_msg_payload_len = len; + msg->ce_mask |= QUEUE_MSG_ATTR_PAYLOAD; + return 0; +} + +int nfnl_queue_msg_test_payload(const struct nfnl_queue_msg *msg) +{ + return !!(msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD); +} + +const void *nfnl_queue_msg_get_payload(const struct nfnl_queue_msg *msg, int *len) +{ + if (!(msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD)) { + *len = 0; + return NULL; + } + + *len = msg->queue_msg_payload_len; + return msg->queue_msg_payload; +} + +/** +* Return the number of items matching a filter in the cache +* @arg msg queue msg +* @arg verdict NF_DROP, NF_ACCEPT, NF_REPEAT, etc +*/ +void nfnl_queue_msg_set_verdict(struct nfnl_queue_msg *msg, + unsigned int verdict) +{ + msg->queue_msg_verdict = verdict; + msg->ce_mask |= QUEUE_MSG_ATTR_VERDICT; +} + +int nfnl_queue_msg_test_verdict(const struct nfnl_queue_msg *msg) +{ + return !!(msg->ce_mask & QUEUE_MSG_ATTR_VERDICT); +} + +unsigned int nfnl_queue_msg_get_verdict(const struct nfnl_queue_msg *msg) +{ + return msg->queue_msg_verdict; +} + +static const struct trans_tbl nfnl_queue_msg_attrs[] = { + __ADD(QUEUE_MSG_ATTR_GROUP, group) + __ADD(QUEUE_MSG_ATTR_FAMILY, family) + __ADD(QUEUE_MSG_ATTR_PACKETID, packetid) + __ADD(QUEUE_MSG_ATTR_HWPROTO, hwproto) + __ADD(QUEUE_MSG_ATTR_HOOK, hook) + __ADD(QUEUE_MSG_ATTR_MARK, mark) + __ADD(QUEUE_MSG_ATTR_TIMESTAMP, timestamp) + __ADD(QUEUE_MSG_ATTR_INDEV, indev) + __ADD(QUEUE_MSG_ATTR_OUTDEV, outdev) + __ADD(QUEUE_MSG_ATTR_PHYSINDEV, physindev) + __ADD(QUEUE_MSG_ATTR_PHYSOUTDEV, physoutdev) + __ADD(QUEUE_MSG_ATTR_HWADDR, hwaddr) + __ADD(QUEUE_MSG_ATTR_PAYLOAD, payload) + __ADD(QUEUE_MSG_ATTR_VERDICT, verdict) +}; + +static char *nfnl_queue_msg_attrs2str(int attrs, char *buf, size_t len) +{ + return __flags2str(attrs, buf, len, nfnl_queue_msg_attrs, + ARRAY_SIZE(nfnl_queue_msg_attrs)); +} + +/** @} */ + +struct nl_object_ops queue_msg_obj_ops = { + .oo_name = "netfilter/queuemsg", + .oo_size = sizeof(struct nfnl_queue_msg), + .oo_free_data = nfnl_queue_msg_free_data, + .oo_clone = nfnl_queue_msg_clone, + .oo_dump = { + [NL_DUMP_LINE] = nfnl_queue_msg_dump, + [NL_DUMP_DETAILS] = nfnl_queue_msg_dump, + [NL_DUMP_STATS] = nfnl_queue_msg_dump, + }, + .oo_attrs2str = nfnl_queue_msg_attrs2str, +}; + +/** @} */ diff --git a/lib/netfilter/queue_obj.c b/lib/netfilter/queue_obj.c new file mode 100644 index 0000000..5edcc68 --- /dev/null +++ b/lib/netfilter/queue_obj.c @@ -0,0 +1,215 @@ +/* + * lib/netfilter/queue_obj.c Netfilter Queue + * + * 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) 2007, 2008 Patrick McHardy + */ + +/** + * @ingroup nfnl + * @defgroup queue Queue + * @brief + * @{ + */ + +#include +#include +#include + +/** @cond SKIP */ +#define QUEUE_ATTR_GROUP (1UL << 0) +#define QUEUE_ATTR_MAXLEN (1UL << 1) +#define QUEUE_ATTR_COPY_MODE (1UL << 2) +#define QUEUE_ATTR_COPY_RANGE (1UL << 3) +/** @endcond */ + + +static void nfnl_queue_dump(struct nl_object *a, struct nl_dump_params *p) +{ + struct nfnl_queue *queue = (struct nfnl_queue *) a; + char buf[64]; + + nl_new_line(p); + + if (queue->ce_mask & QUEUE_ATTR_GROUP) + nl_dump(p, "group=%u ", queue->queue_group); + + if (queue->ce_mask & QUEUE_ATTR_MAXLEN) + nl_dump(p, "maxlen=%u ", queue->queue_maxlen); + + if (queue->ce_mask & QUEUE_ATTR_COPY_MODE) + nl_dump(p, "copy_mode=%s ", + nfnl_queue_copy_mode2str(queue->queue_copy_mode, + buf, sizeof(buf))); + + if (queue->ce_mask & QUEUE_ATTR_COPY_RANGE) + nl_dump(p, "copy_range=%u ", queue->queue_copy_range); + + nl_dump(p, "\n"); +} + +static const struct trans_tbl copy_modes[] = { + __ADD(NFNL_QUEUE_COPY_NONE, none) + __ADD(NFNL_QUEUE_COPY_META, meta) + __ADD(NFNL_QUEUE_COPY_PACKET, packet) +}; + +char *nfnl_queue_copy_mode2str(enum nfnl_queue_copy_mode copy_mode, char *buf, + size_t len) +{ + return __type2str(copy_mode, buf, len, copy_modes, + ARRAY_SIZE(copy_modes)); +} + +enum nfnl_queue_copy_mode nfnl_queue_str2copy_mode(const char *name) +{ + return __str2type(name, copy_modes, ARRAY_SIZE(copy_modes)); +} + +/** + * @name Allocation/Freeing + * @{ + */ + +struct nfnl_queue *nfnl_queue_alloc(void) +{ + return (struct nfnl_queue *) nl_object_alloc(&queue_obj_ops); +} + +void nfnl_queue_get(struct nfnl_queue *queue) +{ + nl_object_get((struct nl_object *) queue); +} + +void nfnl_queue_put(struct nfnl_queue *queue) +{ + nl_object_put((struct nl_object *) queue); +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ + +void nfnl_queue_set_group(struct nfnl_queue *queue, uint16_t group) +{ + queue->queue_group = group; + queue->ce_mask |= QUEUE_ATTR_GROUP; +} + +int nfnl_queue_test_group(const struct nfnl_queue *queue) +{ + return !!(queue->ce_mask & QUEUE_ATTR_GROUP); +} + +uint16_t nfnl_queue_get_group(const struct nfnl_queue *queue) +{ + return queue->queue_group; +} + +void nfnl_queue_set_maxlen(struct nfnl_queue *queue, uint32_t maxlen) +{ + queue->queue_maxlen = maxlen; + queue->ce_mask |= QUEUE_ATTR_MAXLEN; +} + +int nfnl_queue_test_maxlen(const struct nfnl_queue *queue) +{ + return !!(queue->ce_mask & QUEUE_ATTR_MAXLEN); +} + +uint32_t nfnl_queue_get_maxlen(const struct nfnl_queue *queue) +{ + return queue->queue_maxlen; +} + +void nfnl_queue_set_copy_mode(struct nfnl_queue *queue, enum nfnl_queue_copy_mode mode) +{ + queue->queue_copy_mode = mode; + queue->ce_mask |= QUEUE_ATTR_COPY_MODE; +} + +int nfnl_queue_test_copy_mode(const struct nfnl_queue *queue) +{ + return !!(queue->ce_mask & QUEUE_ATTR_COPY_MODE); +} + +enum nfnl_queue_copy_mode nfnl_queue_get_copy_mode(const struct nfnl_queue *queue) +{ + return queue->queue_copy_mode; +} + +void nfnl_queue_set_copy_range(struct nfnl_queue *queue, uint32_t copy_range) +{ + queue->queue_copy_range = copy_range; + queue->ce_mask |= QUEUE_ATTR_COPY_RANGE; +} + +int nfnl_queue_test_copy_range(const struct nfnl_queue *queue) +{ + return !!(queue->ce_mask & QUEUE_ATTR_COPY_RANGE); +} + +uint32_t nfnl_queue_get_copy_range(const struct nfnl_queue *queue) +{ + return queue->queue_copy_range; +} + +static int nfnl_queue_compare(struct nl_object *_a, struct nl_object *_b, + uint32_t attrs, int flags) +{ + struct nfnl_queue *a = (struct nfnl_queue *) _a; + struct nfnl_queue *b = (struct nfnl_queue *) _b; + int diff = 0; + +#define NFNL_QUEUE_DIFF(ATTR, EXPR) \ + ATTR_DIFF(attrs, QUEUE_ATTR_##ATTR, a, b, EXPR) +#define NFNL_QUEUE_DIFF_VAL(ATTR, FIELD) \ + NFNL_QUEUE_DIFF(ATTR, a->FIELD != b->FIELD) + + diff |= NFNL_QUEUE_DIFF_VAL(GROUP, queue_group); + diff |= NFNL_QUEUE_DIFF_VAL(MAXLEN, queue_maxlen); + diff |= NFNL_QUEUE_DIFF_VAL(COPY_MODE, queue_copy_mode); + diff |= NFNL_QUEUE_DIFF_VAL(COPY_RANGE, queue_copy_range); + +#undef NFNL_QUEUE_DIFF +#undef NFNL_QUEUE_DIFF_VAL + + return diff; +} + +static const struct trans_tbl nfnl_queue_attrs[] = { + __ADD(QUEUE_ATTR_GROUP, group) + __ADD(QUEUE_ATTR_MAXLEN, maxlen) + __ADD(QUEUE_ATTR_COPY_MODE, copy_mode) + __ADD(QUEUE_ATTR_COPY_RANGE, copy_range) +}; + +static char *nfnl_queue_attrs2str(int attrs, char *buf, size_t len) +{ + return __flags2str(attrs, buf, len, nfnl_queue_attrs, + ARRAY_SIZE(nfnl_queue_attrs)); +} + +/** @} */ + +struct nl_object_ops queue_obj_ops = { + .oo_name = "netfilter/queue", + .oo_size = sizeof(struct nfnl_queue), + .oo_dump = { + [NL_DUMP_LINE] = nfnl_queue_dump, + [NL_DUMP_DETAILS] = nfnl_queue_dump, + [NL_DUMP_STATS] = nfnl_queue_dump, + }, + .oo_compare = nfnl_queue_compare, + .oo_attrs2str = nfnl_queue_attrs2str, + .oo_id_attrs = QUEUE_ATTR_GROUP, +}; + +/** @} */ diff --git a/lib/nl.c b/lib/nl.c new file mode 100644 index 0000000..565747a --- /dev/null +++ b/lib/nl.c @@ -0,0 +1,1124 @@ +/* + * lib/nl.c Core Netlink Interface + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +/** + * @defgroup core Core Library (libnl) + * + * Socket handling, connection management, sending and receiving of data, + * message construction and parsing, object caching system, ... + * + * This is the API reference of the core library. It is not meant as a guide + * but as a reference. Please refer to the core library guide for detailed + * documentation on the library architecture and examples: + * + * * @ref_asciidoc{core,_,Netlink Core Library Development Guide} + * + * + * @{ + */ + +#include +#include +#include +#include +#include +#include + +/** + * @defgroup core_types Data Types + * + * Core library data types + * @{ + * @} + * + * @defgroup send_recv Send & Receive Data + * + * Connection management, sending & receiving of data + * + * Related sections in the development guide: + * - @core_doc{core_send_recv, Sending & Receiving} + * - @core_doc{core_sockets, Sockets} + * + * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ + */ + +/** + * @name Connection Management + * @{ + */ + +/** + * Create file descriptor and bind socket. + * @arg sk Netlink socket (required) + * @arg protocol Netlink protocol to use (required) + * + * Creates a new Netlink socket using `socket()` and binds the socket to the + * protocol and local port specified in the `sk` socket object. Fails if + * the socket is already connected. + * + * @note If available, the `close-on-exec` (`SOCK_CLOEXEC`) feature is enabled + * automatically on the new file descriptor. This causes the socket to + * be closed automatically if any of the `exec` family functions succeed. + * This is essential for multi threaded programs. + * + * @see nl_socket_alloc() + * @see nl_close() + * + * @return 0 on success or a negative error code. + * + * @retval -NLE_BAD_SOCK Socket is already connected + */ +int nl_connect(struct nl_sock *sk, int protocol) +{ + int err, flags = 0; + socklen_t addrlen; + +#ifdef SOCK_CLOEXEC + flags |= SOCK_CLOEXEC; +#endif + + if (sk->s_fd != -1) + return -NLE_BAD_SOCK; + + sk->s_fd = socket(AF_NETLINK, SOCK_RAW | flags, protocol); + if (sk->s_fd < 0) { + err = -nl_syserr2nlerr(errno); + goto errout; + } + + if (!(sk->s_flags & NL_SOCK_BUFSIZE_SET)) { + err = nl_socket_set_buffer_size(sk, 0, 0); + if (err < 0) + goto errout; + } + + err = bind(sk->s_fd, (struct sockaddr*) &sk->s_local, + sizeof(sk->s_local)); + if (err < 0) { + err = -nl_syserr2nlerr(errno); + goto errout; + } + + addrlen = sizeof(sk->s_local); + err = getsockname(sk->s_fd, (struct sockaddr *) &sk->s_local, + &addrlen); + if (err < 0) { + err = -nl_syserr2nlerr(errno); + goto errout; + } + + if (addrlen != sizeof(sk->s_local)) { + err = -NLE_NOADDR; + goto errout; + } + + if (sk->s_local.nl_family != AF_NETLINK) { + err = -NLE_AF_NOSUPPORT; + goto errout; + } + + sk->s_proto = protocol; + + return 0; +errout: + if (sk->s_fd != -1) { + close(sk->s_fd); + sk->s_fd = -1; + } + + return err; +} + +/** + * Close Netlink socket + * @arg sk Netlink socket (required) + * + * Closes the Netlink socket using `close()`. + * + * @note The socket is closed automatically if a `struct nl_sock` object is + * freed using `nl_socket_free()`. + * + * @see nl_connect() + */ +void nl_close(struct nl_sock *sk) +{ + if (sk->s_fd >= 0) { + close(sk->s_fd); + sk->s_fd = -1; + } + + sk->s_proto = 0; +} + +/** @} */ + +/** + * @name Send + * @{ + */ + +/** + * Transmit raw data over Netlink socket. + * @arg sk Netlink socket (required) + * @arg buf Buffer carrying data to send (required) + * @arg size Size of buffer (required) + * + * Transmits "raw" data over the specified Netlink socket. Unlike the other + * transmit functions it does not modify the data in any way. It directly + * passes the buffer \c buf of \c size to sendto(). + * + * The message is addressed to the peer as specified in the socket by either + * the nl_socket_set_peer_port() or nl_socket_set_peer_groups() function. + * + * @note Because there is no indication on the message boundaries of the data + * being sent, the \c NL_CB_MSG_OUT callback handler will not be invoked + * for data that is being sent using this function. + * + * @see nl_socket_set_peer_port() + * @see nl_socket_set_peer_groups() + * @see nl_sendmsg() + * + * @return Number of bytes sent or a negative error code. + */ +int nl_sendto(struct nl_sock *sk, void *buf, size_t size) +{ + int ret; + + if (!buf) + return -NLE_INVAL; + + if (sk->s_fd < 0) + return -NLE_BAD_SOCK; + + ret = sendto(sk->s_fd, buf, size, 0, (struct sockaddr *) + &sk->s_peer, sizeof(sk->s_peer)); + if (ret < 0) + return -nl_syserr2nlerr(errno); + + return ret; +} + +/** + * Transmit Netlink message using sendmsg() + * @arg sk Netlink socket (required) + * @arg msg Netlink message to be sent (required) + * @arg hdr sendmsg() message header (required) + * + * Transmits the message specified in \c hdr over the Netlink socket using the + * sendmsg() system call. + * + * @attention + * The `msg` argument will *not* be used to derive the message payload that + * is being sent out. The `msg` argument is *only* passed on to the + * `NL_CB_MSG_OUT` callback. The caller is responsible to initialize the + * `hdr` struct properly and have it point to the message payload and + * socket address. + * + * @note + * This function uses `nlmsg_set_src()` to modify the `msg` argument prior to + * invoking the `NL_CB_MSG_OUT` callback to provide the local port number. + * + * @callback This function triggers the `NL_CB_MSG_OUT` callback. + * + * @attention + * Think twice before using this function. It provides a low level access to + * the Netlink socket. Among other limitations, it does not add credentials + * even if enabled or respect the destination address specified in the `msg` + * object. + * + * @see nl_socket_set_local_port() + * @see nl_send_auto() + * @see nl_send_iovec() + * + * @return Number of bytes sent on success or a negative error code. + * + * @lowlevel + */ +int nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr) +{ + struct nl_cb *cb; + int ret; + + if (sk->s_fd < 0) + return -NLE_BAD_SOCK; + + nlmsg_set_src(msg, &sk->s_local); + + cb = sk->s_cb; + if (cb->cb_set[NL_CB_MSG_OUT]) + if ((ret = nl_cb_call(cb, NL_CB_MSG_OUT, msg)) != NL_OK) + return ret; + + ret = sendmsg(sk->s_fd, hdr, 0); + if (ret < 0) + return -nl_syserr2nlerr(errno); + + NL_DBG(4, "sent %d bytes\n", ret); + return ret; +} + + +/** + * Transmit Netlink message (taking IO vector) + * @arg sk Netlink socket (required) + * @arg msg Netlink message to be sent (required) + * @arg iov IO vector to be sent (required) + * @arg iovlen Number of struct iovec to be sent (required) + * + * This function is identical to nl_send() except that instead of taking a + * `struct nl_msg` object it takes an IO vector. Please see the description + * of `nl_send()`. + * + * @callback This function triggers the `NL_CB_MSG_OUT` callback. + * + * @see nl_send() + * + * @return Number of bytes sent on success or a negative error code. + * + * @lowlevel + */ +int nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, unsigned iovlen) +{ + struct sockaddr_nl *dst; + struct ucred *creds; + struct msghdr hdr = { + .msg_name = (void *) &sk->s_peer, + .msg_namelen = sizeof(struct sockaddr_nl), + .msg_iov = iov, + .msg_iovlen = iovlen, + }; + + /* Overwrite destination if specified in the message itself, defaults + * to the peer address of the socket. + */ + dst = nlmsg_get_dst(msg); + if (dst->nl_family == AF_NETLINK) + hdr.msg_name = dst; + + /* Add credentials if present. */ + creds = nlmsg_get_creds(msg); + if (creds != NULL) { + char buf[CMSG_SPACE(sizeof(struct ucred))]; + struct cmsghdr *cmsg; + + hdr.msg_control = buf; + hdr.msg_controllen = sizeof(buf); + + cmsg = CMSG_FIRSTHDR(&hdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_CREDENTIALS; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); + memcpy(CMSG_DATA(cmsg), creds, sizeof(struct ucred)); + } + + return nl_sendmsg(sk, msg, &hdr); +} + +/** + * Transmit Netlink message + * @arg sk Netlink socket (required) + * @arg msg Netlink message (required) + * + * Transmits the Netlink message `msg` over the Netlink socket using the + * `sendmsg()` system call. This function is based on `nl_send_iovec()` but + * takes care of initializing a `struct iovec` based on the `msg` object. + * + * The message is addressed to the peer as specified in the socket by either + * the nl_socket_set_peer_port() or nl_socket_set_peer_groups() function. + * The peer address can be overwritten by specifying an address in the `msg` + * object using nlmsg_set_dst(). + * + * If present in the `msg`, credentials set by the nlmsg_set_creds() function + * are added to the control buffer of the message. + * + * @par Overwriting Capability: + * Calls to this function can be overwritten by providing an alternative using + * the nl_cb_overwrite_send() function. + * + * @callback This function triggers the `NL_CB_MSG_OUT` callback. + * + * @attention + * Unlike `nl_send_auto()`, this function does *not* finalize the message in + * terms of automatically adding needed flags or filling out port numbers. + * + * @see nl_send_auto() + * @see nl_send_iovec() + * @see nl_socket_set_peer_port() + * @see nl_socket_set_peer_groups() + * @see nlmsg_set_dst() + * @see nlmsg_set_creds() + * @see nl_cb_overwrite_send() + * + * @return Number of bytes sent on success or a negative error code. +*/ +int nl_send(struct nl_sock *sk, struct nl_msg *msg) +{ + struct nl_cb *cb = sk->s_cb; + + if (cb->cb_send_ow) + return cb->cb_send_ow(sk, msg); + else { + struct iovec iov = { + .iov_base = (void *) nlmsg_hdr(msg), + .iov_len = nlmsg_hdr(msg)->nlmsg_len, + }; + + return nl_send_iovec(sk, msg, &iov, 1); + } +} + +/** + * Finalize Netlink message + * @arg sk Netlink socket (required) + * @arg msg Netlink message (required) + * + * This function finalizes a Netlink message by completing the message with + * desirable flags and values depending on the socket configuration. + * + * - If not yet filled out, the source address of the message (`nlmsg_pid`) + * will be set to the local port number of the socket. + * - If not yet specified, the next available sequence number is assigned + * to the message (`nlmsg_seq`). + * - If not yet specified, the protocol field of the message will be set to + * the protocol field of the socket. + * - The `NLM_F_REQUEST` Netlink message flag will be set. + * - The `NLM_F_ACK` flag will be set if Auto-ACK mode is enabled on the + * socket. + */ +void nl_complete_msg(struct nl_sock *sk, struct nl_msg *msg) +{ + struct nlmsghdr *nlh; + + nlh = nlmsg_hdr(msg); + if (nlh->nlmsg_pid == NL_AUTO_PORT) + nlh->nlmsg_pid = sk->s_local.nl_pid; + + if (nlh->nlmsg_seq == NL_AUTO_SEQ) + nlh->nlmsg_seq = sk->s_seq_next++; + + if (msg->nm_protocol == -1) + msg->nm_protocol = sk->s_proto; + + nlh->nlmsg_flags |= NLM_F_REQUEST; + + if (!(sk->s_flags & NL_NO_AUTO_ACK)) + nlh->nlmsg_flags |= NLM_F_ACK; +} + +/** + * Finalize and transmit Netlink message + * @arg sk Netlink socket (required) + * @arg msg Netlink message (required) + * + * Finalizes the message by passing it to `nl_complete_msg()` and transmits it + * by passing it to `nl_send()`. + * + * @callback This function triggers the `NL_CB_MSG_OUT` callback. + * + * @see nl_complete_msg() + * @see nl_send() + * + * @return Number of bytes sent or a negative error code. + */ +int nl_send_auto(struct nl_sock *sk, struct nl_msg *msg) +{ + nl_complete_msg(sk, msg); + + return nl_send(sk, msg); +} + +/** + * Finalize and transmit Netlink message and wait for ACK or error message + * @arg sk Netlink socket (required) + * @arg msg Netlink message (required) + * + * Passes the `msg` to `nl_send_auto()` to finalize and transmit it. Frees the + * message and waits (sleeps) for the ACK or error message to be received. + * + * @attention + * Disabling Auto-ACK (nl_socket_disable_auto_ack()) will cause this function + * to return immediately after transmitting the message. However, the peer may + * still be returning an error message in response to the request. It is the + * responsibility of the caller to handle such messages. + * + * @callback This function triggers the `NL_CB_MSG_OUT` callback. + * + * @attention + * This function frees the `msg` object after transmitting it by calling + * `nlmsg_free()`. + * + * @see nl_send_auto(). + * @see nl_wait_for_ack() + * + * @return 0 on success or a negative error code. + */ +int nl_send_sync(struct nl_sock *sk, struct nl_msg *msg) +{ + int err; + + err = nl_send_auto(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +/** + * Construct and transmit a Netlink message + * @arg sk Netlink socket (required) + * @arg type Netlink message type (required) + * @arg flags Netlink message flags (optional) + * @arg buf Data buffer (optional) + * @arg size Size of data buffer (optional) + * + * Allocates a new Netlink message based on `type` and `flags`. If `buf` + * points to payload of length `size` that payload will be appended to the + * message. + * + * Sends out the message using `nl_send_auto()` and frees the message + * afterwards. + * + * @see nl_send_auto() + * + * @return Number of characters sent on success or a negative error code. + * @retval -NLE_NOMEM Unable to allocate Netlink message + */ +int nl_send_simple(struct nl_sock *sk, int type, int flags, void *buf, + size_t size) +{ + int err; + struct nl_msg *msg; + + msg = nlmsg_alloc_simple(type, flags); + if (!msg) + return -NLE_NOMEM; + + if (buf && size) { + err = nlmsg_append(msg, buf, size, NLMSG_ALIGNTO); + if (err < 0) + goto errout; + } + + err = nl_send_auto(sk, msg); +errout: + nlmsg_free(msg); + + return err; +} + +/** @} */ + +/** + * @name Receive + * @{ + */ + +/** + * Receive data from netlink socket + * @arg sk Netlink socket (required) + * @arg nla Netlink socket structure to hold address of peer (required) + * @arg buf Destination pointer for message content (required) + * @arg creds Destination pointer for credentials (optional) + * + * Receives data from a connected netlink socket using recvmsg() and returns + * the number of bytes read. The read data is stored in a newly allocated + * buffer that is assigned to \c *buf. The peer's netlink address will be + * stored in \c *nla. + * + * This function blocks until data is available to be read unless the socket + * has been put into non-blocking mode using nl_socket_set_nonblocking() in + * which case this function will return immediately with a return value of 0. + * + * The buffer size used when reading from the netlink socket and thus limiting + * the maximum size of a netlink message that can be read defaults to the size + * of a memory page (getpagesize()). The buffer size can be modified on a per + * socket level using the function nl_socket_set_msg_buf_size(). + * + * If message peeking is enabled using nl_socket_enable_msg_peek() the size of + * the message to be read will be determined using the MSG_PEEK flag prior to + * performing the actual read. This leads to an additional recvmsg() call for + * every read operation which has performance implications and is not + * recommended for high throughput protocols. + * + * An eventual interruption of the recvmsg() system call is automatically + * handled by retrying the operation. + * + * If receiving of credentials has been enabled using the function + * nl_socket_set_passcred(), this function will allocate a new struct ucred + * filled with the received credentials and assign it to \c *creds. The caller + * is responsible for freeing the buffer. + * + * @note The caller is responsible to free the returned data buffer and if + * enabled, the credentials buffer. + * + * @see nl_socket_set_nonblocking() + * @see nl_socket_set_msg_buf_size() + * @see nl_socket_enable_msg_peek() + * @see nl_socket_set_passcred() + * + * @return Number of bytes read, 0 on EOF, 0 on no data event (non-blocking + * mode), or a negative error code. + */ +int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla, + unsigned char **buf, struct ucred **creds) +{ + ssize_t n; + int flags = 0; + static int page_size = 0; + struct iovec iov; + struct msghdr msg = { + .msg_name = (void *) nla, + .msg_namelen = sizeof(struct sockaddr_nl), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + struct ucred* tmpcreds = NULL; + int retval = 0; + + if (!buf || !nla) + return -NLE_INVAL; + + if (sk->s_flags & NL_MSG_PEEK) + flags |= MSG_PEEK | MSG_TRUNC; + + if (page_size == 0) + page_size = getpagesize() * 4; + + iov.iov_len = sk->s_bufsize ? : page_size; + iov.iov_base = malloc(iov.iov_len); + + if (!iov.iov_base) { + retval = -NLE_NOMEM; + goto abort; + } + + if (creds && (sk->s_flags & NL_SOCK_PASSCRED)) { + msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred)); + msg.msg_control = malloc(msg.msg_controllen); + if (!msg.msg_control) { + retval = -NLE_NOMEM; + goto abort; + } + } +retry: + + n = recvmsg(sk->s_fd, &msg, flags); + if (!n) { + retval = 0; + goto abort; + } + if (n < 0) { + if (errno == EINTR) { + NL_DBG(3, "recvmsg() returned EINTR, retrying\n"); + goto retry; + } + retval = -nl_syserr2nlerr(errno); + goto abort; + } + + if (msg.msg_flags & MSG_CTRUNC) { + void *tmp; + msg.msg_controllen *= 2; + tmp = realloc(msg.msg_control, msg.msg_controllen); + if (!tmp) { + retval = -NLE_NOMEM; + goto abort; + } + msg.msg_control = tmp; + goto retry; + } + + if (iov.iov_len < n || (msg.msg_flags & MSG_TRUNC)) { + void *tmp; + /* Provided buffer is not long enough, enlarge it + * to size of n (which should be total length of the message) + * and try again. */ + iov.iov_len = n; + tmp = realloc(iov.iov_base, iov.iov_len); + if (!tmp) { + retval = -NLE_NOMEM; + goto abort; + } + iov.iov_base = tmp; + flags = 0; + goto retry; + } + + if (flags != 0) { + /* Buffer is big enough, do the actual reading */ + flags = 0; + goto retry; + } + + if (msg.msg_namelen != sizeof(struct sockaddr_nl)) { + retval = -NLE_NOADDR; + goto abort; + } + + if (creds && (sk->s_flags & NL_SOCK_PASSCRED)) { + struct cmsghdr *cmsg; + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level != SOL_SOCKET) + continue; + if (cmsg->cmsg_type != SCM_CREDENTIALS) + continue; + tmpcreds = malloc(sizeof(*tmpcreds)); + if (!tmpcreds) { + retval = -NLE_NOMEM; + goto abort; + } + memcpy(tmpcreds, CMSG_DATA(cmsg), sizeof(*tmpcreds)); + break; + } + } + + retval = n; +abort: + free(msg.msg_control); + + if (retval <= 0) { + free(iov.iov_base); + iov.iov_base = NULL; + free(tmpcreds); + tmpcreds = NULL; + } else + *buf = iov.iov_base; + + if (creds) + *creds = tmpcreds; + + return retval; +} + +/** @cond SKIP */ +#define NL_CB_CALL(cb, type, msg) \ +do { \ + err = nl_cb_call(cb, type, msg); \ + switch (err) { \ + case NL_OK: \ + err = 0; \ + break; \ + case NL_SKIP: \ + goto skip; \ + case NL_STOP: \ + goto stop; \ + default: \ + goto out; \ + } \ +} while (0) +/** @endcond */ + +static int recvmsgs(struct nl_sock *sk, struct nl_cb *cb) +{ + int n, err = 0, multipart = 0, interrupted = 0, nrecv = 0; + unsigned char *buf = NULL; + struct nlmsghdr *hdr; + + /* + nla is passed on to not only to nl_recv() but may also be passed + to a function pointer provided by the caller which may or may not + initialize the variable. Thomas Graf. + */ + struct sockaddr_nl nla = {0}; + struct nl_msg *msg = NULL; + struct ucred *creds = NULL; + +continue_reading: + NL_DBG(3, "Attempting to read from %p\n", sk); + if (cb->cb_recv_ow) + n = cb->cb_recv_ow(sk, &nla, &buf, &creds); + else + n = nl_recv(sk, &nla, &buf, &creds); + + if (n <= 0) + return n; + + NL_DBG(3, "recvmsgs(%p): Read %d bytes\n", sk, n); + + hdr = (struct nlmsghdr *) buf; + while (nlmsg_ok(hdr, n)) { + NL_DBG(3, "recvmsgs(%p): Processing valid message...\n", sk); + + nlmsg_free(msg); + msg = nlmsg_convert(hdr); + if (!msg) { + err = -NLE_NOMEM; + goto out; + } + + nlmsg_set_proto(msg, sk->s_proto); + nlmsg_set_src(msg, &nla); + if (creds) + nlmsg_set_creds(msg, creds); + + nrecv++; + + /* Raw callback is the first, it gives the most control + * to the user and he can do his very own parsing. */ + if (cb->cb_set[NL_CB_MSG_IN]) + NL_CB_CALL(cb, NL_CB_MSG_IN, msg); + + /* Sequence number checking. The check may be done by + * the user, otherwise a very simple check is applied + * enforcing strict ordering */ + if (cb->cb_set[NL_CB_SEQ_CHECK]) { + NL_CB_CALL(cb, NL_CB_SEQ_CHECK, msg); + + /* Only do sequence checking if auto-ack mode is enabled */ + } else if (!(sk->s_flags & NL_NO_AUTO_ACK)) { + if (hdr->nlmsg_seq != sk->s_seq_expect) { + if (cb->cb_set[NL_CB_INVALID]) + NL_CB_CALL(cb, NL_CB_INVALID, msg); + else { + err = -NLE_SEQ_MISMATCH; + goto out; + } + } + } + + if (hdr->nlmsg_type == NLMSG_DONE || + hdr->nlmsg_type == NLMSG_ERROR || + hdr->nlmsg_type == NLMSG_NOOP || + hdr->nlmsg_type == NLMSG_OVERRUN) { + /* We can't check for !NLM_F_MULTI since some netlink + * users in the kernel are broken. */ + sk->s_seq_expect++; + NL_DBG(3, "recvmsgs(%p): Increased expected " \ + "sequence number to %d\n", + sk, sk->s_seq_expect); + } + + if (hdr->nlmsg_flags & NLM_F_MULTI) + multipart = 1; + + if (hdr->nlmsg_flags & NLM_F_DUMP_INTR) { + if (cb->cb_set[NL_CB_DUMP_INTR]) + NL_CB_CALL(cb, NL_CB_DUMP_INTR, msg); + else { + /* + * We have to continue reading to clear + * all messages until a NLMSG_DONE is + * received and report the inconsistency. + */ + interrupted = 1; + } + } + + /* Other side wishes to see an ack for this message */ + if (hdr->nlmsg_flags & NLM_F_ACK) { + if (cb->cb_set[NL_CB_SEND_ACK]) + NL_CB_CALL(cb, NL_CB_SEND_ACK, msg); + else { + /* FIXME: implement */ + } + } + + /* messages terminates a multpart message, this is + * usually the end of a message and therefore we slip + * out of the loop by default. the user may overrule + * this action by skipping this packet. */ + if (hdr->nlmsg_type == NLMSG_DONE) { + multipart = 0; + if (cb->cb_set[NL_CB_FINISH]) + NL_CB_CALL(cb, NL_CB_FINISH, msg); + } + + /* Message to be ignored, the default action is to + * skip this message if no callback is specified. The + * user may overrule this action by returning + * NL_PROCEED. */ + else if (hdr->nlmsg_type == NLMSG_NOOP) { + if (cb->cb_set[NL_CB_SKIPPED]) + NL_CB_CALL(cb, NL_CB_SKIPPED, msg); + else + goto skip; + } + + /* Data got lost, report back to user. The default action is to + * quit parsing. The user may overrule this action by retuning + * NL_SKIP or NL_PROCEED (dangerous) */ + else if (hdr->nlmsg_type == NLMSG_OVERRUN) { + if (cb->cb_set[NL_CB_OVERRUN]) + NL_CB_CALL(cb, NL_CB_OVERRUN, msg); + else { + err = -NLE_MSG_OVERFLOW; + goto out; + } + } + + /* Message carries a nlmsgerr */ + else if (hdr->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *e = nlmsg_data(hdr); + + if (hdr->nlmsg_len < nlmsg_size(sizeof(*e))) { + /* Truncated error message, the default action + * is to stop parsing. The user may overrule + * this action by returning NL_SKIP or + * NL_PROCEED (dangerous) */ + if (cb->cb_set[NL_CB_INVALID]) + NL_CB_CALL(cb, NL_CB_INVALID, msg); + else { + err = -NLE_MSG_TRUNC; + goto out; + } + } else if (e->error) { + /* Error message reported back from kernel. */ + if (cb->cb_err) { + err = cb->cb_err(&nla, e, + cb->cb_err_arg); + if (err < 0) + goto out; + else if (err == NL_SKIP) + goto skip; + else if (err == NL_STOP) { + err = -nl_syserr2nlerr(e->error); + goto out; + } + } else { + err = -nl_syserr2nlerr(e->error); + goto out; + } + } else if (cb->cb_set[NL_CB_ACK]) + NL_CB_CALL(cb, NL_CB_ACK, msg); + } else { + /* Valid message (not checking for MULTIPART bit to + * get along with broken kernels. NL_SKIP has no + * effect on this. */ + if (cb->cb_set[NL_CB_VALID]) + NL_CB_CALL(cb, NL_CB_VALID, msg); + } +skip: + err = 0; + hdr = nlmsg_next(hdr, &n); + } + + nlmsg_free(msg); + free(buf); + free(creds); + buf = NULL; + msg = NULL; + creds = NULL; + + if (multipart) { + /* Multipart message not yet complete, continue reading */ + goto continue_reading; + } +stop: + err = 0; +out: + nlmsg_free(msg); + free(buf); + free(creds); + + if (interrupted) + err = -NLE_DUMP_INTR; + + if (!err) + err = nrecv; + + return err; +} + +/** + * Receive a set of messages from a netlink socket and report parsed messages + * @arg sk Netlink socket. + * @arg cb set of callbacks to control behaviour. + * + * This function is identical to nl_recvmsgs() to the point that it will + * return the number of parsed messages instead of 0 on success. + * + * @see nl_recvmsgs() + * + * @return Number of received messages or a negative error code from nl_recv(). + */ +int nl_recvmsgs_report(struct nl_sock *sk, struct nl_cb *cb) +{ + if (cb->cb_recvmsgs_ow) + return cb->cb_recvmsgs_ow(sk, cb); + else + return recvmsgs(sk, cb); +} + +/** + * Receive a set of messages from a netlink socket. + * @arg sk Netlink socket. + * @arg cb set of callbacks to control behaviour. + * + * Repeatedly calls nl_recv() or the respective replacement if provided + * by the application (see nl_cb_overwrite_recv()) and parses the + * received data as netlink messages. Stops reading if one of the + * callbacks returns NL_STOP or nl_recv returns either 0 or a negative error code. + * + * A non-blocking sockets causes the function to return immediately if + * no data is available. + * + * @see nl_recvmsgs_report() + * + * @return 0 on success or a negative error code from nl_recv(). + */ +int nl_recvmsgs(struct nl_sock *sk, struct nl_cb *cb) +{ + int err; + + if ((err = nl_recvmsgs_report(sk, cb)) > 0) + err = 0; + + return err; +} + +/** + * Receive a set of message from a netlink socket using handlers in nl_sock. + * @arg sk Netlink socket. + * + * Calls nl_recvmsgs() with the handlers configured in the netlink socket. + */ +int nl_recvmsgs_default(struct nl_sock *sk) +{ + return nl_recvmsgs(sk, sk->s_cb); + +} + +static int ack_wait_handler(struct nl_msg *msg, void *arg) +{ + return NL_STOP; +} + +/** + * Wait for ACK. + * @arg sk Netlink socket. + * @pre The netlink socket must be in blocking state. + * + * Waits until an ACK is received for the latest not yet acknowledged + * netlink message. + */ +int nl_wait_for_ack(struct nl_sock *sk) +{ + int err; + struct nl_cb *cb; + + cb = nl_cb_clone(sk->s_cb); + if (cb == NULL) + return -NLE_NOMEM; + + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, NULL); + err = nl_recvmsgs(sk, cb); + nl_cb_put(cb); + + return err; +} + +/** @cond SKIP */ +struct pickup_param +{ + int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *, + struct nlmsghdr *, struct nl_parser_param *); + struct nl_object *result; +}; + +static int __store_answer(struct nl_object *obj, struct nl_parser_param *p) +{ + struct pickup_param *pp = p->pp_arg; + /* + * the parser will put() the object at the end, expecting the cache + * to take the reference. + */ + nl_object_get(obj); + pp->result = obj; + + return 0; +} + +static int __pickup_answer(struct nl_msg *msg, void *arg) +{ + struct pickup_param *pp = arg; + struct nl_parser_param parse_arg = { + .pp_cb = __store_answer, + .pp_arg = pp, + }; + + return pp->parser(NULL, &msg->nm_src, msg->nm_nlh, &parse_arg); +} + +/** @endcond */ + +/** + * Pickup netlink answer, parse is and return object + * @arg sk Netlink socket + * @arg parser Parser function to parse answer + * @arg result Result pointer to return parsed object + * + * @return 0 on success or a negative error code. + */ +int nl_pickup(struct nl_sock *sk, + int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *, + struct nlmsghdr *, struct nl_parser_param *), + struct nl_object **result) +{ + struct nl_cb *cb; + int err; + struct pickup_param pp = { + .parser = parser, + }; + + cb = nl_cb_clone(sk->s_cb); + if (cb == NULL) + return -NLE_NOMEM; + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, __pickup_answer, &pp); + + err = nl_recvmsgs(sk, cb); + if (err < 0) + goto errout; + + *result = pp.result; +errout: + nl_cb_put(cb); + + return err; +} + +/** @} */ + +/** + * @name Deprecated + * @{ + */ + +/** + * @deprecated Please use nl_complete_msg() + */ +void nl_auto_complete(struct nl_sock *sk, struct nl_msg *msg) +{ + nl_complete_msg(sk, msg); +} + +/** + * @deprecated Please use nl_send_auto() + */ +int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg) +{ + return nl_send_auto(sk, msg); +} + + +/** @} */ + +/** @} */ + +/** @} */ diff --git a/lib/object.c b/lib/object.c new file mode 100644 index 0000000..b1ebe51 --- /dev/null +++ b/lib/object.c @@ -0,0 +1,538 @@ +/* + * lib/object.c Generic Cacheable Object + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +/** + * @ingroup core_types + * @defgroup object Object (Cacheable) + * + * Generic object data type, for inheritance purposes to implement cacheable + * data types. + * + * Related sections in the development guide: + * + * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ + */ + +#include +#include +#include +#include +#include + +static inline struct nl_object_ops *obj_ops(struct nl_object *obj) +{ + if (!obj->ce_ops) + BUG(); + + return obj->ce_ops; +} + +/** + * @name Object Creation/Deletion + * @{ + */ + +/** + * Allocate a new object of kind specified by the operations handle + * @arg ops cache operations handle + * @return The new object or NULL + */ +struct nl_object *nl_object_alloc(struct nl_object_ops *ops) +{ + struct nl_object *new; + + if (ops->oo_size < sizeof(*new)) + BUG(); + + new = calloc(1, ops->oo_size); + if (!new) + return NULL; + + new->ce_refcnt = 1; + nl_init_list_head(&new->ce_list); + + new->ce_ops = ops; + if (ops->oo_constructor) + ops->oo_constructor(new); + + NL_DBG(4, "Allocated new object %p\n", new); + + return new; +} + +/** + * Allocate new object of kind specified by the name + * @arg kind name of object type + * @arg result Result pointer + * + * @return 0 on success or a negative error code. + */ +int nl_object_alloc_name(const char *kind, struct nl_object **result) +{ + struct nl_cache_ops *ops; + + ops = nl_cache_ops_lookup_safe(kind); + if (!ops) + return -NLE_OPNOTSUPP; + + *result = nl_object_alloc(ops->co_obj_ops); + nl_cache_ops_put(ops); + if (!*result) + return -NLE_NOMEM; + + return 0; +} + +struct nl_derived_object { + NLHDR_COMMON + char data; +}; + +/** + * Allocate a new object and copy all data from an existing object + * @arg obj object to inherite data from + * @return The new object or NULL. + */ +struct nl_object *nl_object_clone(struct nl_object *obj) +{ + struct nl_object *new; + struct nl_object_ops *ops = obj_ops(obj); + int doff = offsetof(struct nl_derived_object, data); + int size; + + new = nl_object_alloc(ops); + if (!new) + return NULL; + + size = ops->oo_size - doff; + if (size < 0) + BUG(); + + new->ce_ops = obj->ce_ops; + new->ce_msgtype = obj->ce_msgtype; + new->ce_mask = obj->ce_mask; + + if (size) + memcpy((void *)new + doff, (void *)obj + doff, size); + + if (ops->oo_clone) { + if (ops->oo_clone(new, obj) < 0) { + nl_object_free(new); + return NULL; + } + } else if (size && ops->oo_free_data) + BUG(); + + return new; +} + +/** + * Merge a cacheable object + * @arg dst object to be merged into + * @arg src new object to be merged into dst + * + * @return 0 or a negative error code. + */ +int nl_object_update(struct nl_object *dst, struct nl_object *src) +{ + struct nl_object_ops *ops = obj_ops(dst); + + if (ops->oo_update) + return ops->oo_update(dst, src); + + return -NLE_OPNOTSUPP; +} + +/** + * Free a cacheable object + * @arg obj object to free + * + * @return 0 or a negative error code. + */ +void nl_object_free(struct nl_object *obj) +{ + struct nl_object_ops *ops; + + if (!obj) + return; + + ops = obj_ops(obj); + + if (obj->ce_refcnt > 0) + NL_DBG(1, "Warning: Freeing object in use...\n"); + + if (obj->ce_cache) + nl_cache_remove(obj); + + if (ops->oo_free_data) + ops->oo_free_data(obj); + + free(obj); + + NL_DBG(4, "Freed object %p\n", obj); +} + +/** @} */ + +/** + * @name Reference Management + * @{ + */ + +/** + * Acquire a reference on a object + * @arg obj object to acquire reference from + */ +void nl_object_get(struct nl_object *obj) +{ + obj->ce_refcnt++; + NL_DBG(4, "New reference to object %p, total %d\n", + obj, obj->ce_refcnt); +} + +/** + * Release a reference from an object + * @arg obj object to release reference from + */ +void nl_object_put(struct nl_object *obj) +{ + if (!obj) + return; + + obj->ce_refcnt--; + NL_DBG(4, "Returned object reference %p, %d remaining\n", + obj, obj->ce_refcnt); + + if (obj->ce_refcnt < 0) + BUG(); + + if (obj->ce_refcnt <= 0) + nl_object_free(obj); +} + +/** + * Check whether this object is used by multiple users + * @arg obj object to check + * @return true or false + */ +int nl_object_shared(struct nl_object *obj) +{ + return obj->ce_refcnt > 1; +} + +/** @} */ + +/** + * @name Marks + * @{ + */ + +/** + * Add mark to object + * @arg obj Object to mark + */ +void nl_object_mark(struct nl_object *obj) +{ + obj->ce_flags |= NL_OBJ_MARK; +} + +/** + * Remove mark from object + * @arg obj Object to unmark + */ +void nl_object_unmark(struct nl_object *obj) +{ + obj->ce_flags &= ~NL_OBJ_MARK; +} + +/** + * Return true if object is marked + * @arg obj Object to check + * @return true if object is marked, otherwise false + */ +int nl_object_is_marked(struct nl_object *obj) +{ + return (obj->ce_flags & NL_OBJ_MARK); +} + +/** @} */ + +/** + * @name Utillities + * @{ + */ + +/** + * Dump this object according to the specified parameters + * @arg obj object to dump + * @arg params dumping parameters + */ +void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params) +{ + if (params->dp_buf) + memset(params->dp_buf, 0, params->dp_buflen); + + dump_from_ops(obj, params); +} + +void nl_object_dump_buf(struct nl_object *obj, char *buf, size_t len) +{ + struct nl_dump_params dp = { + .dp_buf = buf, + .dp_buflen = len, + }; + + return nl_object_dump(obj, &dp); +} + +/** + * Check if the identifiers of two objects are identical + * @arg a an object + * @arg b another object of same type + * + * @return true if both objects have equal identifiers, otherwise false. + */ +int nl_object_identical(struct nl_object *a, struct nl_object *b) +{ + struct nl_object_ops *ops = obj_ops(a); + uint32_t req_attrs; + + /* Both objects must be of same type */ + if (ops != obj_ops(b)) + return 0; + + if (ops->oo_id_attrs_get) { + int req_attrs_a = ops->oo_id_attrs_get(a); + int req_attrs_b = ops->oo_id_attrs_get(b); + if (req_attrs_a != req_attrs_b) + return 0; + req_attrs = req_attrs_a; + } else { + req_attrs = ops->oo_id_attrs; + } + if (req_attrs == 0xFFFFFFFF) + req_attrs = a->ce_mask & b->ce_mask; + + /* Both objects must provide all required attributes to uniquely + * identify an object */ + if ((a->ce_mask & req_attrs) != req_attrs || + (b->ce_mask & req_attrs) != req_attrs) + return 0; + + /* Can't judge unless we can compare */ + if (ops->oo_compare == NULL) + return 0; + + return !(ops->oo_compare(a, b, req_attrs, 0)); +} + +/** + * Compute bitmask representing difference in attribute values + * @arg a an object + * @arg b another object of same type + * + * The bitmask returned is specific to an object type, each bit set represents + * an attribute which mismatches in either of the two objects. Unavailability + * of an attribute in one object and presence in the other is regarded a + * mismatch as well. + * + * @return Bitmask describing differences or 0 if they are completely identical. + */ +uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b) +{ + struct nl_object_ops *ops = obj_ops(a); + + if (ops != obj_ops(b) || ops->oo_compare == NULL) + return UINT_MAX; + + return ops->oo_compare(a, b, ~0, 0); +} + +/** + * Match a filter against an object + * @arg obj object to check + * @arg filter object of same type acting as filter + * + * @return 1 if the object matches the filter or 0 + * if no filter procedure is available or if the + * filter does not match. + */ +int nl_object_match_filter(struct nl_object *obj, struct nl_object *filter) +{ + struct nl_object_ops *ops = obj_ops(obj); + + if (ops != obj_ops(filter) || ops->oo_compare == NULL) + return 0; + + return !(ops->oo_compare(obj, filter, filter->ce_mask, + LOOSE_COMPARISON)); +} + +/** + * Convert bitmask of attributes to a character string + * @arg obj object of same type as attribute bitmask + * @arg attrs bitmask of attribute types + * @arg buf destination buffer + * @arg len length of destination buffer + * + * Converts the bitmask of attribute types into a list of attribute + * names separated by comas. + * + * @return destination buffer. + */ +char *nl_object_attrs2str(struct nl_object *obj, uint32_t attrs, + char *buf, size_t len) +{ + struct nl_object_ops *ops = obj_ops(obj); + + if (ops->oo_attrs2str != NULL) + return ops->oo_attrs2str(attrs, buf, len); + else { + memset(buf, 0, len); + return buf; + } +} + +/** + * Return list of attributes present in an object + * @arg obj an object + * @arg buf destination buffer + * @arg len length of destination buffer + * + * @return destination buffer. + */ +char *nl_object_attr_list(struct nl_object *obj, char *buf, size_t len) +{ + return nl_object_attrs2str(obj, obj->ce_mask, buf, len); +} + +/** + * Generate object hash key + * @arg obj the object + * @arg hashkey destination buffer to be used for key stream + * @arg hashtbl_sz hash table size + * + * @return hash key in destination buffer + */ +void nl_object_keygen(struct nl_object *obj, uint32_t *hashkey, + uint32_t hashtbl_sz) +{ + struct nl_object_ops *ops = obj_ops(obj); + + if (ops->oo_keygen) + ops->oo_keygen(obj, hashkey, hashtbl_sz); + else + *hashkey = 0; + + return; +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ + +/** + * Return number of references held + * @arg obj object + * + * @return The number of references held to this object + */ +int nl_object_get_refcnt(struct nl_object *obj) +{ + return obj->ce_refcnt; +} + +/** + * Return cache the object is associated with + * @arg obj object + * + * @note The returned pointer is not protected with a reference counter, + * it is your responsibility. + * + * @return Pointer to cache or NULL if not associated with a cache. + */ +struct nl_cache *nl_object_get_cache(struct nl_object *obj) +{ + return obj->ce_cache; +} + +/** + * Return the object's type + * @arg obj object + * + * FIXME: link to list of object types + * + * @return Name of the object type + */ +const char *nl_object_get_type(const struct nl_object *obj) +{ + if (!obj->ce_ops) + BUG(); + + return obj->ce_ops->oo_name; +} + +/** + * Return the netlink message type the object was derived from + * @arg obj object + * + * @return Netlink message type or 0. + */ +int nl_object_get_msgtype(const struct nl_object *obj) +{ + return obj->ce_msgtype; +} + +/** + * Return object operations structure + * @arg obj object + * + * @return Pointer to the object operations structure + */ +struct nl_object_ops *nl_object_get_ops(const struct nl_object *obj) +{ + return obj->ce_ops; +} + +/** + * Return object id attribute mask + * @arg obj object + * + * @return object id attribute mask + */ +uint32_t nl_object_get_id_attrs(struct nl_object *obj) +{ + struct nl_object_ops *ops = obj_ops(obj); + uint32_t id_attrs; + + if (!ops) + return 0; + + if (ops->oo_id_attrs_get) + id_attrs = ops->oo_id_attrs_get(obj); + else + id_attrs = ops->oo_id_attrs; + + return id_attrs; +} + +/** @} */ + +/** @} */ diff --git a/lib/route/addr.c b/lib/route/addr.c new file mode 100644 index 0000000..71fca94 --- /dev/null +++ b/lib/route/addr.c @@ -0,0 +1,1120 @@ +/* + * lib/route/addr.c Addresses + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + * Copyright (c) 2003-2006 Baruch Even , + * Mediatrix Telecom, inc. + */ + +/** + * @ingroup rtnl + * @defgroup rtaddr Addresses + * @brief + * + * @note The maximum size of an address label is IFNAMSIZ. + * + * @note The address may not contain a prefix length if the peer address + * has been specified already. + * + * @par 1) Address Addition + * @code + * // Allocate an empty address object to be filled out with the attributes + * // of the new address. + * struct rtnl_addr *addr = rtnl_addr_alloc(); + * + * // Fill out the mandatory attributes of the new address. Setting the + * // local address will automatically set the address family and the + * // prefix length to the correct values. + * rtnl_addr_set_ifindex(addr, ifindex); + * rtnl_addr_set_local(addr, local_addr); + * + * // The label of the address can be specified, currently only supported + * // by IPv4 and DECnet. + * rtnl_addr_set_label(addr, "mylabel"); + * + * // The peer address can be specified if necessary, in either case a peer + * // address will be sent to the kernel in order to fullfil the interface + * // requirements. If none is set, it will equal the local address. + * // Note: Real peer addresses are only supported by IPv4 for now. + * rtnl_addr_set_peer(addr, peer_addr); + * + * // In case you want to have the address have a scope other than global + * // it may be overwritten using rtnl_addr_set_scope(). The scope currently + * // cannot be set for IPv6 addresses. + * rtnl_addr_set_scope(addr, rtnl_str2scope("site")); + * + * // Broadcast address may be specified using the relevant + * // functions, the address family will be verified if one of the other + * // addresses has been set already. Currently only works for IPv4. + * rtnl_addr_set_broadcast(addr, broadcast_addr); + * + * // Build the netlink message and send it to the kernel, the operation will + * // block until the operation has been completed. Alternatively the required + * // netlink message can be built using rtnl_addr_build_add_request() to be + * // sent out using nl_send_auto_complete(). + * rtnl_addr_add(sk, addr, 0); + * + * // Free the memory + * rtnl_addr_put(addr); + * @endcode + * + * @par 2) Address Deletion + * @code + * // Allocate an empty address object to be filled out with the attributes + * // matching the address to be deleted. Alternatively a fully equipped + * // address object out of a cache can be used instead. + * struct rtnl_addr *addr = rtnl_addr_alloc(); + * + * // The only mandatory parameter besides the address family is the interface + * // index the address is on, i.e. leaving out all other parameters will + * // result in all addresses of the specified address family interface tuple + * // to be deleted. + * rtnl_addr_set_ifindex(addr, ifindex); + * + * // Specyfing the address family manually is only required if neither the + * // local nor peer address have been specified. + * rtnl_addr_set_family(addr, AF_INET); + * + * // Specyfing the local address is optional but the best choice to delete + * // specific addresses. + * rtnl_addr_set_local(addr, local_addr); + * + * // The label of the address can be specified, currently only supported + * // by IPv4 and DECnet. + * rtnl_addr_set_label(addr, "mylabel"); + * + * // The peer address can be specified if necessary, in either case a peer + * // address will be sent to the kernel in order to fullfil the interface + * // requirements. If none is set, it will equal the local address. + * // Note: Real peer addresses are only supported by IPv4 for now. + * rtnl_addr_set_peer(addr, peer_addr); + * + * // Build the netlink message and send it to the kernel, the operation will + * // block until the operation has been completed. Alternatively the required + * // netlink message can be built using rtnl_addr_build_delete_request() + * // to be sent out using nl_send_auto_complete(). + * rtnl_addr_delete(sk, addr, 0); + * + * // Free the memory + * rtnl_addr_put(addr); + * @endcode + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define ADDR_ATTR_FAMILY 0x0001 +#define ADDR_ATTR_PREFIXLEN 0x0002 +#define ADDR_ATTR_FLAGS 0x0004 +#define ADDR_ATTR_SCOPE 0x0008 +#define ADDR_ATTR_IFINDEX 0x0010 +#define ADDR_ATTR_LABEL 0x0020 +#define ADDR_ATTR_CACHEINFO 0x0040 +#define ADDR_ATTR_PEER 0x0080 +#define ADDR_ATTR_LOCAL 0x0100 +#define ADDR_ATTR_BROADCAST 0x0200 +#define ADDR_ATTR_MULTICAST 0x0400 +#define ADDR_ATTR_ANYCAST 0x0800 + +static struct nl_cache_ops rtnl_addr_ops; +static struct nl_object_ops addr_obj_ops; +/** @endcond */ + +static void addr_constructor(struct nl_object *obj) +{ + struct rtnl_addr *addr = nl_object_priv(obj); + + addr->a_scope = RT_SCOPE_NOWHERE; +} + +static void addr_free_data(struct nl_object *obj) +{ + struct rtnl_addr *addr = nl_object_priv(obj); + + if (!addr) + return; + + nl_addr_put(addr->a_peer); + nl_addr_put(addr->a_local); + nl_addr_put(addr->a_bcast); + nl_addr_put(addr->a_multicast); + nl_addr_put(addr->a_anycast); + rtnl_link_put(addr->a_link); +} + +static int addr_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct rtnl_addr *dst = nl_object_priv(_dst); + struct rtnl_addr *src = nl_object_priv(_src); + + if (src->a_link) { + nl_object_get(OBJ_CAST(src->a_link)); + dst->a_link = src->a_link; + } + + if (src->a_peer) + if (!(dst->a_peer = nl_addr_clone(src->a_peer))) + return -NLE_NOMEM; + + if (src->a_local) + if (!(dst->a_local = nl_addr_clone(src->a_local))) + return -NLE_NOMEM; + + if (src->a_bcast) + if (!(dst->a_bcast = nl_addr_clone(src->a_bcast))) + return -NLE_NOMEM; + + if (src->a_multicast) + if (!(dst->a_multicast = nl_addr_clone(src->a_multicast))) + return -NLE_NOMEM; + + if (src->a_anycast) + if (!(dst->a_anycast = nl_addr_clone(src->a_anycast))) + return -NLE_NOMEM; + + return 0; +} + +static struct nla_policy addr_policy[IFA_MAX+1] = { + [IFA_LABEL] = { .type = NLA_STRING, + .maxlen = IFNAMSIZ }, + [IFA_CACHEINFO] = { .minlen = sizeof(struct ifa_cacheinfo) }, +}; + +static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *nlh, struct nl_parser_param *pp) +{ + struct rtnl_addr *addr; + struct ifaddrmsg *ifa; + struct nlattr *tb[IFA_MAX+1]; + int err, family; + struct nl_cache *link_cache; + struct nl_addr *plen_addr = NULL; + + addr = rtnl_addr_alloc(); + if (!addr) + return -NLE_NOMEM; + + addr->ce_msgtype = nlh->nlmsg_type; + + err = nlmsg_parse(nlh, sizeof(*ifa), tb, IFA_MAX, addr_policy); + if (err < 0) + goto errout; + + ifa = nlmsg_data(nlh); + addr->a_family = family = ifa->ifa_family; + addr->a_prefixlen = ifa->ifa_prefixlen; + addr->a_flags = ifa->ifa_flags; + addr->a_scope = ifa->ifa_scope; + addr->a_ifindex = ifa->ifa_index; + + addr->ce_mask = (ADDR_ATTR_FAMILY | ADDR_ATTR_PREFIXLEN | + ADDR_ATTR_FLAGS | ADDR_ATTR_SCOPE | ADDR_ATTR_IFINDEX); + + if (tb[IFA_LABEL]) { + nla_strlcpy(addr->a_label, tb[IFA_LABEL], IFNAMSIZ); + addr->ce_mask |= ADDR_ATTR_LABEL; + } + + /* IPv6 only */ + if (tb[IFA_CACHEINFO]) { + struct ifa_cacheinfo *ca; + + ca = nla_data(tb[IFA_CACHEINFO]); + addr->a_cacheinfo.aci_prefered = ca->ifa_prefered; + addr->a_cacheinfo.aci_valid = ca->ifa_valid; + addr->a_cacheinfo.aci_cstamp = ca->cstamp; + addr->a_cacheinfo.aci_tstamp = ca->tstamp; + addr->ce_mask |= ADDR_ATTR_CACHEINFO; + } + + if (tb[IFA_LOCAL]) { + addr->a_local = nl_addr_alloc_attr(tb[IFA_LOCAL], family); + if (!addr->a_local) + goto errout_nomem; + addr->ce_mask |= ADDR_ATTR_LOCAL; + plen_addr = addr->a_local; + } + + if (tb[IFA_ADDRESS]) { + struct nl_addr *a; + + a = nl_addr_alloc_attr(tb[IFA_ADDRESS], family); + if (!a) + goto errout_nomem; + + /* IPv6 sends the local address as IFA_ADDRESS with + * no IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS + * with IFA_ADDRESS being the peer address if they differ */ + if (!tb[IFA_LOCAL] || !nl_addr_cmp(a, addr->a_local)) { + nl_addr_put(addr->a_local); + addr->a_local = a; + addr->ce_mask |= ADDR_ATTR_LOCAL; + } else { + addr->a_peer = a; + addr->ce_mask |= ADDR_ATTR_PEER; + } + + plen_addr = a; + } + + if (plen_addr) + nl_addr_set_prefixlen(plen_addr, addr->a_prefixlen); + + /* IPv4 only */ + if (tb[IFA_BROADCAST]) { + addr->a_bcast = nl_addr_alloc_attr(tb[IFA_BROADCAST], family); + if (!addr->a_bcast) + goto errout_nomem; + + addr->ce_mask |= ADDR_ATTR_BROADCAST; + } + + /* IPv6 only */ + if (tb[IFA_MULTICAST]) { + addr->a_multicast = nl_addr_alloc_attr(tb[IFA_MULTICAST], + family); + if (!addr->a_multicast) + goto errout_nomem; + + addr->ce_mask |= ADDR_ATTR_MULTICAST; + } + + /* IPv6 only */ + if (tb[IFA_ANYCAST]) { + addr->a_anycast = nl_addr_alloc_attr(tb[IFA_ANYCAST], + family); + if (!addr->a_anycast) + goto errout_nomem; + + addr->ce_mask |= ADDR_ATTR_ANYCAST; + } + + if ((link_cache = __nl_cache_mngt_require("route/link"))) { + struct rtnl_link *link; + + if ((link = rtnl_link_get(link_cache, addr->a_ifindex))) { + rtnl_addr_set_link(addr, link); + + /* rtnl_addr_set_link incs refcnt */ + rtnl_link_put(link); + } + } + + err = pp->pp_cb((struct nl_object *) addr, pp); +errout: + rtnl_addr_put(addr); + + return err; + +errout_nomem: + err = -NLE_NOMEM; + goto errout; +} + +static int addr_request_update(struct nl_cache *cache, struct nl_sock *sk) +{ + return nl_rtgen_request(sk, RTM_GETADDR, AF_UNSPEC, NLM_F_DUMP); +} + +static void addr_dump_line(struct nl_object *obj, struct nl_dump_params *p) +{ + struct rtnl_addr *addr = (struct rtnl_addr *) obj; + struct nl_cache *link_cache; + char buf[128]; + + link_cache = nl_cache_mngt_require_safe("route/link"); + + if (addr->ce_mask & ADDR_ATTR_LOCAL) + nl_dump_line(p, "%s", + nl_addr2str(addr->a_local, buf, sizeof(buf))); + else + nl_dump_line(p, "none"); + + if (addr->ce_mask & ADDR_ATTR_PEER) + nl_dump(p, " peer %s", + nl_addr2str(addr->a_peer, buf, sizeof(buf))); + + nl_dump(p, " %s ", nl_af2str(addr->a_family, buf, sizeof(buf))); + + if (link_cache) + nl_dump(p, "dev %s ", + rtnl_link_i2name(link_cache, addr->a_ifindex, + buf, sizeof(buf))); + else + nl_dump(p, "dev %d ", addr->a_ifindex); + + nl_dump(p, "scope %s", + rtnl_scope2str(addr->a_scope, buf, sizeof(buf))); + + rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf)); + if (buf[0]) + nl_dump(p, " <%s>", buf); + + nl_dump(p, "\n"); + + if (link_cache) + nl_cache_put(link_cache); +} + +static void addr_dump_details(struct nl_object *obj, struct nl_dump_params *p) +{ + struct rtnl_addr *addr = (struct rtnl_addr *) obj; + char buf[128]; + + addr_dump_line(obj, p); + + if (addr->ce_mask & (ADDR_ATTR_LABEL | ADDR_ATTR_BROADCAST | + ADDR_ATTR_MULTICAST)) { + nl_dump_line(p, " "); + + if (addr->ce_mask & ADDR_ATTR_LABEL) + nl_dump(p, " label %s", addr->a_label); + + if (addr->ce_mask & ADDR_ATTR_BROADCAST) + nl_dump(p, " broadcast %s", + nl_addr2str(addr->a_bcast, buf, sizeof(buf))); + + if (addr->ce_mask & ADDR_ATTR_MULTICAST) + nl_dump(p, " multicast %s", + nl_addr2str(addr->a_multicast, buf, + sizeof(buf))); + + if (addr->ce_mask & ADDR_ATTR_ANYCAST) + nl_dump(p, " anycast %s", + nl_addr2str(addr->a_anycast, buf, + sizeof(buf))); + + nl_dump(p, "\n"); + } + + if (addr->ce_mask & ADDR_ATTR_CACHEINFO) { + struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo; + + nl_dump_line(p, " valid-lifetime %s", + ci->aci_valid == 0xFFFFFFFFU ? "forever" : + nl_msec2str(ci->aci_valid * 1000, + buf, sizeof(buf))); + + nl_dump(p, " preferred-lifetime %s\n", + ci->aci_prefered == 0xFFFFFFFFU ? "forever" : + nl_msec2str(ci->aci_prefered * 1000, + buf, sizeof(buf))); + + nl_dump_line(p, " created boot-time+%s ", + nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10, + buf, sizeof(buf))); + + nl_dump(p, "last-updated boot-time+%s\n", + nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10, + buf, sizeof(buf))); + } +} + +static void addr_dump_stats(struct nl_object *obj, struct nl_dump_params *p) +{ + addr_dump_details(obj, p); +} + +static int addr_compare(struct nl_object *_a, struct nl_object *_b, + uint32_t attrs, int flags) +{ + struct rtnl_addr *a = (struct rtnl_addr *) _a; + struct rtnl_addr *b = (struct rtnl_addr *) _b; + int diff = 0; + +#define ADDR_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ADDR_ATTR_##ATTR, a, b, EXPR) + + diff |= ADDR_DIFF(IFINDEX, a->a_ifindex != b->a_ifindex); + diff |= ADDR_DIFF(FAMILY, a->a_family != b->a_family); + diff |= ADDR_DIFF(SCOPE, a->a_scope != b->a_scope); + diff |= ADDR_DIFF(LABEL, strcmp(a->a_label, b->a_label)); + diff |= ADDR_DIFF(PEER, nl_addr_cmp(a->a_peer, b->a_peer)); + diff |= ADDR_DIFF(LOCAL, nl_addr_cmp(a->a_local, b->a_local)); + diff |= ADDR_DIFF(MULTICAST, nl_addr_cmp(a->a_multicast, + b->a_multicast)); + diff |= ADDR_DIFF(BROADCAST, nl_addr_cmp(a->a_bcast, b->a_bcast)); + diff |= ADDR_DIFF(ANYCAST, nl_addr_cmp(a->a_anycast, b->a_anycast)); + + if (flags & LOOSE_COMPARISON) + diff |= ADDR_DIFF(FLAGS, + (a->a_flags ^ b->a_flags) & b->a_flag_mask); + else + diff |= ADDR_DIFF(FLAGS, a->a_flags != b->a_flags); + +#undef ADDR_DIFF + + return diff; +} + +static const struct trans_tbl addr_attrs[] = { + __ADD(ADDR_ATTR_FAMILY, family) + __ADD(ADDR_ATTR_PREFIXLEN, prefixlen) + __ADD(ADDR_ATTR_FLAGS, flags) + __ADD(ADDR_ATTR_SCOPE, scope) + __ADD(ADDR_ATTR_IFINDEX, ifindex) + __ADD(ADDR_ATTR_LABEL, label) + __ADD(ADDR_ATTR_CACHEINFO, cacheinfo) + __ADD(ADDR_ATTR_PEER, peer) + __ADD(ADDR_ATTR_LOCAL, local) + __ADD(ADDR_ATTR_BROADCAST, broadcast) + __ADD(ADDR_ATTR_MULTICAST, multicast) +}; + +static char *addr_attrs2str(int attrs, char *buf, size_t len) +{ + return __flags2str(attrs, buf, len, addr_attrs, + ARRAY_SIZE(addr_attrs)); +} + +/** + * @name Allocation/Freeing + * @{ + */ + +struct rtnl_addr *rtnl_addr_alloc(void) +{ + return (struct rtnl_addr *) nl_object_alloc(&addr_obj_ops); +} + +void rtnl_addr_put(struct rtnl_addr *addr) +{ + nl_object_put((struct nl_object *) addr); +} + +/** @} */ + +/** + * @name Cache Management + * @{ + */ + +int rtnl_addr_alloc_cache(struct nl_sock *sk, struct nl_cache **result) +{ + return nl_cache_alloc_and_fill(&rtnl_addr_ops, sk, result); +} + +/** + * Search address in cache + * @arg cache Address cache + * @arg ifindex Interface index of address + * @arg addr Local address part + * + * Searches address cache previously allocated with rtnl_addr_alloc_cache() + * for an address with a matching local address. + * + * The reference counter is incremented before returning the address, therefore + * the reference must be given back with rtnl_addr_put() after usage. + * + * @return Address object or NULL if no match was found. + */ +struct rtnl_addr *rtnl_addr_get(struct nl_cache *cache, int ifindex, + struct nl_addr *addr) +{ + struct rtnl_addr *a; + + if (cache->c_ops != &rtnl_addr_ops) + return NULL; + + nl_list_for_each_entry(a, &cache->c_items, ce_list) { + if (ifindex && a->a_ifindex != ifindex) + continue; + + if (a->ce_mask & ADDR_ATTR_LOCAL && + !nl_addr_cmp(a->a_local, addr)) { + nl_object_get((struct nl_object *) a); + return a; + } + } + + return NULL; +} + +/** @} */ + +static int build_addr_msg(struct rtnl_addr *tmpl, int cmd, int flags, + struct nl_msg **result) +{ + struct nl_msg *msg; + struct ifaddrmsg am = { + .ifa_family = tmpl->a_family, + .ifa_index = tmpl->a_ifindex, + .ifa_prefixlen = tmpl->a_prefixlen, + }; + + if (tmpl->ce_mask & ADDR_ATTR_SCOPE) + am.ifa_scope = tmpl->a_scope; + else { + /* compatibility hack */ + if (tmpl->a_family == AF_INET && + tmpl->ce_mask & ADDR_ATTR_LOCAL && + *((char *) nl_addr_get_binary_addr(tmpl->a_local)) == 127) + am.ifa_scope = RT_SCOPE_HOST; + else + am.ifa_scope = RT_SCOPE_UNIVERSE; + } + + msg = nlmsg_alloc_simple(cmd, flags); + if (!msg) + return -NLE_NOMEM; + + if (nlmsg_append(msg, &am, sizeof(am), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if (tmpl->ce_mask & ADDR_ATTR_LOCAL) + NLA_PUT_ADDR(msg, IFA_LOCAL, tmpl->a_local); + + if (tmpl->ce_mask & ADDR_ATTR_PEER) + NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_peer); + else if (tmpl->ce_mask & ADDR_ATTR_LOCAL) + NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_local); + + if (tmpl->ce_mask & ADDR_ATTR_LABEL) + NLA_PUT_STRING(msg, IFA_LABEL, tmpl->a_label); + + if (tmpl->ce_mask & ADDR_ATTR_BROADCAST) + NLA_PUT_ADDR(msg, IFA_BROADCAST, tmpl->a_bcast); + + if (tmpl->ce_mask & ADDR_ATTR_CACHEINFO) { + struct ifa_cacheinfo ca = { + .ifa_valid = tmpl->a_cacheinfo.aci_valid, + .ifa_prefered = tmpl->a_cacheinfo.aci_prefered, + }; + + NLA_PUT(msg, IFA_CACHEINFO, sizeof(ca), &ca); + } + + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +/** + * @name Addition + * @{ + */ + +/** + * Build netlink request message to request addition of new address + * @arg addr Address object representing the new address. + * @arg flags Additional netlink message flags. + * @arg result Pointer to store resulting message. + * + * Builds a new netlink message requesting the addition of a new + * address. The netlink message header isn't fully equipped with + * all relevant fields and must thus be sent out via nl_send_auto_complete() + * or supplemented as needed. + * + * Minimal required attributes: + * - interface index (rtnl_addr_set_ifindex()) + * - local address (rtnl_addr_set_local()) + * + * The scope will default to universe except for loopback addresses in + * which case a host scope is used if not specified otherwise. + * + * @note Free the memory after usage using nlmsg_free(). + * + * @return 0 on success or a negative error code. + */ +int rtnl_addr_build_add_request(struct rtnl_addr *addr, int flags, + struct nl_msg **result) +{ + uint32_t required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY | + ADDR_ATTR_PREFIXLEN | ADDR_ATTR_LOCAL; + + if ((addr->ce_mask & required) != required) + return -NLE_MISSING_ATTR; + + return build_addr_msg(addr, RTM_NEWADDR, NLM_F_CREATE | flags, result); +} + +/** + * Request addition of new address + * @arg sk Netlink socket. + * @arg addr Address object representing the new address. + * @arg flags Additional netlink message flags. + * + * Builds a netlink message by calling rtnl_addr_build_add_request(), + * sends the request to the kernel and waits for the next ACK to be + * received and thus blocks until the request has been fullfilled. + * + * @see rtnl_addr_build_add_request() + * + * @return 0 on sucess or a negative error if an error occured. + */ +int rtnl_addr_add(struct nl_sock *sk, struct rtnl_addr *addr, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_addr_build_add_request(addr, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +/** @} */ + +/** + * @name Deletion + * @{ + */ + +/** + * Build a netlink request message to request deletion of an address + * @arg addr Address object to be deleteted. + * @arg flags Additional netlink message flags. + * @arg result Pointer to store resulting message. + * + * Builds a new netlink message requesting a deletion of an address. + * The netlink message header isn't fully equipped with all relevant + * fields and must thus be sent out via nl_send_auto_complete() + * or supplemented as needed. + * + * Minimal required attributes: + * - interface index (rtnl_addr_set_ifindex()) + * - address family (rtnl_addr_set_family()) + * + * Optional attributes: + * - local address (rtnl_addr_set_local()) + * - label (rtnl_addr_set_label(), IPv4/DECnet only) + * - peer address (rtnl_addr_set_peer(), IPv4 only) + * + * @note Free the memory after usage using nlmsg_free(). + * + * @return 0 on success or a negative error code. + */ +int rtnl_addr_build_delete_request(struct rtnl_addr *addr, int flags, + struct nl_msg **result) +{ + uint32_t required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY; + + if ((addr->ce_mask & required) != required) + return -NLE_MISSING_ATTR; + + return build_addr_msg(addr, RTM_DELADDR, flags, result); +} + +/** + * Request deletion of an address + * @arg sk Netlink socket. + * @arg addr Address object to be deleted. + * @arg flags Additional netlink message flags. + * + * Builds a netlink message by calling rtnl_addr_build_delete_request(), + * sends the request to the kernel and waits for the next ACK to be + * received and thus blocks until the request has been fullfilled. + * + * @see rtnl_addr_build_delete_request(); + * + * @return 0 on sucess or a negative error if an error occured. + */ +int rtnl_addr_delete(struct nl_sock *sk, struct rtnl_addr *addr, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_addr_build_delete_request(addr, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ + +int rtnl_addr_set_label(struct rtnl_addr *addr, const char *label) +{ + if (strlen(label) > sizeof(addr->a_label) - 1) + return -NLE_RANGE; + + strcpy(addr->a_label, label); + addr->ce_mask |= ADDR_ATTR_LABEL; + + return 0; +} + +char *rtnl_addr_get_label(struct rtnl_addr *addr) +{ + if (addr->ce_mask & ADDR_ATTR_LABEL) + return addr->a_label; + else + return NULL; +} + +void rtnl_addr_set_ifindex(struct rtnl_addr *addr, int ifindex) +{ + addr->a_ifindex = ifindex; + addr->ce_mask |= ADDR_ATTR_IFINDEX; +} + +int rtnl_addr_get_ifindex(struct rtnl_addr *addr) +{ + return addr->a_ifindex; +} + +void rtnl_addr_set_link(struct rtnl_addr *addr, struct rtnl_link *link) +{ + rtnl_link_put(addr->a_link); + + if (!link) + return; + + nl_object_get(OBJ_CAST(link)); + addr->a_link = link; + addr->a_ifindex = link->l_index; + addr->ce_mask |= ADDR_ATTR_IFINDEX; +} + +struct rtnl_link *rtnl_addr_get_link(struct rtnl_addr *addr) +{ + if (addr->a_link) { + nl_object_get(OBJ_CAST(addr->a_link)); + return addr->a_link; + } + + return NULL; +} + +void rtnl_addr_set_family(struct rtnl_addr *addr, int family) +{ + addr->a_family = family; + addr->ce_mask |= ADDR_ATTR_FAMILY; +} + +int rtnl_addr_get_family(struct rtnl_addr *addr) +{ + return addr->a_family; +} + +/** + * Set the prefix length / netmask + * @arg addr Address + * @arg prefixlen Length of prefix (netmask) + * + * Modifies the length of the prefix. If the address object contains a peer + * address the prefix length will apply to it, otherwise the prefix length + * will apply to the local address of the address. + * + * If the address object contains a peer or local address the corresponding + * `struct nl_addr` will be updated with the new prefix length. + * + * @note Specifying a length of 0 will remove the prefix length alltogether. + * + * @see rtnl_addr_get_prefixlen() + */ +void rtnl_addr_set_prefixlen(struct rtnl_addr *addr, int prefixlen) +{ + addr->a_prefixlen = prefixlen; + + if (prefixlen) + addr->ce_mask |= ADDR_ATTR_PREFIXLEN; + else + addr->ce_mask &= ~ADDR_ATTR_PREFIXLEN; + + /* + * The prefix length always applies to the peer address if + * a peer address is present. + */ + if (addr->a_peer) + nl_addr_set_prefixlen(addr->a_peer, prefixlen); + else if (addr->a_local) + nl_addr_set_prefixlen(addr->a_local, prefixlen); +} + +int rtnl_addr_get_prefixlen(struct rtnl_addr *addr) +{ + return addr->a_prefixlen; +} + +void rtnl_addr_set_scope(struct rtnl_addr *addr, int scope) +{ + addr->a_scope = scope; + addr->ce_mask |= ADDR_ATTR_SCOPE; +} + +int rtnl_addr_get_scope(struct rtnl_addr *addr) +{ + return addr->a_scope; +} + +void rtnl_addr_set_flags(struct rtnl_addr *addr, unsigned int flags) +{ + addr->a_flag_mask |= flags; + addr->a_flags |= flags; + addr->ce_mask |= ADDR_ATTR_FLAGS; +} + +void rtnl_addr_unset_flags(struct rtnl_addr *addr, unsigned int flags) +{ + addr->a_flag_mask |= flags; + addr->a_flags &= ~flags; + addr->ce_mask |= ADDR_ATTR_FLAGS; +} + +unsigned int rtnl_addr_get_flags(struct rtnl_addr *addr) +{ + return addr->a_flags; +} + +static inline int __assign_addr(struct rtnl_addr *addr, struct nl_addr **pos, + struct nl_addr *new, int flag) +{ + if (new) { + if (addr->ce_mask & ADDR_ATTR_FAMILY) { + if (new->a_family != addr->a_family) + return -NLE_AF_MISMATCH; + } else + addr->a_family = new->a_family; + + if (*pos) + nl_addr_put(*pos); + + *pos = nl_addr_get(new); + addr->ce_mask |= (flag | ADDR_ATTR_FAMILY); + } else { + if (*pos) + nl_addr_put(*pos); + + *pos = NULL; + addr->ce_mask &= ~flag; + } + + return 0; +} + +int rtnl_addr_set_local(struct rtnl_addr *addr, struct nl_addr *local) +{ + int err; + + /* Prohibit local address with prefix length if peer address is present */ + if ((addr->ce_mask & ADDR_ATTR_PEER) && local && + nl_addr_get_prefixlen(local)) + return -NLE_INVAL; + + err = __assign_addr(addr, &addr->a_local, local, ADDR_ATTR_LOCAL); + if (err < 0) + return err; + + /* Never overwrite the prefix length if a peer address is present */ + if (!(addr->ce_mask & ADDR_ATTR_PEER)) + rtnl_addr_set_prefixlen(addr, local ? nl_addr_get_prefixlen(local) : 0); + + return 0; +} + +struct nl_addr *rtnl_addr_get_local(struct rtnl_addr *addr) +{ + return addr->a_local; +} + +int rtnl_addr_set_peer(struct rtnl_addr *addr, struct nl_addr *peer) +{ + int err; + + if (peer && peer->a_family != AF_INET) + return -NLE_AF_NOSUPPORT; + + err = __assign_addr(addr, &addr->a_peer, peer, ADDR_ATTR_PEER); + if (err < 0) + return err; + + rtnl_addr_set_prefixlen(addr, peer ? nl_addr_get_prefixlen(peer) : 0); + + return 0; +} + +struct nl_addr *rtnl_addr_get_peer(struct rtnl_addr *addr) +{ + return addr->a_peer; +} + +int rtnl_addr_set_broadcast(struct rtnl_addr *addr, struct nl_addr *bcast) +{ + if (bcast && bcast->a_family != AF_INET) + return -NLE_AF_NOSUPPORT; + + return __assign_addr(addr, &addr->a_bcast, bcast, ADDR_ATTR_BROADCAST); +} + +struct nl_addr *rtnl_addr_get_broadcast(struct rtnl_addr *addr) +{ + return addr->a_bcast; +} + +int rtnl_addr_set_multicast(struct rtnl_addr *addr, struct nl_addr *multicast) +{ + if (multicast && multicast->a_family != AF_INET6) + return -NLE_AF_NOSUPPORT; + + return __assign_addr(addr, &addr->a_multicast, multicast, + ADDR_ATTR_MULTICAST); +} + +struct nl_addr *rtnl_addr_get_multicast(struct rtnl_addr *addr) +{ + return addr->a_multicast; +} + +int rtnl_addr_set_anycast(struct rtnl_addr *addr, struct nl_addr *anycast) +{ + if (anycast && anycast->a_family != AF_INET6) + return -NLE_AF_NOSUPPORT; + + return __assign_addr(addr, &addr->a_anycast, anycast, + ADDR_ATTR_ANYCAST); +} + +struct nl_addr *rtnl_addr_get_anycast(struct rtnl_addr *addr) +{ + return addr->a_anycast; +} + +uint32_t rtnl_addr_get_valid_lifetime(struct rtnl_addr *addr) +{ + if (addr->ce_mask & ADDR_ATTR_CACHEINFO) + return addr->a_cacheinfo.aci_valid; + else + return 0xFFFFFFFFU; +} + +void rtnl_addr_set_valid_lifetime(struct rtnl_addr *addr, uint32_t lifetime) +{ + addr->a_cacheinfo.aci_valid = lifetime; + addr->ce_mask |= ADDR_ATTR_CACHEINFO; +} + +uint32_t rtnl_addr_get_preferred_lifetime(struct rtnl_addr *addr) +{ + if (addr->ce_mask & ADDR_ATTR_CACHEINFO) + return addr->a_cacheinfo.aci_prefered; + else + return 0xFFFFFFFFU; +} + +void rtnl_addr_set_preferred_lifetime(struct rtnl_addr *addr, uint32_t lifetime) +{ + addr->a_cacheinfo.aci_prefered = lifetime; + addr->ce_mask |= ADDR_ATTR_CACHEINFO; +} + +uint32_t rtnl_addr_get_create_time(struct rtnl_addr *addr) +{ + return addr->a_cacheinfo.aci_cstamp; +} + +uint32_t rtnl_addr_get_last_update_time(struct rtnl_addr *addr) +{ + return addr->a_cacheinfo.aci_tstamp; +} + +/** @} */ + +/** + * @name Flags Translations + * @{ + */ + +static const struct trans_tbl addr_flags[] = { + __ADD(IFA_F_SECONDARY, secondary) + __ADD(IFA_F_NODAD, nodad) + __ADD(IFA_F_OPTIMISTIC, optimistic) + __ADD(IFA_F_HOMEADDRESS, homeaddress) + __ADD(IFA_F_DEPRECATED, deprecated) + __ADD(IFA_F_TENTATIVE, tentative) + __ADD(IFA_F_PERMANENT, permanent) +}; + +char *rtnl_addr_flags2str(int flags, char *buf, size_t size) +{ + return __flags2str(flags, buf, size, addr_flags, + ARRAY_SIZE(addr_flags)); +} + +int rtnl_addr_str2flags(const char *name) +{ + return __str2flags(name, addr_flags, ARRAY_SIZE(addr_flags)); +} + +/** @} */ + +static struct nl_object_ops addr_obj_ops = { + .oo_name = "route/addr", + .oo_size = sizeof(struct rtnl_addr), + .oo_constructor = addr_constructor, + .oo_free_data = addr_free_data, + .oo_clone = addr_clone, + .oo_dump = { + [NL_DUMP_LINE] = addr_dump_line, + [NL_DUMP_DETAILS] = addr_dump_details, + [NL_DUMP_STATS] = addr_dump_stats, + }, + .oo_compare = addr_compare, + .oo_attrs2str = addr_attrs2str, + .oo_id_attrs = (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX | + ADDR_ATTR_LOCAL | ADDR_ATTR_PREFIXLEN), +}; + +static struct nl_af_group addr_groups[] = { + { AF_INET, RTNLGRP_IPV4_IFADDR }, + { AF_INET6, RTNLGRP_IPV6_IFADDR }, + { END_OF_GROUP_LIST }, +}; + +static struct nl_cache_ops rtnl_addr_ops = { + .co_name = "route/addr", + .co_hdrsize = sizeof(struct ifaddrmsg), + .co_msgtypes = { + { RTM_NEWADDR, NL_ACT_NEW, "new" }, + { RTM_DELADDR, NL_ACT_DEL, "del" }, + { RTM_GETADDR, NL_ACT_GET, "get" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_ROUTE, + .co_groups = addr_groups, + .co_request_update = addr_request_update, + .co_msg_parser = addr_msg_parser, + .co_obj_ops = &addr_obj_ops, +}; + +static void __init addr_init(void) +{ + nl_cache_mngt_register(&rtnl_addr_ops); +} + +static void __exit addr_exit(void) +{ + nl_cache_mngt_unregister(&rtnl_addr_ops); +} + +/** @} */ diff --git a/lib/route/class.c b/lib/route/class.c new file mode 100644 index 0000000..050f42a --- /dev/null +++ b/lib/route/class.c @@ -0,0 +1,473 @@ +/* + * lib/route/class.c Traffic Classes + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2013 Thomas Graf + */ + +/** + * @ingroup tc + * @defgroup class Traffic Classes + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct nl_cache_ops rtnl_class_ops; +static struct nl_object_ops class_obj_ops; + +static void class_dump_details(struct rtnl_tc *tc, struct nl_dump_params *p) +{ + struct rtnl_class *class = (struct rtnl_class *) tc; + char buf[32]; + + if (class->c_info) + nl_dump(p, "child-qdisc %s ", + rtnl_tc_handle2str(class->c_info, buf, sizeof(buf))); +} + + +static int class_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *nlh, struct nl_parser_param *pp) +{ + struct rtnl_class *class; + int err; + + if (!(class = rtnl_class_alloc())) + return -NLE_NOMEM; + + if ((err = rtnl_tc_msg_parse(nlh, TC_CAST(class))) < 0) + goto errout; + + err = pp->pp_cb(OBJ_CAST(class), pp); +errout: + rtnl_class_put(class); + + return err; +} + +static int class_request_update(struct nl_cache *cache, struct nl_sock *sk) +{ + struct tcmsg tchdr = { + .tcm_family = AF_UNSPEC, + .tcm_ifindex = cache->c_iarg1, + }; + + return nl_send_simple(sk, RTM_GETTCLASS, NLM_F_DUMP, &tchdr, + sizeof(tchdr)); +} + +/** + * @name Allocation/Freeing + * @{ + */ + +struct rtnl_class *rtnl_class_alloc(void) +{ + struct rtnl_tc *tc; + + tc = TC_CAST(nl_object_alloc(&class_obj_ops)); + if (tc) + tc->tc_type = RTNL_TC_TYPE_CLASS; + + return (struct rtnl_class *) tc; +} + +void rtnl_class_put(struct rtnl_class *class) +{ + nl_object_put((struct nl_object *) class); +} + +/** @} */ + + +/** + * @name Addition/Modification/Deletion + * @{ + */ + +static int class_build(struct rtnl_class *class, int type, int flags, + struct nl_msg **result) +{ + uint32_t needed = TCA_ATTR_PARENT | TCA_ATTR_HANDLE; + + if ((class->ce_mask & needed) == needed && + TC_H_MAJ(class->c_parent) && TC_H_MAJ(class->c_handle) && + TC_H_MAJ(class->c_parent) != TC_H_MAJ(class->c_handle)) { + APPBUG("TC_H_MAJ(parent) must match TC_H_MAJ(handle)"); + return -NLE_INVAL; + } + + return rtnl_tc_msg_build(TC_CAST(class), type, flags, result); +} + +/** + * Build a netlink message requesting the addition of a traffic class + * @arg class Traffic class to add + * @arg flags Additional netlink message flags + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_class_add() with + * the exception that it will not send the message but return it int the + * provided return pointer instead. + * + * @see rtnl_class_add() + * + * @return 0 on success or a negative error code. + */ +int rtnl_class_build_add_request(struct rtnl_class *class, int flags, + struct nl_msg **result) +{ + return class_build(class, RTM_NEWTCLASS, flags, result); +} + +/** + * Add/Update traffic class + * @arg sk Netlink socket + * @arg class Traffic class to add + * @arg flags Additional netlink message flags + * + * Builds a \c RTM_NEWTCLASS netlink message requesting the addition + * of a new traffic class and sends the message to the kernel. The + * configuration of the traffic class is derived from the attributes + * of the specified traffic class. + * + * The following flags may be specified: + * - \c NLM_F_CREATE: Create traffic class if it does not exist, + * otherwise -NLE_OBJ_NOTFOUND is returned. + * - \c NLM_F_EXCL: Return -NLE_EXISTS if a traffic class with + * matching handle exists already. + * + * Existing traffic classes with matching handles will be updated, + * unless the flag \c NLM_F_EXCL is specified. If no matching traffic + * class exists, it will be created if the flag \c NLM_F_CREATE is set, + * otherwise the error -NLE_OBJ_NOTFOUND is returned. + * + * If the parent qdisc does not support classes, the error + * \c NLE_OPNOTSUPP is returned. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @return 0 on success or a negative error code. + */ +int rtnl_class_add(struct nl_sock *sk, struct rtnl_class *class, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_class_build_add_request(class, flags, &msg)) < 0) + return err; + + return nl_send_sync(sk, msg); +} + +/** + * Build netlink message requesting the deletion of a traffic class + * @arg class Traffic class to delete + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_class_delete() with + * the exception that it will not send the message but return it in the + * provided return pointer instead. + * + * @see rtnl_class_delete() + * + * @return 0 on success or a negative error code. + */ +int rtnl_class_build_delete_request(struct rtnl_class *class, struct nl_msg **result) +{ + struct nl_msg *msg; + struct tcmsg tchdr; + uint32_t required = TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE; + + if ((class->ce_mask & required) != required) { + APPBUG("ifindex and handle must be specified"); + return -NLE_MISSING_ATTR; + } + + if (!(msg = nlmsg_alloc_simple(RTM_DELTCLASS, 0))) + return -NLE_NOMEM; + + memset(&tchdr, 0, sizeof(tchdr)); + tchdr.tcm_family = AF_UNSPEC; + tchdr.tcm_ifindex = class->c_ifindex; + tchdr.tcm_handle = class->c_handle; + + if (class->ce_mask & TCA_ATTR_PARENT) + tchdr.tcm_parent = class->c_parent; + + if (nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO) < 0) { + nlmsg_free(msg); + return -NLE_MSGSIZE; + } + + *result = msg; + return 0; +} + +/** + * Delete traffic class + * @arg sk Netlink socket + * @arg class Traffic class to delete + * + * Builds a \c RTM_DELTCLASS netlink message requesting the deletion + * of a traffic class and sends the message to the kernel. + * + * The message is constructed out of the following attributes: + * - \c ifindex and \c handle (required) + * - \c parent (optional, must match if provided) + * + * All other class attributes including all class type specific + * attributes are ignored. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @return 0 on success or a negative error code. + */ +int rtnl_class_delete(struct nl_sock *sk, struct rtnl_class *class) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_class_build_delete_request(class, &msg)) < 0) + return err; + + return nl_send_sync(sk, msg); +} + +/** @} */ + +/** + * @name Leaf Qdisc + * @{ + */ + +/** + * Lookup the leaf qdisc of a traffic class + * @arg class the parent traffic class + * @arg cache a qdisc cache allocated using rtnl_qdisc_alloc_cache() + * + * @return Matching Qdisc or NULL if the traffic class has no leaf qdisc + */ +struct rtnl_qdisc *rtnl_class_leaf_qdisc(struct rtnl_class *class, + struct nl_cache *cache) +{ + struct rtnl_qdisc *leaf; + + if (!class->c_info) + return NULL; + + leaf = rtnl_qdisc_get_by_parent(cache, class->c_ifindex, + class->c_handle); + if (!leaf || leaf->q_handle != class->c_info) + return NULL; + + return leaf; +} + +/** @} */ + +/** + * @name Cache Related Functions + * @{ + */ + +/** + * Allocate a cache and fill it with all configured traffic classes + * @arg sk Netlink socket + * @arg ifindex Interface index of the network device + * @arg result Pointer to store the created cache + * + * Allocates a new traffic class cache and fills it with a list of all + * configured traffic classes on a specific network device. Release the + * cache with nl_cache_free(). + * + * @return 0 on success or a negative error code. + */ +int rtnl_class_alloc_cache(struct nl_sock *sk, int ifindex, + struct nl_cache **result) +{ + struct nl_cache * cache; + int err; + + if (!ifindex) { + APPBUG("ifindex must be specified"); + return -NLE_INVAL; + } + + if (!(cache = nl_cache_alloc(&rtnl_class_ops))) + return -NLE_NOMEM; + + cache->c_iarg1 = ifindex; + + if (sk && (err = nl_cache_refill(sk, cache)) < 0) { + nl_cache_free(cache); + return err; + } + + *result = cache; + return 0; +} + +/** + * Search traffic class by interface index and handle + * @arg cache Traffic class cache + * @arg ifindex Interface index + * @arg handle ID of traffic class + * + * Searches a traffic class cache previously allocated with + * rtnl_class_alloc_cache() and searches for a traffi class matching + * the interface index and handle. + * + * The reference counter is incremented before returning the traffic + * class, therefore the reference must be given back with rtnl_class_put() + * after usage. + * + * @return Traffic class or NULL if no match was found. + */ +struct rtnl_class *rtnl_class_get(struct nl_cache *cache, int ifindex, + uint32_t handle) +{ + struct rtnl_class *class; + + if (cache->c_ops != &rtnl_class_ops) + return NULL; + + nl_list_for_each_entry(class, &cache->c_items, ce_list) { + if (class->c_handle == handle && class->c_ifindex == ifindex) { + nl_object_get((struct nl_object *) class); + return class; + } + } + return NULL; +} + +/** @} */ + +/** + * @name Deprecated Functions + * @{ + */ + +/** + * Call a callback for each child of a class + * + * @deprecated Use of this function is deprecated, it does not allow + * to handle the out of memory situation that can occur. + */ +void rtnl_class_foreach_child(struct rtnl_class *class, struct nl_cache *cache, + void (*cb)(struct nl_object *, void *), void *arg) +{ + struct rtnl_class *filter; + + filter = rtnl_class_alloc(); + if (!filter) + return; + + rtnl_tc_set_parent(TC_CAST(filter), class->c_handle); + rtnl_tc_set_ifindex(TC_CAST(filter), class->c_ifindex); + rtnl_tc_set_kind(TC_CAST(filter), class->c_kind); + + nl_cache_foreach_filter(cache, OBJ_CAST(filter), cb, arg); + rtnl_class_put(filter); +} + +/** + * Call a callback for each classifier attached to the class + * + * @deprecated Use of this function is deprecated, it does not allow + * to handle the out of memory situation that can occur. + */ +void rtnl_class_foreach_cls(struct rtnl_class *class, struct nl_cache *cache, + void (*cb)(struct nl_object *, void *), void *arg) +{ + struct rtnl_cls *filter; + + filter = rtnl_cls_alloc(); + if (!filter) + return; + + rtnl_tc_set_ifindex((struct rtnl_tc *) filter, class->c_ifindex); + rtnl_tc_set_parent((struct rtnl_tc *) filter, class->c_parent); + + nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg); + rtnl_cls_put(filter); +} + +/** @} */ + +static struct rtnl_tc_type_ops class_ops = { + .tt_type = RTNL_TC_TYPE_CLASS, + .tt_dump_prefix = "class", + .tt_dump = { + [NL_DUMP_DETAILS] = class_dump_details, + }, +}; + +static struct nl_object_ops class_obj_ops = { + .oo_name = "route/class", + .oo_size = sizeof(struct rtnl_class), + .oo_free_data = rtnl_tc_free_data, + .oo_clone = rtnl_tc_clone, + .oo_dump = { + [NL_DUMP_LINE] = rtnl_tc_dump_line, + [NL_DUMP_DETAILS] = rtnl_tc_dump_details, + [NL_DUMP_STATS] = rtnl_tc_dump_stats, + }, + .oo_compare = rtnl_tc_compare, + .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE), +}; + +static struct nl_cache_ops rtnl_class_ops = { + .co_name = "route/class", + .co_hdrsize = sizeof(struct tcmsg), + .co_msgtypes = { + { RTM_NEWTCLASS, NL_ACT_NEW, "new" }, + { RTM_DELTCLASS, NL_ACT_DEL, "del" }, + { RTM_GETTCLASS, NL_ACT_GET, "get" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_ROUTE, + .co_request_update = &class_request_update, + .co_msg_parser = &class_msg_parser, + .co_obj_ops = &class_obj_ops, +}; + +static void __init class_init(void) +{ + rtnl_tc_type_register(&class_ops); + nl_cache_mngt_register(&rtnl_class_ops); +} + +static void __exit class_exit(void) +{ + nl_cache_mngt_unregister(&rtnl_class_ops); + rtnl_tc_type_unregister(&class_ops); +} + +/** @} */ diff --git a/lib/route/classid.c b/lib/route/classid.c new file mode 100644 index 0000000..f2d3a01 --- /dev/null +++ b/lib/route/classid.c @@ -0,0 +1,456 @@ +/* + * lib/route/classid.c ClassID Management + * + * 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-2013 Thomas Graf + */ + +/** + * @ingroup tc + * @defgroup classid ClassID Management + * @{ + */ + +#include +#include +#include +#include +#include + +struct classid_map +{ + uint32_t classid; + char * name; + struct nl_list_head name_list; +}; + +#define CLASSID_NAME_HT_SIZ 256 + +static struct nl_list_head tbl_name[CLASSID_NAME_HT_SIZ]; + +static void *id_root = NULL; + +static int compare_id(const void *pa, const void *pb) +{ + const struct classid_map *ma = pa; + const struct classid_map *mb = pb; + + if (ma->classid < mb->classid) + return -1; + + if (ma->classid > mb->classid) + return 1; + + return 0; +} + +/* djb2 */ +static unsigned int classid_tbl_hash(const char *str) +{ + unsigned long hash = 5381; + int c; + + while ((c = *str++)) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + return hash % CLASSID_NAME_HT_SIZ; +} + +static int classid_lookup(const char *name, uint32_t *result) +{ + struct classid_map *map; + int n = classid_tbl_hash(name); + + nl_list_for_each_entry(map, &tbl_name[n], name_list) { + if (!strcasecmp(map->name, name)) { + *result = map->classid; + return 0; + } + } + + return -NLE_OBJ_NOTFOUND; +} + +static char *name_lookup(const uint32_t classid) +{ + void *res; + struct classid_map cm = { + .classid = classid, + .name = "search entry", + }; + + if ((res = tfind(&cm, &id_root, &compare_id))) + return (*(struct classid_map **) res)->name; + + return NULL; +} + +/** + * @name Traffic Control Handle Translations + * @{ + */ + +/** + * Convert a traffic control handle to a character string (Reentrant). + * @arg handle traffic control handle + * @arg buf destination buffer + * @arg len buffer length + * + * Converts a tarffic control handle to a character string in the + * form of \c MAJ:MIN and stores it in the specified destination buffer. + * + * @return The destination buffer or the type encoded in hexidecimal + * form if no match was found. + */ +char *rtnl_tc_handle2str(uint32_t handle, char *buf, size_t len) +{ + if (TC_H_ROOT == handle) + snprintf(buf, len, "root"); + else if (TC_H_UNSPEC == handle) + snprintf(buf, len, "none"); + else if (TC_H_INGRESS == handle) + snprintf(buf, len, "ingress"); + else { + char *name; + + if ((name = name_lookup(handle))) + snprintf(buf, len, "%s", name); + else if (0 == TC_H_MAJ(handle)) + snprintf(buf, len, ":%x", TC_H_MIN(handle)); + else if (0 == TC_H_MIN(handle)) + snprintf(buf, len, "%x:", TC_H_MAJ(handle) >> 16); + else + snprintf(buf, len, "%x:%x", + TC_H_MAJ(handle) >> 16, TC_H_MIN(handle)); + } + + return buf; +} + +/** + * Convert a charactering strint to a traffic control handle + * @arg str traffic control handle as character string + * @arg res destination buffer + * + * Converts the provided character string specifying a traffic + * control handle to the corresponding numeric value. + * + * The handle must be provided in one of the following formats: + * - NAME + * - root + * - none + * - MAJ: + * - :MIN + * - NAME:MIN + * - MAJ:MIN + * - MAJMIN + * + * @return 0 on success or a negative error code + */ +int rtnl_tc_str2handle(const char *str, uint32_t *res) +{ + char *colon, *end; + uint32_t h; + int err; + + if (!strcasecmp(str, "root")) { + *res = TC_H_ROOT; + return 0; + } + + if (!strcasecmp(str, "none")) { + *res = TC_H_UNSPEC; + return 0; + } + + if (!strcasecmp(str, "ingress")) { + *res = TC_H_INGRESS; + return 0; + } + + h = strtoul(str, &colon, 16); + + /* MAJ is not a number */ + if (colon == str) { +not_a_number: + if (*colon == ':') { + /* :YYYY */ + h = 0; + } else { + size_t len; + char name[64] = { 0 }; + + if (!(colon = strpbrk(str, ":"))) { + /* NAME */ + return classid_lookup(str, res); + } else { + /* NAME:YYYY */ + len = colon - str; + if (len >= sizeof(name)) + return -NLE_INVAL; + + memcpy(name, str, len); + + if ((err = classid_lookup(name, &h)) < 0) + return err; + + /* Name must point to a qdisc alias */ + if (TC_H_MIN(h)) + return -NLE_INVAL; + + /* NAME: is not allowed */ + if (colon[1] == '\0') + return -NLE_INVAL; + + goto update; + } + } + } + + if (':' == *colon) { + /* check if we would lose bits */ + if (TC_H_MAJ(h)) + return -NLE_RANGE; + h <<= 16; + + if ('\0' == colon[1]) { + /* XXXX: */ + *res = h; + } else { + /* XXXX:YYYY */ + uint32_t l; + +update: + l = strtoul(colon+1, &end, 16); + + /* check if we overlap with major part */ + if (TC_H_MAJ(l)) + return -NLE_RANGE; + + if ('\0' != *end) + return -NLE_INVAL; + + *res = (h | l); + } + } else if ('\0' == *colon) { + /* XXXXYYYY */ + *res = h; + } else + goto not_a_number; + + return 0; +} + +static void free_nothing(void *arg) +{ +} + +static void classid_map_free(struct classid_map *map) +{ + if (!map) + return; + + free(map->name); + free(map); +} + +static void clear_hashtable(void) +{ + int i; + + for (i = 0; i < CLASSID_NAME_HT_SIZ; i++) { + struct classid_map *map, *n; + + nl_list_for_each_entry_safe(map, n, &tbl_name[i], name_list) + classid_map_free(map); + + nl_init_list_head(&tbl_name[i]); + + } + + if (id_root) { + tdestroy(&id_root, &free_nothing); + id_root = NULL; + } +} + +static int classid_map_add(uint32_t classid, const char *name) +{ + struct classid_map *map; + int n; + + if (!(map = calloc(1, sizeof(*map)))) + return -NLE_NOMEM; + + map->classid = classid; + map->name = strdup(name); + + n = classid_tbl_hash(map->name); + nl_list_add_tail(&map->name_list, &tbl_name[n]); + + if (!tsearch((void *) map, &id_root, &compare_id)) { + classid_map_free(map); + return -NLE_NOMEM; + } + + return 0; +} + +/** + * (Re-)read classid file + * + * Rereads the contents of the classid file (typically found at the location + * /etc/libnl/classid) and refreshes the classid maps. + * + * @return 0 on success or a negative error code. + */ +int rtnl_tc_read_classid_file(void) +{ + static time_t last_read; + struct stat st; + char buf[256], *path; + FILE *fd; + int err; + + if (build_sysconf_path(&path, "classid") < 0) + return -NLE_NOMEM; + + /* if stat fails, just (re-)read the file */ + if (stat(path, &st) == 0) { + /* Don't re-read file if file is unchanged */ + if (last_read == st.st_mtime) { + err = 0; + goto errout; + } + } + + if (!(fd = fopen(path, "r"))) { + err = -nl_syserr2nlerr(errno); + goto errout; + } + + clear_hashtable(); + + while (fgets(buf, sizeof(buf), fd)) { + uint32_t classid; + char *ptr, *tok; + + /* ignore comments and empty lines */ + if (*buf == '#' || *buf == '\n' || *buf == '\r') + continue; + + /* token 1 */ + if (!(tok = strtok_r(buf, " \t", &ptr))) { + err = -NLE_INVAL; + goto errout_close; + } + + if ((err = rtnl_tc_str2handle(tok, &classid)) < 0) + goto errout_close; + + if (!(tok = strtok_r(NULL, " \t\n\r#", &ptr))) { + err = -NLE_INVAL; + goto errout_close; + } + + if ((err = classid_map_add(classid, tok)) < 0) + goto errout_close; + } + + err = 0; + last_read = st.st_mtime; + +errout_close: + fclose(fd); +errout: + free(path); + + return err; + +} + +int rtnl_classid_generate(const char *name, uint32_t *result, uint32_t parent) +{ + static uint32_t base = 0x4000 << 16; + uint32_t classid; + char *path; + FILE *fd; + int err = 0; + + if (parent == TC_H_ROOT || parent == TC_H_INGRESS) { + do { + base += (1 << 16); + if (base == TC_H_MAJ(TC_H_ROOT)) + base = 0x4000 << 16; + } while (name_lookup(base)); + + classid = base; + } else { + classid = TC_H_MAJ(parent); + do { + if (TC_H_MIN(++classid) == TC_H_MIN(TC_H_ROOT)) + return -NLE_RANGE; + } while (name_lookup(classid)); + } + + NL_DBG(2, "Generated new classid %#x\n", classid); + + if (build_sysconf_path(&path, "classid") < 0) + return -NLE_NOMEM; + + if (!(fd = fopen(path, "a"))) { + err = -nl_syserr2nlerr(errno); + goto errout; + } + + fprintf(fd, "%x:", TC_H_MAJ(classid) >> 16); + if (TC_H_MIN(classid)) + fprintf(fd, "%x", TC_H_MIN(classid)); + fprintf(fd, "\t\t\t%s\n", name); + + fclose(fd); + + if ((err = classid_map_add(classid, name)) < 0) { + /* + * Error adding classid map, re-read classid file is best + * option here. It is likely to fail as well but better + * than nothing, entry was added to the file already anyway. + */ + rtnl_tc_read_classid_file(); + } + + *result = classid; + err = 0; +errout: + free(path); + + return err; +} + +/** @} */ + +static void __init classid_init(void) +{ + int err, i; + + for (i = 0; i < CLASSID_NAME_HT_SIZ; i++) + nl_init_list_head(&tbl_name[i]); + + if ((err = rtnl_tc_read_classid_file()) < 0) + NL_DBG(1, "Failed to read classid file: %s\n", nl_geterror(err)); +} + +static void free_map(void *map) { + free(((struct classid_map *)map)->name); + free(map); +}; + +static void __exit classid_exit(void) +{ + tdestroy(id_root, free_map); +} +/** @} */ diff --git a/lib/route/cls.c b/lib/route/cls.c new file mode 100644 index 0000000..7a809bb --- /dev/null +++ b/lib/route/cls.c @@ -0,0 +1,441 @@ +/* + * lib/route/classifier.c Classifier + * + * 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-2013 Thomas Graf + */ + +/** + * @ingroup tc + * @defgroup cls Classifiers + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define CLS_ATTR_PRIO (TCA_ATTR_MAX << 1) +#define CLS_ATTR_PROTOCOL (TCA_ATTR_MAX << 2) +/** @endcond */ + +static struct nl_object_ops cls_obj_ops; +static struct nl_cache_ops rtnl_cls_ops; + + +static int cls_build(struct rtnl_cls *cls, int type, int flags, + struct nl_msg **result) +{ + int err, prio, proto; + struct tcmsg *tchdr; + uint32_t required = TCA_ATTR_IFINDEX; + + if ((cls->ce_mask & required) != required) { + APPBUG("ifindex must be specified"); + return -NLE_MISSING_ATTR; + } + + err = rtnl_tc_msg_build(TC_CAST(cls), type, flags, result); + if (err < 0) + return err; + + tchdr = nlmsg_data(nlmsg_hdr(*result)); + prio = rtnl_cls_get_prio(cls); + proto = rtnl_cls_get_protocol(cls); + tchdr->tcm_info = TC_H_MAKE(prio << 16, htons(proto)); + + return 0; +} + +/** + * @name Allocation/Freeing + * @{ + */ + +struct rtnl_cls *rtnl_cls_alloc(void) +{ + struct rtnl_tc *tc; + + tc = TC_CAST(nl_object_alloc(&cls_obj_ops)); + if (tc) + tc->tc_type = RTNL_TC_TYPE_CLS; + + return (struct rtnl_cls *) tc; +} + +void rtnl_cls_put(struct rtnl_cls *cls) +{ + nl_object_put((struct nl_object *) cls); +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ + +void rtnl_cls_set_prio(struct rtnl_cls *cls, uint16_t prio) +{ + cls->c_prio = prio; + cls->ce_mask |= CLS_ATTR_PRIO; +} + +uint16_t rtnl_cls_get_prio(struct rtnl_cls *cls) +{ + if (cls->ce_mask & CLS_ATTR_PRIO) + return cls->c_prio; + else + return 0; +} + +void rtnl_cls_set_protocol(struct rtnl_cls *cls, uint16_t protocol) +{ + cls->c_protocol = protocol; + cls->ce_mask |= CLS_ATTR_PROTOCOL; +} + +uint16_t rtnl_cls_get_protocol(struct rtnl_cls *cls) +{ + if (cls->ce_mask & CLS_ATTR_PROTOCOL) + return cls->c_protocol; + else + return ETH_P_ALL; +} + +/** @} */ + + +/** + * @name Addition/Modification/Deletion + * @{ + */ + +/** + * Build a netlink message requesting the addition of a classifier + * @arg cls Classifier to add + * @arg flags Additional netlink message flags + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_cls_add() with + * the exception that it will not send the message but return it int the + * provided return pointer instead. + * + * @see rtnl_cls_add() + * + * @return 0 on success or a negative error code. + */ +int rtnl_cls_build_add_request(struct rtnl_cls *cls, int flags, + struct nl_msg **result) +{ + if (!(flags & NLM_F_CREATE) && !(cls->ce_mask & CLS_ATTR_PRIO)) { + APPBUG("prio must be specified if not a new classifier"); + return -NLE_MISSING_ATTR; + } + + return cls_build(cls, RTM_NEWTFILTER, flags, result); +} + +/** + * Add/Update classifier + * @arg sk Netlink socket + * @arg cls Classifier to add/update + * @arg flags Additional netlink message flags + * + * Builds a \c RTM_NEWTFILTER netlink message requesting the addition + * of a new classifier and sends the message to the kernel. The + * configuration of the classifier is derived from the attributes of + * the specified traffic class. + * + * The following flags may be specified: + * - \c NLM_F_CREATE: Create classifier if it does not exist, + * otherwise -NLE_OBJ_NOTFOUND is returned. + * - \c NLM_F_EXCL: Return -NLE_EXISTS if a classifier with + * matching handle exists already. + * + * Existing classifiers with matching handles will be updated, unless + * the flag \c NLM_F_EXCL is specified. If no matching classifier + * exists, it will be created if the flag \c NLM_F_CREATE is set, + * otherwise the error -NLE_OBJ_NOTFOUND is returned. + * + * If the parent qdisc does not support classes, the error + * \c NLE_OPNOTSUPP is returned. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @return 0 on success or a negative error code. + */ +int rtnl_cls_add(struct nl_sock *sk, struct rtnl_cls *cls, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_cls_build_add_request(cls, flags, &msg)) < 0) + return err; + + return nl_send_sync(sk, msg); +} + +/** + * Build a netlink message to change classifier attributes + * @arg cls classifier to change + * @arg flags additional netlink message flags + * @arg result Pointer to store resulting message. + * + * Builds a new netlink message requesting a change of a neigh + * attributes. The netlink message header isn't fully equipped with + * all relevant fields and must thus be sent out via nl_send_auto_complete() + * or supplemented as needed. + * + * @return 0 on success or a negative error code. + */ +int rtnl_cls_build_change_request(struct rtnl_cls *cls, int flags, + struct nl_msg **result) +{ + return cls_build(cls, RTM_NEWTFILTER, NLM_F_REPLACE | flags, result); +} + +/** + * Change a classifier + * @arg sk Netlink socket. + * @arg cls classifier to change + * @arg flags additional netlink message flags + * + * Builds a netlink message by calling rtnl_cls_build_change_request(), + * sends the request to the kernel and waits for the next ACK to be + * received and thus blocks until the request has been processed. + * + * @return 0 on sucess or a negative error if an error occured. + */ +int rtnl_cls_change(struct nl_sock *sk, struct rtnl_cls *cls, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_cls_build_change_request(cls, flags, &msg)) < 0) + return err; + + return nl_send_sync(sk, msg); +} + +/** + * Build netlink message requesting the deletion of a classifier + * @arg cls Classifier to delete + * @arg flags Additional netlink message flags + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_cls_delete() with + * the exception that it will not send the message but return it in the + * provided return pointer instead. + * + * @see rtnl_cls_delete() + * + * @return 0 on success or a negative error code. + */ +int rtnl_cls_build_delete_request(struct rtnl_cls *cls, int flags, + struct nl_msg **result) +{ + uint32_t required = CLS_ATTR_PRIO; + + if ((cls->ce_mask & required) != required) { + APPBUG("prio must be specified"); + return -NLE_MISSING_ATTR; + } + + return cls_build(cls, RTM_DELTFILTER, flags, result); +} + +/** + * Delete classifier + * @arg sk Netlink socket + * @arg cls Classifier to delete + * @arg flags Additional netlink message flags + * + * Builds a \c RTM_DELTFILTER netlink message requesting the deletion + * of a classifier and sends the message to the kernel. + * + * The message is constructed out of the following attributes: + * - \c ifindex (required) + * - \c prio (required) + * - \c protocol (required) + * - \c handle (required) + * - \c parent (optional, if not specified parent equals root-qdisc) + * - \c kind (optional, must match if provided) + * + * All other classifier attributes including all class type specific + * attributes are ignored. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @return 0 on success or a negative error code. + */ +int rtnl_cls_delete(struct nl_sock *sk, struct rtnl_cls *cls, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_cls_build_delete_request(cls, flags, &msg)) < 0) + return err; + + return nl_send_sync(sk, msg); +} + +/** @} */ + +/** + * @name Cache Related Functions + * @{ + */ + +/** + * Allocate a cache and fill it with all configured classifiers + * @arg sk Netlink socket + * @arg ifindex Interface index of the network device + * @arg parent Parent qdisc/traffic class class + * @arg result Pointer to store the created cache + * + * Allocates a new classifier cache and fills it with a list of all + * configured classifier attached to the specified parent qdisc/traffic + * class on the specified network device. Release the cache with + * nl_cache_free(). + * + * @return 0 on success or a negative error code. + */ +int rtnl_cls_alloc_cache(struct nl_sock *sk, int ifindex, uint32_t parent, struct nl_cache **result) +{ + struct nl_cache * cache; + int err; + + if (!(cache = nl_cache_alloc(&rtnl_cls_ops))) + return -NLE_NOMEM; + + cache->c_iarg1 = ifindex; + cache->c_iarg2 = parent; + + if (sk && (err = nl_cache_refill(sk, cache)) < 0) { + nl_cache_free(cache); + return err; + } + + *result = cache; + return 0; +} + +/** @} */ + +static void cls_dump_line(struct rtnl_tc *tc, struct nl_dump_params *p) +{ + struct rtnl_cls *cls = (struct rtnl_cls *) tc; + char buf[32]; + + nl_dump(p, " prio %u protocol %s", cls->c_prio, + nl_ether_proto2str(cls->c_protocol, buf, sizeof(buf))); +} + +static int cls_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *nlh, struct nl_parser_param *pp) +{ + struct rtnl_cls *cls; + int err; + + if (!(cls = rtnl_cls_alloc())) + return -NLE_NOMEM; + + if ((err = rtnl_tc_msg_parse(nlh, TC_CAST(cls))) < 0) + goto errout; + + cls->c_prio = TC_H_MAJ(cls->c_info) >> 16; + cls->c_protocol = ntohs(TC_H_MIN(cls->c_info)); + + err = pp->pp_cb(OBJ_CAST(cls), pp); +errout: + rtnl_cls_put(cls); + + return err; +} + +static int cls_request_update(struct nl_cache *cache, struct nl_sock *sk) +{ + struct tcmsg tchdr = { + .tcm_family = AF_UNSPEC, + .tcm_ifindex = cache->c_iarg1, + .tcm_parent = cache->c_iarg2, + }; + + return nl_send_simple(sk, RTM_GETTFILTER, NLM_F_DUMP, &tchdr, + sizeof(tchdr)); +} + +static struct rtnl_tc_type_ops cls_ops = { + .tt_type = RTNL_TC_TYPE_CLS, + .tt_dump_prefix = "cls", + .tt_dump = { + [NL_DUMP_LINE] = cls_dump_line, + }, +}; + +static struct nl_cache_ops rtnl_cls_ops = { + .co_name = "route/cls", + .co_hdrsize = sizeof(struct tcmsg), + .co_msgtypes = { + { RTM_NEWTFILTER, NL_ACT_NEW, "new" }, + { RTM_DELTFILTER, NL_ACT_DEL, "del" }, + { RTM_GETTFILTER, NL_ACT_GET, "get" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_ROUTE, + .co_request_update = cls_request_update, + .co_msg_parser = cls_msg_parser, + .co_obj_ops = &cls_obj_ops, +}; + +static struct nl_object_ops cls_obj_ops = { + .oo_name = "route/cls", + .oo_size = sizeof(struct rtnl_cls), + .oo_free_data = rtnl_tc_free_data, + .oo_clone = rtnl_tc_clone, + .oo_dump = { + [NL_DUMP_LINE] = rtnl_tc_dump_line, + [NL_DUMP_DETAILS] = rtnl_tc_dump_details, + [NL_DUMP_STATS] = rtnl_tc_dump_stats, + }, + .oo_compare = rtnl_tc_compare, + .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE), +}; + +static void __init cls_init(void) +{ + rtnl_tc_type_register(&cls_ops); + nl_cache_mngt_register(&rtnl_cls_ops); +} + +static void __exit cls_exit(void) +{ + nl_cache_mngt_unregister(&rtnl_cls_ops); + rtnl_tc_type_unregister(&cls_ops); +} + +/** @} */ diff --git a/lib/route/cls/basic.c b/lib/route/cls/basic.c new file mode 100644 index 0000000..fb1c382 --- /dev/null +++ b/lib/route/cls/basic.c @@ -0,0 +1,229 @@ +/* + * lib/route/cls/basic.c Basic Classifier + * + * 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-2013 Thomas Graf + */ + +/** + * @ingroup cls + * @defgroup cls_basic Basic Classifier + * + * @par Introduction + * The basic classifier is the simplest form of a classifier. It does + * not have any special classification capabilities, instead it can be + * used to classify exclusively based on extended matches or to + * create a "catch-all" filter. + * + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include + +struct rtnl_basic +{ + uint32_t b_target; + struct rtnl_ematch_tree * b_ematch; + int b_mask; +}; + +/** @cond SKIP */ +#define BASIC_ATTR_TARGET 0x001 +#define BASIC_ATTR_EMATCH 0x002 +/** @endcond */ + +static struct nla_policy basic_policy[TCA_BASIC_MAX+1] = { + [TCA_BASIC_CLASSID] = { .type = NLA_U32 }, + [TCA_BASIC_EMATCHES] = { .type = NLA_NESTED }, +}; + +static int basic_clone(void *_dst, void *_src) +{ + return -NLE_OPNOTSUPP; +} + +static void basic_free_data(struct rtnl_tc *tc, void *data) +{ + struct rtnl_basic *b = data; + + if (!b) + return; + + rtnl_ematch_tree_free(b->b_ematch); +} + +static int basic_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct nlattr *tb[TCA_BASIC_MAX + 1]; + struct rtnl_basic *b = data; + int err; + + err = tca_parse(tb, TCA_BASIC_MAX, tc, basic_policy); + if (err < 0) + return err; + + if (tb[TCA_BASIC_CLASSID]) { + b->b_target = nla_get_u32(tb[TCA_BASIC_CLASSID]); + b->b_mask |= BASIC_ATTR_TARGET; + } + + if (tb[TCA_BASIC_EMATCHES]) { + if ((err = rtnl_ematch_parse_attr(tb[TCA_BASIC_EMATCHES], + &b->b_ematch)) < 0) + return err; + + if (b->b_ematch) + b->b_mask |= BASIC_ATTR_EMATCH; + } + + return 0; +} + +static void basic_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_basic *b = data; + char buf[32]; + + if (!b) + return; + + if (b->b_mask & BASIC_ATTR_EMATCH) + nl_dump(p, " ematch"); + else + nl_dump(p, " match-all"); + + if (b->b_mask & BASIC_ATTR_TARGET) + nl_dump(p, " target %s", + rtnl_tc_handle2str(b->b_target, buf, sizeof(buf))); +} + +static void basic_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_basic *b = data; + + if (!b) + return; + + if (b->b_mask & BASIC_ATTR_EMATCH) { + nl_dump_line(p, " ematch "); + rtnl_ematch_tree_dump(b->b_ematch, p); + } else + nl_dump(p, "no options.\n"); +} + +static int basic_msg_fill(struct rtnl_tc *tc, void *data, + struct nl_msg *msg) +{ + struct rtnl_basic *b = data; + + if (!b) + return 0; + + if (!(b->b_mask & BASIC_ATTR_TARGET)) + return -NLE_MISSING_ATTR; + + NLA_PUT_U32(msg, TCA_BASIC_CLASSID, b->b_target); + + if (b->b_mask & BASIC_ATTR_EMATCH && + rtnl_ematch_fill_attr(msg, TCA_BASIC_EMATCHES, b->b_ematch) < 0) + goto nla_put_failure; + + return 0; + +nla_put_failure: + return -NLE_NOMEM; +} + +/** + * @name Attribute Modifications + * @{ + */ + +void rtnl_basic_set_target(struct rtnl_cls *cls, uint32_t target) +{ + struct rtnl_basic *b; + + if (!(b = rtnl_tc_data(TC_CAST(cls)))) + return; + + b->b_target = target; + b->b_mask |= BASIC_ATTR_TARGET; +} + +uint32_t rtnl_basic_get_target(struct rtnl_cls *cls) +{ + struct rtnl_basic *b; + + if (!(b = rtnl_tc_data(TC_CAST(cls)))) + return 0; + + return b->b_target; +} + +void rtnl_basic_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree) +{ + struct rtnl_basic *b; + + if (!(b = rtnl_tc_data(TC_CAST(cls)))) + return; + + if (b->b_ematch) { + rtnl_ematch_tree_free(b->b_ematch); + b->b_mask &= ~BASIC_ATTR_EMATCH; + } + + b->b_ematch = tree; + + if (tree) + b->b_mask |= BASIC_ATTR_EMATCH; +} + +struct rtnl_ematch_tree *rtnl_basic_get_ematch(struct rtnl_cls *cls) +{ + struct rtnl_basic *b; + + if (!(b = rtnl_tc_data(TC_CAST(cls)))) + return NULL; + + return b->b_ematch; +} + +/** @} */ + +static struct rtnl_tc_ops basic_ops = { + .to_kind = "basic", + .to_type = RTNL_TC_TYPE_CLS, + .to_size = sizeof(struct rtnl_basic), + .to_msg_parser = basic_msg_parser, + .to_clone = basic_clone, + .to_free_data = basic_free_data, + .to_msg_fill = basic_msg_fill, + .to_dump = { + [NL_DUMP_LINE] = basic_dump_line, + [NL_DUMP_DETAILS] = basic_dump_details, + }, +}; + +static void __init basic_init(void) +{ + rtnl_tc_register(&basic_ops); +} + +static void __exit basic_exit(void) +{ + rtnl_tc_unregister(&basic_ops); +} + +/** @} */ diff --git a/lib/route/cls/cgroup.c b/lib/route/cls/cgroup.c new file mode 100644 index 0000000..c5b7561 --- /dev/null +++ b/lib/route/cls/cgroup.c @@ -0,0 +1,189 @@ +/* + * lib/route/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 Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2009-2013 Thomas Graf + */ + +/** + * @ingroup cls + * @defgroup cls_cgroup Control Groups Classifier + * + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define CGROUP_ATTR_EMATCH 0x001 +/** @endcond */ + +static struct nla_policy cgroup_policy[TCA_CGROUP_MAX+1] = { + [TCA_CGROUP_EMATCHES] = { .type = NLA_NESTED }, +}; + +static int cgroup_clone(void *dst, void *src) +{ + return -NLE_OPNOTSUPP; +} + +static void cgroup_free_data(struct rtnl_tc *tc, void *data) +{ + struct rtnl_cgroup *c = data; + + if (!c) + return; + + rtnl_ematch_tree_free(c->cg_ematch); +} + +static int cgroup_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct nlattr *tb[TCA_CGROUP_MAX + 1]; + struct rtnl_cgroup *c = data; + int err; + + err = tca_parse(tb, TCA_CGROUP_MAX, tc, cgroup_policy); + if (err < 0) + return err; + + if (tb[TCA_CGROUP_EMATCHES]) { + if ((err = rtnl_ematch_parse_attr(tb[TCA_CGROUP_EMATCHES], + &c->cg_ematch)) < 0) + return err; + c->cg_mask |= CGROUP_ATTR_EMATCH; + } + +#if 0 + TODO: + TCA_CGROUP_ACT, + TCA_CGROUP_POLICE, +#endif + + return 0; +} + +static void cgroup_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_cgroup *c = data; + + if (!c) + return; + + if (c->cg_mask & CGROUP_ATTR_EMATCH) + nl_dump(p, " ematch"); + else + nl_dump(p, " match-all"); +} + +static void cgroup_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_cgroup *c = data; + + if (!c) + return; + + if (c->cg_mask & CGROUP_ATTR_EMATCH) { + nl_dump_line(p, " ematch "); + + if (c->cg_ematch) + rtnl_ematch_tree_dump(c->cg_ematch, p); + else + nl_dump(p, ""); + } else + nl_dump(p, "no options"); +} + +static int cgroup_fill_msg(struct rtnl_tc *tc, void *data, + struct nl_msg *msg) +{ + struct rtnl_cgroup *c = data; + + if (!c) + BUG(); + + if (!(tc->ce_mask & TCA_ATTR_HANDLE)) + return -NLE_MISSING_ATTR; + + if (c->cg_mask & CGROUP_ATTR_EMATCH) + return rtnl_ematch_fill_attr(msg, TCA_CGROUP_EMATCHES, + c->cg_ematch); + + return 0; +} + + +/** + * @name Attribute Modifications + * @{ + */ + +void rtnl_cgroup_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree) +{ + struct rtnl_cgroup *c; + + if (!(c = rtnl_tc_data(TC_CAST(cls)))) + BUG(); + + if (c->cg_ematch) { + rtnl_ematch_tree_free(c->cg_ematch); + c->cg_mask &= ~CGROUP_ATTR_EMATCH; + } + + c->cg_ematch = tree; + + if (tree) + c->cg_mask |= CGROUP_ATTR_EMATCH; +} + +struct rtnl_ematch_tree *rtnl_cgroup_get_ematch(struct rtnl_cls *cls) +{ + struct rtnl_cgroup *c; + + if (!(c = rtnl_tc_data(TC_CAST(cls)))) + BUG(); + + return c->cg_ematch; +} + +/** @} */ + +static struct rtnl_tc_ops cgroup_ops = { + .to_kind = "cgroup", + .to_type = RTNL_TC_TYPE_CLS, + .to_size = sizeof(struct rtnl_cgroup), + .to_clone = cgroup_clone, + .to_msg_parser = cgroup_msg_parser, + .to_free_data = cgroup_free_data, + .to_msg_fill = cgroup_fill_msg, + .to_dump = { + [NL_DUMP_LINE] = cgroup_dump_line, + [NL_DUMP_DETAILS] = cgroup_dump_details, + }, +}; + +static void __init cgroup_init(void) +{ + rtnl_tc_register(&cgroup_ops); +} + +static void __exit cgroup_exit(void) +{ + rtnl_tc_unregister(&cgroup_ops); +} + +/** @} */ diff --git a/lib/route/cls/ematch.c b/lib/route/cls/ematch.c new file mode 100644 index 0000000..89b5067 --- /dev/null +++ b/lib/route/cls/ematch.c @@ -0,0 +1,701 @@ +/* + * lib/route/cls/ematch.c Extended Matches + * + * 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-2013 Thomas Graf + */ + +/** + * @ingroup cls + * @defgroup ematch Extended Match + * + * @{ + */ + +#include +#include +#include +#include +#include +#include + +#include "ematch_syntax.h" +#include "ematch_grammar.h" + +/** + * @name Module API + * @{ + */ + +static NL_LIST_HEAD(ematch_ops_list); + +/** + * Register ematch module + * @arg ops Module operations. + * + * This function must be called by each ematch module at initialization + * time. It registers the calling module as available module. + * + * @return 0 on success or a negative error code. + */ +int rtnl_ematch_register(struct rtnl_ematch_ops *ops) +{ + if (rtnl_ematch_lookup_ops(ops->eo_kind)) + return -NLE_EXIST; + + NL_DBG(1, "ematch module \"%s\" registered\n", ops->eo_name); + + nl_list_add_tail(&ops->eo_list, &ematch_ops_list); + + return 0; +} + +/** + * Lookup ematch module by identification number. + * @arg kind Module kind. + * + * Searches the list of registered ematch modules for match and returns it. + * + * @return Module operations or NULL if not found. + */ +struct rtnl_ematch_ops *rtnl_ematch_lookup_ops(int kind) +{ + struct rtnl_ematch_ops *ops; + + nl_list_for_each_entry(ops, &ematch_ops_list, eo_list) + if (ops->eo_kind == kind) + return ops; + + return NULL; +} + +/** + * Lookup ematch module by name + * @arg name Name of ematch module. + * + * Searches the list of registered ematch modules for a match and returns it. + * + * @return Module operations or NULL if not fuond. + */ +struct rtnl_ematch_ops *rtnl_ematch_lookup_ops_by_name(const char *name) +{ + struct rtnl_ematch_ops *ops; + + nl_list_for_each_entry(ops, &ematch_ops_list, eo_list) + if (!strcasecmp(ops->eo_name, name)) + return ops; + + return NULL; +} + +/** @} */ + +/** + * @name Match + */ + +/** + * Allocate ematch object. + * + * Allocates and initializes an ematch object. + * + * @return New ematch object or NULL. + */ +struct rtnl_ematch *rtnl_ematch_alloc(void) +{ + struct rtnl_ematch *e; + + if (!(e = calloc(1, sizeof(*e)))) + return NULL; + + NL_DBG(2, "allocated ematch %p\n", e); + + NL_INIT_LIST_HEAD(&e->e_list); + NL_INIT_LIST_HEAD(&e->e_childs); + + return e; +} + +/** + * Add ematch to the end of the parent's list of children. + * @arg parent parent ematch object + * @arg child ematch object to be added to parent + * + * The parent must be a container ematch. + */ +int rtnl_ematch_add_child(struct rtnl_ematch *parent, + struct rtnl_ematch *child) +{ + if (parent->e_kind != TCF_EM_CONTAINER) + return -NLE_OPNOTSUPP; + + NL_DBG(2, "added ematch %p \"%s\" to container %p\n", + child, child->e_ops->eo_name, parent); + + nl_list_add_tail(&child->e_list, &parent->e_childs); + + return 0; +} + +/** + * Remove ematch from the list of ematches it is linked to. + * @arg ematch ematch object + */ +void rtnl_ematch_unlink(struct rtnl_ematch *ematch) +{ + NL_DBG(2, "unlinked ematch %p from any lists\n", ematch); + + if (!nl_list_empty(&ematch->e_childs)) + NL_DBG(1, "warning: ematch %p with childs was unlinked\n", + ematch); + + nl_list_del(&ematch->e_list); + nl_init_list_head(&ematch->e_list); +} + +void rtnl_ematch_free(struct rtnl_ematch *ematch) +{ + NL_DBG(2, "freed ematch %p\n", ematch); + rtnl_ematch_unlink(ematch); + free(ematch->e_data); + free(ematch); +} + +int rtnl_ematch_set_ops(struct rtnl_ematch *ematch, struct rtnl_ematch_ops *ops) +{ + if (ematch->e_ops) + return -NLE_EXIST; + + ematch->e_ops = ops; + ematch->e_kind = ops->eo_kind; + + if (ops->eo_datalen) { + ematch->e_data = calloc(1, ops->eo_datalen); + if (!ematch->e_data) + return -NLE_NOMEM; + + ematch->e_datalen = ops->eo_datalen; + } + + return 0; +} + +int rtnl_ematch_set_kind(struct rtnl_ematch *ematch, uint16_t kind) +{ + struct rtnl_ematch_ops *ops; + + if (ematch->e_kind) + return -NLE_EXIST; + + ematch->e_kind = kind; + + if ((ops = rtnl_ematch_lookup_ops(kind))) + rtnl_ematch_set_ops(ematch, ops); + + return 0; +} + +int rtnl_ematch_set_name(struct rtnl_ematch *ematch, const char *name) +{ + struct rtnl_ematch_ops *ops; + + if (ematch->e_kind) + return -NLE_EXIST; + + if (!(ops = rtnl_ematch_lookup_ops_by_name(name))) + return -NLE_OPNOTSUPP; + + rtnl_ematch_set_ops(ematch, ops); + + return 0; +} + +void rtnl_ematch_set_flags(struct rtnl_ematch *ematch, uint16_t flags) +{ + ematch->e_flags |= flags; +} + +void rtnl_ematch_unset_flags(struct rtnl_ematch *ematch, uint16_t flags) +{ + ematch->e_flags &= ~flags; +} + +uint16_t rtnl_ematch_get_flags(struct rtnl_ematch *ematch) +{ + return ematch->e_flags; +} + +void *rtnl_ematch_data(struct rtnl_ematch *ematch) +{ + return ematch->e_data; +} + +/** @} */ + +/** + * @name Tree + */ + +/** + * Allocate ematch tree object + * @arg progid program id + */ +struct rtnl_ematch_tree *rtnl_ematch_tree_alloc(uint16_t progid) +{ + struct rtnl_ematch_tree *tree; + + if (!(tree = calloc(1, sizeof(*tree)))) + return NULL; + + NL_INIT_LIST_HEAD(&tree->et_list); + tree->et_progid = progid; + + NL_DBG(2, "allocated new ematch tree %p, progid=%u\n", tree, progid); + + return tree; +} + +static void free_ematch_list(struct nl_list_head *head) +{ + struct rtnl_ematch *pos, *next; + + nl_list_for_each_entry_safe(pos, next, head, e_list) { + if (!nl_list_empty(&pos->e_childs)) + free_ematch_list(&pos->e_childs); + rtnl_ematch_free(pos); + } +} + +/** + * Free ematch tree object + * @arg tree ematch tree object + * + * This function frees the ematch tree and all ematches attached to it. + */ +void rtnl_ematch_tree_free(struct rtnl_ematch_tree *tree) +{ + if (!tree) + return; + + free_ematch_list(&tree->et_list); + free(tree); + + NL_DBG(2, "Freed ematch tree %p\n", tree); +} + +/** + * Add ematch object to the end of the ematch tree + * @arg tree ematch tree object + * @arg ematch ematch object to add + */ +void rtnl_ematch_tree_add(struct rtnl_ematch_tree *tree, + struct rtnl_ematch *ematch) +{ + nl_list_add_tail(&ematch->e_list, &tree->et_list); +} + +static inline uint32_t container_ref(struct rtnl_ematch *ematch) +{ + return *((uint32_t *) rtnl_ematch_data(ematch)); +} + +static int link_tree(struct rtnl_ematch *index[], int nmatches, int pos, + struct nl_list_head *root) +{ + struct rtnl_ematch *ematch; + int i; + + for (i = pos; i < nmatches; i++) { + ematch = index[i]; + + nl_list_add_tail(&ematch->e_list, root); + + if (ematch->e_kind == TCF_EM_CONTAINER) + link_tree(index, nmatches, container_ref(ematch), + &ematch->e_childs); + + if (!(ematch->e_flags & TCF_EM_REL_MASK)) + return 0; + } + + /* Last entry in chain can't possibly have no relation */ + return -NLE_INVAL; +} + +static struct nla_policy tree_policy[TCA_EMATCH_TREE_MAX+1] = { + [TCA_EMATCH_TREE_HDR] = { .minlen=sizeof(struct tcf_ematch_tree_hdr) }, + [TCA_EMATCH_TREE_LIST] = { .type = NLA_NESTED }, +}; + +/** + * Parse ematch netlink attributes + * + * @return 0 on success or a negative error code. + */ +int rtnl_ematch_parse_attr(struct nlattr *attr, struct rtnl_ematch_tree **result) +{ + struct nlattr *a, *tb[TCA_EMATCH_TREE_MAX+1]; + struct tcf_ematch_tree_hdr *thdr; + struct rtnl_ematch_tree *tree; + struct rtnl_ematch **index; + int nmatches = 0, err, remaining; + + NL_DBG(2, "Parsing attribute %p as ematch tree\n", attr); + + err = nla_parse_nested(tb, TCA_EMATCH_TREE_MAX, attr, tree_policy); + if (err < 0) + return err; + + if (!tb[TCA_EMATCH_TREE_HDR]) + return -NLE_MISSING_ATTR; + + thdr = nla_data(tb[TCA_EMATCH_TREE_HDR]); + + /* Ignore empty trees */ + if (thdr->nmatches == 0) { + NL_DBG(2, "Ignoring empty ematch configuration\n"); + return 0; + } + + if (!tb[TCA_EMATCH_TREE_LIST]) + return -NLE_MISSING_ATTR; + + NL_DBG(2, "ematch tree found with nmatches=%u, progid=%u\n", + thdr->nmatches, thdr->progid); + + /* + * Do some basic sanity checking since we will allocate + * index[thdr->nmatches]. Calculate how many ematch headers fit into + * the provided data and make sure nmatches does not exceed it. + */ + if (thdr->nmatches > (nla_len(tb[TCA_EMATCH_TREE_LIST]) / + nla_total_size(sizeof(struct tcf_ematch_hdr)))) + return -NLE_INVAL; + + if (!(index = calloc(thdr->nmatches, sizeof(struct rtnl_ematch *)))) + return -NLE_NOMEM; + + if (!(tree = rtnl_ematch_tree_alloc(thdr->progid))) { + err = -NLE_NOMEM; + goto errout; + } + + nla_for_each_nested(a, tb[TCA_EMATCH_TREE_LIST], remaining) { + struct rtnl_ematch_ops *ops; + struct tcf_ematch_hdr *hdr; + struct rtnl_ematch *ematch; + void *data; + size_t len; + + NL_DBG(3, "parsing ematch attribute %d, len=%u\n", + nmatches+1, nla_len(a)); + + if (nla_len(a) < sizeof(*hdr)) { + err = -NLE_INVAL; + goto errout; + } + + /* Quit as soon as we've parsed more matches than expected */ + if (nmatches >= thdr->nmatches) { + err = -NLE_RANGE; + goto errout; + } + + hdr = nla_data(a); + data = nla_data(a) + NLA_ALIGN(sizeof(*hdr)); + len = nla_len(a) - NLA_ALIGN(sizeof(*hdr)); + + NL_DBG(3, "ematch attribute matchid=%u, kind=%u, flags=%u\n", + hdr->matchid, hdr->kind, hdr->flags); + + /* + * Container matches contain a reference to another sequence + * of matches. Ensure that the reference is within boundries. + */ + if (hdr->kind == TCF_EM_CONTAINER && + *((uint32_t *) data) >= thdr->nmatches) { + err = -NLE_INVAL; + goto errout; + } + + if (!(ematch = rtnl_ematch_alloc())) { + err = -NLE_NOMEM; + goto errout; + } + + ematch->e_id = hdr->matchid; + ematch->e_kind = hdr->kind; + ematch->e_flags = hdr->flags; + + if ((ops = rtnl_ematch_lookup_ops(hdr->kind))) { + if (ops->eo_minlen && len < ops->eo_minlen) { + rtnl_ematch_free(ematch); + err = -NLE_INVAL; + goto errout; + } + + rtnl_ematch_set_ops(ematch, ops); + + if (ops->eo_parse && + (err = ops->eo_parse(ematch, data, len)) < 0) { + rtnl_ematch_free(ematch); + goto errout; + } + } + + NL_DBG(3, "index[%d] = %p\n", nmatches, ematch); + index[nmatches++] = ematch; + } + + if (nmatches != thdr->nmatches) { + err = -NLE_INVAL; + goto errout; + } + + err = link_tree(index, nmatches, 0, &tree->et_list); + if (err < 0) + goto errout; + + free(index); + *result = tree; + + return 0; + +errout: + rtnl_ematch_tree_free(tree); + free(index); + return err; +} + +static void dump_ematch_sequence(struct nl_list_head *head, + struct nl_dump_params *p) +{ + struct rtnl_ematch *match; + + nl_list_for_each_entry(match, head, e_list) { + if (match->e_flags & TCF_EM_INVERT) + nl_dump(p, "!"); + + if (match->e_kind == TCF_EM_CONTAINER) { + nl_dump(p, "("); + dump_ematch_sequence(&match->e_childs, p); + nl_dump(p, ")"); + } else if (!match->e_ops) { + nl_dump(p, "[unknown ematch %d]", match->e_kind); + } else { + if (match->e_ops->eo_dump) + match->e_ops->eo_dump(match, p); + else + nl_dump(p, "[data]"); + } + + switch (match->e_flags & TCF_EM_REL_MASK) { + case TCF_EM_REL_AND: + nl_dump(p, " AND "); + break; + case TCF_EM_REL_OR: + nl_dump(p, " OR "); + break; + default: + /* end of first level ematch sequence */ + return; + } + } +} + +void rtnl_ematch_tree_dump(struct rtnl_ematch_tree *tree, + struct nl_dump_params *p) +{ + if (!tree) + BUG(); + + dump_ematch_sequence(&tree->et_list, p); + nl_dump(p, "\n"); +} + +static int update_container_index(struct nl_list_head *list, int *index) +{ + struct rtnl_ematch *e; + + nl_list_for_each_entry(e, list, e_list) + e->e_index = (*index)++; + + nl_list_for_each_entry(e, list, e_list) { + if (e->e_kind == TCF_EM_CONTAINER) { + int err; + + if (nl_list_empty(&e->e_childs)) + return -NLE_OBJ_NOTFOUND; + + *((uint32_t *) e->e_data) = *index; + + err = update_container_index(&e->e_childs, index); + if (err < 0) + return err; + } + } + + return 0; +} + +static int fill_ematch_sequence(struct nl_msg *msg, struct nl_list_head *list) +{ + struct rtnl_ematch *e; + + nl_list_for_each_entry(e, list, e_list) { + struct tcf_ematch_hdr match = { + .matchid = e->e_id, + .kind = e->e_kind, + .flags = e->e_flags, + }; + struct nlattr *attr; + int err = 0; + + if (!(attr = nla_nest_start(msg, e->e_index + 1))) + return -NLE_NOMEM; + + if (nlmsg_append(msg, &match, sizeof(match), 0) < 0) + return -NLE_NOMEM; + + if (e->e_ops->eo_fill) + err = e->e_ops->eo_fill(e, msg); + else if (e->e_flags & TCF_EM_SIMPLE) + err = nlmsg_append(msg, e->e_data, 4, 0); + else if (e->e_datalen > 0) + err = nlmsg_append(msg, e->e_data, e->e_datalen, 0); + + NL_DBG(3, "msg %p: added ematch [%d] id=%d kind=%d flags=%d\n", + msg, e->e_index, match.matchid, match.kind, match.flags); + + if (err < 0) + return -NLE_NOMEM; + + nla_nest_end(msg, attr); + } + + nl_list_for_each_entry(e, list, e_list) { + if (e->e_kind == TCF_EM_CONTAINER && + fill_ematch_sequence(msg, &e->e_childs) < 0) + return -NLE_NOMEM; + } + + return 0; +} + +int rtnl_ematch_fill_attr(struct nl_msg *msg, int attrid, + struct rtnl_ematch_tree *tree) +{ + struct tcf_ematch_tree_hdr thdr = { + .progid = tree->et_progid, + }; + struct nlattr *list, *topattr; + int err, index = 0; + + /* Assign index number to each ematch to allow for references + * to be made while constructing the sequence of matches. */ + err = update_container_index(&tree->et_list, &index); + if (err < 0) + return err; + + if (!(topattr = nla_nest_start(msg, attrid))) + goto nla_put_failure; + + thdr.nmatches = index; + NLA_PUT(msg, TCA_EMATCH_TREE_HDR, sizeof(thdr), &thdr); + + if (!(list = nla_nest_start(msg, TCA_EMATCH_TREE_LIST))) + goto nla_put_failure; + + if (fill_ematch_sequence(msg, &tree->et_list) < 0) + goto nla_put_failure; + + nla_nest_end(msg, list); + + nla_nest_end(msg, topattr); + + return 0; + +nla_put_failure: + return -NLE_NOMEM; +} + +/** @} */ + +extern int ematch_parse(void *, char **, struct nl_list_head *); + +int rtnl_ematch_parse_expr(const char *expr, char **errp, + struct rtnl_ematch_tree **result) +{ + struct rtnl_ematch_tree *tree; + YY_BUFFER_STATE buf = NULL; + yyscan_t scanner = NULL; + int err; + + NL_DBG(2, "Parsing ematch expression \"%s\"\n", expr); + + if (!(tree = rtnl_ematch_tree_alloc(RTNL_EMATCH_PROGID))) + return -NLE_FAILURE; + + if ((err = ematch_lex_init(&scanner)) < 0) { + err = -NLE_FAILURE; + goto errout; + } + + buf = ematch__scan_string(expr, scanner); + + if ((err = ematch_parse(scanner, errp, &tree->et_list)) != 0) { + ematch__delete_buffer(buf, scanner); + err = -NLE_PARSE_ERR; + goto errout; + } + + if (scanner) + ematch_lex_destroy(scanner); + + *result = tree; + + return 0; + +errout: + if (scanner) + ematch_lex_destroy(scanner); + + rtnl_ematch_tree_free(tree); + + return err; +} + +static const char *layer_txt[] = { + [TCF_LAYER_LINK] = "eth", + [TCF_LAYER_NETWORK] = "ip", + [TCF_LAYER_TRANSPORT] = "tcp", +}; + +char *rtnl_ematch_offset2txt(uint8_t layer, uint16_t offset, char *buf, size_t len) +{ + snprintf(buf, len, "%s+%u", + (layer <= TCF_LAYER_MAX) ? layer_txt[layer] : "?", + offset); + + return buf; +} + +static const char *operand_txt[] = { + [TCF_EM_OPND_EQ] = "=", + [TCF_EM_OPND_LT] = "<", + [TCF_EM_OPND_GT] = ">", +}; + +char *rtnl_ematch_opnd2txt(uint8_t opnd, char *buf, size_t len) +{ + snprintf(buf, len, "%s", + opnd <= ARRAY_SIZE(operand_txt) ? operand_txt[opnd] : "?"); + + return buf; +} + +/** @} */ diff --git a/lib/route/cls/ematch/cmp.c b/lib/route/cls/ematch/cmp.c new file mode 100644 index 0000000..2997cdb --- /dev/null +++ b/lib/route/cls/ematch/cmp.c @@ -0,0 +1,93 @@ +/* + * lib/route/cls/ematch/cmp.c Simple packet data comparison ematch + * + * 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-2013 Thomas Graf + */ + +/** + * @ingroup ematch + * @defgroup em_cmp Simple packet data comparison + * + * @{ + */ + +#include +#include +#include +#include +#include + +void rtnl_ematch_cmp_set(struct rtnl_ematch *e, struct tcf_em_cmp *cfg) +{ + memcpy(rtnl_ematch_data(e), cfg, sizeof(*cfg)); +} + +struct tcf_em_cmp *rtnl_ematch_cmp_get(struct rtnl_ematch *e) +{ + return rtnl_ematch_data(e); +} + +static int cmp_parse(struct rtnl_ematch *e, void *data, size_t len) +{ + memcpy(rtnl_ematch_data(e), data, len); + + return 0; +} + +static const char *align_txt[] = { + [TCF_EM_ALIGN_U8] = "u8", + [TCF_EM_ALIGN_U16] = "u16", + [TCF_EM_ALIGN_U32] = "u32" +}; + +static const char *layer_txt[] = { + [TCF_LAYER_LINK] = "eth", + [TCF_LAYER_NETWORK] = "ip", + [TCF_LAYER_TRANSPORT] = "tcp" +}; + +static const char *operand_txt[] = { + [TCF_EM_OPND_EQ] = "=", + [TCF_EM_OPND_LT] = "<", + [TCF_EM_OPND_GT] = ">", +}; + +static void cmp_dump(struct rtnl_ematch *e, struct nl_dump_params *p) +{ + struct tcf_em_cmp *cmp = rtnl_ematch_data(e); + + if (cmp->flags & TCF_EM_CMP_TRANS) + nl_dump(p, "ntoh%c(", (cmp->align == TCF_EM_ALIGN_U32) ? 'l' : 's'); + + nl_dump(p, "%s at %s+%u", + align_txt[cmp->align], layer_txt[cmp->layer], cmp->off); + + if (cmp->mask) + nl_dump(p, " & 0x%x", cmp->mask); + + if (cmp->flags & TCF_EM_CMP_TRANS) + nl_dump(p, ")"); + + nl_dump(p, " %s %u", operand_txt[cmp->opnd], cmp->val); +} + +static struct rtnl_ematch_ops cmp_ops = { + .eo_kind = TCF_EM_CMP, + .eo_name = "cmp", + .eo_minlen = sizeof(struct tcf_em_cmp), + .eo_datalen = sizeof(struct tcf_em_cmp), + .eo_parse = cmp_parse, + .eo_dump = cmp_dump, +}; + +static void __init cmp_init(void) +{ + rtnl_ematch_register(&cmp_ops); +} + +/** @} */ diff --git a/lib/route/cls/ematch/container.c b/lib/route/cls/ematch/container.c new file mode 100644 index 0000000..813391a --- /dev/null +++ b/lib/route/cls/ematch/container.c @@ -0,0 +1,47 @@ +/* + * lib/route/cls/ematch/container.c Container Ematch + * + * 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-2013 Thomas Graf + */ + +#include +#include +#include +#include + +static int container_parse(struct rtnl_ematch *e, void *data, size_t len __attribute__((unused))) +{ + /* + The kernel may provide more than 4 bytes of data in the future and we want + older libnl versions to be ok with that. We want interfaces to be growable + so we only ever enforce a minimum data length and copy as much as we are + aware of. Thomas Graf. + */ + memcpy(e->e_data, data, sizeof(uint32_t)); + + return 0; +} + +static int container_fill(struct rtnl_ematch *e, struct nl_msg *msg) +{ + return nlmsg_append(msg, e->e_data, sizeof(uint32_t), 0); +} + +static struct rtnl_ematch_ops container_ops = { + .eo_kind = TCF_EM_CONTAINER, + .eo_name = "container", + .eo_minlen = sizeof(uint32_t), + .eo_datalen = sizeof(uint32_t), + .eo_parse = container_parse, + .eo_fill = container_fill, +}; + +static void __init container_init(void) +{ + rtnl_ematch_register(&container_ops); +} diff --git a/lib/route/cls/ematch/meta.c b/lib/route/cls/ematch/meta.c new file mode 100644 index 0000000..44f11b9 --- /dev/null +++ b/lib/route/cls/ematch/meta.c @@ -0,0 +1,334 @@ +/* + * lib/route/cls/ematch/meta.c Metadata Match + * + * 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-2013 Thomas Graf + */ + +/** + * @ingroup ematch + * @defgroup em_meta Metadata Match + * + * @{ + */ + +#include +#include +#include +#include +#include + +struct rtnl_meta_value +{ + uint8_t mv_type; + uint8_t mv_shift; + uint16_t mv_id; + size_t mv_len; +}; + +struct meta_data +{ + struct rtnl_meta_value * left; + struct rtnl_meta_value * right; + uint8_t opnd; +}; + +static struct rtnl_meta_value *meta_alloc(uint8_t type, uint16_t id, + uint8_t shift, void *data, + size_t len) +{ + struct rtnl_meta_value *value; + + if (!(value = calloc(1, sizeof(*value) + len))) + return NULL; + + value->mv_type = type; + value->mv_id = id; + value->mv_shift = shift; + value->mv_len = len; + + memcpy(value + 1, data, len); + + return value; +} + +struct rtnl_meta_value *rtnl_meta_value_alloc_int(uint64_t value) +{ + return meta_alloc(TCF_META_TYPE_INT, TCF_META_ID_VALUE, 0, &value, 8); +} + +struct rtnl_meta_value *rtnl_meta_value_alloc_var(void *data, size_t len) +{ + return meta_alloc(TCF_META_TYPE_VAR, TCF_META_ID_VALUE, 0, data, len); +} + +struct rtnl_meta_value *rtnl_meta_value_alloc_id(uint8_t type, uint16_t id, + uint8_t shift, uint64_t mask) +{ + size_t masklen = 0; + + if (id > TCF_META_ID_MAX) + return NULL; + + if (mask) { + if (type == TCF_META_TYPE_VAR) + return NULL; + + masklen = 8; + } + + return meta_alloc(type, id, shift, &mask, masklen); +} + +void rtnl_meta_value_put(struct rtnl_meta_value *mv) +{ + free(mv); +} + +void rtnl_ematch_meta_set_lvalue(struct rtnl_ematch *e, struct rtnl_meta_value *v) +{ + struct meta_data *m = rtnl_ematch_data(e); + m->left = v; +} + +void rtnl_ematch_meta_set_rvalue(struct rtnl_ematch *e, struct rtnl_meta_value *v) +{ + struct meta_data *m = rtnl_ematch_data(e); + m->right = v; +} + +void rtnl_ematch_meta_set_operand(struct rtnl_ematch *e, uint8_t opnd) +{ + struct meta_data *m = rtnl_ematch_data(e); + m->opnd = opnd; +} + +static struct nla_policy meta_policy[TCA_EM_META_MAX+1] = { + [TCA_EM_META_HDR] = { .minlen = sizeof(struct tcf_meta_hdr) }, + [TCA_EM_META_LVALUE] = { .minlen = 1, }, + [TCA_EM_META_RVALUE] = { .minlen = 1, }, +}; + +static int meta_parse(struct rtnl_ematch *e, void *data, size_t len) +{ + struct meta_data *m = rtnl_ematch_data(e); + struct nlattr *tb[TCA_EM_META_MAX+1]; + struct rtnl_meta_value *v; + struct tcf_meta_hdr *hdr; + void *vdata = NULL; + size_t vlen = 0; + int err; + + if ((err = nla_parse(tb, TCA_EM_META_MAX, data, len, meta_policy)) < 0) + return err; + + if (!tb[TCA_EM_META_HDR]) + return -NLE_MISSING_ATTR; + + hdr = nla_data(tb[TCA_EM_META_HDR]); + + if (tb[TCA_EM_META_LVALUE]) { + vdata = nla_data(tb[TCA_EM_META_LVALUE]); + vlen = nla_len(tb[TCA_EM_META_LVALUE]); + } + + v = meta_alloc(TCF_META_TYPE(hdr->left.kind), + TCF_META_ID(hdr->left.kind), + hdr->left.shift, vdata, vlen); + if (!v) + return -NLE_NOMEM; + + m->left = v; + + vlen = 0; + if (tb[TCA_EM_META_RVALUE]) { + vdata = nla_data(tb[TCA_EM_META_RVALUE]); + vlen = nla_len(tb[TCA_EM_META_RVALUE]); + } + + v = meta_alloc(TCF_META_TYPE(hdr->right.kind), + TCF_META_ID(hdr->right.kind), + hdr->right.shift, vdata, vlen); + if (!v) { + rtnl_meta_value_put(m->left); + return -NLE_NOMEM; + } + + m->right = v; + m->opnd = hdr->left.op; + + return 0; +} + +static const struct trans_tbl meta_int[] = { + __ADD(TCF_META_ID_RANDOM, random) + __ADD(TCF_META_ID_LOADAVG_0, loadavg_0) + __ADD(TCF_META_ID_LOADAVG_1, loadavg_1) + __ADD(TCF_META_ID_LOADAVG_2, loadavg_2) + __ADD(TCF_META_ID_DEV, dev) + __ADD(TCF_META_ID_PRIORITY, prio) + __ADD(TCF_META_ID_PROTOCOL, proto) + __ADD(TCF_META_ID_PKTTYPE, pkttype) + __ADD(TCF_META_ID_PKTLEN, pktlen) + __ADD(TCF_META_ID_DATALEN, datalen) + __ADD(TCF_META_ID_MACLEN, maclen) + __ADD(TCF_META_ID_NFMARK, mark) + __ADD(TCF_META_ID_TCINDEX, tcindex) + __ADD(TCF_META_ID_RTCLASSID, rtclassid) + __ADD(TCF_META_ID_RTIIF, rtiif) + __ADD(TCF_META_ID_SK_FAMILY, sk_family) + __ADD(TCF_META_ID_SK_STATE, sk_state) + __ADD(TCF_META_ID_SK_REUSE, sk_reuse) + __ADD(TCF_META_ID_SK_REFCNT, sk_refcnt) + __ADD(TCF_META_ID_SK_RCVBUF, sk_rcvbuf) + __ADD(TCF_META_ID_SK_SNDBUF, sk_sndbuf) + __ADD(TCF_META_ID_SK_SHUTDOWN, sk_sutdown) + __ADD(TCF_META_ID_SK_PROTO, sk_proto) + __ADD(TCF_META_ID_SK_TYPE, sk_type) + __ADD(TCF_META_ID_SK_RMEM_ALLOC, sk_rmem_alloc) + __ADD(TCF_META_ID_SK_WMEM_ALLOC, sk_wmem_alloc) + __ADD(TCF_META_ID_SK_WMEM_QUEUED, sk_wmem_queued) + __ADD(TCF_META_ID_SK_RCV_QLEN, sk_rcv_qlen) + __ADD(TCF_META_ID_SK_SND_QLEN, sk_snd_qlen) + __ADD(TCF_META_ID_SK_ERR_QLEN, sk_err_qlen) + __ADD(TCF_META_ID_SK_FORWARD_ALLOCS, sk_forward_allocs) + __ADD(TCF_META_ID_SK_ALLOCS, sk_allocs) + __ADD(TCF_META_ID_SK_ROUTE_CAPS, sk_route_caps) + __ADD(TCF_META_ID_SK_HASH, sk_hash) + __ADD(TCF_META_ID_SK_LINGERTIME, sk_lingertime) + __ADD(TCF_META_ID_SK_ACK_BACKLOG, sk_ack_backlog) + __ADD(TCF_META_ID_SK_MAX_ACK_BACKLOG, sk_max_ack_backlog) + __ADD(TCF_META_ID_SK_PRIO, sk_prio) + __ADD(TCF_META_ID_SK_RCVLOWAT, sk_rcvlowat) + __ADD(TCF_META_ID_SK_RCVTIMEO, sk_rcvtimeo) + __ADD(TCF_META_ID_SK_SNDTIMEO, sk_sndtimeo) + __ADD(TCF_META_ID_SK_SENDMSG_OFF, sk_sendmsg_off) + __ADD(TCF_META_ID_SK_WRITE_PENDING, sk_write_pending) + __ADD(TCF_META_ID_VLAN_TAG, vlan) + __ADD(TCF_META_ID_RXHASH, rxhash) +}; + +static char *int_id2str(int id, char *buf, size_t size) +{ + return __type2str(id, buf, size, meta_int, ARRAY_SIZE(meta_int)); +} + +static const struct trans_tbl meta_var[] = { + __ADD(TCF_META_ID_DEV,devname) + __ADD(TCF_META_ID_SK_BOUND_IF,sk_bound_if) +}; + +static char *var_id2str(int id, char *buf, size_t size) +{ + return __type2str(id, buf, size, meta_var, ARRAY_SIZE(meta_var)); +} + +static void dump_value(struct rtnl_meta_value *v, struct nl_dump_params *p) +{ + char buf[32]; + + switch (v->mv_type) { + case TCF_META_TYPE_INT: + if (v->mv_id == TCF_META_ID_VALUE) { + nl_dump(p, "%u", + *(uint32_t *) (v + 1)); + } else { + nl_dump(p, "%s", + int_id2str(v->mv_id, buf, sizeof(buf))); + + if (v->mv_shift) + nl_dump(p, " >> %u", v->mv_shift); + + if (v->mv_len == 4) + nl_dump(p, " & %#x", *(uint32_t *) (v + 1)); + else if (v->mv_len == 8) + nl_dump(p, " & %#x", *(uint64_t *) (v + 1)); + } + break; + + case TCF_META_TYPE_VAR: + if (v->mv_id == TCF_META_ID_VALUE) { + nl_dump(p, "%s", (char *) (v + 1)); + } else { + nl_dump(p, "%s", + var_id2str(v->mv_id, buf, sizeof(buf))); + + if (v->mv_shift) + nl_dump(p, " >> %u", v->mv_shift); + } + break; + } +} + +static void meta_dump(struct rtnl_ematch *e, struct nl_dump_params *p) +{ + struct meta_data *m = rtnl_ematch_data(e); + char buf[32]; + + nl_dump(p, "meta("); + dump_value(m->left, p); + + nl_dump(p, " %s ", rtnl_ematch_opnd2txt(m->opnd, buf, sizeof(buf))); + + dump_value(m->right, p); + nl_dump(p, ")"); +} + +static int meta_fill(struct rtnl_ematch *e, struct nl_msg *msg) +{ + struct meta_data *m = rtnl_ematch_data(e); + struct tcf_meta_hdr hdr; + + if (!(m->left && m->right)) + return -NLE_MISSING_ATTR; + + memset(&hdr, 0, sizeof(hdr)); + hdr.left.kind = (m->left->mv_type << 12) & TCF_META_TYPE_MASK; + hdr.left.kind |= m->left->mv_id & TCF_META_ID_MASK; + hdr.left.shift = m->left->mv_shift; + hdr.left.op = m->opnd; + hdr.right.kind = (m->right->mv_type << 12) & TCF_META_TYPE_MASK; + hdr.right.kind |= m->right->mv_id & TCF_META_ID_MASK; + + NLA_PUT(msg, TCA_EM_META_HDR, sizeof(hdr), &hdr); + + if (m->left->mv_len) + NLA_PUT(msg, TCA_EM_META_LVALUE, m->left->mv_len, (m->left + 1)); + + if (m->right->mv_len) + NLA_PUT(msg, TCA_EM_META_RVALUE, m->right->mv_len, (m->right + 1)); + + return 0; + +nla_put_failure: + return -NLE_NOMEM; +} + +static void meta_free(struct rtnl_ematch *e) +{ + struct meta_data *m = rtnl_ematch_data(e); + free(m->left); + free(m->right); +} + +static struct rtnl_ematch_ops meta_ops = { + .eo_kind = TCF_EM_META, + .eo_name = "meta", + .eo_minlen = sizeof(struct tcf_meta_hdr), + .eo_datalen = sizeof(struct meta_data), + .eo_parse = meta_parse, + .eo_dump = meta_dump, + .eo_fill = meta_fill, + .eo_free = meta_free, +}; + +static void __init meta_init(void) +{ + rtnl_ematch_register(&meta_ops); +} + +/** @} */ diff --git a/lib/route/cls/ematch/nbyte.c b/lib/route/cls/ematch/nbyte.c new file mode 100644 index 0000000..8852489 --- /dev/null +++ b/lib/route/cls/ematch/nbyte.c @@ -0,0 +1,139 @@ +/* + * lib/route/cls/ematch/nbyte.c Nbyte comparison + * + * 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-2013 Thomas Graf + */ + +/** + * @ingroup ematch + * @defgroup em_nbyte N-Byte Comparison + * + * @{ + */ + +#include +#include +#include +#include +#include + +struct nbyte_data +{ + struct tcf_em_nbyte cfg; + uint8_t * pattern; +}; + +void rtnl_ematch_nbyte_set_offset(struct rtnl_ematch *e, uint8_t layer, + uint16_t offset) +{ + struct nbyte_data *n = rtnl_ematch_data(e); + n->cfg.off = offset; + n->cfg.layer = layer; +} + +uint16_t rtnl_ematch_nbyte_get_offset(struct rtnl_ematch *e) +{ + return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.off; +} + +uint8_t rtnl_ematch_nbyte_get_layer(struct rtnl_ematch *e) +{ + return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.layer; +} + +void rtnl_ematch_nbyte_set_pattern(struct rtnl_ematch *e, + uint8_t *pattern, size_t len) +{ + struct nbyte_data *n = rtnl_ematch_data(e); + + if (n->pattern) + free(n->pattern); + + n->pattern = pattern; + n->cfg.len = len; +} + +uint8_t *rtnl_ematch_nbyte_get_pattern(struct rtnl_ematch *e) +{ + return ((struct nbyte_data *) rtnl_ematch_data(e))->pattern; +} + +size_t rtnl_ematch_nbyte_get_len(struct rtnl_ematch *e) +{ + return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.len; +} + +static const char *layer_txt(struct tcf_em_nbyte *nbyte) +{ + switch (nbyte->layer) { + case TCF_LAYER_LINK: + return "link"; + case TCF_LAYER_NETWORK: + return "net"; + case TCF_LAYER_TRANSPORT: + return "trans"; + default: + return "?"; + } +} + +static int nbyte_parse(struct rtnl_ematch *e, void *data, size_t len) +{ + struct nbyte_data *n = rtnl_ematch_data(e); + size_t hdrlen = sizeof(struct tcf_em_nbyte); + size_t plen = len - hdrlen; + + memcpy(&n->cfg, data, hdrlen); + if (plen > 0) { + if (!(n->pattern = calloc(1, plen))) + return -NLE_NOMEM; + + memcpy(n->pattern, data + hdrlen, plen); + } + + return 0; +} + +static void nbyte_dump(struct rtnl_ematch *e, struct nl_dump_params *p) +{ + struct nbyte_data *n = rtnl_ematch_data(e); + int i; + + nl_dump(p, "pattern(%u:[", n->cfg.len); + + for (i = 0; i < n->cfg.len; i++) { + nl_dump(p, "%02x", n->pattern[i]); + if (i+1 < n->cfg.len) + nl_dump(p, " "); + } + + nl_dump(p, "] at %s+%u)", layer_txt(&n->cfg), n->cfg.off); +} + +static void nbyte_free(struct rtnl_ematch *e) +{ + struct nbyte_data *n = rtnl_ematch_data(e); + free(n->pattern); +} + +static struct rtnl_ematch_ops nbyte_ops = { + .eo_kind = TCF_EM_NBYTE, + .eo_name = "nbyte", + .eo_minlen = sizeof(struct tcf_em_nbyte), + .eo_datalen = sizeof(struct nbyte_data), + .eo_parse = nbyte_parse, + .eo_dump = nbyte_dump, + .eo_free = nbyte_free, +}; + +static void __init nbyte_init(void) +{ + rtnl_ematch_register(&nbyte_ops); +} + +/** @} */ diff --git a/lib/route/cls/ematch/text.c b/lib/route/cls/ematch/text.c new file mode 100644 index 0000000..e8cdcae --- /dev/null +++ b/lib/route/cls/ematch/text.c @@ -0,0 +1,183 @@ +/* + * lib/route/cls/ematch/text.c Text Search + * + * 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-2013 Thomas Graf + */ + +/** + * @ingroup ematch + * @defgroup em_text Text Search + * + * @{ + */ + +#include +#include +#include +#include +#include + +struct text_data +{ + struct tcf_em_text cfg; + char * pattern; +}; + +void rtnl_ematch_text_set_from(struct rtnl_ematch *e, uint8_t layer, + uint16_t offset) +{ + struct text_data *t = rtnl_ematch_data(e); + t->cfg.from_offset = offset; + t->cfg.from_layer = layer; +} + +uint16_t rtnl_ematch_text_get_from_offset(struct rtnl_ematch *e) +{ + return ((struct text_data *) rtnl_ematch_data(e))->cfg.from_offset; +} + +uint8_t rtnl_ematch_text_get_from_layer(struct rtnl_ematch *e) +{ + return ((struct text_data *) rtnl_ematch_data(e))->cfg.from_layer; +} + +void rtnl_ematch_text_set_to(struct rtnl_ematch *e, uint8_t layer, + uint16_t offset) +{ + struct text_data *t = rtnl_ematch_data(e); + t->cfg.to_offset = offset; + t->cfg.to_layer = layer; +} + +uint16_t rtnl_ematch_text_get_to_offset(struct rtnl_ematch *e) +{ + return ((struct text_data *) rtnl_ematch_data(e))->cfg.to_offset; +} + +uint8_t rtnl_ematch_text_get_to_layer(struct rtnl_ematch *e) +{ + return ((struct text_data *) rtnl_ematch_data(e))->cfg.to_layer; +} + +void rtnl_ematch_text_set_pattern(struct rtnl_ematch *e, + char *pattern, size_t len) +{ + struct text_data *t = rtnl_ematch_data(e); + + if (t->pattern) + free(t->pattern); + + t->pattern = pattern; + t->cfg.pattern_len = len; +} + +char *rtnl_ematch_text_get_pattern(struct rtnl_ematch *e) +{ + return ((struct text_data *) rtnl_ematch_data(e))->pattern; +} + +size_t rtnl_ematch_text_get_len(struct rtnl_ematch *e) +{ + return ((struct text_data *) rtnl_ematch_data(e))->cfg.pattern_len; +} + +void rtnl_ematch_text_set_algo(struct rtnl_ematch *e, const char *algo) +{ + struct text_data *t = rtnl_ematch_data(e); + + strncpy(t->cfg.algo, algo, sizeof(t->cfg.algo)); +} + +char *rtnl_ematch_text_get_algo(struct rtnl_ematch *e) +{ + struct text_data *t = rtnl_ematch_data(e); + + return t->cfg.algo[0] ? t->cfg.algo : NULL; +} + +static int text_parse(struct rtnl_ematch *e, void *data, size_t len) +{ + struct text_data *t = rtnl_ematch_data(e); + size_t hdrlen = sizeof(struct tcf_em_text); + size_t plen = len - hdrlen; + + memcpy(&t->cfg, data, hdrlen); + + if (t->cfg.pattern_len > plen) + return -NLE_INVAL; + + if (t->cfg.pattern_len > 0) { + if (!(t->pattern = calloc(1, t->cfg.pattern_len))) + return -NLE_NOMEM; + + memcpy(t->pattern, data + hdrlen, t->cfg.pattern_len); + } + + return 0; +} + +static void text_dump(struct rtnl_ematch *e, struct nl_dump_params *p) +{ + struct text_data *t = rtnl_ematch_data(e); + char buf[64]; + + nl_dump(p, "text(%s \"%s\"", + t->cfg.algo[0] ? t->cfg.algo : "no-algo", + t->pattern ? : "no-pattern"); + + if (t->cfg.from_layer || t->cfg.from_offset) { + nl_dump(p, " from %s", + rtnl_ematch_offset2txt(t->cfg.from_layer, + t->cfg.from_offset, + buf, sizeof(buf))); + } + + if (t->cfg.to_layer || t->cfg.to_offset) { + nl_dump(p, " to %s", + rtnl_ematch_offset2txt(t->cfg.to_layer, + t->cfg.to_offset, + buf, sizeof(buf))); + } + + nl_dump(p, ")"); +} + +static int text_fill(struct rtnl_ematch *e, struct nl_msg *msg) +{ + struct text_data *t = rtnl_ematch_data(e); + int err; + + if ((err = nlmsg_append(msg, &t->cfg, sizeof(t->cfg), 0)) < 0) + return err; + + return nlmsg_append(msg, t->pattern, t->cfg.pattern_len, 0); +} + +static void text_free(struct rtnl_ematch *e) +{ + struct text_data *t = rtnl_ematch_data(e); + free(t->pattern); +} + +static struct rtnl_ematch_ops text_ops = { + .eo_kind = TCF_EM_TEXT, + .eo_name = "text", + .eo_minlen = sizeof(struct tcf_em_text), + .eo_datalen = sizeof(struct text_data), + .eo_parse = text_parse, + .eo_dump = text_dump, + .eo_fill = text_fill, + .eo_free = text_free, +}; + +static void __init text_init(void) +{ + rtnl_ematch_register(&text_ops); +} + +/** @} */ diff --git a/lib/route/cls/ematch_grammar.l b/lib/route/cls/ematch_grammar.l new file mode 100644 index 0000000..96ef1a0 --- /dev/null +++ b/lib/route/cls/ematch_grammar.l @@ -0,0 +1,162 @@ +/* + * lib/route/cls/ematch_grammar.l ematch expression grammar + * + * 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-2013 Thomas Graf + */ + +%{ + #include + #include + #include + #include + #include + #include "ematch_syntax.h" +%} + +%option 8bit +%option reentrant +%option warn +%option noyywrap +%option noinput +%option nounput +%option bison-bridge +%option prefix="ematch_" + +%x QUOTE + +%% + +[ \t\r\n]+ + +\" { + NL_DBG(4, "Beginning of quote\n"); + yylval->q.len = 32; + if (!(yylval->q.data = calloc(1, yylval->q.len))) + return ERROR; + + yylval->q.index = 0; + BEGIN(QUOTE); + } + +[^\\\n\"]+ { + memcpy(yylval->q.data + yylval->q.index, yytext, + strlen(yytext)); + yylval->q.index += strlen(yytext); + } + +\" { + BEGIN(0); + return QUOTED; + } + + +[[:digit:]]+ | +0[xX][[:xdigit:]]+ { + yylval->i = strtoul(yytext, NULL, 0); + return NUMBER; + } + +eq | +"=" return KW_EQ; +gt | +">" return KW_GT; +lt | +"<" return KW_LT; + +[aA][nN][dD] | +"&&" { yylval->i = TCF_EM_REL_AND; return LOGIC; } +[oO][rR] | +"||" { yylval->i = TCF_EM_REL_OR; return LOGIC; } +[nN][oO][tT] | +"!" return NOT; + +[cC][mM][pP] { yylval->i = TCF_EM_CMP; return EMATCH_CMP; } +[pP][aA][tT][tT][eE][rR][nN] { yylval->i = TCF_EM_NBYTE; return EMATCH_NBYTE; } +[tT][eE][xX][tT] { yylval->i = TCF_EM_TEXT; return EMATCH_TEXT; } +[mM][eE][tT][aA] { yylval->i = TCF_EM_META; return EMATCH_META; } + +"(" return KW_OPEN; +")" return KW_CLOSE; +[mM][aA][sS][kK] | +"&" return KW_MASK; +[sS][hH][iI][fF][tT] | +">>" return KW_SHIFT; +[aA][tT] return KW_AT; +"+" return KW_PLUS; +[fF][rR][oO][mM] return KW_FROM; +[tT][oO] return KW_TO; + +[uU]8 { yylval->i = TCF_EM_ALIGN_U8; return ALIGN; } +[uU]16 { yylval->i = TCF_EM_ALIGN_U16; return ALIGN; } +[uU]32 { yylval->i = TCF_EM_ALIGN_U32; return ALIGN; } + +[lL][iI][nN][kK] | +[eE][tT][hH] { yylval->i = TCF_LAYER_LINK; return LAYER; } +[nN][eE][tT] | +[iI][pP]6 | +[iI][pP] { yylval->i = TCF_LAYER_NETWORK; return LAYER; } +[tT][rR][aA][nN][sS][pP][oO][rR][tT] | +[tT][cC][pP] { yylval->i = TCF_LAYER_TRANSPORT; return LAYER; } + +random return META_RANDOM; +loadavg_0 return META_LOADAVG_0; +loadavg_1 return META_LOADAVG_1; +loadavg_2 return META_LOADAVG_2; +dev return META_DEV; +prio return META_PRIO; +proto return META_PROTO; +pkttype return META_PKTTYPE; +pktlen return META_PKTLEN; +datalen return META_DATALEN; +maclen return META_MACLEN; +mark return META_MARK; +tcindex return META_TCINDEX; +rtclassid return META_RTCLASSID; +rtiif return META_RTIIF; +sk_family return META_SK_FAMILY; +sk_state return META_SK_STATE; +sk_reuse return META_SK_REUSE; +sk_refcnt return META_SK_REFCNT; +sk_rcvbuf return META_SK_RCVBUF; +sk_sndbuf return META_SK_SNDBUF; +sk_shutdown return META_SK_SHUTDOWN; +sk_proto return META_SK_PROTO; +sk_type return META_SK_TYPE; +sk_rmem_alloc return META_SK_RMEM_ALLOC; +sk_wmem_alloc return META_SK_WMEM_ALLOC; +sk_wmem_queued return META_SK_WMEM_QUEUED; +sk_rcv_qlen return META_SK_RCV_QLEN; +sk_snd_qlen return META_SK_SND_QLEN; +sk_err_qlen return META_SK_ERR_QLEN; +sk_forward_allocs return META_SK_FORWARD_ALLOCS; +sk_allocs return META_SK_ALLOCS; +sk_route_caps return META_SK_ROUTE_CAPS; +sk_hash return META_SK_HASH; +sk_lingertime return META_SK_LINGERTIME; +sk_ack_backlog return META_SK_ACK_BACKLOG; +sk_max_ack_backlog return META_SK_MAX_ACK_BACKLOG; +sk_prio return META_SK_PRIO; +sk_rcvlowat return META_SK_RCVLOWAT; +sk_rcvtimeo return META_SK_RCVTIMEO; +sk_sndtimeo return META_SK_SNDTIMEO; +sk_sendmsg_off return META_SK_SENDMSG_OFF; +sk_write_pending return META_SK_WRITE_PENDING; +vlan return META_VLAN; +rxhash return META_RXHASH; + +devname return META_DEVNAME; +sk_bound_if return META_SK_BOUND_IF; + + +[^ \t\r\n+()=<>&|\"]+ { + yylval->s = strdup(yytext); + if (yylval->s == NULL) + return ERROR; + NL_DBG(4, "lex STR=%s\n", yylval->s); + return STR; + } diff --git a/lib/route/cls/ematch_syntax.y b/lib/route/cls/ematch_syntax.y new file mode 100644 index 0000000..da21039 --- /dev/null +++ b/lib/route/cls/ematch_syntax.y @@ -0,0 +1,501 @@ +/* + * lib/route/cls/ematch_syntax.y ematch expression syntax + * + * 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-2013 Thomas Graf + */ + +%{ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define META_ALLOC rtnl_meta_value_alloc_id +#define META_ID(name) TCF_META_ID_##name +#define META_INT TCF_META_TYPE_INT +#define META_VAR TCF_META_TYPE_VAR +%} + +%error-verbose +%define api.pure +%name-prefix "ematch_" + +%parse-param {void *scanner} +%parse-param {char **errp} +%parse-param {struct nl_list_head *root} +%lex-param {void *scanner} + +%union { + struct tcf_em_cmp cmp; + struct ematch_quoted q; + struct rtnl_ematch * e; + struct rtnl_pktloc * loc; + struct rtnl_meta_value *mv; + uint32_t i; + uint64_t i64; + char * s; +} + +%{ +extern int ematch_lex(YYSTYPE *, void *); + +static void yyerror(void *scanner, char **errp, struct nl_list_head *root, const char *msg) +{ + if (msg) + *errp = strdup(msg); + else + *errp = NULL; +} +%} + +%token ERROR LOGIC NOT OPERAND NUMBER ALIGN LAYER +%token KW_OPEN "(" +%token KW_CLOSE ")" +%token KW_PLUS "+" +%token KW_MASK "mask" +%token KW_SHIFT ">>" +%token KW_AT "at" +%token EMATCH_CMP "cmp" +%token EMATCH_NBYTE "pattern" +%token EMATCH_TEXT "text" +%token EMATCH_META "meta" +%token KW_EQ "=" +%token KW_GT ">" +%token KW_LT "<" +%token KW_FROM "from" +%token KW_TO "to" + +%token META_RANDOM "random" +%token META_LOADAVG_0 "loadavg_0" +%token META_LOADAVG_1 "loadavg_1" +%token META_LOADAVG_2 "loadavg_2" +%token META_DEV "dev" +%token META_PRIO "prio" +%token META_PROTO "proto" +%token META_PKTTYPE "pkttype" +%token META_PKTLEN "pktlen" +%token META_DATALEN "datalen" +%token META_MACLEN "maclen" +%token META_MARK "mark" +%token META_TCINDEX "tcindex" +%token META_RTCLASSID "rtclassid" +%token META_RTIIF "rtiif" +%token META_SK_FAMILY "sk_family" +%token META_SK_STATE "sk_state" +%token META_SK_REUSE "sk_reuse" +%token META_SK_REFCNT "sk_refcnt" +%token META_SK_RCVBUF "sk_rcvbuf" +%token META_SK_SNDBUF "sk_sndbuf" +%token META_SK_SHUTDOWN "sk_shutdown" +%token META_SK_PROTO "sk_proto" +%token META_SK_TYPE "sk_type" +%token META_SK_RMEM_ALLOC "sk_rmem_alloc" +%token META_SK_WMEM_ALLOC "sk_wmem_alloc" +%token META_SK_WMEM_QUEUED "sk_wmem_queued" +%token META_SK_RCV_QLEN "sk_rcv_qlen" +%token META_SK_SND_QLEN "sk_snd_qlen" +%token META_SK_ERR_QLEN "sk_err_qlen" +%token META_SK_FORWARD_ALLOCS "sk_forward_allocs" +%token META_SK_ALLOCS "sk_allocs" +%token META_SK_ROUTE_CAPS "sk_route_caps" +%token META_SK_HASH "sk_hash" +%token META_SK_LINGERTIME "sk_lingertime" +%token META_SK_ACK_BACKLOG "sk_ack_backlog" +%token META_SK_MAX_ACK_BACKLOG "sk_max_ack_backlog" +%token META_SK_PRIO "sk_prio" +%token META_SK_RCVLOWAT "sk_rcvlowat" +%token META_SK_RCVTIMEO "sk_rcvtimeo" +%token META_SK_SNDTIMEO "sk_sndtimeo" +%token META_SK_SENDMSG_OFF "sk_sendmsg_off" +%token META_SK_WRITE_PENDING "sk_write_pending" +%token META_VLAN "vlan" +%token META_RXHASH "rxhash" +%token META_DEVNAME "devname" +%token META_SK_BOUND_IF "sk_bound_if" + +%token STR + +%token QUOTED + +%type align operand shift meta_int_id meta_var_id +%type mask +%type expr match ematch +%type cmp_expr cmp_match +%type pktloc text_from text_to +%type pattern +%type meta_value + +%destructor { free($$); NL_DBG(2, "string destructor\n"); } +%destructor { rtnl_pktloc_put($$); NL_DBG(2, "pktloc destructor\n"); } +%destructor { free($$.data); NL_DBG(2, "quoted destructor\n"); } +%destructor { rtnl_meta_value_put($$); NL_DBG(2, "meta value destructor\n"); } + +%start input + +%% + +input: + /* empty */ + | expr + { + nl_list_add_tail(root, &$1->e_list); + } + ; + +expr: + match + { + $$ = $1; + } + | match LOGIC expr + { + rtnl_ematch_set_flags($1, $2); + + /* make ematch new head */ + nl_list_add_tail(&$1->e_list, &$3->e_list); + + $$ = $1; + } + ; + +match: + NOT ematch + { + rtnl_ematch_set_flags($2, TCF_EM_INVERT); + $$ = $2; + } + | ematch + { + $$ = $1; + } + ; + +ematch: + /* CMP */ + cmp_match + { + struct rtnl_ematch *e; + + if (!(e = rtnl_ematch_alloc())) { + *errp = strdup("Unable to allocate ematch object"); + YYABORT; + } + + if (rtnl_ematch_set_kind(e, TCF_EM_CMP) < 0) + BUG(); + + rtnl_ematch_cmp_set(e, &$1); + $$ = e; + } + | EMATCH_NBYTE "(" pktloc KW_EQ pattern ")" + { + struct rtnl_ematch *e; + + if (!(e = rtnl_ematch_alloc())) { + *errp = strdup("Unable to allocate ematch object"); + YYABORT; + } + + if (rtnl_ematch_set_kind(e, TCF_EM_NBYTE) < 0) + BUG(); + + rtnl_ematch_nbyte_set_offset(e, $3->layer, $3->offset); + rtnl_pktloc_put($3); + rtnl_ematch_nbyte_set_pattern(e, (uint8_t *) $5.data, $5.index); + + $$ = e; + } + | EMATCH_TEXT "(" STR QUOTED text_from text_to ")" + { + struct rtnl_ematch *e; + + if (!(e = rtnl_ematch_alloc())) { + *errp = strdup("Unable to allocate ematch object"); + YYABORT; + } + + if (rtnl_ematch_set_kind(e, TCF_EM_TEXT) < 0) + BUG(); + + rtnl_ematch_text_set_algo(e, $3); + rtnl_ematch_text_set_pattern(e, $4.data, $4.index); + + if ($5) { + rtnl_ematch_text_set_from(e, $5->layer, $5->offset); + rtnl_pktloc_put($5); + } + + if ($6) { + rtnl_ematch_text_set_to(e, $6->layer, $6->offset); + rtnl_pktloc_put($6); + } + + $$ = e; + } + | EMATCH_META "(" meta_value operand meta_value ")" + { + struct rtnl_ematch *e; + + if (!(e = rtnl_ematch_alloc())) { + *errp = strdup("Unable to allocate ematch object"); + YYABORT; + } + + if (rtnl_ematch_set_kind(e, TCF_EM_META) < 0) + BUG(); + + rtnl_ematch_meta_set_lvalue(e, $3); + rtnl_ematch_meta_set_rvalue(e, $5); + rtnl_ematch_meta_set_operand(e, $4); + + $$ = e; + } + /* CONTAINER */ + | "(" expr ")" + { + struct rtnl_ematch *e; + + if (!(e = rtnl_ematch_alloc())) { + *errp = strdup("Unable to allocate ematch object"); + YYABORT; + } + + if (rtnl_ematch_set_kind(e, TCF_EM_CONTAINER) < 0) + BUG(); + + /* Make e->childs the list head of a the ematch sequence */ + nl_list_add_tail(&e->e_childs, &$2->e_list); + + $$ = e; + } + ; + +/* + * CMP match + * + * match := cmp(expr) | expr + * expr := pktloc (=|>|<) NUMBER + * pktloc := alias | definition + * + */ +cmp_match: + EMATCH_CMP "(" cmp_expr ")" + { $$ = $3; } + | cmp_expr + { $$ = $1; } + ; + +cmp_expr: + pktloc operand NUMBER + { + if ($1->align == TCF_EM_ALIGN_U16 || + $1->align == TCF_EM_ALIGN_U32) + $$.flags = TCF_EM_CMP_TRANS; + + memset(&$$, 0, sizeof($$)); + + $$.mask = $1->mask; + $$.off = $1->offset; + $$.align = $1->align; + $$.layer = $1->layer; + $$.opnd = $2; + $$.val = $3; + + rtnl_pktloc_put($1); + } + ; + +text_from: + /* empty */ + { $$ = NULL; } + | "from" pktloc + { $$ = $2; } + ; + +text_to: + /* empty */ + { $$ = NULL; } + | "to" pktloc + { $$ = $2; } + ; + +meta_value: + QUOTED + { $$ = rtnl_meta_value_alloc_var($1.data, $1.len); } + | NUMBER + { $$ = rtnl_meta_value_alloc_int($1); } + | meta_int_id shift mask + { $$ = META_ALLOC(META_INT, $1, $2, $3); } + | meta_var_id shift + { $$ = META_ALLOC(META_VAR, $1, $2, 0); } + ; + +meta_int_id: + META_RANDOM { $$ = META_ID(RANDOM); } + |META_LOADAVG_0 { $$ = META_ID(LOADAVG_0); } + |META_LOADAVG_1 { $$ = META_ID(LOADAVG_1); } + |META_LOADAVG_2 { $$ = META_ID(LOADAVG_2); } + | META_DEV { $$ = META_ID(DEV); } + | META_PRIO { $$ = META_ID(PRIORITY); } + | META_PROTO { $$ = META_ID(PROTOCOL); } + | META_PKTTYPE { $$ = META_ID(PKTTYPE); } + | META_PKTLEN { $$ = META_ID(PKTLEN); } + | META_DATALEN { $$ = META_ID(DATALEN); } + | META_MACLEN { $$ = META_ID(MACLEN); } + | META_MARK { $$ = META_ID(NFMARK); } + | META_TCINDEX { $$ = META_ID(TCINDEX); } + | META_RTCLASSID { $$ = META_ID(RTCLASSID); } + | META_RTIIF { $$ = META_ID(RTIIF); } + | META_SK_FAMILY { $$ = META_ID(SK_FAMILY); } + | META_SK_STATE { $$ = META_ID(SK_STATE); } + | META_SK_REUSE { $$ = META_ID(SK_REUSE); } + | META_SK_REFCNT { $$ = META_ID(SK_REFCNT); } + | META_SK_RCVBUF { $$ = META_ID(SK_RCVBUF); } + | META_SK_SNDBUF { $$ = META_ID(SK_SNDBUF); } + | META_SK_SHUTDOWN { $$ = META_ID(SK_SHUTDOWN); } + | META_SK_PROTO { $$ = META_ID(SK_PROTO); } + | META_SK_TYPE { $$ = META_ID(SK_TYPE); } + | META_SK_RMEM_ALLOC { $$ = META_ID(SK_RMEM_ALLOC); } + | META_SK_WMEM_ALLOC { $$ = META_ID(SK_WMEM_ALLOC); } + | META_SK_WMEM_QUEUED { $$ = META_ID(SK_WMEM_QUEUED); } + | META_SK_RCV_QLEN { $$ = META_ID(SK_RCV_QLEN); } + | META_SK_SND_QLEN { $$ = META_ID(SK_SND_QLEN); } + | META_SK_ERR_QLEN { $$ = META_ID(SK_ERR_QLEN); } + | META_SK_FORWARD_ALLOCS { $$ = META_ID(SK_FORWARD_ALLOCS); } + | META_SK_ALLOCS { $$ = META_ID(SK_ALLOCS); } + | META_SK_ROUTE_CAPS { $$ = META_ID(SK_ROUTE_CAPS); } + | META_SK_HASH { $$ = META_ID(SK_HASH); } + | META_SK_LINGERTIME { $$ = META_ID(SK_LINGERTIME); } + | META_SK_ACK_BACKLOG { $$ = META_ID(SK_ACK_BACKLOG); } + | META_SK_MAX_ACK_BACKLOG { $$ = META_ID(SK_MAX_ACK_BACKLOG); } + | META_SK_PRIO { $$ = META_ID(SK_PRIO); } + | META_SK_RCVLOWAT { $$ = META_ID(SK_RCVLOWAT); } + | META_SK_RCVTIMEO { $$ = META_ID(SK_RCVTIMEO); } + | META_SK_SNDTIMEO { $$ = META_ID(SK_SNDTIMEO); } + | META_SK_SENDMSG_OFF { $$ = META_ID(SK_SENDMSG_OFF); } + | META_SK_WRITE_PENDING { $$ = META_ID(SK_WRITE_PENDING); } + | META_VLAN { $$ = META_ID(VLAN_TAG); } + | META_RXHASH { $$ = META_ID(RXHASH); } + ; + +meta_var_id: + META_DEVNAME { $$ = META_ID(DEV); } + | META_SK_BOUND_IF { $$ = META_ID(SK_BOUND_IF); } + ; + +/* + * pattern + */ +pattern: + QUOTED + { + $$ = $1; + } + | STR + { + struct nl_addr *addr; + + if (nl_addr_parse($1, AF_UNSPEC, &addr) == 0) { + $$.len = nl_addr_get_len(addr); + + $$.index = min_t(int, $$.len, nl_addr_get_prefixlen(addr)/8); + + if (!($$.data = calloc(1, $$.len))) { + nl_addr_put(addr); + YYABORT; + } + + memcpy($$.data, nl_addr_get_binary_addr(addr), $$.len); + nl_addr_put(addr); + } else { + if (asprintf(errp, "invalid pattern \"%s\"", $1) == -1) + *errp = NULL; + YYABORT; + } + } + ; + +/* + * packet location + */ + +pktloc: + STR + { + struct rtnl_pktloc *loc; + + if (rtnl_pktloc_lookup($1, &loc) < 0) { + if (asprintf(errp, "Packet location \"%s\" not found", $1) == -1) + *errp = NULL; + YYABORT; + } + + $$ = loc; + } + /* [u8|u16|u32|NUM at] LAYER + OFFSET [mask MASK] */ + | align LAYER "+" NUMBER mask + { + struct rtnl_pktloc *loc; + + if ($5 && (!$1 || $1 > TCF_EM_ALIGN_U32)) { + *errp = strdup("mask only allowed for alignments u8|u16|u32"); + YYABORT; + } + + if (!(loc = rtnl_pktloc_alloc())) { + *errp = strdup("Unable to allocate packet location object"); + YYABORT; + } + + loc->name = strdup(""); + loc->align = $1; + loc->layer = $2; + loc->offset = $4; + loc->mask = $5; + + $$ = loc; + } + ; + +align: + /* empty */ + { $$ = 0; } + | ALIGN "at" + { $$ = $1; } + | NUMBER "at" + { $$ = $1; } + ; + +mask: + /* empty */ + { $$ = 0; } + | KW_MASK NUMBER + { $$ = $2; } + ; + +shift: + /* empty */ + { $$ = 0; } + | KW_SHIFT NUMBER + { $$ = $2; } + ; + +operand: + KW_EQ + { $$ = TCF_EM_OPND_EQ; } + | KW_GT + { $$ = TCF_EM_OPND_GT; } + | KW_LT + { $$ = TCF_EM_OPND_LT; } + ; diff --git a/lib/route/cls/fw.c b/lib/route/cls/fw.c new file mode 100644 index 0000000..b569d4f --- /dev/null +++ b/lib/route/cls/fw.c @@ -0,0 +1,219 @@ +/* + * lib/route/cls/fw.c fw classifier + * + * 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-2013 Thomas Graf + * Copyright (c) 2006 Petr Gotthard + * Copyright (c) 2006 Siemens AG Oesterreich + */ + +/** + * @ingroup cls + * @defgroup cls_fw Firewall Classifier + * + * @{ + */ + +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define FW_ATTR_CLASSID 0x001 +#define FW_ATTR_ACTION 0x002 +#define FW_ATTR_POLICE 0x004 +#define FW_ATTR_INDEV 0x008 +#define FW_ATTR_MASK 0x010 +/** @endcond */ + +static struct nla_policy fw_policy[TCA_FW_MAX+1] = { + [TCA_FW_CLASSID] = { .type = NLA_U32 }, + [TCA_FW_INDEV] = { .type = NLA_STRING, + .maxlen = IFNAMSIZ }, + [TCA_FW_MASK] = { .type = NLA_U32 }, +}; + +static int fw_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct nlattr *tb[TCA_FW_MAX + 1]; + struct rtnl_fw *f = data; + int err; + + err = tca_parse(tb, TCA_FW_MAX, tc, fw_policy); + if (err < 0) + return err; + + if (tb[TCA_FW_CLASSID]) { + f->cf_classid = nla_get_u32(tb[TCA_FW_CLASSID]); + f->cf_mask |= FW_ATTR_CLASSID; + } + + if (tb[TCA_FW_ACT]) { + f->cf_act = nl_data_alloc_attr(tb[TCA_FW_ACT]); + if (!f->cf_act) + return -NLE_NOMEM; + f->cf_mask |= FW_ATTR_ACTION; + } + + if (tb[TCA_FW_POLICE]) { + f->cf_police = nl_data_alloc_attr(tb[TCA_FW_POLICE]); + if (!f->cf_police) + return -NLE_NOMEM; + f->cf_mask |= FW_ATTR_POLICE; + } + + if (tb[TCA_FW_INDEV]) { + nla_strlcpy(f->cf_indev, tb[TCA_FW_INDEV], IFNAMSIZ); + f->cf_mask |= FW_ATTR_INDEV; + } + + if (tb[TCA_FW_MASK]) { + f->cf_fwmask = nla_get_u32(tb[TCA_FW_MASK]); + f->cf_mask |= FW_ATTR_MASK; + } + + return 0; +} + +static void fw_free_data(struct rtnl_tc *tc, void *data) +{ + struct rtnl_fw *f = data; + + nl_data_free(f->cf_act); + nl_data_free(f->cf_police); +} + +static int fw_clone(void *_dst, void *_src) +{ + struct rtnl_fw *dst = _dst, *src = _src; + + if (src->cf_act && !(dst->cf_act = nl_data_clone(src->cf_act))) + return -NLE_NOMEM; + + if (src->cf_police && !(dst->cf_police = nl_data_clone(src->cf_police))) + return -NLE_NOMEM; + + return 0; +} + +static void fw_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_fw *f = data; + + if (!f) + return; + + if (f->cf_mask & FW_ATTR_CLASSID) { + char buf[32]; + + nl_dump(p, " target %s", + rtnl_tc_handle2str(f->cf_classid, buf, sizeof(buf))); + } + + if (f->cf_mask & FW_ATTR_MASK) + nl_dump(p, " mask 0x%x", f->cf_fwmask); +} + +static void fw_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_fw *f = data; + + if (f && f->cf_mask & FW_ATTR_INDEV) + nl_dump(p, "indev %s ", f->cf_indev); +} + +static int fw_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + struct rtnl_fw *f = data; + + if (!f) + return 0; + + if (f->cf_mask & FW_ATTR_CLASSID) + NLA_PUT_U32(msg, TCA_FW_CLASSID, f->cf_classid); + + if (f->cf_mask & FW_ATTR_ACTION) + NLA_PUT_DATA(msg, TCA_FW_ACT, f->cf_act); + + if (f->cf_mask & FW_ATTR_POLICE) + NLA_PUT_DATA(msg, TCA_FW_POLICE, f->cf_police); + + if (f->cf_mask & FW_ATTR_INDEV) + NLA_PUT_STRING(msg, TCA_FW_INDEV, f->cf_indev); + + if (f->cf_mask & FW_ATTR_MASK) + NLA_PUT_U32(msg, TCA_FW_MASK, f->cf_fwmask); + + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +/** + * @name Attribute Modifications + * @{ + */ + +int rtnl_fw_set_classid(struct rtnl_cls *cls, uint32_t classid) +{ + struct rtnl_fw *f; + + if (!(f = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + f->cf_classid = classid; + f->cf_mask |= FW_ATTR_CLASSID; + + return 0; +} + +int rtnl_fw_set_mask(struct rtnl_cls *cls, uint32_t mask) +{ + struct rtnl_fw *f; + + if (!(f = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + f->cf_fwmask = mask; + f->cf_mask |= FW_ATTR_MASK; + + return 0; +} + +/** @} */ + +static struct rtnl_tc_ops fw_ops = { + .to_kind = "fw", + .to_type = RTNL_TC_TYPE_CLS, + .to_size = sizeof(struct rtnl_fw), + .to_msg_parser = fw_msg_parser, + .to_msg_fill = fw_msg_fill, + .to_free_data = fw_free_data, + .to_clone = fw_clone, + .to_dump = { + [NL_DUMP_LINE] = fw_dump_line, + [NL_DUMP_DETAILS] = fw_dump_details, + }, +}; + +static void __init fw_init(void) +{ + rtnl_tc_register(&fw_ops); +} + +static void __exit fw_exit(void) +{ + rtnl_tc_unregister(&fw_ops); +} + +/** @} */ diff --git a/lib/route/cls/police.c b/lib/route/cls/police.c new file mode 100644 index 0000000..1f5d284 --- /dev/null +++ b/lib/route/cls/police.c @@ -0,0 +1,66 @@ +/* + * lib/route/cls/police.c Policer + * + * 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-2013 Thomas Graf + */ + +#include +#include +#include +#include +#include +#include +#include + +/** + * @name Policer Type + * @{ + */ + +static const struct trans_tbl police_types[] = { + __ADD(TC_POLICE_UNSPEC,unspec) + __ADD(TC_POLICE_OK,ok) + __ADD(TC_POLICE_RECLASSIFY,reclassify) + __ADD(TC_POLICE_SHOT,shot) +#ifdef TC_POLICE_PIPE + __ADD(TC_POLICE_PIPE,pipe) +#endif +}; + +/** + * Transform a policer type number into a character string (Reentrant). + * @arg type policer type + * @arg buf destination buffer + * @arg len buffer length + * + * Transforms a policer type number into a character string and stores + * it in the provided buffer. + * + * @return The destination buffer or the type encoded in hex if no match was found. + */ +char * nl_police2str(int type, char *buf, size_t len) +{ + return __type2str(type, buf, len, police_types, + ARRAY_SIZE(police_types)); +} + +/** + * Transform a character string into a policer type number + * @arg name policer type name + * + * Transform the provided character string specifying a policer + * type into the corresponding numeric value + * + * @return Policer type number or a negative value. + */ +int nl_str2police(const char *name) +{ + return __str2type(name, police_types, ARRAY_SIZE(police_types)); +} + +/** @} */ diff --git a/lib/route/cls/u32.c b/lib/route/cls/u32.c new file mode 100644 index 0000000..c468ba7 --- /dev/null +++ b/lib/route/cls/u32.c @@ -0,0 +1,636 @@ +/* + * lib/route/cls/u32.c u32 classifier + * + * 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-2013 Thomas Graf + * Copyright (c) 2005-2006 Petr Gotthard + * Copyright (c) 2005-2006 Siemens AG Oesterreich + */ + +/** + * @ingroup cls + * @defgroup cls_u32 Universal 32-bit Classifier + * + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define U32_ATTR_DIVISOR 0x001 +#define U32_ATTR_HASH 0x002 +#define U32_ATTR_CLASSID 0x004 +#define U32_ATTR_LINK 0x008 +#define U32_ATTR_PCNT 0x010 +#define U32_ATTR_SELECTOR 0x020 +#define U32_ATTR_ACTION 0x040 +#define U32_ATTR_POLICE 0x080 +#define U32_ATTR_INDEV 0x100 +/** @endcond */ + +static inline struct tc_u32_sel *u32_selector(struct rtnl_u32 *u) +{ + return (struct tc_u32_sel *) u->cu_selector->d_data; +} + +static inline struct tc_u32_sel *u32_selector_alloc(struct rtnl_u32 *u) +{ + if (!u->cu_selector) + u->cu_selector = nl_data_alloc(NULL, sizeof(struct tc_u32_sel)); + + return u32_selector(u); +} + +static struct nla_policy u32_policy[TCA_U32_MAX+1] = { + [TCA_U32_DIVISOR] = { .type = NLA_U32 }, + [TCA_U32_HASH] = { .type = NLA_U32 }, + [TCA_U32_CLASSID] = { .type = NLA_U32 }, + [TCA_U32_LINK] = { .type = NLA_U32 }, + [TCA_U32_INDEV] = { .type = NLA_STRING, + .maxlen = IFNAMSIZ }, + [TCA_U32_SEL] = { .minlen = sizeof(struct tc_u32_sel) }, + [TCA_U32_PCNT] = { .minlen = sizeof(struct tc_u32_pcnt) }, +}; + +static int u32_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct rtnl_u32 *u = data; + struct nlattr *tb[TCA_U32_MAX + 1]; + int err; + + err = tca_parse(tb, TCA_U32_MAX, tc, u32_policy); + if (err < 0) + return err; + + if (tb[TCA_U32_DIVISOR]) { + u->cu_divisor = nla_get_u32(tb[TCA_U32_DIVISOR]); + u->cu_mask |= U32_ATTR_DIVISOR; + } + + if (tb[TCA_U32_SEL]) { + u->cu_selector = nl_data_alloc_attr(tb[TCA_U32_SEL]); + if (!u->cu_selector) + goto errout_nomem; + u->cu_mask |= U32_ATTR_SELECTOR; + } + + if (tb[TCA_U32_HASH]) { + u->cu_hash = nla_get_u32(tb[TCA_U32_HASH]); + u->cu_mask |= U32_ATTR_HASH; + } + + if (tb[TCA_U32_CLASSID]) { + u->cu_classid = nla_get_u32(tb[TCA_U32_CLASSID]); + u->cu_mask |= U32_ATTR_CLASSID; + } + + if (tb[TCA_U32_LINK]) { + u->cu_link = nla_get_u32(tb[TCA_U32_LINK]); + u->cu_mask |= U32_ATTR_LINK; + } + + if (tb[TCA_U32_ACT]) { + u->cu_act = nl_data_alloc_attr(tb[TCA_U32_ACT]); + if (!u->cu_act) + goto errout_nomem; + u->cu_mask |= U32_ATTR_ACTION; + } + + if (tb[TCA_U32_POLICE]) { + u->cu_police = nl_data_alloc_attr(tb[TCA_U32_POLICE]); + if (!u->cu_police) + goto errout_nomem; + u->cu_mask |= U32_ATTR_POLICE; + } + + if (tb[TCA_U32_PCNT]) { + struct tc_u32_sel *sel; + size_t pcnt_size; + + if (!tb[TCA_U32_SEL]) { + err = -NLE_MISSING_ATTR; + goto errout; + } + + sel = u->cu_selector->d_data; + pcnt_size = sizeof(struct tc_u32_pcnt) + + (sel->nkeys * sizeof(uint64_t)); + if (nla_len(tb[TCA_U32_PCNT]) < pcnt_size) { + err = -NLE_INVAL; + goto errout; + } + + u->cu_pcnt = nl_data_alloc_attr(tb[TCA_U32_PCNT]); + if (!u->cu_pcnt) + goto errout_nomem; + u->cu_mask |= U32_ATTR_PCNT; + } + + if (tb[TCA_U32_INDEV]) { + nla_strlcpy(u->cu_indev, tb[TCA_U32_INDEV], IFNAMSIZ); + u->cu_mask |= U32_ATTR_INDEV; + } + + return 0; + +errout_nomem: + err = -NLE_NOMEM; +errout: + return err; +} + +static void u32_free_data(struct rtnl_tc *tc, void *data) +{ + struct rtnl_u32 *u = data; + + nl_data_free(u->cu_selector); + nl_data_free(u->cu_act); + nl_data_free(u->cu_police); + nl_data_free(u->cu_pcnt); +} + +static int u32_clone(void *_dst, void *_src) +{ + struct rtnl_u32 *dst = _dst, *src = _src; + + if (src->cu_selector && + !(dst->cu_selector = nl_data_clone(src->cu_selector))) + return -NLE_NOMEM; + + if (src->cu_act && !(dst->cu_act = nl_data_clone(src->cu_act))) + return -NLE_NOMEM; + + if (src->cu_police && !(dst->cu_police = nl_data_clone(src->cu_police))) + return -NLE_NOMEM; + + if (src->cu_pcnt && !(dst->cu_pcnt = nl_data_clone(src->cu_pcnt))) + return -NLE_NOMEM; + + return 0; +} + +static void u32_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_u32 *u = data; + char buf[32]; + + if (!u) + return; + + if (u->cu_mask & U32_ATTR_DIVISOR) + nl_dump(p, " divisor %u", u->cu_divisor); + else if (u->cu_mask & U32_ATTR_CLASSID) + nl_dump(p, " target %s", + rtnl_tc_handle2str(u->cu_classid, buf, sizeof(buf))); +} + +static void print_selector(struct nl_dump_params *p, struct tc_u32_sel *sel, + struct rtnl_u32 *u) +{ + int i; + struct tc_u32_key *key; + + if (sel->hmask || sel->hoff) { + /* I guess this will never be used since the kernel only + * exports the selector if no divisor is set but hash offset + * and hash mask make only sense in hash filters with divisor + * set */ + nl_dump(p, " hash at %u & 0x%x", sel->hoff, sel->hmask); + } + + if (sel->flags & (TC_U32_OFFSET | TC_U32_VAROFFSET)) { + nl_dump(p, " offset at %u", sel->off); + + if (sel->flags & TC_U32_VAROFFSET) + nl_dump(p, " variable (at %u & 0x%x) >> %u", + sel->offoff, ntohs(sel->offmask), sel->offshift); + } + + if (sel->flags) { + int flags = sel->flags; + nl_dump(p, " <"); + +#define PRINT_FLAG(f) if (flags & TC_U32_##f) { \ + flags &= ~TC_U32_##f; nl_dump(p, #f "%s", flags ? "," : ""); } + + PRINT_FLAG(TERMINAL); + PRINT_FLAG(OFFSET); + PRINT_FLAG(VAROFFSET); + PRINT_FLAG(EAT); +#undef PRINT_FLAG + + nl_dump(p, ">"); + } + + + for (i = 0; i < sel->nkeys; i++) { + key = (struct tc_u32_key *) ((char *) sel + sizeof(*sel)) + i; + + nl_dump(p, "\n"); + nl_dump_line(p, " match key at %s%u ", + key->offmask ? "nexthdr+" : "", key->off); + + if (key->offmask) + nl_dump(p, "[0x%u] ", key->offmask); + + nl_dump(p, "& 0x%08x == 0x%08x", ntohl(key->mask), ntohl(key->val)); + + if (p->dp_type == NL_DUMP_STATS && + (u->cu_mask & U32_ATTR_PCNT)) { + struct tc_u32_pcnt *pcnt = u->cu_pcnt->d_data; + nl_dump(p, " successful %" PRIu64, pcnt->kcnts[i]); + } + } +} + +static void u32_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_u32 *u = data; + struct tc_u32_sel *s; + + if (!u) + return; + + if (!(u->cu_mask & U32_ATTR_SELECTOR)) { + nl_dump(p, "no-selector\n"); + return; + } + + s = u->cu_selector->d_data; + + nl_dump(p, "nkeys %u ", s->nkeys); + + if (u->cu_mask & U32_ATTR_HASH) + nl_dump(p, "ht key 0x%x hash 0x%u", + TC_U32_USERHTID(u->cu_hash), TC_U32_HASH(u->cu_hash)); + + if (u->cu_mask & U32_ATTR_LINK) + nl_dump(p, "link %u ", u->cu_link); + + if (u->cu_mask & U32_ATTR_INDEV) + nl_dump(p, "indev %s ", u->cu_indev); + + print_selector(p, s, u); + nl_dump(p, "\n"); + +#if 0 +#define U32_ATTR_ACTION 0x040 +#define U32_ATTR_POLICE 0x080 + + struct nl_data act; + struct nl_data police; +#endif +} + +static void u32_dump_stats(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_u32 *u = data; + + if (!u) + return; + + if (u->cu_mask & U32_ATTR_PCNT) { + struct tc_u32_pcnt *pc = u->cu_pcnt->d_data; + nl_dump(p, "\n"); + nl_dump_line(p, " hit %8" PRIu64 " count %8" PRIu64 "\n", + pc->rhit, pc->rcnt); + } +} + +static int u32_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + struct rtnl_u32 *u = data; + + if (!u) + return 0; + + if (u->cu_mask & U32_ATTR_DIVISOR) + NLA_PUT_U32(msg, TCA_U32_DIVISOR, u->cu_divisor); + + if (u->cu_mask & U32_ATTR_HASH) + NLA_PUT_U32(msg, TCA_U32_HASH, u->cu_hash); + + if (u->cu_mask & U32_ATTR_CLASSID) + NLA_PUT_U32(msg, TCA_U32_CLASSID, u->cu_classid); + + if (u->cu_mask & U32_ATTR_LINK) + NLA_PUT_U32(msg, TCA_U32_LINK, u->cu_link); + + if (u->cu_mask & U32_ATTR_SELECTOR) + NLA_PUT_DATA(msg, TCA_U32_SEL, u->cu_selector); + + if (u->cu_mask & U32_ATTR_ACTION) + NLA_PUT_DATA(msg, TCA_U32_ACT, u->cu_act); + + if (u->cu_mask & U32_ATTR_POLICE) + NLA_PUT_DATA(msg, TCA_U32_POLICE, u->cu_police); + + if (u->cu_mask & U32_ATTR_INDEV) + NLA_PUT_STRING(msg, TCA_U32_INDEV, u->cu_indev); + + return 0; + +nla_put_failure: + return -NLE_NOMEM; +} + +/** + * @name Attribute Modifications + * @{ + */ + +void rtnl_u32_set_handle(struct rtnl_cls *cls, int htid, int hash, + int nodeid) +{ + uint32_t handle = (htid << 20) | (hash << 12) | nodeid; + + rtnl_tc_set_handle((struct rtnl_tc *) cls, handle ); +} + +int rtnl_u32_set_classid(struct rtnl_cls *cls, uint32_t classid) +{ + struct rtnl_u32 *u; + + if (!(u = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + u->cu_classid = classid; + u->cu_mask |= U32_ATTR_CLASSID; + + return 0; +} + +int rtnl_u32_set_divisor(struct rtnl_cls *cls, uint32_t divisor) +{ + struct rtnl_u32 *u; + + if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + u->cu_divisor = divisor; + u->cu_mask |= U32_ATTR_DIVISOR; + return 0; +} + +int rtnl_u32_set_link(struct rtnl_cls *cls, uint32_t link) +{ + struct rtnl_u32 *u; + + if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + u->cu_link = link; + u->cu_mask |= U32_ATTR_LINK; + return 0; +} + +int rtnl_u32_set_hashtable(struct rtnl_cls *cls, uint32_t ht) +{ + struct rtnl_u32 *u; + + if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + u->cu_hash = ht; + u->cu_mask |= U32_ATTR_HASH; + return 0; +} + +int rtnl_u32_set_hashmask(struct rtnl_cls *cls, uint32_t hashmask, uint32_t offset) +{ + struct rtnl_u32 *u; + struct tc_u32_sel *sel; + int err; + + hashmask = htonl(hashmask); + + if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + sel = u32_selector_alloc(u); + if (!sel) + return -NLE_NOMEM; + + err = nl_data_append(u->cu_selector, NULL, sizeof(struct tc_u32_key)); + if(err < 0) + return err; + + sel = u32_selector(u); + + sel->hmask = hashmask; + sel->hoff = offset; + return 0; +} + +int rtnl_u32_set_cls_terminal(struct rtnl_cls *cls) +{ + struct rtnl_u32 *u; + struct tc_u32_sel *sel; + int err; + + if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + sel = u32_selector_alloc(u); + if (!sel) + return -NLE_NOMEM; + + err = nl_data_append(u->cu_selector, NULL, sizeof(struct tc_u32_key)); + if(err < 0) + return err; + + sel = u32_selector(u); + + sel->flags |= TC_U32_TERMINAL; + return 0; +} + +/** @} */ + +/** + * @name Selector Modifications + * @{ + */ + +int rtnl_u32_set_flags(struct rtnl_cls *cls, int flags) +{ + struct tc_u32_sel *sel; + struct rtnl_u32 *u; + + if (!(u = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + sel = u32_selector_alloc(u); + if (!sel) + return -NLE_NOMEM; + + sel->flags |= flags; + u->cu_mask |= U32_ATTR_SELECTOR; + + return 0; +} + +/** + * Append new 32-bit key to the selector + * + * @arg cls classifier to be modifier + * @arg val value to be matched (network byte-order) + * @arg mask mask to be applied before matching (network byte-order) + * @arg off offset, in bytes, to start matching + * @arg offmask offset mask + * + * General selectors define the pattern, mask and offset the pattern will be + * matched to the packet contents. Using the general selectors you can match + * virtually any single bit in the IP (or upper layer) header. + * +*/ +int rtnl_u32_add_key(struct rtnl_cls *cls, uint32_t val, uint32_t mask, + int off, int offmask) +{ + struct tc_u32_sel *sel; + struct rtnl_u32 *u; + int err; + + if (!(u = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + sel = u32_selector_alloc(u); + if (!sel) + return -NLE_NOMEM; + + err = nl_data_append(u->cu_selector, NULL, sizeof(struct tc_u32_key)); + if (err < 0) + return err; + + /* the selector might have been moved by realloc */ + sel = u32_selector(u); + + sel->keys[sel->nkeys].mask = mask; + sel->keys[sel->nkeys].val = val & mask; + sel->keys[sel->nkeys].off = off; + sel->keys[sel->nkeys].offmask = offmask; + sel->nkeys++; + u->cu_mask |= U32_ATTR_SELECTOR; + + return 0; +} + +int rtnl_u32_add_key_uint8(struct rtnl_cls *cls, uint8_t val, uint8_t mask, + int off, int offmask) +{ + int shift = 24 - 8 * (off & 3); + + return rtnl_u32_add_key(cls, htonl((uint32_t)val << shift), + htonl((uint32_t)mask << shift), + off & ~3, offmask); +} + +/** + * Append new selector key to match a 16-bit number + * + * @arg cls classifier to be modified + * @arg val value to be matched (host byte-order) + * @arg mask mask to be applied before matching (host byte-order) + * @arg off offset, in bytes, to start matching + * @arg offmask offset mask +*/ +int rtnl_u32_add_key_uint16(struct rtnl_cls *cls, uint16_t val, uint16_t mask, + int off, int offmask) +{ + int shift = ((off & 3) == 0 ? 16 : 0); + if (off % 2) + return -NLE_INVAL; + + return rtnl_u32_add_key(cls, htonl((uint32_t)val << shift), + htonl((uint32_t)mask << shift), + off & ~3, offmask); +} + +/** + * Append new selector key to match a 32-bit number + * + * @arg cls classifier to be modified + * @arg val value to be matched (host byte-order) + * @arg mask mask to be applied before matching (host byte-order) + * @arg off offset, in bytes, to start matching + * @arg offmask offset mask +*/ +int rtnl_u32_add_key_uint32(struct rtnl_cls *cls, uint32_t val, uint32_t mask, + int off, int offmask) +{ + return rtnl_u32_add_key(cls, htonl(val), htonl(mask), + off & ~3, offmask); +} + +int rtnl_u32_add_key_in_addr(struct rtnl_cls *cls, struct in_addr *addr, + uint8_t bitmask, int off, int offmask) +{ + uint32_t mask = 0xFFFFFFFF << (32 - bitmask); + return rtnl_u32_add_key(cls, addr->s_addr, htonl(mask), off, offmask); +} + +int rtnl_u32_add_key_in6_addr(struct rtnl_cls *cls, struct in6_addr *addr, + uint8_t bitmask, int off, int offmask) +{ + int i, err; + + for (i = 1; i <= 4; i++) { + if (32 * i - bitmask <= 0) { + if ((err = rtnl_u32_add_key(cls, addr->s6_addr32[i-1], + 0xFFFFFFFF, off+4*(i-1), offmask)) < 0) + return err; + } + else if (32 * i - bitmask < 32) { + uint32_t mask = 0xFFFFFFFF << (32 * i - bitmask); + if ((err = rtnl_u32_add_key(cls, addr->s6_addr32[i-1], + htonl(mask), off+4*(i-1), offmask)) < 0) + return err; + } + /* otherwise, if (32*i - bitmask >= 32) no key is generated */ + } + + return 0; +} + +/** @} */ + +static struct rtnl_tc_ops u32_ops = { + .to_kind = "u32", + .to_type = RTNL_TC_TYPE_CLS, + .to_size = sizeof(struct rtnl_u32), + .to_msg_parser = u32_msg_parser, + .to_free_data = u32_free_data, + .to_clone = u32_clone, + .to_msg_fill = u32_msg_fill, + .to_dump = { + [NL_DUMP_LINE] = u32_dump_line, + [NL_DUMP_DETAILS] = u32_dump_details, + [NL_DUMP_STATS] = u32_dump_stats, + }, +}; + +static void __init u32_init(void) +{ + rtnl_tc_register(&u32_ops); +} + +static void __exit u32_exit(void) +{ + rtnl_tc_unregister(&u32_ops); +} + +/** @} */ diff --git a/lib/route/link.c b/lib/route/link.c new file mode 100644 index 0000000..77dd7f1 --- /dev/null +++ b/lib/route/link.c @@ -0,0 +1,2644 @@ +/* + * lib/route/link.c Links (Interfaces) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +/** + * @ingroup rtnl + * @defgroup link Links (Interfaces) + * + * @details + * @route_doc{route_link, Link Documentation} + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define LINK_ATTR_MTU (1 << 0) +#define LINK_ATTR_LINK (1 << 1) +#define LINK_ATTR_TXQLEN (1 << 2) +#define LINK_ATTR_WEIGHT (1 << 3) +#define LINK_ATTR_MASTER (1 << 4) +#define LINK_ATTR_QDISC (1 << 5) +#define LINK_ATTR_MAP (1 << 6) +#define LINK_ATTR_ADDR (1 << 7) +#define LINK_ATTR_BRD (1 << 8) +#define LINK_ATTR_FLAGS (1 << 9) +#define LINK_ATTR_IFNAME (1 << 10) +#define LINK_ATTR_IFINDEX (1 << 11) +#define LINK_ATTR_FAMILY (1 << 12) +#define LINK_ATTR_ARPTYPE (1 << 13) +#define LINK_ATTR_STATS (1 << 14) +#define LINK_ATTR_CHANGE (1 << 15) +#define LINK_ATTR_OPERSTATE (1 << 16) +#define LINK_ATTR_LINKMODE (1 << 17) +#define LINK_ATTR_LINKINFO (1 << 18) +#define LINK_ATTR_IFALIAS (1 << 19) +#define LINK_ATTR_NUM_VF (1 << 20) +#define LINK_ATTR_PROMISCUITY (1 << 21) +#define LINK_ATTR_NUM_TX_QUEUES (1 << 22) +#define LINK_ATTR_NUM_RX_QUEUES (1 << 23) +#define LINK_ATTR_GROUP (1 << 24) +#define LINK_ATTR_CARRIER (1 << 25) +#define LINK_ATTR_PROTINFO (1 << 26) +#define LINK_ATTR_AF_SPEC (1 << 27) + +static struct nl_cache_ops rtnl_link_ops; +static struct nl_object_ops link_obj_ops; +/** @endcond */ + +static struct rtnl_link_af_ops *af_lookup_and_alloc(struct rtnl_link *link, + int family) +{ + struct rtnl_link_af_ops *af_ops; + void *data; + + af_ops = rtnl_link_af_ops_lookup(family); + if (!af_ops) + return NULL; + + if (!(data = rtnl_link_af_alloc(link, af_ops))) { + rtnl_link_af_ops_put(af_ops); + return NULL; + } + + return af_ops; +} + +static int af_free(struct rtnl_link *link, struct rtnl_link_af_ops *ops, + void *data, void *arg) +{ + if (ops->ao_free) + ops->ao_free(link, data); + + rtnl_link_af_ops_put(ops); + + return 0; +} + +static int af_clone(struct rtnl_link *link, struct rtnl_link_af_ops *ops, + void *data, void *arg) +{ + struct rtnl_link *dst = arg; + + if (ops->ao_clone && + !(dst->l_af_data[ops->ao_family] = ops->ao_clone(dst, data))) + return -NLE_NOMEM; + + return 0; +} + +static int af_fill(struct rtnl_link *link, struct rtnl_link_af_ops *ops, + void *data, void *arg) +{ + struct nl_msg *msg = arg; + struct nlattr *af_attr; + int err; + + if (!ops->ao_fill_af) + return 0; + + if (!(af_attr = nla_nest_start(msg, ops->ao_family))) + return -NLE_MSGSIZE; + + if ((err = ops->ao_fill_af(link, arg, data)) < 0) + return err; + + nla_nest_end(msg, af_attr); + + return 0; +} + +static int af_dump_line(struct rtnl_link *link, struct rtnl_link_af_ops *ops, + void *data, void *arg) +{ + struct nl_dump_params *p = arg; + + if (ops->ao_dump[NL_DUMP_LINE]) + ops->ao_dump[NL_DUMP_LINE](link, p, data); + + return 0; +} + +static int af_dump_details(struct rtnl_link *link, struct rtnl_link_af_ops *ops, + void *data, void *arg) +{ + struct nl_dump_params *p = arg; + + if (ops->ao_dump[NL_DUMP_DETAILS]) + ops->ao_dump[NL_DUMP_DETAILS](link, p, data); + + return 0; +} + +static int af_dump_stats(struct rtnl_link *link, struct rtnl_link_af_ops *ops, + void *data, void *arg) +{ + struct nl_dump_params *p = arg; + + if (ops->ao_dump[NL_DUMP_STATS]) + ops->ao_dump[NL_DUMP_STATS](link, p, data); + + return 0; +} + +static int do_foreach_af(struct rtnl_link *link, + int (*cb)(struct rtnl_link *, + struct rtnl_link_af_ops *, void *, void *), + void *arg) +{ + int i, err; + + for (i = 0; i < AF_MAX; i++) { + if (link->l_af_data[i]) { + struct rtnl_link_af_ops *ops; + + if (!(ops = rtnl_link_af_ops_lookup(i))) + BUG(); + + err = cb(link, ops, link->l_af_data[i], arg); + + rtnl_link_af_ops_put(ops); + + if (err < 0) + return err; + } + } + + return 0; +} + +static void release_link_info(struct rtnl_link *link) +{ + struct rtnl_link_info_ops *io = link->l_info_ops; + + if (io != NULL) { + if (io->io_free) + io->io_free(link); + rtnl_link_info_ops_put(io); + link->l_info_ops = NULL; + } +} + +static void link_free_data(struct nl_object *c) +{ + struct rtnl_link *link = nl_object_priv(c); + + if (link) { + struct rtnl_link_info_ops *io; + + if ((io = link->l_info_ops) != NULL) + release_link_info(link); + + /* proto info af reference */ + rtnl_link_af_ops_put(link->l_af_ops); + + nl_addr_put(link->l_addr); + nl_addr_put(link->l_bcast); + + free(link->l_ifalias); + free(link->l_info_kind); + + do_foreach_af(link, af_free, NULL); + } +} + +static int link_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct rtnl_link *dst = nl_object_priv(_dst); + struct rtnl_link *src = nl_object_priv(_src); + int err; + + if (src->l_addr) + if (!(dst->l_addr = nl_addr_clone(src->l_addr))) + return -NLE_NOMEM; + + if (src->l_bcast) + if (!(dst->l_bcast = nl_addr_clone(src->l_bcast))) + return -NLE_NOMEM; + + if (src->l_ifalias) + if (!(dst->l_ifalias = strdup(src->l_ifalias))) + return -NLE_NOMEM; + + if (src->l_info_kind) + if (!(dst->l_info_kind = strdup(src->l_info_kind))) + return -NLE_NOMEM; + + if (src->l_info_ops && src->l_info_ops->io_clone) { + err = src->l_info_ops->io_clone(dst, src); + if (err < 0) + return err; + } + + if ((err = do_foreach_af(src, af_clone, dst)) < 0) + return err; + + return 0; +} + +static struct nla_policy link_policy[IFLA_MAX+1] = { + [IFLA_IFNAME] = { .type = NLA_STRING, + .maxlen = IFNAMSIZ }, + [IFLA_MTU] = { .type = NLA_U32 }, + [IFLA_TXQLEN] = { .type = NLA_U32 }, + [IFLA_LINK] = { .type = NLA_U32 }, + [IFLA_WEIGHT] = { .type = NLA_U32 }, + [IFLA_MASTER] = { .type = NLA_U32 }, + [IFLA_OPERSTATE] = { .type = NLA_U8 }, + [IFLA_LINKMODE] = { .type = NLA_U8 }, + [IFLA_LINKINFO] = { .type = NLA_NESTED }, + [IFLA_QDISC] = { .type = NLA_STRING, + .maxlen = IFQDISCSIZ }, + [IFLA_STATS] = { .minlen = sizeof(struct rtnl_link_stats) }, + [IFLA_STATS64] = { .minlen = sizeof(struct rtnl_link_stats64)}, + [IFLA_MAP] = { .minlen = sizeof(struct rtnl_link_ifmap) }, + [IFLA_IFALIAS] = { .type = NLA_STRING, .maxlen = IFALIASZ }, + [IFLA_NUM_VF] = { .type = NLA_U32 }, + [IFLA_AF_SPEC] = { .type = NLA_NESTED }, + [IFLA_PROMISCUITY] = { .type = NLA_U32 }, + [IFLA_NUM_TX_QUEUES] = { .type = NLA_U32 }, + [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 }, + [IFLA_GROUP] = { .type = NLA_U32 }, + [IFLA_CARRIER] = { .type = NLA_U8 }, +}; + +static struct nla_policy link_info_policy[IFLA_INFO_MAX+1] = { + [IFLA_INFO_KIND] = { .type = NLA_STRING }, + [IFLA_INFO_DATA] = { .type = NLA_NESTED }, + [IFLA_INFO_XSTATS] = { .type = NLA_NESTED }, +}; + +static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *n, struct nl_parser_param *pp) +{ + struct rtnl_link *link; + struct ifinfomsg *ifi; + struct nlattr *tb[IFLA_MAX+1]; + struct rtnl_link_af_ops *af_ops = NULL; + int err, family; + struct nla_policy real_link_policy[IFLA_MAX+1]; + + memcpy(&real_link_policy, link_policy, sizeof(link_policy)); + + link = rtnl_link_alloc(); + if (link == NULL) { + err = -NLE_NOMEM; + goto errout; + } + + link->ce_msgtype = n->nlmsg_type; + + if (!nlmsg_valid_hdr(n, sizeof(*ifi))) + return -NLE_MSG_TOOSHORT; + + ifi = nlmsg_data(n); + link->l_family = family = ifi->ifi_family; + link->l_arptype = ifi->ifi_type; + link->l_index = ifi->ifi_index; + link->l_flags = ifi->ifi_flags; + link->l_change = ifi->ifi_change; + link->ce_mask = (LINK_ATTR_IFNAME | LINK_ATTR_FAMILY | + LINK_ATTR_ARPTYPE| LINK_ATTR_IFINDEX | + LINK_ATTR_FLAGS | LINK_ATTR_CHANGE); + + if ((af_ops = af_lookup_and_alloc(link, family))) { + if (af_ops->ao_protinfo_policy) { + memcpy(&real_link_policy[IFLA_PROTINFO], + af_ops->ao_protinfo_policy, + sizeof(struct nla_policy)); + } + + link->l_af_ops = af_ops; + } + + err = nlmsg_parse(n, sizeof(*ifi), tb, IFLA_MAX, real_link_policy); + if (err < 0) + goto errout; + + if (tb[IFLA_IFNAME] == NULL) { + err = -NLE_MISSING_ATTR; + goto errout; + } + + nla_strlcpy(link->l_name, tb[IFLA_IFNAME], IFNAMSIZ); + + + if (tb[IFLA_STATS]) { + struct rtnl_link_stats *st = nla_data(tb[IFLA_STATS]); + + link->l_stats[RTNL_LINK_RX_PACKETS] = st->rx_packets; + link->l_stats[RTNL_LINK_TX_PACKETS] = st->tx_packets; + link->l_stats[RTNL_LINK_RX_BYTES] = st->rx_bytes; + link->l_stats[RTNL_LINK_TX_BYTES] = st->tx_bytes; + link->l_stats[RTNL_LINK_RX_ERRORS] = st->rx_errors; + link->l_stats[RTNL_LINK_TX_ERRORS] = st->tx_errors; + link->l_stats[RTNL_LINK_RX_DROPPED] = st->rx_dropped; + link->l_stats[RTNL_LINK_TX_DROPPED] = st->tx_dropped; + link->l_stats[RTNL_LINK_MULTICAST] = st->multicast; + link->l_stats[RTNL_LINK_COLLISIONS] = st->collisions; + + link->l_stats[RTNL_LINK_RX_LEN_ERR] = st->rx_length_errors; + link->l_stats[RTNL_LINK_RX_OVER_ERR] = st->rx_over_errors; + link->l_stats[RTNL_LINK_RX_CRC_ERR] = st->rx_crc_errors; + link->l_stats[RTNL_LINK_RX_FRAME_ERR] = st->rx_frame_errors; + link->l_stats[RTNL_LINK_RX_FIFO_ERR] = st->rx_fifo_errors; + link->l_stats[RTNL_LINK_RX_MISSED_ERR] = st->rx_missed_errors; + + link->l_stats[RTNL_LINK_TX_ABORT_ERR] = st->tx_aborted_errors; + link->l_stats[RTNL_LINK_TX_CARRIER_ERR] = st->tx_carrier_errors; + link->l_stats[RTNL_LINK_TX_FIFO_ERR] = st->tx_fifo_errors; + link->l_stats[RTNL_LINK_TX_HBEAT_ERR] = st->tx_heartbeat_errors; + link->l_stats[RTNL_LINK_TX_WIN_ERR] = st->tx_window_errors; + + link->l_stats[RTNL_LINK_RX_COMPRESSED] = st->rx_compressed; + link->l_stats[RTNL_LINK_TX_COMPRESSED] = st->tx_compressed; + + link->ce_mask |= LINK_ATTR_STATS; + } + + if (tb[IFLA_STATS64]) { + /* + * This structure contains 64bit parameters, and per the + * documentation in lib/attr.c, must not be accessed + * directly (because of alignment to 4 instead of 8). + * Therefore, copy the data to the stack and access it from + * there, where it will be aligned to 8. + */ + struct rtnl_link_stats64 st; + + nla_memcpy(&st, tb[IFLA_STATS64], + sizeof(struct rtnl_link_stats64)); + + link->l_stats[RTNL_LINK_RX_PACKETS] = st.rx_packets; + link->l_stats[RTNL_LINK_TX_PACKETS] = st.tx_packets; + link->l_stats[RTNL_LINK_RX_BYTES] = st.rx_bytes; + link->l_stats[RTNL_LINK_TX_BYTES] = st.tx_bytes; + link->l_stats[RTNL_LINK_RX_ERRORS] = st.rx_errors; + link->l_stats[RTNL_LINK_TX_ERRORS] = st.tx_errors; + link->l_stats[RTNL_LINK_RX_DROPPED] = st.rx_dropped; + link->l_stats[RTNL_LINK_TX_DROPPED] = st.tx_dropped; + link->l_stats[RTNL_LINK_MULTICAST] = st.multicast; + link->l_stats[RTNL_LINK_COLLISIONS] = st.collisions; + + link->l_stats[RTNL_LINK_RX_LEN_ERR] = st.rx_length_errors; + link->l_stats[RTNL_LINK_RX_OVER_ERR] = st.rx_over_errors; + link->l_stats[RTNL_LINK_RX_CRC_ERR] = st.rx_crc_errors; + link->l_stats[RTNL_LINK_RX_FRAME_ERR] = st.rx_frame_errors; + link->l_stats[RTNL_LINK_RX_FIFO_ERR] = st.rx_fifo_errors; + link->l_stats[RTNL_LINK_RX_MISSED_ERR] = st.rx_missed_errors; + + link->l_stats[RTNL_LINK_TX_ABORT_ERR] = st.tx_aborted_errors; + link->l_stats[RTNL_LINK_TX_CARRIER_ERR] = st.tx_carrier_errors; + link->l_stats[RTNL_LINK_TX_FIFO_ERR] = st.tx_fifo_errors; + link->l_stats[RTNL_LINK_TX_HBEAT_ERR] = st.tx_heartbeat_errors; + link->l_stats[RTNL_LINK_TX_WIN_ERR] = st.tx_window_errors; + + link->l_stats[RTNL_LINK_RX_COMPRESSED] = st.rx_compressed; + link->l_stats[RTNL_LINK_TX_COMPRESSED] = st.tx_compressed; + + link->ce_mask |= LINK_ATTR_STATS; + } + + if (tb[IFLA_TXQLEN]) { + link->l_txqlen = nla_get_u32(tb[IFLA_TXQLEN]); + link->ce_mask |= LINK_ATTR_TXQLEN; + } + + if (tb[IFLA_MTU]) { + link->l_mtu = nla_get_u32(tb[IFLA_MTU]); + link->ce_mask |= LINK_ATTR_MTU; + } + + if (tb[IFLA_ADDRESS]) { + link->l_addr = nl_addr_alloc_attr(tb[IFLA_ADDRESS], AF_UNSPEC); + if (link->l_addr == NULL) { + err = -NLE_NOMEM; + goto errout; + } + nl_addr_set_family(link->l_addr, + nl_addr_guess_family(link->l_addr)); + link->ce_mask |= LINK_ATTR_ADDR; + } + + if (tb[IFLA_BROADCAST]) { + link->l_bcast = nl_addr_alloc_attr(tb[IFLA_BROADCAST], + AF_UNSPEC); + if (link->l_bcast == NULL) { + err = -NLE_NOMEM; + goto errout; + } + nl_addr_set_family(link->l_bcast, + nl_addr_guess_family(link->l_bcast)); + link->ce_mask |= LINK_ATTR_BRD; + } + + if (tb[IFLA_LINK]) { + link->l_link = nla_get_u32(tb[IFLA_LINK]); + link->ce_mask |= LINK_ATTR_LINK; + } + + if (tb[IFLA_WEIGHT]) { + link->l_weight = nla_get_u32(tb[IFLA_WEIGHT]); + link->ce_mask |= LINK_ATTR_WEIGHT; + } + + if (tb[IFLA_QDISC]) { + nla_strlcpy(link->l_qdisc, tb[IFLA_QDISC], IFQDISCSIZ); + link->ce_mask |= LINK_ATTR_QDISC; + } + + if (tb[IFLA_MAP]) { + nla_memcpy(&link->l_map, tb[IFLA_MAP], + sizeof(struct rtnl_link_ifmap)); + link->ce_mask |= LINK_ATTR_MAP; + } + + if (tb[IFLA_MASTER]) { + link->l_master = nla_get_u32(tb[IFLA_MASTER]); + link->ce_mask |= LINK_ATTR_MASTER; + } + + if (tb[IFLA_CARRIER]) { + link->l_carrier = nla_get_u8(tb[IFLA_CARRIER]); + link->ce_mask |= LINK_ATTR_CARRIER; + } + + if (tb[IFLA_OPERSTATE]) { + link->l_operstate = nla_get_u8(tb[IFLA_OPERSTATE]); + link->ce_mask |= LINK_ATTR_OPERSTATE; + } + + if (tb[IFLA_LINKMODE]) { + link->l_linkmode = nla_get_u8(tb[IFLA_LINKMODE]); + link->ce_mask |= LINK_ATTR_LINKMODE; + } + + if (tb[IFLA_IFALIAS]) { + link->l_ifalias = nla_strdup(tb[IFLA_IFALIAS]); + if (link->l_ifalias == NULL) { + err = -NLE_NOMEM; + goto errout; + } + link->ce_mask |= LINK_ATTR_IFALIAS; + } + + if (tb[IFLA_NUM_VF]) { + link->l_num_vf = nla_get_u32(tb[IFLA_NUM_VF]); + link->ce_mask |= LINK_ATTR_NUM_VF; + } + + if (tb[IFLA_LINKINFO]) { + struct nlattr *li[IFLA_INFO_MAX+1]; + + err = nla_parse_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO], + link_info_policy); + if (err < 0) + goto errout; + + if (li[IFLA_INFO_KIND]) { + struct rtnl_link_info_ops *ops; + char *kind; + + kind = nla_strdup(li[IFLA_INFO_KIND]); + if (kind == NULL) { + err = -NLE_NOMEM; + goto errout; + } + link->l_info_kind = kind; + link->ce_mask |= LINK_ATTR_LINKINFO; + + ops = rtnl_link_info_ops_lookup(kind); + link->l_info_ops = ops; + + if (ops) { + if (ops->io_parse && + (li[IFLA_INFO_DATA] || li[IFLA_INFO_XSTATS])) { + err = ops->io_parse(link, li[IFLA_INFO_DATA], + li[IFLA_INFO_XSTATS]); + if (err < 0) + goto errout; + } else { + /* XXX: Warn about unparsed info? */ + } + } + } + link->ce_mask |= LINK_ATTR_LINKINFO; + } + + if (tb[IFLA_PROTINFO] && af_ops && af_ops->ao_parse_protinfo) { + err = af_ops->ao_parse_protinfo(link, tb[IFLA_PROTINFO], + link->l_af_data[link->l_family]); + if (err < 0) + goto errout; + link->ce_mask |= LINK_ATTR_PROTINFO; + } + + if (tb[IFLA_AF_SPEC]) { + struct nlattr *af_attr; + int remaining; + + nla_for_each_nested(af_attr, tb[IFLA_AF_SPEC], remaining) { + af_ops = af_lookup_and_alloc(link, nla_type(af_attr)); + if (af_ops && af_ops->ao_parse_af) { + char *af_data = link->l_af_data[nla_type(af_attr)]; + + err = af_ops->ao_parse_af(link, af_attr, af_data); + if (err < 0) + goto errout; + } + + } + link->ce_mask |= LINK_ATTR_AF_SPEC; + } + + if (tb[IFLA_PROMISCUITY]) { + link->l_promiscuity = nla_get_u32(tb[IFLA_PROMISCUITY]); + link->ce_mask |= LINK_ATTR_PROMISCUITY; + } + + if (tb[IFLA_NUM_TX_QUEUES]) { + link->l_num_tx_queues = nla_get_u32(tb[IFLA_NUM_TX_QUEUES]); + link->ce_mask |= LINK_ATTR_NUM_TX_QUEUES; + } + + if (tb[IFLA_NUM_RX_QUEUES]) { + link->l_num_rx_queues = nla_get_u32(tb[IFLA_NUM_RX_QUEUES]); + link->ce_mask |= LINK_ATTR_NUM_RX_QUEUES; + } + + if (tb[IFLA_GROUP]) { + link->l_group = nla_get_u32(tb[IFLA_GROUP]); + link->ce_mask |= LINK_ATTR_GROUP; + } + + err = pp->pp_cb((struct nl_object *) link, pp); +errout: + rtnl_link_af_ops_put(af_ops); + rtnl_link_put(link); + return err; +} + +static int link_request_update(struct nl_cache *cache, struct nl_sock *sk) +{ + int family = cache->c_iarg1; + + return nl_rtgen_request(sk, RTM_GETLINK, family, NLM_F_DUMP); +} + +static void link_dump_line(struct nl_object *obj, struct nl_dump_params *p) +{ + char buf[128]; + struct nl_cache *cache = obj->ce_cache; + struct rtnl_link *link = (struct rtnl_link *) obj; + + nl_dump_line(p, "%s %s ", link->l_name, + nl_llproto2str(link->l_arptype, buf, sizeof(buf))); + + if (link->l_addr && !nl_addr_iszero(link->l_addr)) + nl_dump(p, "%s ", nl_addr2str(link->l_addr, buf, sizeof(buf))); + + if (link->ce_mask & LINK_ATTR_MASTER) { + struct rtnl_link *master = rtnl_link_get(cache, link->l_master); + nl_dump(p, "master %s ", master ? master->l_name : "inv"); + if (master) + rtnl_link_put(master); + } + + rtnl_link_flags2str(link->l_flags, buf, sizeof(buf)); + if (buf[0]) + nl_dump(p, "<%s> ", buf); + + if (link->ce_mask & LINK_ATTR_LINK) { + struct rtnl_link *ll = rtnl_link_get(cache, link->l_link); + nl_dump(p, "slave-of %s ", ll ? ll->l_name : "NONE"); + if (ll) + rtnl_link_put(ll); + } + + if (link->ce_mask & LINK_ATTR_GROUP) + nl_dump(p, "group %u ", link->l_group); + + if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_LINE]) + link->l_info_ops->io_dump[NL_DUMP_LINE](link, p); + + do_foreach_af(link, af_dump_line, p); + + nl_dump(p, "\n"); +} + +static void link_dump_details(struct nl_object *obj, struct nl_dump_params *p) +{ + struct rtnl_link *link = (struct rtnl_link *) obj; + char buf[64]; + + link_dump_line(obj, p); + + nl_dump_line(p, " mtu %u ", link->l_mtu); + nl_dump(p, "txqlen %u weight %u ", link->l_txqlen, link->l_weight); + + if (link->ce_mask & LINK_ATTR_QDISC) + nl_dump(p, "qdisc %s ", link->l_qdisc); + + if (link->ce_mask & LINK_ATTR_MAP && link->l_map.lm_irq) + nl_dump(p, "irq %u ", link->l_map.lm_irq); + + if (link->ce_mask & LINK_ATTR_IFINDEX) + nl_dump(p, "index %u ", link->l_index); + + if (link->ce_mask & LINK_ATTR_PROMISCUITY && link->l_promiscuity > 0) + nl_dump(p, "promisc-mode (%u users) ", link->l_promiscuity); + + nl_dump(p, "\n"); + + if (link->ce_mask & LINK_ATTR_IFALIAS) + nl_dump_line(p, " alias %s\n", link->l_ifalias); + + nl_dump_line(p, " "); + + if (link->ce_mask & LINK_ATTR_NUM_TX_QUEUES) + nl_dump(p, "txq %u ", link->l_num_tx_queues); + + if (link->ce_mask & LINK_ATTR_NUM_RX_QUEUES) + nl_dump(p, "rxq %u ", link->l_num_rx_queues); + + if (link->ce_mask & LINK_ATTR_BRD) + nl_dump(p, "brd %s ", nl_addr2str(link->l_bcast, buf, + sizeof(buf))); + + if ((link->ce_mask & LINK_ATTR_OPERSTATE) && + link->l_operstate != IF_OPER_UNKNOWN) { + rtnl_link_operstate2str(link->l_operstate, buf, sizeof(buf)); + nl_dump(p, "state %s ", buf); + } + + if (link->ce_mask & LINK_ATTR_NUM_VF) + nl_dump(p, "num-vf %u ", link->l_num_vf); + + nl_dump(p, "mode %s ", + rtnl_link_mode2str(link->l_linkmode, buf, sizeof(buf))); + + nl_dump(p, "carrier %s", + rtnl_link_carrier2str(link->l_carrier, buf, sizeof(buf))); + + nl_dump(p, "\n"); + + if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_DETAILS]) + link->l_info_ops->io_dump[NL_DUMP_DETAILS](link, p); + + do_foreach_af(link, af_dump_details, p); +} + +static void link_dump_stats(struct nl_object *obj, struct nl_dump_params *p) +{ + struct rtnl_link *link = (struct rtnl_link *) obj; + char *unit, fmt[64]; + float res; + + link_dump_details(obj, p); + + nl_dump_line(p, " Stats: bytes packets errors " + " dropped fifo-err compressed\n"); + + res = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_RX_BYTES], &unit); + + strcpy(fmt, " RX %X.2f %s %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 "\n"); + fmt[9] = *unit == 'B' ? '9' : '7'; + + nl_dump_line(p, fmt, res, unit, + link->l_stats[RTNL_LINK_RX_PACKETS], + link->l_stats[RTNL_LINK_RX_ERRORS], + link->l_stats[RTNL_LINK_RX_DROPPED], + link->l_stats[RTNL_LINK_RX_FIFO_ERR], + link->l_stats[RTNL_LINK_RX_COMPRESSED]); + + res = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_TX_BYTES], &unit); + + strcpy(fmt, " TX %X.2f %s %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 "\n"); + fmt[9] = *unit == 'B' ? '9' : '7'; + + nl_dump_line(p, fmt, res, unit, + link->l_stats[RTNL_LINK_TX_PACKETS], + link->l_stats[RTNL_LINK_TX_ERRORS], + link->l_stats[RTNL_LINK_TX_DROPPED], + link->l_stats[RTNL_LINK_TX_FIFO_ERR], + link->l_stats[RTNL_LINK_TX_COMPRESSED]); + + nl_dump_line(p, " Errors: length over crc " + " frame missed multicast\n"); + + nl_dump_line(p, " RX %10" PRIu64 " %10" PRIu64 " %10" + PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" + PRIu64 "\n", + link->l_stats[RTNL_LINK_RX_LEN_ERR], + link->l_stats[RTNL_LINK_RX_OVER_ERR], + link->l_stats[RTNL_LINK_RX_CRC_ERR], + link->l_stats[RTNL_LINK_RX_FRAME_ERR], + link->l_stats[RTNL_LINK_RX_MISSED_ERR], + link->l_stats[RTNL_LINK_MULTICAST]); + + nl_dump_line(p, " aborted carrier heartbeat " + " window collision\n"); + + nl_dump_line(p, " TX %10" PRIu64 " %10" PRIu64 " %10" + PRIu64 " %10" PRIu64 " %10" PRIu64 "\n", + link->l_stats[RTNL_LINK_TX_ABORT_ERR], + link->l_stats[RTNL_LINK_TX_CARRIER_ERR], + link->l_stats[RTNL_LINK_TX_HBEAT_ERR], + link->l_stats[RTNL_LINK_TX_WIN_ERR], + link->l_stats[RTNL_LINK_COLLISIONS]); + + if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_STATS]) + link->l_info_ops->io_dump[NL_DUMP_STATS](link, p); + + do_foreach_af(link, af_dump_stats, p); +} + +#if 0 +static int link_handle_event(struct nl_object *a, struct rtnl_link_event_cb *cb) +{ + struct rtnl_link *l = (struct rtnl_link *) a; + struct nl_cache *c = dp_cache(a); + int nevents = 0; + + if (l->l_change == ~0U) { + if (l->ce_msgtype == RTM_NEWLINK) + cb->le_register(l); + else + cb->le_unregister(l); + + return 1; + } + + if (l->l_change & IFF_SLAVE) { + if (l->l_flags & IFF_SLAVE) { + struct rtnl_link *m = rtnl_link_get(c, l->l_master); + cb->le_new_bonding(l, m); + if (m) + rtnl_link_put(m); + } else + cb->le_cancel_bonding(l); + } + +#if 0 + if (l->l_change & IFF_UP && l->l_change & IFF_RUNNING) + dp_dump_line(p, line++, "link %s changed state to %s.\n", + l->l_name, l->l_flags & IFF_UP ? "up" : "down"); + + if (l->l_change & IFF_PROMISC) { + dp_new_line(p, line++); + dp_dump(p, "link %s %s promiscuous mode.\n", + l->l_name, l->l_flags & IFF_PROMISC ? "entered" : "left"); + } + + if (line == 0) + dp_dump_line(p, line++, "link %s sent unknown event.\n", + l->l_name); +#endif + + return nevents; +} +#endif + + +static void link_keygen(struct nl_object *obj, uint32_t *hashkey, + uint32_t table_sz) +{ + struct rtnl_link *link = (struct rtnl_link *) obj; + unsigned int lkey_sz; + struct link_hash_key { + uint32_t l_index; + uint32_t l_family; + } __attribute__((packed)) lkey; + + lkey_sz = sizeof(lkey); + lkey.l_index = link->l_index; + lkey.l_family = link->l_family; + + *hashkey = nl_hash(&lkey, lkey_sz, 0) % table_sz; + + NL_DBG(5, "link %p key (dev %d fam %d) keysz %d, hash 0x%x\n", + link, lkey.l_index, lkey.l_family, lkey_sz, *hashkey); + + return; +} + +static int link_compare(struct nl_object *_a, struct nl_object *_b, + uint32_t attrs, int flags) +{ + struct rtnl_link *a = (struct rtnl_link *) _a; + struct rtnl_link *b = (struct rtnl_link *) _b; + int diff = 0; + +#define LINK_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, LINK_ATTR_##ATTR, a, b, EXPR) + + diff |= LINK_DIFF(IFINDEX, a->l_index != b->l_index); + diff |= LINK_DIFF(MTU, a->l_mtu != b->l_mtu); + diff |= LINK_DIFF(LINK, a->l_link != b->l_link); + diff |= LINK_DIFF(TXQLEN, a->l_txqlen != b->l_txqlen); + diff |= LINK_DIFF(WEIGHT, a->l_weight != b->l_weight); + diff |= LINK_DIFF(MASTER, a->l_master != b->l_master); + diff |= LINK_DIFF(FAMILY, a->l_family != b->l_family); + diff |= LINK_DIFF(OPERSTATE, a->l_operstate != b->l_operstate); + diff |= LINK_DIFF(LINKMODE, a->l_linkmode != b->l_linkmode); + diff |= LINK_DIFF(QDISC, strcmp(a->l_qdisc, b->l_qdisc)); + diff |= LINK_DIFF(IFNAME, strcmp(a->l_name, b->l_name)); + diff |= LINK_DIFF(ADDR, nl_addr_cmp(a->l_addr, b->l_addr)); + diff |= LINK_DIFF(BRD, nl_addr_cmp(a->l_bcast, b->l_bcast)); + diff |= LINK_DIFF(IFALIAS, strcmp(a->l_ifalias, b->l_ifalias)); + diff |= LINK_DIFF(NUM_VF, a->l_num_vf != b->l_num_vf); + diff |= LINK_DIFF(PROMISCUITY, a->l_promiscuity != b->l_promiscuity); + diff |= LINK_DIFF(NUM_TX_QUEUES,a->l_num_tx_queues != b->l_num_tx_queues); + diff |= LINK_DIFF(NUM_RX_QUEUES,a->l_num_rx_queues != b->l_num_rx_queues); + diff |= LINK_DIFF(GROUP, a->l_group != b->l_group); + + if (flags & LOOSE_COMPARISON) + diff |= LINK_DIFF(FLAGS, + (a->l_flags ^ b->l_flags) & b->l_flag_mask); + else + diff |= LINK_DIFF(FLAGS, a->l_flags != b->l_flags); + + /* + * Compare LINK_ATTR_PROTINFO af_data + */ + if (a->l_family == b->l_family) { + if (rtnl_link_af_data_compare(a, b, a->l_family) != 0) + goto protinfo_mismatch; + } + +out: + return diff; + +protinfo_mismatch: + diff |= LINK_DIFF(PROTINFO, 1); + goto out; + +#undef LINK_DIFF +} + +static const struct trans_tbl link_attrs[] = { + __ADD(LINK_ATTR_MTU, mtu) + __ADD(LINK_ATTR_LINK, link) + __ADD(LINK_ATTR_TXQLEN, txqlen) + __ADD(LINK_ATTR_WEIGHT, weight) + __ADD(LINK_ATTR_MASTER, master) + __ADD(LINK_ATTR_QDISC, qdisc) + __ADD(LINK_ATTR_MAP, map) + __ADD(LINK_ATTR_ADDR, address) + __ADD(LINK_ATTR_BRD, broadcast) + __ADD(LINK_ATTR_FLAGS, flags) + __ADD(LINK_ATTR_IFNAME, name) + __ADD(LINK_ATTR_IFINDEX, ifindex) + __ADD(LINK_ATTR_FAMILY, family) + __ADD(LINK_ATTR_ARPTYPE, arptype) + __ADD(LINK_ATTR_STATS, stats) + __ADD(LINK_ATTR_CHANGE, change) + __ADD(LINK_ATTR_OPERSTATE, operstate) + __ADD(LINK_ATTR_LINKMODE, linkmode) + __ADD(LINK_ATTR_IFALIAS, ifalias) + __ADD(LINK_ATTR_NUM_VF, num_vf) + __ADD(LINK_ATTR_PROMISCUITY, promiscuity) + __ADD(LINK_ATTR_NUM_TX_QUEUES, num_tx_queues) + __ADD(LINK_ATTR_NUM_RX_QUEUES, num_rx_queues) + __ADD(LINK_ATTR_GROUP, group) + __ADD(LINK_ATTR_CARRIER, carrier) +}; + +static char *link_attrs2str(int attrs, char *buf, size_t len) +{ + return __flags2str(attrs, buf, len, link_attrs, + ARRAY_SIZE(link_attrs)); +} + +/** + * @name Get / List + * @{ + */ + + +/** + * Allocate link cache and fill in all configured links. + * @arg sk Netlink socket. + * @arg family Link address family or AF_UNSPEC + * @arg result Pointer to store resulting cache. + * + * Allocates and initializes a new link cache. A netlink message is sent to + * the kernel requesting a full dump of all configured links. The returned + * messages are parsed and filled into the cache. If the operation succeeds + * the resulting cache will a link object for each link configured in the + * kernel. + * + * If \c family is set to an address family other than \c AF_UNSPEC the + * contents of the cache can be limited to a specific address family. + * Currently the following address families are supported: + * - AF_BRIDGE + * - AF_INET6 + * + * @route_doc{link_list, Get List of Links} + * @see rtnl_link_get() + * @see rtnl_link_get_by_name() + * @return 0 on success or a negative error code. + */ +int rtnl_link_alloc_cache(struct nl_sock *sk, int family, struct nl_cache **result) +{ + struct nl_cache * cache; + int err; + + cache = nl_cache_alloc(&rtnl_link_ops); + if (!cache) + return -NLE_NOMEM; + + cache->c_iarg1 = family; + + if (sk && (err = nl_cache_refill(sk, cache)) < 0) { + nl_cache_free(cache); + return err; + } + + *result = cache; + return 0; +} + +/** + * Lookup link in cache by interface index + * @arg cache Link cache + * @arg ifindex Interface index + * + * Searches through the provided cache looking for a link with matching + * interface index. + * + * @attention The reference counter of the returned link object will be + * incremented. Use rtnl_link_put() to release the reference. + * + * @route_doc{link_list, Get List of Links} + * @see rtnl_link_get_by_name() + * @return Link object or NULL if no match was found. + */ +struct rtnl_link *rtnl_link_get(struct nl_cache *cache, int ifindex) +{ + struct rtnl_link *link; + + if (cache->c_ops != &rtnl_link_ops) + return NULL; + + nl_list_for_each_entry(link, &cache->c_items, ce_list) { + if (link->l_index == ifindex) { + nl_object_get((struct nl_object *) link); + return link; + } + } + + return NULL; +} + +/** + * Lookup link in cache by link name + * @arg cache Link cache + * @arg name Name of link + * + * Searches through the provided cache looking for a link with matching + * link name + * + * @attention The reference counter of the returned link object will be + * incremented. Use rtnl_link_put() to release the reference. + * + * @route_doc{link_list, Get List of Links} + * @see rtnl_link_get() + * @return Link object or NULL if no match was found. + */ +struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache, + const char *name) +{ + struct rtnl_link *link; + + if (cache->c_ops != &rtnl_link_ops) + return NULL; + + nl_list_for_each_entry(link, &cache->c_items, ce_list) { + if (!strcmp(name, link->l_name)) { + nl_object_get((struct nl_object *) link); + return link; + } + } + + return NULL; +} + +/** + * Construct RTM_GETLINK netlink message + * @arg ifindex Interface index + * @arg name Name of link + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_link_get_kernel() + * with the exception that it will not send the message but return it in + * the provided return pointer instead. + * + * @see rtnl_link_get_kernel() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_build_get_request(int ifindex, const char *name, + struct nl_msg **result) +{ + struct ifinfomsg ifi; + struct nl_msg *msg; + + if (ifindex <= 0 && !name) { + APPBUG("ifindex or name must be specified"); + return -NLE_MISSING_ATTR; + } + + memset(&ifi, 0, sizeof(ifi)); + + if (!(msg = nlmsg_alloc_simple(RTM_GETLINK, 0))) + return -NLE_NOMEM; + + if (ifindex > 0) + ifi.ifi_index = ifindex; + + if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if (name) + NLA_PUT_STRING(msg, IFLA_IFNAME, name); + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +/** + * Get a link object directly from kernel + * @arg sk Netlink socket + * @arg ifindex Interface index + * @arg name Name of link + * @arg result Pointer to store resulting link object + * + * This function builds a \c RTM_GETLINK netlink message to request + * a specific link directly from the kernel. The returned answer is + * parsed into a struct rtnl_link object and returned via the result + * pointer or -NLE_OBJ_NOTFOUND is returned if no matching link was + * found. + * + * @route_doc{link_direct_lookup, Lookup Single Link (Direct Lookup)} + * @return 0 on success or a negative error code. + */ +int rtnl_link_get_kernel(struct nl_sock *sk, int ifindex, const char *name, + struct rtnl_link **result) +{ + struct nl_msg *msg = NULL; + struct nl_object *obj; + int err; + + if ((err = rtnl_link_build_get_request(ifindex, name, &msg)) < 0) + return err; + + err = nl_send_auto(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + if ((err = nl_pickup(sk, link_msg_parser, &obj)) < 0) + return err; + + /* We have used link_msg_parser(), object is definitely a link */ + *result = (struct rtnl_link *) obj; + + /* If an object has been returned, we also need to wait for the ACK */ + if (err == 0 && obj) + wait_for_ack(sk); + + return 0; +} + +/** + * Translate interface index to corresponding link name + * @arg cache Link cache + * @arg ifindex Interface index + * @arg dst String to store name + * @arg len Length of destination string + * + * Translates the specified interface index to the corresponding + * link name and stores the name in the destination string. + * + * @route_doc{link_translate_ifindex, Translating interface index to link name} + * @see rtnl_link_name2i() + * @return Name of link or NULL if no match was found. + */ +char * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst, + size_t len) +{ + struct rtnl_link *link = rtnl_link_get(cache, ifindex); + + if (link) { + strncpy(dst, link->l_name, len - 1); + rtnl_link_put(link); + return dst; + } + + return NULL; +} + +/** + * Translate link name to corresponding interface index + * @arg cache Link cache + * @arg name Name of link + * + * @route_doc{link_translate_ifindex, Translating interface index to link name} + * @see rtnl_link_i2name() + * @return Interface index or 0 if no match was found. + */ +int rtnl_link_name2i(struct nl_cache *cache, const char *name) +{ + int ifindex = 0; + struct rtnl_link *link; + + link = rtnl_link_get_by_name(cache, name); + if (link) { + ifindex = link->l_index; + rtnl_link_put(link); + } + + return ifindex; +} + +/** @} */ + +static int build_link_msg(int cmd, struct ifinfomsg *hdr, + struct rtnl_link *link, int flags, struct nl_msg **result) +{ + struct nl_msg *msg; + struct nlattr *af_spec; + + msg = nlmsg_alloc_simple(cmd, flags); + if (!msg) + return -NLE_NOMEM; + + if (nlmsg_append(msg, hdr, sizeof(*hdr), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if (link->ce_mask & LINK_ATTR_ADDR) + NLA_PUT_ADDR(msg, IFLA_ADDRESS, link->l_addr); + + if (link->ce_mask & LINK_ATTR_BRD) + NLA_PUT_ADDR(msg, IFLA_BROADCAST, link->l_bcast); + + if (link->ce_mask & LINK_ATTR_MTU) + NLA_PUT_U32(msg, IFLA_MTU, link->l_mtu); + + if (link->ce_mask & LINK_ATTR_TXQLEN) + NLA_PUT_U32(msg, IFLA_TXQLEN, link->l_txqlen); + + if (link->ce_mask & LINK_ATTR_WEIGHT) + NLA_PUT_U32(msg, IFLA_WEIGHT, link->l_weight); + + if (link->ce_mask & LINK_ATTR_IFNAME) + NLA_PUT_STRING(msg, IFLA_IFNAME, link->l_name); + + if (link->ce_mask & LINK_ATTR_OPERSTATE) + NLA_PUT_U8(msg, IFLA_OPERSTATE, link->l_operstate); + + if (link->ce_mask & LINK_ATTR_CARRIER) + NLA_PUT_U8(msg, IFLA_CARRIER, link->l_carrier); + + if (link->ce_mask & LINK_ATTR_LINKMODE) + NLA_PUT_U8(msg, IFLA_LINKMODE, link->l_linkmode); + + if (link->ce_mask & LINK_ATTR_IFALIAS) + NLA_PUT_STRING(msg, IFLA_IFALIAS, link->l_ifalias); + + if (link->ce_mask & LINK_ATTR_LINK) + NLA_PUT_U32(msg, IFLA_LINK, link->l_link); + + if (link->ce_mask & LINK_ATTR_MASTER) + NLA_PUT_U32(msg, IFLA_MASTER, link->l_master); + + if (link->ce_mask & LINK_ATTR_NUM_TX_QUEUES) + NLA_PUT_U32(msg, IFLA_NUM_TX_QUEUES, link->l_num_tx_queues); + + if (link->ce_mask & LINK_ATTR_NUM_RX_QUEUES) + NLA_PUT_U32(msg, IFLA_NUM_RX_QUEUES, link->l_num_rx_queues); + + if (link->ce_mask & LINK_ATTR_GROUP) + NLA_PUT_U32(msg, IFLA_GROUP, link->l_group); + + if (link->ce_mask & LINK_ATTR_LINKINFO) { + struct nlattr *info; + + if (!(info = nla_nest_start(msg, IFLA_LINKINFO))) + goto nla_put_failure; + + NLA_PUT_STRING(msg, IFLA_INFO_KIND, link->l_info_kind); + + if (link->l_info_ops) { + if (link->l_info_ops->io_put_attrs && + link->l_info_ops->io_put_attrs(msg, link) < 0) + goto nla_put_failure; + } + + nla_nest_end(msg, info); + } + + if (!(af_spec = nla_nest_start(msg, IFLA_AF_SPEC))) + goto nla_put_failure; + + if (do_foreach_af(link, af_fill, msg) < 0) + goto nla_put_failure; + + nla_nest_end(msg, af_spec); + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +/** + * @name Add / Modify + * @{ + */ + +/** + * Build a netlink message requesting the addition of new virtual link + * @arg link new link to add + * @arg flags additional netlink message flags + * @arg result pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_link_add() with + * the exception that it will not send the message but return it in the + * provided return pointer instead. + * + * @see rtnl_link_add() + * + * @note This operation is not supported on all kernel versions. + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_build_add_request(struct rtnl_link *link, int flags, + struct nl_msg **result) +{ + struct ifinfomsg ifi = { + .ifi_family = link->l_family, + .ifi_index = link->l_index, + .ifi_flags = link->l_flags, + }; + + return build_link_msg(RTM_NEWLINK, &ifi, link, flags, result); +} + +/** + * Add virtual link + * @arg sk netlink socket. + * @arg link new link to add + * @arg flags additional netlink message flags + * + * Builds a \c RTM_NEWLINK netlink message requesting the addition of + * a new virtual link. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @copydoc auto_ack_warning + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags) +{ + struct nl_msg *msg; + int err; + + err = rtnl_link_build_add_request(link, flags, &msg); + if (err < 0) + return err; + + return nl_send_sync(sk, msg); +} + +/** + * Build a netlink message requesting the modification of link + * @arg orig original link to change + * @arg changes link containing the changes to be made + * @arg flags additional netlink message flags + * @arg result pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_link_change() with + * the exception that it will not send the message but return it in the + * provided return pointer instead. + * + * @see rtnl_link_change() + * + * @note The resulting message will have message type set to RTM_NEWLINK + * which may not work with older kernels. You may have to modify it + * to RTM_SETLINK (does not allow changing link info attributes) to + * have the change request work with older kernels. + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_build_change_request(struct rtnl_link *orig, + struct rtnl_link *changes, int flags, + struct nl_msg **result) +{ + struct ifinfomsg ifi = { + .ifi_family = orig->l_family, + .ifi_index = orig->l_index, + }; + int err; + + if (changes->ce_mask & LINK_ATTR_FLAGS) { + ifi.ifi_flags = orig->l_flags & ~changes->l_flag_mask; + ifi.ifi_flags |= changes->l_flags; + } + + if (changes->l_family && changes->l_family != orig->l_family) { + APPBUG("link change: family is immutable"); + return -NLE_IMMUTABLE; + } + + /* Avoid unnecessary name change requests */ + if (orig->ce_mask & LINK_ATTR_IFINDEX && + orig->ce_mask & LINK_ATTR_IFNAME && + changes->ce_mask & LINK_ATTR_IFNAME && + !strcmp(orig->l_name, changes->l_name)) + changes->ce_mask &= ~LINK_ATTR_IFNAME; + + if ((err = build_link_msg(RTM_NEWLINK, &ifi, changes, flags, result)) < 0) + goto errout; + + return 0; + +errout: + return err; +} + +/** + * Change link + * @arg sk netlink socket. + * @arg orig original link to be changed + * @arg changes link containing the changes to be made + * @arg flags additional netlink message flags + * + * Builds a \c RTM_NEWLINK netlink message requesting the change of + * a network link. If -EOPNOTSUPP is returned by the kernel, the + * message type will be changed to \c RTM_SETLINK and the message is + * resent to work around older kernel versions. + * + * The link to be changed is looked up based on the interface index + * supplied in the \p orig link. Optionaly the link name is used but + * only if no interface index is provided, otherwise providing an + * link name will result in the link name being changed. + * + * If no matching link exists, the function will return + * -NLE_OBJ_NOTFOUND. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @copydoc auto_ack_warning + * + * @note The link name can only be changed if the link has been put + * in opertional down state. (~IF_UP) + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_change(struct nl_sock *sk, struct rtnl_link *orig, + struct rtnl_link *changes, int flags) +{ + struct nl_msg *msg; + int err; + + err = rtnl_link_build_change_request(orig, changes, flags, &msg); + if (err < 0) + return err; + +retry: + err = nl_send_auto_complete(sk, msg); + if (err < 0) + goto errout; + + err = wait_for_ack(sk); + if (err == -NLE_OPNOTSUPP && msg->nm_nlh->nlmsg_type == RTM_NEWLINK) { + msg->nm_nlh->nlmsg_type = RTM_SETLINK; + goto retry; + } + +errout: + nlmsg_free(msg); + return err; +} + +/** @} */ + +/** + * @name Delete + * @{ + */ + +/** + * Build a netlink message requesting the deletion of a link + * @arg link Link to delete + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_link_delete() with + * the exception that it will not send the message but return it in the + * provided return pointer instead. + * + * @see rtnl_link_delete() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_build_delete_request(const struct rtnl_link *link, + struct nl_msg **result) +{ + struct nl_msg *msg; + struct ifinfomsg ifi = { + .ifi_index = link->l_index, + }; + + if (!(link->ce_mask & (LINK_ATTR_IFINDEX | LINK_ATTR_IFNAME))) { + APPBUG("ifindex or name must be specified"); + return -NLE_MISSING_ATTR; + } + + if (!(msg = nlmsg_alloc_simple(RTM_DELLINK, 0))) + return -NLE_NOMEM; + + if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if (link->ce_mask & LINK_ATTR_IFNAME) + NLA_PUT_STRING(msg, IFLA_IFNAME, link->l_name); + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +/** + * Delete link + * @arg sk Netlink socket + * @arg link Link to delete + * + * Builds a \c RTM_DELLINK netlink message requesting the deletion of + * a network link which has been previously added to the kernel and + * sends the message to the kernel. + * + * If no matching link exists, the function will return + * -NLE_OBJ_NOTFOUND. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @copydoc auto_ack_warning + * + * @note Only virtual links such as dummy interface or vlan interfaces + * can be deleted. It is not possible to delete physical interfaces + * such as ethernet interfaces or the loopback device. + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_delete(struct nl_sock *sk, const struct rtnl_link *link) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_link_build_delete_request(link, &msg)) < 0) + return err; + + return nl_send_sync(sk, msg); +} + +/** @} */ + +/** + * @name Link Object + * @{ + */ + +/** + * Allocate link object + * + * @see rtnl_link_put() + * @return New link object or NULL if allocation failed + */ +struct rtnl_link *rtnl_link_alloc(void) +{ + return (struct rtnl_link *) nl_object_alloc(&link_obj_ops); +} + +/** + * Return a link object reference + * @arg link Link object + */ +void rtnl_link_put(struct rtnl_link *link) +{ + nl_object_put((struct nl_object *) link); +} + +/** + * Set name of link object + * @arg link Link object + * @arg name New name + * + * @note To change the name of a link in the kernel, set the interface + * index to the link you wish to change, modify the link name using + * this function and pass the link object to rtnl_link_change() or + * rtnl_link_add(). + * + * @route_doc{link_attr_name, Link Name} + * @see rtnl_link_get_name() + * @see rtnl_link_set_ifindex() + */ +void rtnl_link_set_name(struct rtnl_link *link, const char *name) +{ + strncpy(link->l_name, name, sizeof(link->l_name) - 1); + link->ce_mask |= LINK_ATTR_IFNAME; +} + +/** + * Return name of link object + * @arg link Link object + * + * @route_doc{link_attr_name, Link Name} + * @see rtnl_link_set_name() + * @return Link name or NULL if name is not specified + */ +char *rtnl_link_get_name(struct rtnl_link *link) +{ + return link->ce_mask & LINK_ATTR_IFNAME ? link->l_name : NULL; +} + +/** + * Set the group identifier of a link object + * @arg link Link object + * @arg group Group identifier + */ +void rtnl_link_set_group(struct rtnl_link *link, uint32_t group) +{ + link->l_group = group; + link->ce_mask |= LINK_ATTR_GROUP; +} + +/** + * Return the group identifier of link object + * @arg link Link object + * + * @return Group identifier or 0 if not set. + */ +uint32_t rtnl_link_get_group(struct rtnl_link *link) +{ + return link->l_group; +} + +static inline void __assign_addr(struct rtnl_link *link, struct nl_addr **pos, + struct nl_addr *new, int flag) +{ + if (*pos) + nl_addr_put(*pos); + + nl_addr_get(new); + *pos = new; + + link->ce_mask |= flag; +} + +/** + * Set link layer address of link object + * @arg link Link object + * @arg addr New link layer address + * + * The function increments the reference counter of the address object + * and overwrites any existing link layer address previously assigned. + * + * @route_doc{link_attr_address, Link layer address} + * @see rtnl_link_get_addr() + */ +void rtnl_link_set_addr(struct rtnl_link *link, struct nl_addr *addr) +{ + __assign_addr(link, &link->l_addr, addr, LINK_ATTR_ADDR); +} + +/** + * Return link layer address of link object + * @arg link Link object + * + * @copydoc pointer_lifetime_warning + * @route_doc{link_attr_address, Link Layer Address} + * @see rtnl_link_set_addr() + * @return Link layer address or NULL if not set. + */ +struct nl_addr *rtnl_link_get_addr(struct rtnl_link *link) +{ + return link->ce_mask & LINK_ATTR_ADDR ? link->l_addr : NULL; +} + +/** + * Set link layer broadcast address of link object + * @arg link Link object + * @arg addr New broadcast address + * + * The function increments the reference counter of the address object + * and overwrites any existing link layer broadcast address previously + * assigned. + * + * @route_doc{link_attr_broadcast, Link Layer Broadcast Address} + * @see rtnl_link_get_broadcast() + */ +void rtnl_link_set_broadcast(struct rtnl_link *link, struct nl_addr *addr) +{ + __assign_addr(link, &link->l_bcast, addr, LINK_ATTR_BRD); +} + +/** + * Return link layer broadcast address of link object + * @arg link Link object + * + * @copydoc pointer_lifetime_warning + * @route_doc{link_attr_address, Link Layer Address} + * @see rtnl_link_set_broadcast() + * @return Link layer address or NULL if not set. + */ +struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *link) +{ + return link->ce_mask & LINK_ATTR_BRD ? link->l_bcast : NULL; +} + +/** + * Set flags of link object + * @arg link Link object + * @arg flags Flags + * + * @see rtnl_link_get_flags() + * @see rtnl_link_unset_flags() + */ +void rtnl_link_set_flags(struct rtnl_link *link, unsigned int flags) +{ + link->l_flag_mask |= flags; + link->l_flags |= flags; + link->ce_mask |= LINK_ATTR_FLAGS; +} + +/** + * Unset flags of link object + * @arg link Link object + * @arg flags Flags + * + * @see rtnl_link_set_flags() + * @see rtnl_link_get_flags() + */ +void rtnl_link_unset_flags(struct rtnl_link *link, unsigned int flags) +{ + link->l_flag_mask |= flags; + link->l_flags &= ~flags; + link->ce_mask |= LINK_ATTR_FLAGS; +} + +/** + * Return flags of link object + * @arg link Link object + * + * @route_doc{link_attr_flags, Link Flags} + * @see rtnl_link_set_flags() + * @see rtnl_link_unset_flags() + * @return Link flags or 0 if none have been set. + */ +unsigned int rtnl_link_get_flags(struct rtnl_link *link) +{ + return link->l_flags; +} + +/** + * Set address family of link object + * + * @see rtnl_link_get_family() + */ +void rtnl_link_set_family(struct rtnl_link *link, int family) +{ + link->l_family = family; + link->ce_mask |= LINK_ATTR_FAMILY; + + if (link->l_af_ops) + af_free(link, link->l_af_ops, + link->l_af_data[link->l_af_ops->ao_family], NULL); + + link->l_af_ops = af_lookup_and_alloc(link, family); +} + +/** + * Return address family of link object + * @arg link Link object + * + * @see rtnl_link_set_family() + * @return Address family or \c AF_UNSPEC if not specified. + */ +int rtnl_link_get_family(struct rtnl_link *link) +{ + return link->ce_mask & LINK_ATTR_FAMILY ? link->l_family : AF_UNSPEC; +} + +/** + * Set hardware type of link object + * @arg link Link object + * @arg arptype New hardware type \c (ARPHRD_*) + * + * @route_doc{link_attr_arptype, Hardware Type} + * @copydoc read_only_attribute + * @see rtnl_link_get_arptype() + */ +void rtnl_link_set_arptype(struct rtnl_link *link, unsigned int arptype) +{ + link->l_arptype = arptype; + link->ce_mask |= LINK_ATTR_ARPTYPE; +} + +/** + * Get hardware type of link object + * @arg link Link object + * + * @route_doc{link_attr_arptype, Hardware Type} + * @see rtnl_link_set_arptype() + * @return Hardware type \c (ARPHRD_ETHER *) or \c ARPHRD_VOID + */ +unsigned int rtnl_link_get_arptype(struct rtnl_link *link) +{ + if (link->ce_mask & LINK_ATTR_ARPTYPE) + return link->l_arptype; + else + return ARPHRD_VOID; +} + +/** + * Set interface index of link object + * @arg link Link object + * @arg ifindex Interface index + * + * @route_doc{link_attr_ifindex, Interface Index} + * @see rtnl_link_get_ifindex() + */ +void rtnl_link_set_ifindex(struct rtnl_link *link, int ifindex) +{ + link->l_index = ifindex; + link->ce_mask |= LINK_ATTR_IFINDEX; +} + + +/** + * Return interface index of link object + * @arg link Link object + * + * @route_doc{link_attr_ifindex, Interface Index} + * @see rtnl_link_set_ifindex() + * @return Interface index or 0 if not set. + */ +int rtnl_link_get_ifindex(struct rtnl_link *link) +{ + return link->l_index; +} + +/** + * Set Maximum Transmission Unit of link object + * @arg link Link object + * @arg mtu New MTU value in number of bytes + * + * @route_doc{link_attr_mtu, Maximum Transmission Unit} + * @see rtnl_link_get_mtu() + */ +void rtnl_link_set_mtu(struct rtnl_link *link, unsigned int mtu) +{ + link->l_mtu = mtu; + link->ce_mask |= LINK_ATTR_MTU; +} + +/** + * Return maximum transmission unit of link object + * @arg link Link object + * + * @route_doc{link_attr_mtu, Maximum Transmission Unit} + * @see rtnl_link_set_mtu() + * @return MTU in bytes or 0 if not set + */ +unsigned int rtnl_link_get_mtu(struct rtnl_link *link) +{ + return link->l_mtu; +} + +/** + * Set transmission queue length + * @arg link Link object + * @arg txqlen New queue length + * + * The unit is dependant on the link type. The most common units is number + * of packets. + * + * @route_doc{link_attr_txqlen, Transmission Queue Length} + */ +void rtnl_link_set_txqlen(struct rtnl_link *link, unsigned int txqlen) +{ + link->l_txqlen = txqlen; + link->ce_mask |= LINK_ATTR_TXQLEN; +} + +/** + * Return transmission queue length + * @arg link Link object + * + * The unit is dependant on the link type. The most common units is number + * of packets. + * + * @route_doc{link_attr_txqlen, Transmission Queue Length} + * @return queue length or 0 if not specified. + */ +unsigned int rtnl_link_get_txqlen(struct rtnl_link *link) +{ + return link->ce_mask & LINK_ATTR_TXQLEN ? link->l_txqlen : 0; +} + +void rtnl_link_set_link(struct rtnl_link *link, int ifindex) +{ + link->l_link = ifindex; + link->ce_mask |= LINK_ATTR_LINK; +} + +int rtnl_link_get_link(struct rtnl_link *link) +{ + return link->l_link; +} + +/** + * Set master link of link object + * @arg link Link object + * @arg ifindex Interface index of master link + * + * @see rtnl_link_get_master() + */ +void rtnl_link_set_master(struct rtnl_link *link, int ifindex) +{ + link->l_master = ifindex; + link->ce_mask |= LINK_ATTR_MASTER; +} + +/** + * Return master link of link object + * @arg link Link object + * + * @see rtnl_link_set_master() + * @return Interface index of master link or 0 if not specified + */ +int rtnl_link_get_master(struct rtnl_link *link) +{ + return link->l_master; +} + +/** + * Set carrier of link object + * @arg link Link object + * @arg status New carrier status + * + * @see rtnl_link_get_carrier() + */ +void rtnl_link_set_carrier(struct rtnl_link *link, uint8_t status) +{ + link->l_carrier = status; + link->ce_mask |= LINK_ATTR_CARRIER; +} + +/** + * Return carrier status of link object + * @arg link Link object + * + * @see rtnl_link_set_master() + * @return Carrier state. + */ +uint8_t rtnl_link_get_carrier(struct rtnl_link *link) +{ + return link->l_carrier; +} + +/** + * Set operational status of link object + * @arg link Link object + * @arg status New opertional status + * + * @route_doc{link_attr_operstate, Operational Status}} + * @see rtnl_link_get_operstate() + */ +void rtnl_link_set_operstate(struct rtnl_link *link, uint8_t status) +{ + link->l_operstate = status; + link->ce_mask |= LINK_ATTR_OPERSTATE; +} + +/** + * Return operational status of link object + * @arg link Link object + * + * @route_doc{link_attr_operstate, Operational Status} + * @see rtnl_link_set_operstate() + * @return Opertional state or \c IF_OPER_UNKNOWN + */ +uint8_t rtnl_link_get_operstate(struct rtnl_link *link) +{ + return link->l_operstate; +} + +/** + * Set link mode of link object + * @arg link Link object + * @arg mode New link mode + * + * @route_doc{link_attr_mode, Mode} + * @see rtnl_link_get_linkmode() + */ +void rtnl_link_set_linkmode(struct rtnl_link *link, uint8_t mode) +{ + link->l_linkmode = mode; + link->ce_mask |= LINK_ATTR_LINKMODE; +} + +/** + * Return link mode of link object + * @arg link Link object + * + * @route_doc{link_attr_mode, Mode} + * @see rtnl_link_get_linkmode() + * @return Link mode or \c IF_LINK_MODE_DEFAULT + */ +uint8_t rtnl_link_get_linkmode(struct rtnl_link *link) +{ + return link->l_linkmode; +} + +/** + * Return alias name of link object (SNMP IfAlias) + * @arg link Link object + * + * @route_doc{link_attr_alias, Alias} + * @see rtnl_link_set_ifalias() + * @return Alias name or NULL if not set. + */ +const char *rtnl_link_get_ifalias(struct rtnl_link *link) +{ + return link->l_ifalias; +} + +/** + * Set alias name of link object (SNMP IfAlias) + * @arg link Link object + * @arg alias Alias name or NULL to unset + * + * Sets the alias name of the link to the specified name. The alias + * name can be unset by specyfing NULL as the alias. The name will + * be strdup()ed, so no need to provide a persistent character string. + * + * @route_doc{link_attr_alias, Alias} + * @see rtnl_link_get_ifalias() + */ +void rtnl_link_set_ifalias(struct rtnl_link *link, const char *alias) +{ + free(link->l_ifalias); + link->ce_mask &= ~LINK_ATTR_IFALIAS; + + if (alias) { + link->l_ifalias = strdup(alias); + link->ce_mask |= LINK_ATTR_IFALIAS; + } +} + +/** + * Set queueing discipline name of link object + * @arg link Link object + * @arg name Name of queueing discipline + * + * @copydoc read_only_attribute + * + * For more information on how to modify the qdisc of a link, see section + * @ref_route{route_tc, Traffic Control}. + * + * @route_doc{link_attr_qdisc, Queueing Discipline Name} + * @see rtnl_link_get_qdisc() + */ +void rtnl_link_set_qdisc(struct rtnl_link *link, const char *name) +{ + strncpy(link->l_qdisc, name, sizeof(link->l_qdisc) - 1); + link->ce_mask |= LINK_ATTR_QDISC; +} + +/** + * Return name of queueing discipline of link object + * @arg link Link object + * + * @route_doc{link_attr_qdisc, Queueing Discipline Name} + * @see rtnl_link_set_qdisc() + * @return Name of qdisc or NULL if not specified. + */ +char *rtnl_link_get_qdisc(struct rtnl_link *link) +{ + return link->ce_mask & LINK_ATTR_QDISC ? link->l_qdisc : NULL; +} + + +/** + * Return number of PCI virtual functions of link object + * @arg link Link object + * @arg num_vf Pointer to store number of VFs + * + * @return 0 on success or -NLE_OPNOTSUPP if not available + */ +int rtnl_link_get_num_vf(struct rtnl_link *link, uint32_t *num_vf) +{ + if (link->ce_mask & LINK_ATTR_NUM_VF) { + *num_vf = link->l_num_vf; + return 0; + } else + return -NLE_OPNOTSUPP; +} + +/** + * Return value of link statistics counter + * @arg link Link object + * @arg id Identifier of statistical counter + * + * @return Value of counter or 0 if not specified. + */ +uint64_t rtnl_link_get_stat(struct rtnl_link *link, rtnl_link_stat_id_t id) +{ + if (id > RTNL_LINK_STATS_MAX) + return 0; + + return link->l_stats[id]; +} + +/** + * Set value of link statistics counter + * @arg link Link object + * @arg id Identifier of statistical counter + * @arg value New value + * + * \note Changing the value of a statistical counter will not change the + * value in the kernel. + * + * @return 0 on success or a negative error code + */ +int rtnl_link_set_stat(struct rtnl_link *link, rtnl_link_stat_id_t id, + const uint64_t value) +{ + if (id > RTNL_LINK_STATS_MAX) + return -NLE_INVAL; + + link->l_stats[id] = value; + + return 0; +} + +/** + * Set type of link object + * @arg link Link object + * @arg type Name of link type + * + * Looks up the link type module and prepares the link to store type + * specific attributes. If a type has been assigned already it will + * be released with all link type specific attributes lost. + * + * @route_doc{link_modules, Link Modules} + * @return 0 on success or a negative errror code. + */ +int rtnl_link_set_type(struct rtnl_link *link, const char *type) +{ + struct rtnl_link_info_ops *io; + int err; + char *kind; + + free(link->l_info_kind); + link->ce_mask &= ~LINK_ATTR_LINKINFO; + if (link->l_info_ops) + release_link_info(link); + + if (!type) + return 0; + + kind = strdup(type); + if (!kind) + return -NLE_NOMEM; + + io = rtnl_link_info_ops_lookup(type); + if (io) { + if (io->io_alloc && (err = io->io_alloc(link)) < 0) + goto errout; + + link->l_info_ops = io; + } + + link->l_info_kind = kind; + link->ce_mask |= LINK_ATTR_LINKINFO; + + return 0; + +errout: + free(kind); + return err; +} + +/** + * Return type of link + * @arg link Link object + * + * @route_doc{link_modules, Link Modules} + * @return Name of link type or NULL if not specified. + */ +char *rtnl_link_get_type(struct rtnl_link *link) +{ + return link->l_info_kind; +} + +/** + * Set link promiscuity count + * @arg link Link object + * @arg count New promiscuity count + * + * @copydoc read_only_attribute + * + * @see rtnl_link_get_promiscuity() + */ +void rtnl_link_set_promiscuity(struct rtnl_link *link, uint32_t count) +{ + link->l_promiscuity = count; + link->ce_mask |= LINK_ATTR_PROMISCUITY; +} + +/** + * Return link promiscuity count + * @arg link Link object + * + * @see rtnl_link_set_promiscuity() + * @return Link promiscuity count or 0 + */ +uint32_t rtnl_link_get_promiscuity(struct rtnl_link *link) +{ + return link->l_promiscuity; +} + +/** + * Set number of TX queues + * @arg link Link object + * @arg nqueues Number of queues + * + * Sets the number of TX queues of the link object. The value is considered + * by the kernel when creating network devices that can be created via + * netlink. The value will be passed on to alloc_netdev_mqs() + * + * Therefore use of rtnl_link_set_num_tx_queues() only makes sense in + * combination with rtnl_link_add() or if the link object is used as a filter. + * + * @see rtnl_link_get_num_tx_queues() + */ +void rtnl_link_set_num_tx_queues(struct rtnl_link *link, uint32_t nqueues) +{ + link->l_num_tx_queues = nqueues; + link->ce_mask |= LINK_ATTR_NUM_TX_QUEUES; +} + +/** + * Return number of TX queues + * @arg link Link object + * + * @return Number of TX queues or 0 + */ +uint32_t rtnl_link_get_num_tx_queues(struct rtnl_link *link) +{ + return link->l_num_tx_queues; +} + +/** + * Set number of RX queues + * @arg link Link object + * @arg nqueues Number of queues + * + * Sets the number of RX queues of the link object. The value is considered + * by the kernel when creating network devices that can be created via + * netlink. The value will be passed on to alloc_netdev_mqs() + * + * Therefore use of rtnl_link_set_num_rx_queues() only makes sense in + * combination with rtnl_link_add() or if the link object is used as a filter. + * + * @see rtnl_link_get_num_rx_queues() + */ +void rtnl_link_set_num_rx_queues(struct rtnl_link *link, uint32_t nqueues) +{ + link->l_num_rx_queues = nqueues; + link->ce_mask |= LINK_ATTR_NUM_RX_QUEUES; +} + +/** + * Return number of RX queues + * @arg link Link object + * + * @return Number of RX queues or 0 + */ +uint32_t rtnl_link_get_num_rx_queues(struct rtnl_link *link) +{ + return link->l_num_rx_queues; +} + +/** @} */ + +/** + * @name Master/Slave + * @{ + */ + +/** + * Enslave slave link to master link + * @arg sock netlink socket + * @arg master ifindex of master link + * @arg slave ifindex of slave link + * + * This function is identical to rtnl_link_enslave() except that + * it takes interface indices instead of rtnl_link objects. + * + * @see rtnl_link_enslave() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_enslave_ifindex(struct nl_sock *sock, int master, int slave) +{ + struct rtnl_link *link; + int err; + + if (!(link = rtnl_link_alloc())) + return -NLE_NOMEM; + + rtnl_link_set_ifindex(link, slave); + rtnl_link_set_master(link, master); + + if ((err = rtnl_link_change(sock, link, link, 0)) < 0) + goto errout; + + rtnl_link_put(link); + + /* + * Due to the kernel not signaling whether this opertion is + * supported or not, we will retrieve the attribute to see if the + * request was successful. If the master assigned remains unchanged + * we will return NLE_OPNOTSUPP to allow performing backwards + * compatibility of some sort. + */ + if ((err = rtnl_link_get_kernel(sock, slave, NULL, &link)) < 0) + return err; + + if (rtnl_link_get_master(link) != master) + err = -NLE_OPNOTSUPP; + +errout: + rtnl_link_put(link); + + return err; +} + +/** + * Enslave slave link to master link + * @arg sock netlink socket + * @arg master master link + * @arg slave slave link + * + * Constructs a RTM_NEWLINK or RTM_SETLINK message adding the slave to + * the master and sends the request via the specified netlink socket. + * + * @note The feature of enslaving/releasing via netlink has only been added + * recently to the kernel (Feb 2011). Also, the kernel does not signal + * if the operation is not supported. Therefore this function will + * verify if the master assignment has changed and will return + * -NLE_OPNOTSUPP if it did not. + * + * @see rtnl_link_enslave_ifindex() + * @see rtnl_link_release() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_enslave(struct nl_sock *sock, struct rtnl_link *master, + struct rtnl_link *slave) +{ + return rtnl_link_enslave_ifindex(sock, rtnl_link_get_ifindex(master), + rtnl_link_get_ifindex(slave)); +} + +/** + * Release slave link from its master + * @arg sock netlink socket + * @arg slave slave link + * + * This function is identical to rtnl_link_release() except that + * it takes an interface index instead of a rtnl_link object. + * + * @see rtnl_link_release() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_release_ifindex(struct nl_sock *sock, int slave) +{ + return rtnl_link_enslave_ifindex(sock, 0, slave); +} + +/** + * Release slave link from its master + * @arg sock netlink socket + * @arg slave slave link + * + * Constructs a RTM_NEWLINK or RTM_SETLINK message releasing the slave from + * its master and sends the request via the specified netlink socket. + * + * @note The feature of enslaving/releasing via netlink has only been added + * recently to the kernel (Feb 2011). Also, the kernel does not signal + * if the operation is not supported. Therefore this function will + * verify if the master assignment has changed and will return + * -NLE_OPNOTSUPP if it did not. + * + * @see rtnl_link_release_ifindex() + * @see rtnl_link_enslave() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_release(struct nl_sock *sock, struct rtnl_link *slave) +{ + return rtnl_link_release_ifindex(sock, rtnl_link_get_ifindex(slave)); +} + +/** @} */ + +/** + * @name Utilities + * @{ + */ + +static const struct trans_tbl link_flags[] = { + __ADD(IFF_LOOPBACK, loopback) + __ADD(IFF_BROADCAST, broadcast) + __ADD(IFF_POINTOPOINT, pointopoint) + __ADD(IFF_MULTICAST, multicast) + __ADD(IFF_NOARP, noarp) + __ADD(IFF_ALLMULTI, allmulti) + __ADD(IFF_PROMISC, promisc) + __ADD(IFF_MASTER, master) + __ADD(IFF_SLAVE, slave) + __ADD(IFF_DEBUG, debug) + __ADD(IFF_DYNAMIC, dynamic) + __ADD(IFF_AUTOMEDIA, automedia) + __ADD(IFF_PORTSEL, portsel) + __ADD(IFF_NOTRAILERS, notrailers) + __ADD(IFF_UP, up) + __ADD(IFF_RUNNING, running) + __ADD(IFF_LOWER_UP, lowerup) + __ADD(IFF_DORMANT, dormant) + __ADD(IFF_ECHO, echo) +}; + +char *rtnl_link_flags2str(int flags, char *buf, size_t len) +{ + return __flags2str(flags, buf, len, link_flags, + ARRAY_SIZE(link_flags)); +} + +int rtnl_link_str2flags(const char *name) +{ + return __str2flags(name, link_flags, ARRAY_SIZE(link_flags)); +} + +static const struct trans_tbl link_stats[] = { + __ADD(RTNL_LINK_RX_PACKETS, rx_packets) + __ADD(RTNL_LINK_TX_PACKETS, tx_packets) + __ADD(RTNL_LINK_RX_BYTES, rx_bytes) + __ADD(RTNL_LINK_TX_BYTES, tx_bytes) + __ADD(RTNL_LINK_RX_ERRORS, rx_errors) + __ADD(RTNL_LINK_TX_ERRORS, tx_errors) + __ADD(RTNL_LINK_RX_DROPPED, rx_dropped) + __ADD(RTNL_LINK_TX_DROPPED, tx_dropped) + __ADD(RTNL_LINK_RX_COMPRESSED, rx_compressed) + __ADD(RTNL_LINK_TX_COMPRESSED, tx_compressed) + __ADD(RTNL_LINK_RX_FIFO_ERR, rx_fifo_err) + __ADD(RTNL_LINK_TX_FIFO_ERR, tx_fifo_err) + __ADD(RTNL_LINK_RX_LEN_ERR, rx_len_err) + __ADD(RTNL_LINK_RX_OVER_ERR, rx_over_err) + __ADD(RTNL_LINK_RX_CRC_ERR, rx_crc_err) + __ADD(RTNL_LINK_RX_FRAME_ERR, rx_frame_err) + __ADD(RTNL_LINK_RX_MISSED_ERR, rx_missed_err) + __ADD(RTNL_LINK_TX_ABORT_ERR, tx_abort_err) + __ADD(RTNL_LINK_TX_CARRIER_ERR, tx_carrier_err) + __ADD(RTNL_LINK_TX_HBEAT_ERR, tx_hbeat_err) + __ADD(RTNL_LINK_TX_WIN_ERR, tx_win_err) + __ADD(RTNL_LINK_COLLISIONS, collisions) + __ADD(RTNL_LINK_MULTICAST, multicast) + __ADD(RTNL_LINK_IP6_INPKTS, Ip6InReceives) + __ADD(RTNL_LINK_IP6_INHDRERRORS, Ip6InHdrErrors) + __ADD(RTNL_LINK_IP6_INTOOBIGERRORS, Ip6InTooBigErrors) + __ADD(RTNL_LINK_IP6_INNOROUTES, Ip6InNoRoutes) + __ADD(RTNL_LINK_IP6_INADDRERRORS, Ip6InAddrErrors) + __ADD(RTNL_LINK_IP6_INUNKNOWNPROTOS, Ip6InUnknownProtos) + __ADD(RTNL_LINK_IP6_INTRUNCATEDPKTS, Ip6InTruncatedPkts) + __ADD(RTNL_LINK_IP6_INDISCARDS, Ip6InDiscards) + __ADD(RTNL_LINK_IP6_INDELIVERS, Ip6InDelivers) + __ADD(RTNL_LINK_IP6_OUTFORWDATAGRAMS, Ip6OutForwDatagrams) + __ADD(RTNL_LINK_IP6_OUTPKTS, Ip6OutRequests) + __ADD(RTNL_LINK_IP6_OUTDISCARDS, Ip6OutDiscards) + __ADD(RTNL_LINK_IP6_OUTNOROUTES, Ip6OutNoRoutes) + __ADD(RTNL_LINK_IP6_REASMTIMEOUT, Ip6ReasmTimeout) + __ADD(RTNL_LINK_IP6_REASMREQDS, Ip6ReasmReqds) + __ADD(RTNL_LINK_IP6_REASMOKS, Ip6ReasmOKs) + __ADD(RTNL_LINK_IP6_REASMFAILS, Ip6ReasmFails) + __ADD(RTNL_LINK_IP6_FRAGOKS, Ip6FragOKs) + __ADD(RTNL_LINK_IP6_FRAGFAILS, Ip6FragFails) + __ADD(RTNL_LINK_IP6_FRAGCREATES, Ip6FragCreates) + __ADD(RTNL_LINK_IP6_INMCASTPKTS, Ip6InMcastPkts) + __ADD(RTNL_LINK_IP6_OUTMCASTPKTS, Ip6OutMcastPkts) + __ADD(RTNL_LINK_IP6_INBCASTPKTS, Ip6InBcastPkts) + __ADD(RTNL_LINK_IP6_OUTBCASTPKTS, Ip6OutBcastPkts) + __ADD(RTNL_LINK_IP6_INOCTETS, Ip6InOctets) + __ADD(RTNL_LINK_IP6_OUTOCTETS, Ip6OutOctets) + __ADD(RTNL_LINK_IP6_INMCASTOCTETS, Ip6InMcastOctets) + __ADD(RTNL_LINK_IP6_OUTMCASTOCTETS, Ip6OutMcastOctets) + __ADD(RTNL_LINK_IP6_INBCASTOCTETS, Ip6InBcastOctets) + __ADD(RTNL_LINK_IP6_OUTBCASTOCTETS, Ip6OutBcastOctets) + __ADD(RTNL_LINK_ICMP6_INMSGS, ICMP6_InMsgs) + __ADD(RTNL_LINK_ICMP6_INERRORS, ICMP6_InErrors) + __ADD(RTNL_LINK_ICMP6_OUTMSGS, ICMP6_OutMsgs) + __ADD(RTNL_LINK_ICMP6_OUTERRORS, ICMP6_OutErrors) +}; + +char *rtnl_link_stat2str(int st, char *buf, size_t len) +{ + return __type2str(st, buf, len, link_stats, ARRAY_SIZE(link_stats)); +} + +int rtnl_link_str2stat(const char *name) +{ + return __str2type(name, link_stats, ARRAY_SIZE(link_stats)); +} + +static const struct trans_tbl link_operstates[] = { + __ADD(IF_OPER_UNKNOWN, unknown) + __ADD(IF_OPER_NOTPRESENT, notpresent) + __ADD(IF_OPER_DOWN, down) + __ADD(IF_OPER_LOWERLAYERDOWN, lowerlayerdown) + __ADD(IF_OPER_TESTING, testing) + __ADD(IF_OPER_DORMANT, dormant) + __ADD(IF_OPER_UP, up) +}; + +char *rtnl_link_operstate2str(uint8_t st, char *buf, size_t len) +{ + return __type2str(st, buf, len, link_operstates, + ARRAY_SIZE(link_operstates)); +} + +int rtnl_link_str2operstate(const char *name) +{ + return __str2type(name, link_operstates, + ARRAY_SIZE(link_operstates)); +} + +static const struct trans_tbl link_modes[] = { + __ADD(IF_LINK_MODE_DEFAULT, default) + __ADD(IF_LINK_MODE_DORMANT, dormant) +}; + +static const struct trans_tbl carrier_states[] = { + __ADD(IF_CARRIER_DOWN, down) + __ADD(IF_CARRIER_UP, up) +}; + +char *rtnl_link_mode2str(uint8_t st, char *buf, size_t len) +{ + return __type2str(st, buf, len, link_modes, ARRAY_SIZE(link_modes)); +} + +int rtnl_link_str2mode(const char *name) +{ + return __str2type(name, link_modes, ARRAY_SIZE(link_modes)); +} + +char *rtnl_link_carrier2str(uint8_t st, char *buf, size_t len) +{ + return __type2str(st, buf, len, carrier_states, + ARRAY_SIZE(carrier_states)); +} + +int rtnl_link_str2carrier(const char *name) +{ + return __str2type(name, carrier_states, ARRAY_SIZE(carrier_states)); +} + +/** @} */ + +/** + * @name Deprecated Functions + */ + +/** + * @deprecated Use of this function is deprecated, use rtnl_link_set_type() + */ +int rtnl_link_set_info_type(struct rtnl_link *link, const char *type) +{ + return rtnl_link_set_type(link, type); +} + +/** + * @deprecated Use of this function is deprecated, use rtnl_link_get_type() + */ +char *rtnl_link_get_info_type(struct rtnl_link *link) +{ + return rtnl_link_get_type(link); +} + +/** + * @deprecated The weight attribute is unused and obsoleted in all recent kernels + */ +void rtnl_link_set_weight(struct rtnl_link *link, unsigned int weight) +{ + link->l_weight = weight; + link->ce_mask |= LINK_ATTR_WEIGHT; +} + +/** + * @deprecated The weight attribute is unused and obsoleted in all recent kernels + */ +unsigned int rtnl_link_get_weight(struct rtnl_link *link) +{ + return link->l_weight; +} + +/** @} */ + +static struct nl_object_ops link_obj_ops = { + .oo_name = "route/link", + .oo_size = sizeof(struct rtnl_link), + .oo_free_data = link_free_data, + .oo_clone = link_clone, + .oo_dump = { + [NL_DUMP_LINE] = link_dump_line, + [NL_DUMP_DETAILS] = link_dump_details, + [NL_DUMP_STATS] = link_dump_stats, + }, + .oo_compare = link_compare, + .oo_keygen = link_keygen, + .oo_attrs2str = link_attrs2str, + .oo_id_attrs = LINK_ATTR_IFINDEX | LINK_ATTR_FAMILY, +}; + +static struct nl_af_group link_groups[] = { + { AF_UNSPEC, RTNLGRP_LINK }, + { AF_BRIDGE, RTNLGRP_LINK }, + { END_OF_GROUP_LIST }, +}; + +static struct nl_cache_ops rtnl_link_ops = { + .co_name = "route/link", + .co_hdrsize = sizeof(struct ifinfomsg), + .co_msgtypes = { + { RTM_NEWLINK, NL_ACT_NEW, "new" }, + { RTM_DELLINK, NL_ACT_DEL, "del" }, + { RTM_GETLINK, NL_ACT_GET, "get" }, + { RTM_SETLINK, NL_ACT_CHANGE, "set" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_ROUTE, + .co_groups = link_groups, + .co_request_update = link_request_update, + .co_msg_parser = link_msg_parser, + .co_obj_ops = &link_obj_ops, +}; + +static void __init link_init(void) +{ + nl_cache_mngt_register(&rtnl_link_ops); +} + +static void __exit link_exit(void) +{ + nl_cache_mngt_unregister(&rtnl_link_ops); +} + +/** @} */ diff --git a/lib/route/link/api.c b/lib/route/link/api.c new file mode 100644 index 0000000..6d1e12f --- /dev/null +++ b/lib/route/link/api.c @@ -0,0 +1,397 @@ +/* + * lib/route/link/api.c Link Info API + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + */ + +/** + * @ingroup link + * @defgroup link_API Link Modules API + * @brief API for modules implementing specific link types/semantics. + * + * @par 1) Registering/Unregistering a new link info type + * @code + * static struct rtnl_link_info_ops vlan_info_ops = { + * .io_name = "vlan", + * .io_alloc = vlan_alloc, + * .io_parse = vlan_parse, + * .io_dump[NL_DUMP_BRIEF] = vlan_dump_brief, + * .io_dump[NL_DUMP_FULL] = vlan_dump_full, + * .io_free = vlan_free, + * }; + * + * static void __init vlan_init(void) + * { + * rtnl_link_register_info(&vlan_info_ops); + * } + * + * static void __exit vlan_exit(void) + * { + * rtnl_link_unregister_info(&vlan_info_ops); + * } + * @endcode + * + * @{ + */ + +#include +#include +#include +#include +#include + +static NL_LIST_HEAD(info_ops); + +/* lock protecting info_ops and af_ops */ +static NL_RW_LOCK(info_lock); + +static struct rtnl_link_info_ops *__rtnl_link_info_ops_lookup(const char *name) +{ + struct rtnl_link_info_ops *ops; + + nl_list_for_each_entry(ops, &info_ops, io_list) + if (!strcmp(ops->io_name, name)) + return ops; + + return NULL; +} + +/** + * @name Link Info Modules + * @{ + */ + +/** + * Return operations of a specific link info type + * @arg name Name of link info type. + * + * @note The returned pointer must be given back using rtnl_link_info_ops_put() + * + * @return Pointer to operations or NULL if unavailable. + */ +struct rtnl_link_info_ops *rtnl_link_info_ops_lookup(const char *name) +{ + struct rtnl_link_info_ops *ops; + + nl_write_lock(&info_lock); + if ((ops = __rtnl_link_info_ops_lookup(name))) + ops->io_refcnt++; + nl_write_unlock(&info_lock); + + return ops; +} + +/** + * Give back reference to a set of operations. + * @arg ops Link info operations. + */ +void rtnl_link_info_ops_put(struct rtnl_link_info_ops *ops) +{ + if (ops) + ops->io_refcnt--; +} + +/** + * Register operations for a link info type + * @arg ops Link info operations + * + * This function must be called by modules implementing a specific link + * info type. It will make the operations implemented by the module + * available for everyone else. + * + * @return 0 on success or a negative error code. + * @return -NLE_INVAL Link info name not specified. + * @return -NLE_EXIST Operations for address family already registered. + */ +int rtnl_link_register_info(struct rtnl_link_info_ops *ops) +{ + int err = 0; + + if (ops->io_name == NULL) + return -NLE_INVAL; + + nl_write_lock(&info_lock); + if (__rtnl_link_info_ops_lookup(ops->io_name)) { + err = -NLE_EXIST; + goto errout; + } + + NL_DBG(1, "Registered link info operations %s\n", ops->io_name); + + nl_list_add_tail(&ops->io_list, &info_ops); +errout: + nl_write_unlock(&info_lock); + + return err; +} + +/** + * Unregister operations for a link info type + * @arg ops Link info operations + * + * This function must be called if a module implementing a specific link + * info type is unloaded or becomes unavailable. It must provide a + * set of operations which have previously been registered using + * rtnl_link_register_info(). + * + * @return 0 on success or a negative error code + * @return _NLE_OPNOTSUPP Link info operations not registered. + * @return -NLE_BUSY Link info operations still in use. + */ +int rtnl_link_unregister_info(struct rtnl_link_info_ops *ops) +{ + struct rtnl_link_info_ops *t; + int err = -NLE_OPNOTSUPP; + + nl_write_lock(&info_lock); + + nl_list_for_each_entry(t, &info_ops, io_list) { + if (t == ops) { + if (t->io_refcnt > 0) { + err = -NLE_BUSY; + goto errout; + } + + nl_list_del(&t->io_list); + + NL_DBG(1, "Unregistered link info operations %s\n", + ops->io_name); + err = 0; + goto errout; + } + } + +errout: + nl_write_unlock(&info_lock); + + return err; +} + +/** @} */ + +/** + * @name Link Address Family Modules + * @{ + */ + +static struct rtnl_link_af_ops *af_ops[AF_MAX]; + +/** + * Return operations of a specific link address family + * @arg family Address family + * + * @note The returned pointer must be given back using rtnl_link_af_ops_put() + * + * @return Pointer to operations or NULL if unavailable. + */ +struct rtnl_link_af_ops *rtnl_link_af_ops_lookup(const unsigned int family) +{ + if (family == AF_UNSPEC || family >= AF_MAX) + return NULL; + + nl_write_lock(&info_lock); + if (af_ops[family]) + af_ops[family]->ao_refcnt++; + nl_write_unlock(&info_lock); + + return af_ops[family]; +} + +/** + * Give back reference to a set of operations. + * @arg ops Address family operations. + */ +void rtnl_link_af_ops_put(struct rtnl_link_af_ops *ops) +{ + if (ops) + ops->ao_refcnt--; +} + +/** + * Allocate and return data buffer for link address family modules + * @arg link Link object + * @arg ops Address family operations + * + * This function must be called by link address family modules in all + * cases where the API does not provide the data buffer as argument + * already. This typically includes set functions the module provides. + * Calling this function is strictly required to ensure proper allocation + * of the buffer upon first use. Link objects will NOT proactively + * allocate a data buffer for each registered link address family. + * + * @return Pointer to data buffer or NULL on error. + */ +void *rtnl_link_af_alloc(struct rtnl_link *link, + const struct rtnl_link_af_ops *ops) +{ + int family; + + if (!link || !ops) + BUG(); + + family = ops->ao_family; + + if (!link->l_af_data[family]) { + if (!ops->ao_alloc) + BUG(); + + link->l_af_data[family] = ops->ao_alloc(link); + if (!link->l_af_data[family]) + return NULL; + } + + return link->l_af_data[family]; +} + +/** + * Return data buffer for link address family modules + * @arg link Link object + * @arg ops Address family operations + * + * This function returns a pointer to the data buffer for the specified link + * address family module or NULL if the buffer was not allocated yet. This + * function is typically used by get functions of modules which are not + * interested in having the data buffer allocated if no values have been set + * yet. + * + * @return Pointer to data buffer or NULL on error. + */ +void *rtnl_link_af_data(const struct rtnl_link *link, + const struct rtnl_link_af_ops *ops) +{ + if (!link || !ops) + BUG(); + + return link->l_af_data[ops->ao_family]; +} + +/** + * Register operations for a link address family + * @arg ops Address family operations + * + * This function must be called by modules implementing a specific link + * address family. It will make the operations implemented by the module + * available for everyone else. + * + * @return 0 on success or a negative error code. + * @return -NLE_INVAL Address family is out of range (0..AF_MAX) + * @return -NLE_EXIST Operations for address family already registered. + */ +int rtnl_link_af_register(struct rtnl_link_af_ops *ops) +{ + int err = 0; + + if (ops->ao_family == AF_UNSPEC || ops->ao_family >= AF_MAX) + return -NLE_INVAL; + + nl_write_lock(&info_lock); + if (af_ops[ops->ao_family]) { + err = -NLE_EXIST; + goto errout; + } + + ops->ao_refcnt = 0; + af_ops[ops->ao_family] = ops; + + NL_DBG(1, "Registered link address family operations %u\n", + ops->ao_family); + +errout: + nl_write_unlock(&info_lock); + + return err; +} + +/** + * Unregister operations for a link address family + * @arg ops Address family operations + * + * This function must be called if a module implementing a specific link + * address family is unloaded or becomes unavailable. It must provide a + * set of operations which have previously been registered using + * rtnl_link_af_register(). + * + * @return 0 on success or a negative error code + * @return -NLE_INVAL ops is NULL + * @return -NLE_OBJ_NOTFOUND Address family operations not registered. + * @return -NLE_BUSY Address family operations still in use. + */ +int rtnl_link_af_unregister(struct rtnl_link_af_ops *ops) +{ + int err = -NLE_INVAL; + + if (!ops) + return err; + + nl_write_lock(&info_lock); + if (!af_ops[ops->ao_family]) { + err = -NLE_OBJ_NOTFOUND; + goto errout; + } + + if (ops->ao_refcnt > 0) { + err = -NLE_BUSY; + goto errout; + } + + af_ops[ops->ao_family] = NULL; + + NL_DBG(1, "Unregistered link address family operations %u\n", + ops->ao_family); + +errout: + nl_write_unlock(&info_lock); + + return err; +} + +/** + * Compare af data for a link address family + * @arg a Link object a + * @arg b Link object b + * @arg family af data family + * + * This function will compare af_data between two links + * a and b of family given by arg family + * + * @return 0 if address family specific data matches or is not present + * or != 0 if it mismatches. + */ +int rtnl_link_af_data_compare(struct rtnl_link *a, struct rtnl_link *b, + int family) +{ + struct rtnl_link_af_ops *af_ops; + int ret = 0; + + if (!a->l_af_data[family] && !b->l_af_data[family]) + return 0; + + if (!a->l_af_data[family] || !b->l_af_data[family]) + return ~0; + + af_ops = rtnl_link_af_ops_lookup(family); + if (!af_ops) + return ~0; + + if (af_ops->ao_compare == NULL) { + ret = ~0; + goto out; + } + + ret = af_ops->ao_compare(a, b, family, ~0, 0); + +out: + rtnl_link_af_ops_put(af_ops); + + return ret; +} + +/** @} */ + +/** @} */ + diff --git a/lib/route/link/bonding.c b/lib/route/link/bonding.c new file mode 100644 index 0000000..f4c520b --- /dev/null +++ b/lib/route/link/bonding.c @@ -0,0 +1,227 @@ +/* + * lib/route/link/bonding.c Bonding Link Module + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2011-2013 Thomas Graf + */ + +/** + * @ingroup link + * @defgroup bonding Bonding + * + * @details + * \b Link Type Name: "bond" + * + * @route_doc{link_bonding, Bonding Documentation} + * @{ + */ + +#include +#include +#include + +/** + * Allocate link object of type bond + * + * @return Allocated link object or NULL. + */ +struct rtnl_link *rtnl_link_bond_alloc(void) +{ + struct rtnl_link *link; + int err; + + if (!(link = rtnl_link_alloc())) + return NULL; + + if ((err = rtnl_link_set_type(link, "bond")) < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Create a new kernel bonding device + * @arg sock netlink socket + * @arg name name of bonding device or NULL + * @arg opts bonding options (currently unused) + * + * Creates a new bonding device in the kernel. If no name is + * provided, the kernel will automatically pick a name of the + * form "type%d" (e.g. bond0, vlan1, etc.) + * + * The \a opts argument is currently unused. In the future, it + * may be used to carry additional bonding options to be set + * when creating the bonding device. + * + * @note When letting the kernel assign a name, it will become + * difficult to retrieve the interface afterwards because + * you have to guess the name the kernel has chosen. It is + * therefore not recommended to not provide a device name. + * + * @see rtnl_link_bond_enslave() + * @see rtnl_link_bond_release() + * + * @return 0 on success or a negative error code + */ +int rtnl_link_bond_add(struct nl_sock *sock, const char *name, + struct rtnl_link *opts) +{ + struct rtnl_link *link; + int err; + + if (!(link = rtnl_link_bond_alloc())) + return -NLE_NOMEM; + + if (!name && opts) + name = rtnl_link_get_name(opts); + + if (name) + rtnl_link_set_name(link, name); + + err = rtnl_link_add(sock, link, NLM_F_CREATE); + + rtnl_link_put(link); + + return err; +} + +/** + * Add a link to a bond (enslave) + * @arg sock netlink socket + * @arg master ifindex of bonding master + * @arg slave ifindex of slave link to add to bond + * + * This function is identical to rtnl_link_bond_enslave() except that + * it takes interface indices instead of rtnl_link objcets. + * + * @see rtnl_link_bond_enslave() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_bond_enslave_ifindex(struct nl_sock *sock, int master, + int slave) +{ + struct rtnl_link *link; + int err; + + if (!(link = rtnl_link_bond_alloc())) + return -NLE_NOMEM; + + rtnl_link_set_ifindex(link, slave); + rtnl_link_set_master(link, master); + + if ((err = rtnl_link_change(sock, link, link, 0)) < 0) + goto errout; + + rtnl_link_put(link); + + /* + * Due to the kernel not signaling whether this opertion is + * supported or not, we will retrieve the attribute to see if the + * request was successful. If the master assigned remains unchanged + * we will return NLE_OPNOTSUPP to allow performing backwards + * compatibility of some sort. + */ + if ((err = rtnl_link_get_kernel(sock, slave, NULL, &link)) < 0) + return err; + + if (rtnl_link_get_master(link) != master) + err = -NLE_OPNOTSUPP; + +errout: + rtnl_link_put(link); + + return err; +} + +/** + * Add a link to a bond (enslave) + * @arg sock netlink socket + * @arg master bonding master + * @arg slave slave link to add to bond + * + * Constructs a RTM_NEWLINK or RTM_SETLINK message adding the slave to + * the master and sends the request via the specified netlink socket. + * + * @note The feature of enslaving/releasing via netlink has only been added + * recently to the kernel (Feb 2011). Also, the kernel does not signal + * if the operation is not supported. Therefore this function will + * verify if the master assignment has changed and will return + * -NLE_OPNOTSUPP if it did not. + * + * @see rtnl_link_bond_enslave_ifindex() + * @see rtnl_link_bond_release() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_bond_enslave(struct nl_sock *sock, struct rtnl_link *master, + struct rtnl_link *slave) +{ + return rtnl_link_bond_enslave_ifindex(sock, + rtnl_link_get_ifindex(master), + rtnl_link_get_ifindex(slave)); +} + +/** + * Release a link from a bond + * @arg sock netlink socket + * @arg slave slave link to be released + * + * This function is identical to rtnl_link_bond_release() except that + * it takes an interface index instead of a rtnl_link object. + * + * @see rtnl_link_bond_release() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_bond_release_ifindex(struct nl_sock *sock, int slave) +{ + return rtnl_link_bond_enslave_ifindex(sock, 0, slave); +} + +/** + * Release a link from a bond + * @arg sock netlink socket + * @arg slave slave link to be released + * + * Constructs a RTM_NEWLINK or RTM_SETLINK message releasing the slave from + * its master and sends the request via the specified netlink socket. + * + * @note The feature of enslaving/releasing via netlink has only been added + * recently to the kernel (Feb 2011). Also, the kernel does not signal + * if the operation is not supported. Therefore this function will + * verify if the master assignment has changed and will return + * -NLE_OPNOTSUPP if it did not. + * + * @see rtnl_link_bond_release_ifindex() + * @see rtnl_link_bond_enslave() + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_bond_release(struct nl_sock *sock, struct rtnl_link *slave) +{ + return rtnl_link_bond_release_ifindex(sock, + rtnl_link_get_ifindex(slave)); +} + +static struct rtnl_link_info_ops bonding_info_ops = { + .io_name = "bond", +}; + +static void __init bonding_init(void) +{ + rtnl_link_register_info(&bonding_info_ops); +} + +static void __exit bonding_exit(void) +{ + rtnl_link_unregister_info(&bonding_info_ops); +} + +/** @} */ diff --git a/lib/route/link/bridge.c b/lib/route/link/bridge.c new file mode 100644 index 0000000..eb02b22 --- /dev/null +++ b/lib/route/link/bridge.c @@ -0,0 +1,474 @@ +/* + * lib/route/link/bridge.c AF_BRIDGE link support + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2010-2013 Thomas Graf + */ + +/** + * @ingroup link + * @defgroup bridge Bridging + * + * @details + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define BRIDGE_ATTR_PORT_STATE (1 << 0) +#define BRIDGE_ATTR_PRIORITY (1 << 1) +#define BRIDGE_ATTR_COST (1 << 2) +#define BRIDGE_ATTR_FLAGS (1 << 3) + +#define PRIV_FLAG_NEW_ATTRS (1 << 0) + +struct bridge_data +{ + uint8_t b_port_state; + uint8_t b_priv_flags; /* internal flags */ + uint16_t b_priority; + uint32_t b_cost; + uint32_t b_flags; + uint32_t b_flags_mask; + uint32_t ce_mask; /* HACK to support attr macros */ +}; + +static struct rtnl_link_af_ops bridge_ops; + +#define IS_BRIDGE_LINK_ASSERT(link) \ + if (!rtnl_link_is_bridge(link)) { \ + APPBUG("A function was expecting a link object of type bridge."); \ + return -NLE_OPNOTSUPP; \ + } + +static inline struct bridge_data *bridge_data(struct rtnl_link *link) +{ + return rtnl_link_af_data(link, &bridge_ops); +} + +static void *bridge_alloc(struct rtnl_link *link) +{ + return calloc(1, sizeof(struct bridge_data)); +} + +static void *bridge_clone(struct rtnl_link *link, void *data) +{ + struct bridge_data *bd; + + if ((bd = bridge_alloc(link))) + memcpy(bd, data, sizeof(*bd)); + + return bd; +} + +static void bridge_free(struct rtnl_link *link, void *data) +{ + free(data); +} + +static struct nla_policy br_attrs_policy[IFLA_BRPORT_MAX+1] = { + [IFLA_BRPORT_STATE] = { .type = NLA_U8 }, + [IFLA_BRPORT_PRIORITY] = { .type = NLA_U16 }, + [IFLA_BRPORT_COST] = { .type = NLA_U32 }, + [IFLA_BRPORT_MODE] = { .type = NLA_U8 }, + [IFLA_BRPORT_GUARD] = { .type = NLA_U8 }, + [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 }, + [IFLA_BRPORT_FAST_LEAVE] = { .type = NLA_U8 }, +}; + +static void check_flag(struct rtnl_link *link, struct nlattr *attrs[], + int type, int flag) +{ + if (attrs[type] && nla_get_u8(attrs[type])) + rtnl_link_bridge_set_flags(link, flag); +} + +static int bridge_parse_protinfo(struct rtnl_link *link, struct nlattr *attr, + void *data) +{ + struct bridge_data *bd = data; + struct nlattr *br_attrs[IFLA_BRPORT_MAX+1]; + int err; + + /* Backwards compatibility */ + if (!nla_is_nested(attr)) { + if (nla_len(attr) < 1) + return -NLE_RANGE; + + bd->b_port_state = nla_get_u8(attr); + bd->ce_mask |= BRIDGE_ATTR_PORT_STATE; + + return 0; + } + + if ((err = nla_parse_nested(br_attrs, IFLA_BRPORT_MAX, attr, + br_attrs_policy)) < 0) + return err; + + bd->b_priv_flags |= PRIV_FLAG_NEW_ATTRS; + + if (br_attrs[IFLA_BRPORT_STATE]) { + bd->b_port_state = nla_get_u8(br_attrs[IFLA_BRPORT_STATE]); + bd->ce_mask |= BRIDGE_ATTR_PORT_STATE; + } + + if (br_attrs[IFLA_BRPORT_PRIORITY]) { + bd->b_priority = nla_get_u16(br_attrs[IFLA_BRPORT_PRIORITY]); + bd->ce_mask |= BRIDGE_ATTR_PRIORITY; + } + + if (br_attrs[IFLA_BRPORT_COST]) { + bd->b_cost = nla_get_u32(br_attrs[IFLA_BRPORT_COST]); + bd->ce_mask |= BRIDGE_ATTR_COST; + } + + check_flag(link, br_attrs, IFLA_BRPORT_MODE, RTNL_BRIDGE_HAIRPIN_MODE); + check_flag(link, br_attrs, IFLA_BRPORT_GUARD, RTNL_BRIDGE_BPDU_GUARD); + check_flag(link, br_attrs, IFLA_BRPORT_PROTECT, RTNL_BRIDGE_ROOT_BLOCK); + check_flag(link, br_attrs, IFLA_BRPORT_FAST_LEAVE, RTNL_BRIDGE_FAST_LEAVE); + + return 0; +} + +static void bridge_dump_details(struct rtnl_link *link, + struct nl_dump_params *p, void *data) +{ + struct bridge_data *bd = data; + + nl_dump_line(p, " bridge: "); + + if (bd->ce_mask & BRIDGE_ATTR_PORT_STATE) + nl_dump(p, "port-state %u ", bd->b_port_state); + + if (bd->ce_mask & BRIDGE_ATTR_PRIORITY) + nl_dump(p, "prio %u ", bd->b_priority); + + if (bd->ce_mask & BRIDGE_ATTR_COST) + nl_dump(p, "cost %u ", bd->b_cost); + + nl_dump(p, "\n"); +} + +static int bridge_compare(struct rtnl_link *_a, struct rtnl_link *_b, + int family, uint32_t attrs, int flags) +{ + struct bridge_data *a = bridge_data(_a); + struct bridge_data *b = bridge_data(_b); + int diff = 0; + +#define BRIDGE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, BRIDGE_ATTR_##ATTR, a, b, EXPR) + diff |= BRIDGE_DIFF(PORT_STATE, a->b_port_state != b->b_port_state); + diff |= BRIDGE_DIFF(PRIORITY, a->b_priority != b->b_priority); + diff |= BRIDGE_DIFF(COST, a->b_cost != b->b_cost); + + if (flags & LOOSE_COMPARISON) + diff |= BRIDGE_DIFF(FLAGS, + (a->b_flags ^ b->b_flags) & b->b_flags_mask); + else + diff |= BRIDGE_DIFF(FLAGS, a->b_flags != b->b_flags); +#undef BRIDGE_DIFF + + return diff; +} +/** @endcond */ + +/** + * Allocate link object of type bridge + * + * @return Allocated link object or NULL. + */ +struct rtnl_link *rtnl_link_bridge_alloc(void) +{ + struct rtnl_link *link; + int err; + + if (!(link = rtnl_link_alloc())) + return NULL; + + if ((err = rtnl_link_set_type(link, "bridge")) < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if a link is a bridge + * @arg link Link object + * + * @return 1 if the link is a bridge, 0 otherwise. + */ +int rtnl_link_is_bridge(struct rtnl_link *link) +{ + return link->l_family == AF_BRIDGE && + link->l_af_ops == &bridge_ops; +} + +/** + * Check if bridge has extended information + * @arg link Link object of type bridge + * + * Checks if the bridge object has been constructed based on + * information that is only available in newer kernels. This + * affectes the following functions: + * - rtnl_link_bridge_get_cost() + * - rtnl_link_bridge_get_priority() + * - rtnl_link_bridge_get_flags() + * + * @return 1 if extended information is available, otherwise 0 is returned. + */ +int rtnl_link_bridge_has_ext_info(struct rtnl_link *link) +{ + struct bridge_data *bd; + + if (!rtnl_link_is_bridge(link)) + return 0; + + bd = bridge_data(link); + return !!(bd->b_priv_flags & PRIV_FLAG_NEW_ATTRS); +} + +/** + * Set Spanning Tree Protocol (STP) port state + * @arg link Link object of type bridge + * @arg state New STP port state + * + * The value of state must be one of the following: + * - BR_STATE_DISABLED + * - BR_STATE_LISTENING + * - BR_STATE_LEARNING + * - BR_STATE_FORWARDING + * - BR_STATE_BLOCKING + * + * @see rtnl_link_bridge_get_port_state() + * + * @return 0 on success or a negative error code. + * @retval -NLE_OPNOTSUPP Link is not a bridge + * @retval -NLE_INVAL Invalid state value (0..BR_STATE_BLOCKING) + */ +int rtnl_link_bridge_set_port_state(struct rtnl_link *link, uint8_t state) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + if (state > BR_STATE_BLOCKING) + return -NLE_INVAL; + + bd->b_port_state = state; + bd->ce_mask |= BRIDGE_ATTR_PORT_STATE; + + return 0; +} + +/** + * Get Spanning Tree Protocol (STP) port state + * @arg link Link object of type bridge + * + * @see rtnl_link_bridge_set_port_state() + * + * @return The STP port state or a negative error code. + * @retval -NLE_OPNOTSUPP Link is not a bridge + */ +int rtnl_link_bridge_get_port_state(struct rtnl_link *link) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + return bd->b_port_state; +} + +/** + * Set priority + * @arg link Link object of type bridge + * @arg prio Bridge priority + * + * @see rtnl_link_bridge_get_priority() + * + * @return 0 on success or a negative error code. + * @retval -NLE_OPNOTSUPP Link is not a bridge + */ +int rtnl_link_bridge_set_priority(struct rtnl_link *link, uint16_t prio) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + bd->b_priority = prio; + bd->ce_mask |= BRIDGE_ATTR_PRIORITY; + + return 0; +} + +/** + * Get priority + * @arg link Link object of type bridge + * + * @see rtnl_link_bridge_set_priority() + * + * @return 0 on success or a negative error code. + * @retval -NLE_OPNOTSUPP Link is not a bridge + */ +int rtnl_link_bridge_get_priority(struct rtnl_link *link) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + return bd->b_priority; +} + +/** + * Set Spanning Tree Protocol (STP) path cost + * @arg link Link object of type bridge + * @arg cost New STP path cost value + * + * @see rtnl_link_bridge_get_cost() + * + * @return The bridge priority or a negative error code. + * @retval -NLE_OPNOTSUPP Link is not a bridge + */ +int rtnl_link_bridge_set_cost(struct rtnl_link *link, uint32_t cost) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + bd->b_cost = cost; + bd->ce_mask |= BRIDGE_ATTR_COST; + + return 0; +} + +/** + * Get Spanning Tree Protocol (STP) path cost + * @arg link Link object of type bridge + * @arg cost Pointer to store STP cost value + * + * @see rtnl_link_bridge_set_cost() + * + * @return 0 on success or a negative error code. + * @retval -NLE_OPNOTSUPP Link is not a bridge + * @retval -NLE_INVAL `cost` is not a valid pointer + */ +int rtnl_link_bridge_get_cost(struct rtnl_link *link, uint32_t *cost) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + if (!cost) + return -NLE_INVAL; + + *cost = bd->b_cost; + + return 0; +} + +/** + * Unset flags + * @arg link Link object of type bridge + * @arg flags Bridging flags to unset + * + * @see rtnl_link_bridge_set_flags() + * @see rtnl_link_bridge_get_flags() + * + * @return 0 on success or a negative error code. + * @retval -NLE_OPNOTSUPP Link is not a bridge + */ +int rtnl_link_bridge_unset_flags(struct rtnl_link *link, unsigned int flags) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + bd->b_flags_mask |= flags; + bd->b_flags &= ~flags; + bd->ce_mask |= BRIDGE_ATTR_FLAGS; + + return 0; +} + +/** + * Set flags + * @arg link Link object of type bridge + * @arg flags Bridging flags to set + * + * Valid flags are: + * - RTNL_BRIDGE_HAIRPIN_MODE + * - RTNL_BRIDGE_BPDU_GUARD + * - RTNL_BRIDGE_ROOT_BLOCK + * - RTNL_BRIDGE_FAST_LEAVE + * + * @see rtnl_link_bridge_unset_flags() + * @see rtnl_link_bridge_get_flags() + * + * @return 0 on success or a negative error code. + * @retval -NLE_OPNOTSUPP Link is not a bridge + */ +int rtnl_link_bridge_set_flags(struct rtnl_link *link, unsigned int flags) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + bd->b_flags_mask |= flags; + bd->b_flags |= flags; + bd->ce_mask |= BRIDGE_ATTR_FLAGS; + + return 0; +} + +/** + * Get flags + * @arg link Link object of type bridge + * + * @see rtnl_link_bridge_set_flags() + * @see rtnl_link_bridge_unset_flags() + * + * @return Flags or a negative error code. + * @retval -NLE_OPNOTSUPP Link is not a bridge + */ +int rtnl_link_bridge_get_flags(struct rtnl_link *link) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + return bd->b_flags; +} + +static struct rtnl_link_af_ops bridge_ops = { + .ao_family = AF_BRIDGE, + .ao_alloc = &bridge_alloc, + .ao_clone = &bridge_clone, + .ao_free = &bridge_free, + .ao_parse_protinfo = &bridge_parse_protinfo, + .ao_dump[NL_DUMP_DETAILS] = &bridge_dump_details, + .ao_compare = &bridge_compare, +}; + +static void __init bridge_init(void) +{ + rtnl_link_af_register(&bridge_ops); +} + +static void __exit bridge_exit(void) +{ + rtnl_link_af_unregister(&bridge_ops); +} + +/** @} */ diff --git a/lib/route/link/can.c b/lib/route/link/can.c new file mode 100644 index 0000000..60da42d --- /dev/null +++ b/lib/route/link/can.c @@ -0,0 +1,784 @@ +/* + * lib/route/link/can.c CAN Link Info + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2012 Benedikt Spranger + */ + +/** + * @ingroup link + * @defgroup can CAN + * Controller Area Network link module + * + * @details + * \b Link Type Name: "can" + * + * @route_doc{link_can, CAN Documentation} + * + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/** @cond SKIP */ +#define CAN_HAS_BITTIMING (1<<0) +#define CAN_HAS_BITTIMING_CONST (1<<1) +#define CAN_HAS_CLOCK (1<<2) +#define CAN_HAS_STATE (1<<3) +#define CAN_HAS_CTRLMODE (1<<4) +#define CAN_HAS_RESTART_MS (1<<5) +#define CAN_HAS_RESTART (1<<6) +#define CAN_HAS_BERR_COUNTER (1<<7) + +struct can_info { + uint32_t ci_state; + uint32_t ci_restart; + uint32_t ci_restart_ms; + struct can_ctrlmode ci_ctrlmode; + struct can_bittiming ci_bittiming; + struct can_bittiming_const ci_bittiming_const; + struct can_clock ci_clock; + struct can_berr_counter ci_berr_counter; + uint32_t ci_mask; +}; + +/** @endcond */ + +static struct nla_policy can_policy[IFLA_CAN_MAX + 1] = { + [IFLA_CAN_STATE] = { .type = NLA_U32 }, + [IFLA_CAN_CTRLMODE] = { .minlen = sizeof(struct can_ctrlmode) }, + [IFLA_CAN_RESTART_MS] = { .type = NLA_U32 }, + [IFLA_CAN_RESTART] = { .type = NLA_U32 }, + [IFLA_CAN_BITTIMING] = { .minlen = sizeof(struct can_bittiming) }, + [IFLA_CAN_BITTIMING_CONST] + = { .minlen = sizeof(struct can_bittiming_const) }, + [IFLA_CAN_CLOCK] = { .minlen = sizeof(struct can_clock) }, + [IFLA_CAN_BERR_COUNTER] = { .minlen = sizeof(struct can_berr_counter) }, +}; + +static int can_alloc(struct rtnl_link *link) +{ + struct can_info *ci; + + ci = calloc(1, sizeof(*ci)); + if (!ci) + return -NLE_NOMEM; + + link->l_info = ci; + + return 0; +} + +static int can_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_CAN_MAX+1]; + struct can_info *ci; + int err; + + NL_DBG(3, "Parsing CAN link info"); + + if ((err = nla_parse_nested(tb, IFLA_CAN_MAX, data, can_policy)) < 0) + goto errout; + + if ((err = can_alloc(link)) < 0) + goto errout; + + ci = link->l_info; + + if (tb[IFLA_CAN_STATE]) { + ci->ci_state = nla_get_u32(tb[IFLA_CAN_STATE]); + ci->ci_mask |= CAN_HAS_STATE; + } + + if (tb[IFLA_CAN_RESTART]) { + ci->ci_restart = nla_get_u32(tb[IFLA_CAN_RESTART]); + ci->ci_mask |= CAN_HAS_RESTART; + } + + if (tb[IFLA_CAN_RESTART_MS]) { + ci->ci_restart_ms = nla_get_u32(tb[IFLA_CAN_RESTART_MS]); + ci->ci_mask |= CAN_HAS_RESTART_MS; + } + + if (tb[IFLA_CAN_CTRLMODE]) { + nla_memcpy(&ci->ci_ctrlmode, tb[IFLA_CAN_CTRLMODE], + sizeof(ci->ci_ctrlmode)); + ci->ci_mask |= CAN_HAS_CTRLMODE; + } + + if (tb[IFLA_CAN_BITTIMING]) { + nla_memcpy(&ci->ci_bittiming, tb[IFLA_CAN_BITTIMING], + sizeof(ci->ci_bittiming)); + ci->ci_mask |= CAN_HAS_BITTIMING; + } + + if (tb[IFLA_CAN_BITTIMING_CONST]) { + nla_memcpy(&ci->ci_bittiming_const, + tb[IFLA_CAN_BITTIMING_CONST], + sizeof(ci->ci_bittiming_const)); + ci->ci_mask |= CAN_HAS_BITTIMING_CONST; + } + + if (tb[IFLA_CAN_CLOCK]) { + nla_memcpy(&ci->ci_clock, tb[IFLA_CAN_CLOCK], + sizeof(ci->ci_clock)); + ci->ci_mask |= CAN_HAS_CLOCK; + } + + if (tb[IFLA_CAN_BERR_COUNTER]) { + nla_memcpy(&ci->ci_berr_counter, tb[IFLA_CAN_BERR_COUNTER], + sizeof(ci->ci_berr_counter)); + ci->ci_mask |= CAN_HAS_BERR_COUNTER; + } + + err = 0; +errout: + return err; +} + +static void can_free(struct rtnl_link *link) +{ + struct can_info *ci = link->l_info; + + free(ci); + link->l_info = NULL; +} + +static char *print_can_state (uint32_t state) +{ + char *text; + + switch (state) + { + case CAN_STATE_ERROR_ACTIVE: + text = "error active"; + break; + case CAN_STATE_ERROR_WARNING: + text = "error warning"; + break; + case CAN_STATE_ERROR_PASSIVE: + text = "error passive"; + break; + case CAN_STATE_BUS_OFF: + text = "bus off"; + break; + case CAN_STATE_STOPPED: + text = "stopped"; + break; + case CAN_STATE_SLEEPING: + text = "sleeping"; + break; + default: + text = "unknown state"; + } + + return text; +} + +static void can_dump_line(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct can_info *ci = link->l_info; + char buf [64]; + + rtnl_link_can_ctrlmode2str(ci->ci_ctrlmode.flags, buf, sizeof(buf)); + nl_dump(p, "bitrate %d %s <%s>", + ci->ci_bittiming.bitrate, print_can_state(ci->ci_state), buf); +} + +static void can_dump_details(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct can_info *ci = link->l_info; + char buf [64]; + + rtnl_link_can_ctrlmode2str(ci->ci_ctrlmode.flags, buf, sizeof(buf)); + nl_dump(p, " bitrate %d %s <%s>", + ci->ci_bittiming.bitrate, print_can_state(ci->ci_state), buf); + + if (ci->ci_mask & CAN_HAS_RESTART) { + if (ci->ci_restart) + nl_dump_line(p," restarting\n"); + } + + if (ci->ci_mask & CAN_HAS_RESTART_MS) { + nl_dump_line(p," restart interval %d ms\n", + ci->ci_restart_ms); + } + + if (ci->ci_mask & CAN_HAS_BITTIMING) { + nl_dump_line(p," sample point %f %%\n", + ((float) ci->ci_bittiming.sample_point)/10); + nl_dump_line(p," time quanta %d ns\n", + ci->ci_bittiming.tq); + nl_dump_line(p," propagation segment %d tq\n", + ci->ci_bittiming.prop_seg); + nl_dump_line(p," phase buffer segment1 %d tq\n", + ci->ci_bittiming.phase_seg1); + nl_dump_line(p," phase buffer segment2 %d tq\n", + ci->ci_bittiming.phase_seg2); + nl_dump_line(p," synchronisation jump width %d tq\n", + ci->ci_bittiming.sjw); + nl_dump_line(p," bitrate prescaler %d\n", + ci->ci_bittiming.brp); + } + + if (ci->ci_mask & CAN_HAS_BITTIMING_CONST) { + nl_dump_line(p," minimum tsig1 %d tq\n", + ci->ci_bittiming_const.tseg1_min); + nl_dump_line(p," maximum tsig1 %d tq\n", + ci->ci_bittiming_const.tseg1_max); + nl_dump_line(p," minimum tsig2 %d tq\n", + ci->ci_bittiming_const.tseg2_min); + nl_dump_line(p," maximum tsig2 %d tq\n", + ci->ci_bittiming_const.tseg2_max); + nl_dump_line(p," maximum sjw %d tq\n", + ci->ci_bittiming_const.sjw_max); + nl_dump_line(p," minimum brp %d\n", + ci->ci_bittiming_const.brp_min); + nl_dump_line(p," maximum brp %d\n", + ci->ci_bittiming_const.brp_max); + nl_dump_line(p," brp increment %d\n", + ci->ci_bittiming_const.brp_inc); + } + + if (ci->ci_mask & CAN_HAS_CLOCK) { + nl_dump_line(p," base freq %d Hz\n", ci->ci_clock); + + } + + if (ci->ci_mask & CAN_HAS_BERR_COUNTER) { + nl_dump_line(p," bus error RX %d\n", + ci->ci_berr_counter.rxerr); + nl_dump_line(p," bus error TX %d\n", + ci->ci_berr_counter.txerr); + } + + return; +} + +static int can_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct can_info *cdst, *csrc = src->l_info; + int ret; + + dst->l_info = NULL; + ret = rtnl_link_set_type(dst, "can"); + if (ret < 0) + return ret; + + cdst = malloc(sizeof(*cdst)); + if (!cdst) + return -NLE_NOMEM; + + *cdst = *csrc; + dst->l_info = cdst; + + return 0; +} + +static int can_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct can_info *ci = link->l_info; + struct nlattr *data; + + data = nla_nest_start(msg, IFLA_INFO_DATA); + if (!data) + return -NLE_MSGSIZE; + + if (ci->ci_mask & CAN_HAS_RESTART) + NLA_PUT_U32(msg, CAN_HAS_RESTART, ci->ci_restart); + + if (ci->ci_mask & CAN_HAS_RESTART_MS) + NLA_PUT_U32(msg, CAN_HAS_RESTART_MS, ci->ci_restart_ms); + + if (ci->ci_mask & CAN_HAS_CTRLMODE) + NLA_PUT(msg, CAN_HAS_CTRLMODE, sizeof(ci->ci_ctrlmode), + &ci->ci_ctrlmode); + + if (ci->ci_mask & CAN_HAS_BITTIMING) + NLA_PUT(msg, CAN_HAS_BITTIMING, sizeof(ci->ci_bittiming), + &ci->ci_bittiming); + + if (ci->ci_mask & CAN_HAS_BITTIMING_CONST) + NLA_PUT(msg, CAN_HAS_BITTIMING_CONST, + sizeof(ci->ci_bittiming_const), + &ci->ci_bittiming_const); + + if (ci->ci_mask & CAN_HAS_CLOCK) + NLA_PUT(msg, CAN_HAS_CLOCK, sizeof(ci->ci_clock), + &ci->ci_clock); + + nla_nest_end(msg, data); + +nla_put_failure: + + return 0; +} + +static struct rtnl_link_info_ops can_info_ops = { + .io_name = "can", + .io_alloc = can_alloc, + .io_parse = can_parse, + .io_dump = { + [NL_DUMP_LINE] = can_dump_line, + [NL_DUMP_DETAILS] = can_dump_details, + }, + .io_clone = can_clone, + .io_put_attrs = can_put_attrs, + .io_free = can_free, +}; + +/** @cond SKIP */ +#define IS_CAN_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &can_info_ops) { \ + APPBUG("Link is not a CAN link. set type \"can\" first."); \ + return -NLE_OPNOTSUPP; \ + } +/** @endcond */ + +/** + * @name CAN Object + * @{ + */ + +/** + * Check if link is a CAN link + * @arg link Link object + * + * @return True if link is a CAN link, otherwise false is returned. + */ +int rtnl_link_is_can(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "can"); +} + +/** + * Restart CAN device + * @arg link Link object + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_restart(struct rtnl_link *link) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + + ci->ci_restart = 1; + ci->ci_restart |= CAN_HAS_RESTART; + + return 0; +} + +/** + * Get CAN base frequency + * @arg link Link object + * @arg freq frequency in Hz + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_freq(struct rtnl_link *link, uint32_t *freq) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!freq) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_CLOCK) + *freq = ci->ci_clock.freq; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Get CAN state + * @arg link Link object + * @arg state CAN bus state + * @return 0 on success or a negative error code + */ +int rtnl_link_can_state(struct rtnl_link *link, uint32_t *state) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!state) + return -NLE_INVAL; + + *state = ci->ci_state; + + return 0; +} + +/** + * Get CAN RX bus error count + * @arg link Link object + * + * @return RX bus error count on success or a negative error code + */ +int rtnl_link_can_berr_rx(struct rtnl_link *link) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + + if (ci->ci_mask & CAN_HAS_BERR_COUNTER) + return ci->ci_berr_counter.rxerr; + else + return -NLE_AGAIN; +} + +/** + * Get CAN TX bus error count + * @arg link Link object + * + * @return TX bus error count on success or a negative error code + */ +int rtnl_link_can_berr_tx(struct rtnl_link *link) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + + if (ci->ci_mask & CAN_HAS_BERR_COUNTER) + return ci->ci_berr_counter.txerr; + else + return -NLE_AGAIN; +} + +/** + * Get CAN bus error count + * @arg link Link object + * @arg berr Bus error count + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_berr(struct rtnl_link *link, struct can_berr_counter *berr) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!berr) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_BERR_COUNTER) + *berr = ci->ci_berr_counter; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Get CAN harware-dependent bit-timing constant + * @arg link Link object + * @arg bt_const Bit-timing constant + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_get_bt_const(struct rtnl_link *link, + struct can_bittiming_const *bt_const) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!bt_const) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_BITTIMING_CONST) + *bt_const = ci->ci_bittiming_const; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Get CAN device bit-timing + * @arg link Link object + * @arg bit_timing CAN bit-timing + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_get_bittiming(struct rtnl_link *link, + struct can_bittiming *bit_timing) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!bit_timing) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_BITTIMING) + *bit_timing = ci->ci_bittiming; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set CAN device bit-timing + * @arg link Link object + * @arg bit_timing CAN bit-timing + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_set_bittiming(struct rtnl_link *link, + struct can_bittiming *bit_timing) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!bit_timing) + return -NLE_INVAL; + + ci->ci_bittiming = *bit_timing; + ci->ci_mask |= CAN_HAS_BITTIMING; + + return 0; +} + +/** + * Get CAN device bit-timing + * @arg link Link object + * @arg bitrate CAN bitrate + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_get_bitrate(struct rtnl_link *link, uint32_t *bitrate) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!bitrate) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_BITTIMING) + *bitrate = ci->ci_bittiming.bitrate; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set CAN device bit-rate + * @arg link Link object + * @arg bitrate CAN bitrate + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_set_bitrate(struct rtnl_link *link, uint32_t bitrate) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + + ci->ci_bittiming.bitrate = bitrate; + ci->ci_mask |= CAN_HAS_BITTIMING; + + return 0; +} + +/** + * Get CAN device sample point + * @arg link Link object + * @arg sp CAN sample point + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_get_sample_point(struct rtnl_link *link, uint32_t *sp) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!sp) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_BITTIMING) + *sp = ci->ci_bittiming.sample_point; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set CAN device sample point + * @arg link Link object + * @arg sp CAN sample point + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_set_sample_point(struct rtnl_link *link, uint32_t sp) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + + ci->ci_bittiming.sample_point = sp; + ci->ci_mask |= CAN_HAS_BITTIMING; + + return 0; +} + +/** + * Get CAN device restart intervall + * @arg link Link object + * @arg interval Restart intervall in ms + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_get_restart_ms(struct rtnl_link *link, uint32_t *interval) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!interval) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_RESTART_MS) + *interval = ci->ci_restart_ms; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set CAN device restart intervall + * @arg link Link object + * @arg interval Restart intervall in ms + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_set_restart_ms(struct rtnl_link *link, uint32_t interval) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + + ci->ci_restart_ms = interval; + ci->ci_mask |= CAN_HAS_RESTART_MS; + + return 0; +} + +/** + * Get CAN control mode + * @arg link Link object + * @arg ctrlmode CAN control mode + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_get_ctrlmode(struct rtnl_link *link, uint32_t *ctrlmode) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!ctrlmode) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_CTRLMODE) + *ctrlmode = ci->ci_ctrlmode.flags; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set a CAN Control Mode + * @arg link Link object + * @arg ctrlmode CAN control mode + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_set_ctrlmode(struct rtnl_link *link, uint32_t ctrlmode) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + + ci->ci_ctrlmode.flags |= ctrlmode; + ci->ci_ctrlmode.mask |= ctrlmode; + ci->ci_mask |= CAN_HAS_CTRLMODE; + + return 0; +} + +/** + * Unset a CAN Control Mode + * @arg link Link object + * @arg ctrlmode CAN control mode + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_unset_ctrlmode(struct rtnl_link *link, uint32_t ctrlmode) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + + ci->ci_ctrlmode.flags &= ~ctrlmode; + ci->ci_ctrlmode.mask |= ctrlmode; + ci->ci_mask |= CAN_HAS_CTRLMODE; + + return 0; +} + +/** @} */ + +/** + * @name Control Mode Translation + * @{ + */ + +static const struct trans_tbl can_ctrlmode[] = { + __ADD(CAN_CTRLMODE_LOOPBACK, loopback) + __ADD(CAN_CTRLMODE_LISTENONLY, listen-only) + __ADD(CAN_CTRLMODE_3_SAMPLES, triple-sampling) + __ADD(CAN_CTRLMODE_ONE_SHOT, one-shot) + __ADD(CAN_CTRLMODE_BERR_REPORTING, berr-reporting) +}; + +char *rtnl_link_can_ctrlmode2str(int ctrlmode, char *buf, size_t len) +{ + return __flags2str(ctrlmode, buf, len, can_ctrlmode, + ARRAY_SIZE(can_ctrlmode)); +} + +int rtnl_link_can_str2ctrlmode(const char *name) +{ + return __str2flags(name, can_ctrlmode, ARRAY_SIZE(can_ctrlmode)); +} + +/** @} */ + +static void __init can_init(void) +{ + rtnl_link_register_info(&can_info_ops); +} + +static void __exit can_exit(void) +{ + rtnl_link_unregister_info(&can_info_ops); +} + +/** @} */ diff --git a/lib/route/link/dummy.c b/lib/route/link/dummy.c new file mode 100644 index 0000000..1fd9f5a --- /dev/null +++ b/lib/route/link/dummy.c @@ -0,0 +1,40 @@ +/* + * lib/route/link/dummy.c Dummy Interfaces + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2011 Thomas Graf + */ + +/** + * @ingroup link + * @defgroup dummy Dummy + * + * @details + * \b Link Type Name: "dummy" + * + * @{ + */ + +#include +#include +#include + +static struct rtnl_link_info_ops dummy_info_ops = { + .io_name = "dummy", +}; + +static void __init dummy_init(void) +{ + rtnl_link_register_info(&dummy_info_ops); +} + +static void __exit dummy_exit(void) +{ + rtnl_link_unregister_info(&dummy_info_ops); +} + +/** @} */ diff --git a/lib/route/link/inet.c b/lib/route/link/inet.c new file mode 100644 index 0000000..e2c867d --- /dev/null +++ b/lib/route/link/inet.c @@ -0,0 +1,280 @@ +/* + * lib/route/link/inet.c AF_INET link operations + * + * 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 + */ + +/** + * @ingroup link_API + * @defgroup link_inet IPv4 Link Module + * @brief Implementation of IPv4 specific link attributes + * + * + * + * @par Example: Reading the value of IPV4_DEVCONF_FORWARDING + * @code + * struct nl_cache *cache; + * struct rtnl_link *link; + * uint32_t value; + * + * // Allocate a link cache + * rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache); + * + * // Search for the link we wish to see the value from + * link = rtnl_link_get_by_name(cache, "eth0"); + * + * // Read the value of the setting IPV4_DEVCONF_FORWARDING + * if (rtnl_link_inet_get_conf(link, IPV4_DEVCONF_FORWARDING, &value) < 0) + * // Error: Unable to read config setting + * + * printf("forwarding is %s\n", value ? "enabled" : "disabled"); + * @endcode + * + * @par Example: Changing the value of IPV4_DEVCONF_FOWARDING + * @code + * // + * // ... Continueing from the previous example ... + * // + * + * struct rtnl_link *new; + * + * // Allocate a new link to store the changes we wish to make. + * new = rtnl_link_alloc(); + * + * // Set IPV4_DEVCONF_FORWARDING to '1' + * rtnl_link_inet_set_conf(new, IPV4_DEVCONF_FORWARDING, 1); + * + * // Send the change request to the kernel. + * rtnl_link_change(sock, link, new, 0); + * @endcode + * + * @{ + */ + + +#include +#include +#include +#include +#include + +/** @cond SKIP */ +struct inet_data +{ + uint8_t i_confset[IPV4_DEVCONF_MAX]; + uint32_t i_conf[IPV4_DEVCONF_MAX]; +}; +/** @endcond */ + +static void *inet_alloc(struct rtnl_link *link) +{ + return calloc(1, sizeof(struct inet_data)); +} + +static void *inet_clone(struct rtnl_link *link, void *data) +{ + struct inet_data *id; + + if ((id = inet_alloc(link))) + memcpy(id, data, sizeof(*id)); + + return id; +} + +static void inet_free(struct rtnl_link *link, void *data) +{ + free(data); +} + +static struct nla_policy inet_policy[IFLA_INET6_MAX+1] = { + [IFLA_INET_CONF] = { .minlen = IPV4_DEVCONF_MAX * 4 }, +}; + +static int inet_parse_af(struct rtnl_link *link, struct nlattr *attr, void *data) +{ + struct inet_data *id = data; + struct nlattr *tb[IFLA_INET_MAX+1]; + int err; + + err = nla_parse_nested(tb, IFLA_INET_MAX, attr, inet_policy); + if (err < 0) + return err; + + if (tb[IFLA_INET_CONF]) + nla_memcpy(&id->i_conf, tb[IFLA_INET_CONF], sizeof(id->i_conf)); + + return 0; +} + +static int inet_fill_af(struct rtnl_link *link, struct nl_msg *msg, void *data) +{ + struct inet_data *id = data; + struct nlattr *nla; + int i; + + if (!(nla = nla_nest_start(msg, IFLA_INET_CONF))) + return -NLE_MSGSIZE; + + for (i = 0; i < IPV4_DEVCONF_MAX; i++) + if (id->i_confset[i]) + NLA_PUT_U32(msg, i+1, id->i_conf[i]); + + nla_nest_end(msg, nla); + + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +static const struct trans_tbl inet_devconf[] = { + __ADD(IPV4_DEVCONF_FORWARDING, forwarding) + __ADD(IPV4_DEVCONF_MC_FORWARDING, mc_forwarding) + __ADD(IPV4_DEVCONF_PROXY_ARP, proxy_arp) + __ADD(IPV4_DEVCONF_ACCEPT_REDIRECTS, accept_redirects) + __ADD(IPV4_DEVCONF_SECURE_REDIRECTS, secure_redirects) + __ADD(IPV4_DEVCONF_SEND_REDIRECTS, send_redirects) + __ADD(IPV4_DEVCONF_SHARED_MEDIA, shared_media) + __ADD(IPV4_DEVCONF_RP_FILTER, rp_filter) + __ADD(IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE, accept_source_route) + __ADD(IPV4_DEVCONF_BOOTP_RELAY, bootp_relay) + __ADD(IPV4_DEVCONF_LOG_MARTIANS, log_martians) + __ADD(IPV4_DEVCONF_TAG, tag) + __ADD(IPV4_DEVCONF_ARPFILTER, arpfilter) + __ADD(IPV4_DEVCONF_MEDIUM_ID, medium_id) + __ADD(IPV4_DEVCONF_NOXFRM, noxfrm) + __ADD(IPV4_DEVCONF_NOPOLICY, nopolicy) + __ADD(IPV4_DEVCONF_FORCE_IGMP_VERSION, force_igmp_version) + __ADD(IPV4_DEVCONF_ARP_ANNOUNCE, arp_announce) + __ADD(IPV4_DEVCONF_ARP_IGNORE, arp_ignore) + __ADD(IPV4_DEVCONF_PROMOTE_SECONDARIES, promote_secondaries) + __ADD(IPV4_DEVCONF_ARP_ACCEPT, arp_accept) + __ADD(IPV4_DEVCONF_ARP_NOTIFY, arp_notify) + __ADD(IPV4_DEVCONF_ACCEPT_LOCAL, accept_local) + __ADD(IPV4_DEVCONF_SRC_VMARK, src_vmark) + __ADD(IPV4_DEVCONF_PROXY_ARP_PVLAN, proxy_arp_pvlan) +}; + +const char *rtnl_link_inet_devconf2str(int type, char *buf, size_t len) +{ + return __type2str(type, buf, len, inet_devconf, + ARRAY_SIZE(inet_devconf)); +} + +int rtnl_link_inet_str2devconf(const char *name) +{ + return __str2type(name, inet_devconf, ARRAY_SIZE(inet_devconf)); +} + +static void inet_dump_details(struct rtnl_link *link, + struct nl_dump_params *p, void *data) +{ + struct inet_data *id = data; + char buf[64]; + int i, n = 0; + + nl_dump_line(p, " ipv4 devconf:\n"); + nl_dump_line(p, " "); + + for (i = 0; i < IPV4_DEVCONF_MAX; i++) { + nl_dump_line(p, "%-19s %3u", + rtnl_link_inet_devconf2str(i+1, buf, sizeof(buf)), + id->i_conf[i]); + + if (++n == 3) { + nl_dump(p, "\n"); + nl_dump_line(p, " "); + n = 0; + } else + nl_dump(p, " "); + } + + if (n != 0) + nl_dump(p, "\n"); +} + +static struct rtnl_link_af_ops inet_ops = { + .ao_family = AF_INET, + .ao_alloc = &inet_alloc, + .ao_clone = &inet_clone, + .ao_free = &inet_free, + .ao_parse_af = &inet_parse_af, + .ao_fill_af = &inet_fill_af, + .ao_dump[NL_DUMP_DETAILS] = &inet_dump_details, +}; + +/** + * Get value of a ipv4 link configuration setting + * @arg link Link object + * @arg cfgid Configuration identifier + * @arg res Result pointer + * + * Stores the value of the specified configuration setting in the provided + * result pointer. + * + * @return 0 on success or a negative error code. + * @return -NLE_RANGE cfgid is out of range, 1..IPV4_DEVCONF_MAX + * @return -NLE_NOATTR configuration setting not available + */ +int rtnl_link_inet_get_conf(struct rtnl_link *link, const unsigned int cfgid, + uint32_t *res) +{ + struct inet_data *id; + + if (cfgid == 0 || cfgid > IPV4_DEVCONF_MAX) + return -NLE_RANGE; + + if (!(id = rtnl_link_af_alloc(link, &inet_ops))) + return -NLE_NOATTR; + + *res = id->i_conf[cfgid - 1]; + + return 0; +} + +/** + * Change value of a ipv4 link configuration setting + * @arg link Link object + * @arg cfgid Configuration identifier + * @arg value New value + * + * Changes the value in the per link ipv4 configuration array. + * + * @return 0 on success or a negative error code. + * @return -NLE_RANGE cfgid is out of range, 1..IPV4_DEVCONF_MAX + * @return -NLE_NOMEM memory allocation failed + */ +int rtnl_link_inet_set_conf(struct rtnl_link *link, const unsigned int cfgid, + uint32_t value) +{ + struct inet_data *id; + + if (!(id = rtnl_link_af_alloc(link, &inet_ops))) + return -NLE_NOMEM; + + if (cfgid == 0 || cfgid > IPV4_DEVCONF_MAX) + return -NLE_RANGE; + + id->i_confset[cfgid - 1] = 1; + id->i_conf[cfgid - 1] = value; + + return 0; +} + + +static void __init inet_init(void) +{ + rtnl_link_af_register(&inet_ops); +} + +static void __exit inet_exit(void) +{ + rtnl_link_af_unregister(&inet_ops); +} + +/** @} */ diff --git a/lib/route/link/inet6.c b/lib/route/link/inet6.c new file mode 100644 index 0000000..4c627bd --- /dev/null +++ b/lib/route/link/inet6.c @@ -0,0 +1,377 @@ +/* + * lib/route/link/inet6.c AF_INET6 link operations + * + * 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 + */ + +#include +#include +#include +#include +#include + +struct inet6_data +{ + uint32_t i6_flags; + struct ifla_cacheinfo i6_cacheinfo; + uint32_t i6_conf[DEVCONF_MAX]; +}; + +static void *inet6_alloc(struct rtnl_link *link) +{ + return calloc(1, sizeof(struct inet6_data)); +} + +static void *inet6_clone(struct rtnl_link *link, void *data) +{ + struct inet6_data *i6; + + if ((i6 = inet6_alloc(link))) + memcpy(i6, data, sizeof(*i6)); + + return i6; +} + +static void inet6_free(struct rtnl_link *link, void *data) +{ + free(data); +} + +static struct nla_policy inet6_policy[IFLA_INET6_MAX+1] = { + [IFLA_INET6_FLAGS] = { .type = NLA_U32 }, + [IFLA_INET6_CACHEINFO] = { .minlen = sizeof(struct ifla_cacheinfo) }, + [IFLA_INET6_CONF] = { .minlen = DEVCONF_MAX * 4 }, + [IFLA_INET6_STATS] = { .minlen = __IPSTATS_MIB_MAX * 8 }, + [IFLA_INET6_ICMP6STATS] = { .minlen = __ICMP6_MIB_MAX * 8 }, +}; + +static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr, + void *data) +{ + struct inet6_data *i6 = data; + struct nlattr *tb[IFLA_INET6_MAX+1]; + int err; + + err = nla_parse_nested(tb, IFLA_INET6_MAX, attr, inet6_policy); + if (err < 0) + return err; + + if (tb[IFLA_INET6_FLAGS]) + i6->i6_flags = nla_get_u32(tb[IFLA_INET6_FLAGS]); + + if (tb[IFLA_INET6_CACHEINFO]) + nla_memcpy(&i6->i6_cacheinfo, tb[IFLA_INET6_CACHEINFO], + sizeof(i6->i6_cacheinfo)); + + if (tb[IFLA_INET6_CONF]) + nla_memcpy(&i6->i6_conf, tb[IFLA_INET6_CONF], + sizeof(i6->i6_conf)); + + /* + * Due to 32bit data alignment, these addresses must be copied to an + * aligned location prior to access. + */ + if (tb[IFLA_INET6_STATS]) { + unsigned char *cnt = nla_data(tb[IFLA_INET6_STATS]); + uint64_t stat; + int i; + + for (i = 1; i < __IPSTATS_MIB_MAX; i++) { + memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat)); + rtnl_link_set_stat(link, RTNL_LINK_IP6_INPKTS + i - 1, + stat); + } + } + + if (tb[IFLA_INET6_ICMP6STATS]) { + unsigned char *cnt = nla_data(tb[IFLA_INET6_ICMP6STATS]); + uint64_t stat; + int i; + + for (i = 1; i < __ICMP6_MIB_MAX; i++) { + memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat)); + rtnl_link_set_stat(link, RTNL_LINK_ICMP6_INMSGS + i - 1, + stat); + } + } + + return 0; +} + +/* These live in include/net/if_inet6.h and should be moved to include/linux */ +#define IF_RA_OTHERCONF 0x80 +#define IF_RA_MANAGED 0x40 +#define IF_RA_RCVD 0x20 +#define IF_RS_SENT 0x10 +#define IF_READY 0x80000000 + +static const struct trans_tbl inet6_flags[] = { + __ADD(IF_RA_OTHERCONF, ra_otherconf) + __ADD(IF_RA_MANAGED, ra_managed) + __ADD(IF_RA_RCVD, ra_rcvd) + __ADD(IF_RS_SENT, rs_sent) + __ADD(IF_READY, ready) +}; + +static char *inet6_flags2str(int flags, char *buf, size_t len) +{ + return __flags2str(flags, buf, len, inet6_flags, + ARRAY_SIZE(inet6_flags)); +} + +static const struct trans_tbl inet6_devconf[] = { + __ADD(DEVCONF_FORWARDING, forwarding) + __ADD(DEVCONF_HOPLIMIT, hoplimit) + __ADD(DEVCONF_MTU6, mtu6) + __ADD(DEVCONF_ACCEPT_RA, accept_ra) + __ADD(DEVCONF_ACCEPT_REDIRECTS, accept_redirects) + __ADD(DEVCONF_AUTOCONF, autoconf) + __ADD(DEVCONF_DAD_TRANSMITS, dad_transmits) + __ADD(DEVCONF_RTR_SOLICITS, rtr_solicits) + __ADD(DEVCONF_RTR_SOLICIT_INTERVAL, rtr_solicit_interval) + __ADD(DEVCONF_RTR_SOLICIT_DELAY, rtr_solicit_delay) + __ADD(DEVCONF_USE_TEMPADDR, use_tempaddr) + __ADD(DEVCONF_TEMP_VALID_LFT, temp_valid_lft) + __ADD(DEVCONF_TEMP_PREFERED_LFT, temp_prefered_lft) + __ADD(DEVCONF_REGEN_MAX_RETRY, regen_max_retry) + __ADD(DEVCONF_MAX_DESYNC_FACTOR, max_desync_factor) + __ADD(DEVCONF_MAX_ADDRESSES, max_addresses) + __ADD(DEVCONF_FORCE_MLD_VERSION, force_mld_version) + __ADD(DEVCONF_ACCEPT_RA_DEFRTR, accept_ra_defrtr) + __ADD(DEVCONF_ACCEPT_RA_PINFO, accept_ra_pinfo) + __ADD(DEVCONF_ACCEPT_RA_RTR_PREF, accept_ra_rtr_pref) + __ADD(DEVCONF_RTR_PROBE_INTERVAL, rtr_probe_interval) + __ADD(DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN, accept_ra_rt_info) + __ADD(DEVCONF_PROXY_NDP, proxy_ndp) + __ADD(DEVCONF_OPTIMISTIC_DAD, optimistic_dad) + __ADD(DEVCONF_ACCEPT_SOURCE_ROUTE, accept_source_route) + __ADD(DEVCONF_MC_FORWARDING, mc_forwarding) + __ADD(DEVCONF_DISABLE_IPV6, disable_ipv6) + __ADD(DEVCONF_ACCEPT_DAD, accept_dad) + __ADD(DEVCONF_FORCE_TLLAO, force_tllao) +}; + +static char *inet6_devconf2str(int type, char *buf, size_t len) +{ + return __type2str(type, buf, len, inet6_devconf, + ARRAY_SIZE(inet6_devconf)); +} + + +static void inet6_dump_details(struct rtnl_link *link, + struct nl_dump_params *p, void *data) +{ + struct inet6_data *i6 = data; + char buf[64], buf2[64]; + int i, n = 0; + + nl_dump_line(p, " ipv6 max-reasm-len %s", + nl_size2str(i6->i6_cacheinfo.max_reasm_len, buf, sizeof(buf))); + + nl_dump(p, " <%s>\n", + inet6_flags2str(i6->i6_flags, buf, sizeof(buf))); + + + nl_dump_line(p, " create-stamp %.2fs reachable-time %s", + (double) i6->i6_cacheinfo.tstamp / 100., + nl_msec2str(i6->i6_cacheinfo.reachable_time, buf, sizeof(buf))); + + nl_dump(p, " retrans-time %s\n", + nl_msec2str(i6->i6_cacheinfo.retrans_time, buf, sizeof(buf))); + + nl_dump_line(p, " devconf:\n"); + nl_dump_line(p, " "); + + for (i = 0; i < DEVCONF_MAX; i++) { + uint32_t value = i6->i6_conf[i]; + int x, offset; + + switch (i) { + case DEVCONF_TEMP_VALID_LFT: + case DEVCONF_TEMP_PREFERED_LFT: + nl_msec2str((uint64_t) value * 1000., buf2, sizeof(buf2)); + break; + + case DEVCONF_RTR_PROBE_INTERVAL: + case DEVCONF_RTR_SOLICIT_INTERVAL: + case DEVCONF_RTR_SOLICIT_DELAY: + nl_msec2str(value, buf2, sizeof(buf2)); + break; + + default: + snprintf(buf2, sizeof(buf2), "%u", value); + break; + + } + + inet6_devconf2str(i, buf, sizeof(buf)); + + offset = 23 - strlen(buf2); + if (offset < 0) + offset = 0; + + for (x = strlen(buf); x < offset; x++) + buf[x] = ' '; + + strncpy(&buf[offset], buf2, strlen(buf2)); + + nl_dump_line(p, "%s", buf); + + if (++n == 3) { + nl_dump(p, "\n"); + nl_dump_line(p, " "); + n = 0; + } else + nl_dump(p, " "); + } + + if (n != 0) + nl_dump(p, "\n"); +} + +static void inet6_dump_stats(struct rtnl_link *link, + struct nl_dump_params *p, void *data) +{ + double octets; + char *octetsUnit; + + nl_dump(p, " IPv6: InPkts InOctets " + " InDiscards InDelivers\n"); + nl_dump(p, " %18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_INPKTS]); + + octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INOCTETS], + &octetsUnit); + if (octets) + nl_dump(p, "%14.2f %3s ", octets, octetsUnit); + else + nl_dump(p, "%16" PRIu64 " B ", 0); + + nl_dump(p, "%18" PRIu64 " %18" PRIu64 "\n", + link->l_stats[RTNL_LINK_IP6_INDISCARDS], + link->l_stats[RTNL_LINK_IP6_INDELIVERS]); + + nl_dump(p, " OutPkts OutOctets " + " OutDiscards OutForwards\n"); + + nl_dump(p, " %18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_OUTPKTS]); + + octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTOCTETS], + &octetsUnit); + if (octets) + nl_dump(p, "%14.2f %3s ", octets, octetsUnit); + else + nl_dump(p, "%16" PRIu64 " B ", 0); + + nl_dump(p, "%18" PRIu64 " %18" PRIu64 "\n", + link->l_stats[RTNL_LINK_IP6_OUTDISCARDS], + link->l_stats[RTNL_LINK_IP6_OUTFORWDATAGRAMS]); + + nl_dump(p, " InMcastPkts InMcastOctets " + " InBcastPkts InBcastOctests\n"); + + nl_dump(p, " %18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_INMCASTPKTS]); + + octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INMCASTOCTETS], + &octetsUnit); + if (octets) + nl_dump(p, "%14.2f %3s ", octets, octetsUnit); + else + nl_dump(p, "%16" PRIu64 " B ", 0); + + nl_dump(p, "%18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_INBCASTPKTS]); + octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INBCASTOCTETS], + &octetsUnit); + if (octets) + nl_dump(p, "%14.2f %3s\n", octets, octetsUnit); + else + nl_dump(p, "%16" PRIu64 " B\n", 0); + + nl_dump(p, " OutMcastPkts OutMcastOctets " + " OutBcastPkts OutBcastOctests\n"); + + nl_dump(p, " %18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_OUTMCASTPKTS]); + + octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTMCASTOCTETS], + &octetsUnit); + if (octets) + nl_dump(p, "%14.2f %3s ", octets, octetsUnit); + else + nl_dump(p, "%16" PRIu64 " B ", 0); + + nl_dump(p, "%18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_OUTBCASTPKTS]); + octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTBCASTOCTETS], + &octetsUnit); + if (octets) + nl_dump(p, "%14.2f %3s\n", octets, octetsUnit); + else + nl_dump(p, "%16" PRIu64 " B\n", 0); + + nl_dump(p, " ReasmOKs ReasmFails " + " ReasmReqds ReasmTimeout\n"); + nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n", + link->l_stats[RTNL_LINK_IP6_REASMOKS], + link->l_stats[RTNL_LINK_IP6_REASMFAILS], + link->l_stats[RTNL_LINK_IP6_REASMREQDS], + link->l_stats[RTNL_LINK_IP6_REASMTIMEOUT]); + + nl_dump(p, " FragOKs FragFails " + " FragCreates\n"); + nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n", + link->l_stats[RTNL_LINK_IP6_FRAGOKS], + link->l_stats[RTNL_LINK_IP6_FRAGFAILS], + link->l_stats[RTNL_LINK_IP6_FRAGCREATES]); + + nl_dump(p, " InHdrErrors InTooBigErrors " + " InNoRoutes InAddrErrors\n"); + nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n", + link->l_stats[RTNL_LINK_IP6_INHDRERRORS], + link->l_stats[RTNL_LINK_IP6_INTOOBIGERRORS], + link->l_stats[RTNL_LINK_IP6_INNOROUTES], + link->l_stats[RTNL_LINK_IP6_INADDRERRORS]); + + nl_dump(p, " InUnknownProtos InTruncatedPkts " + " OutNoRoutes\n"); + nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n", + link->l_stats[RTNL_LINK_IP6_INUNKNOWNPROTOS], + link->l_stats[RTNL_LINK_IP6_INTRUNCATEDPKTS], + link->l_stats[RTNL_LINK_IP6_OUTNOROUTES]); + + nl_dump(p, " ICMPv6: InMsgs InErrors " + " OutMsgs OutErrors\n"); + nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n", + link->l_stats[RTNL_LINK_ICMP6_INMSGS], + link->l_stats[RTNL_LINK_ICMP6_INERRORS], + link->l_stats[RTNL_LINK_ICMP6_OUTMSGS], + link->l_stats[RTNL_LINK_ICMP6_OUTERRORS]); +} + +static const struct nla_policy protinfo_policy = { + .type = NLA_NESTED, +}; + +static struct rtnl_link_af_ops inet6_ops = { + .ao_family = AF_INET6, + .ao_alloc = &inet6_alloc, + .ao_clone = &inet6_clone, + .ao_free = &inet6_free, + .ao_parse_protinfo = &inet6_parse_protinfo, + .ao_parse_af = &inet6_parse_protinfo, + .ao_dump[NL_DUMP_DETAILS] = &inet6_dump_details, + .ao_dump[NL_DUMP_STATS] = &inet6_dump_stats, + .ao_protinfo_policy = &protinfo_policy, +}; + +static void __init inet6_init(void) +{ + rtnl_link_af_register(&inet6_ops); +} + +static void __exit inet6_exit(void) +{ + rtnl_link_af_unregister(&inet6_ops); +} diff --git a/lib/route/link/vlan.c b/lib/route/link/vlan.c new file mode 100644 index 0000000..9bbe7d5 --- /dev/null +++ b/lib/route/link/vlan.c @@ -0,0 +1,587 @@ +/* + * lib/route/link/vlan.c VLAN Link Info + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2013 Thomas Graf + */ + +/** + * @ingroup link + * @defgroup vlan VLAN + * Virtual LAN link module + * + * @details + * \b Link Type Name: "vlan" + * + * @route_doc{link_vlan, VLAN Documentation} + * + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/** @cond SKIP */ +#define VLAN_HAS_ID (1<<0) +#define VLAN_HAS_FLAGS (1<<1) +#define VLAN_HAS_INGRESS_QOS (1<<2) +#define VLAN_HAS_EGRESS_QOS (1<<3) + +struct vlan_info +{ + uint16_t vi_vlan_id; + uint32_t vi_flags; + uint32_t vi_flags_mask; + uint32_t vi_ingress_qos[VLAN_PRIO_MAX+1]; + uint32_t vi_negress; + uint32_t vi_egress_size; + struct vlan_map * vi_egress_qos; + uint32_t vi_mask; +}; + +/** @endcond */ + +static struct nla_policy vlan_policy[IFLA_VLAN_MAX+1] = { + [IFLA_VLAN_ID] = { .type = NLA_U16 }, + [IFLA_VLAN_FLAGS] = { .minlen = sizeof(struct ifla_vlan_flags) }, + [IFLA_VLAN_INGRESS_QOS] = { .type = NLA_NESTED }, + [IFLA_VLAN_EGRESS_QOS] = { .type = NLA_NESTED }, +}; + +static int vlan_alloc(struct rtnl_link *link) +{ + struct vlan_info *vi; + + if ((vi = calloc(1, sizeof(*vi))) == NULL) + return -NLE_NOMEM; + + link->l_info = vi; + + return 0; +} + +static int vlan_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_VLAN_MAX+1]; + struct vlan_info *vi; + int err; + + NL_DBG(3, "Parsing VLAN link info"); + + if ((err = nla_parse_nested(tb, IFLA_VLAN_MAX, data, vlan_policy)) < 0) + goto errout; + + if ((err = vlan_alloc(link)) < 0) + goto errout; + + vi = link->l_info; + + if (tb[IFLA_VLAN_ID]) { + vi->vi_vlan_id = nla_get_u16(tb[IFLA_VLAN_ID]); + vi->vi_mask |= VLAN_HAS_ID; + } + + if (tb[IFLA_VLAN_FLAGS]) { + struct ifla_vlan_flags flags; + nla_memcpy(&flags, tb[IFLA_VLAN_FLAGS], sizeof(flags)); + + vi->vi_flags = flags.flags; + vi->vi_mask |= VLAN_HAS_FLAGS; + } + + if (tb[IFLA_VLAN_INGRESS_QOS]) { + struct ifla_vlan_qos_mapping *map; + struct nlattr *nla; + int remaining; + + memset(vi->vi_ingress_qos, 0, sizeof(vi->vi_ingress_qos)); + + nla_for_each_nested(nla, tb[IFLA_VLAN_INGRESS_QOS], remaining) { + if (nla_len(nla) < sizeof(*map)) + return -NLE_INVAL; + + map = nla_data(nla); + if (map->from > VLAN_PRIO_MAX) { + return -NLE_INVAL; + } + + vi->vi_ingress_qos[map->from] = map->to; + } + + vi->vi_mask |= VLAN_HAS_INGRESS_QOS; + } + + if (tb[IFLA_VLAN_EGRESS_QOS]) { + struct ifla_vlan_qos_mapping *map; + struct nlattr *nla; + int remaining, i = 0; + + nla_for_each_nested(nla, tb[IFLA_VLAN_EGRESS_QOS], remaining) { + if (nla_len(nla) < sizeof(*map)) + return -NLE_INVAL; + i++; + } + + /* align to have a little reserve */ + vi->vi_egress_size = (i + 32) & ~31; + vi->vi_egress_qos = calloc(vi->vi_egress_size, sizeof(*map)); + if (vi->vi_egress_qos == NULL) + return -NLE_NOMEM; + + i = 0; + nla_for_each_nested(nla, tb[IFLA_VLAN_EGRESS_QOS], remaining) { + map = nla_data(nla); + NL_DBG(4, "Assigning egress qos mapping %d\n", i); + vi->vi_egress_qos[i].vm_from = map->from; + vi->vi_egress_qos[i++].vm_to = map->to; + } + + vi->vi_negress = i; + vi->vi_mask |= VLAN_HAS_EGRESS_QOS; + } + + err = 0; +errout: + return err; +} + +static void vlan_free(struct rtnl_link *link) +{ + struct vlan_info *vi = link->l_info; + + if (vi) { + free(vi->vi_egress_qos); + vi->vi_egress_qos = NULL; + } + + free(vi); + link->l_info = NULL; +} + +static void vlan_dump_line(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct vlan_info *vi = link->l_info; + + nl_dump(p, "vlan-id %d", vi->vi_vlan_id); +} + +static void vlan_dump_details(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct vlan_info *vi = link->l_info; + int printed; + uint32_t i; + char buf[64]; + + rtnl_link_vlan_flags2str(vi->vi_flags, buf, sizeof(buf)); + nl_dump_line(p, " vlan-info id %d <%s>\n", vi->vi_vlan_id, buf); + + if (vi->vi_mask & VLAN_HAS_INGRESS_QOS) { + nl_dump_line(p, + " ingress vlan prio -> qos/socket prio mapping:\n"); + for (i = 0, printed = 0; i <= VLAN_PRIO_MAX; i++) { + if (vi->vi_ingress_qos[i]) { + if (printed == 0) + nl_dump_line(p, " "); + nl_dump(p, "%x -> %#08x, ", + i, vi->vi_ingress_qos[i]); + if (printed++ == 3) { + nl_dump(p, "\n"); + printed = 0; + } + } + } + + if (printed > 0 && printed != 4) + nl_dump(p, "\n"); + } + + if (vi->vi_mask & VLAN_HAS_EGRESS_QOS) { + nl_dump_line(p, + " egress qos/socket prio -> vlan prio mapping:\n"); + for (i = 0, printed = 0; i < vi->vi_negress; i++) { + if (printed == 0) + nl_dump_line(p, " "); + nl_dump(p, "%#08x -> %x, ", + vi->vi_egress_qos[i].vm_from, + vi->vi_egress_qos[i].vm_to); + if (printed++ == 3) { + nl_dump(p, "\n"); + printed = 0; + } + } + + if (printed > 0 && printed != 4) + nl_dump(p, "\n"); + } +} + +static int vlan_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct vlan_info *vdst, *vsrc = src->l_info; + int err; + + dst->l_info = NULL; + if ((err = rtnl_link_set_type(dst, "vlan")) < 0) + return err; + vdst = dst->l_info; + + vdst->vi_egress_qos = calloc(vsrc->vi_egress_size, + sizeof(struct vlan_map)); + if (!vdst->vi_egress_qos) + return -NLE_NOMEM; + + memcpy(vdst->vi_egress_qos, vsrc->vi_egress_qos, + vsrc->vi_egress_size * sizeof(struct vlan_map)); + + return 0; +} + +static int vlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct vlan_info *vi = link->l_info; + struct nlattr *data; + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + return -NLE_MSGSIZE; + + if (vi->vi_mask & VLAN_HAS_ID) + NLA_PUT_U16(msg, IFLA_VLAN_ID, vi->vi_vlan_id); + + if (vi->vi_mask & VLAN_HAS_FLAGS) { + struct ifla_vlan_flags flags = { + .flags = vi->vi_flags, + .mask = vi->vi_flags_mask, + }; + + NLA_PUT(msg, IFLA_VLAN_FLAGS, sizeof(flags), &flags); + } + + if (vi->vi_mask & VLAN_HAS_INGRESS_QOS) { + struct ifla_vlan_qos_mapping map; + struct nlattr *qos; + int i; + + if (!(qos = nla_nest_start(msg, IFLA_VLAN_INGRESS_QOS))) + goto nla_put_failure; + + for (i = 0; i <= VLAN_PRIO_MAX; i++) { + if (vi->vi_ingress_qos[i]) { + map.from = i; + map.to = vi->vi_ingress_qos[i]; + + NLA_PUT(msg, i, sizeof(map), &map); + } + } + + nla_nest_end(msg, qos); + } + + if (vi->vi_mask & VLAN_HAS_EGRESS_QOS) { + struct ifla_vlan_qos_mapping map; + struct nlattr *qos; + uint32_t i; + + if (!(qos = nla_nest_start(msg, IFLA_VLAN_EGRESS_QOS))) + goto nla_put_failure; + + for (i = 0; i < vi->vi_negress; i++) { + map.from = vi->vi_egress_qos[i].vm_from; + map.to = vi->vi_egress_qos[i].vm_to; + + NLA_PUT(msg, i, sizeof(map), &map); + } + + nla_nest_end(msg, qos); + } + + nla_nest_end(msg, data); + +nla_put_failure: + + return 0; +} + +static struct rtnl_link_info_ops vlan_info_ops = { + .io_name = "vlan", + .io_alloc = vlan_alloc, + .io_parse = vlan_parse, + .io_dump = { + [NL_DUMP_LINE] = vlan_dump_line, + [NL_DUMP_DETAILS] = vlan_dump_details, + }, + .io_clone = vlan_clone, + .io_put_attrs = vlan_put_attrs, + .io_free = vlan_free, +}; + +/** @cond SKIP */ +#define IS_VLAN_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &vlan_info_ops) { \ + APPBUG("Link is not a vlan link. set type \"vlan\" first."); \ + return -NLE_OPNOTSUPP; \ + } +/** @endcond */ + +/** + * @name VLAN Object + * @{ + */ + +/** + * Allocate link object of type VLAN + * + * @return Allocated link object or NULL. + */ +struct rtnl_link *rtnl_link_vlan_alloc(void) +{ + struct rtnl_link *link; + int err; + + if (!(link = rtnl_link_alloc())) + return NULL; + + if ((err = rtnl_link_set_type(link, "vlan")) < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if link is a VLAN link + * @arg link Link object + * + * @return True if link is a VLAN link, otherwise false is returned. + */ +int rtnl_link_is_vlan(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "vlan"); +} + +/** + * Set VLAN ID + * @arg link Link object + * @arg id VLAN identifier + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vlan_set_id(struct rtnl_link *link, uint16_t id) +{ + struct vlan_info *vi = link->l_info; + + IS_VLAN_LINK_ASSERT(link); + + vi->vi_vlan_id = id; + vi->vi_mask |= VLAN_HAS_ID; + + return 0; +} + +/** + * Get VLAN Id + * @arg link Link object + * + * @return VLAN id, 0 if not set or a negative error code. + */ +int rtnl_link_vlan_get_id(struct rtnl_link *link) +{ + struct vlan_info *vi = link->l_info; + + IS_VLAN_LINK_ASSERT(link); + + if (vi->vi_mask & VLAN_HAS_ID) + return vi->vi_vlan_id; + else + return 0; +} + +/** + * Set VLAN flags + * @arg link Link object + * @arg flags VLAN flags + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_vlan_set_flags(struct rtnl_link *link, unsigned int flags) +{ + struct vlan_info *vi = link->l_info; + + IS_VLAN_LINK_ASSERT(link); + + vi->vi_flags_mask |= flags; + vi->vi_flags |= flags; + vi->vi_mask |= VLAN_HAS_FLAGS; + + return 0; +} + +/** + * Unset VLAN flags + * @arg link Link object + * @arg flags VLAN flags + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_vlan_unset_flags(struct rtnl_link *link, unsigned int flags) +{ + struct vlan_info *vi = link->l_info; + + IS_VLAN_LINK_ASSERT(link); + + vi->vi_flags_mask |= flags; + vi->vi_flags &= ~flags; + vi->vi_mask |= VLAN_HAS_FLAGS; + + return 0; +} + +/** + * Get VLAN flags + * @arg link Link object + * + * @return VLAN flags, 0 if none set, or a negative error code. + */ +int rtnl_link_vlan_get_flags(struct rtnl_link *link) +{ + struct vlan_info *vi = link->l_info; + + IS_VLAN_LINK_ASSERT(link); + + return vi->vi_flags; +} + +/** @} */ + +/** + * @name Quality of Service + * @{ + */ + +int rtnl_link_vlan_set_ingress_map(struct rtnl_link *link, int from, + uint32_t to) +{ + struct vlan_info *vi = link->l_info; + + IS_VLAN_LINK_ASSERT(link); + + if (from < 0 || from > VLAN_PRIO_MAX) + return -NLE_INVAL; + + vi->vi_ingress_qos[from] = to; + vi->vi_mask |= VLAN_HAS_INGRESS_QOS; + + return 0; +} + +uint32_t *rtnl_link_vlan_get_ingress_map(struct rtnl_link *link) +{ + struct vlan_info *vi = link->l_info; + + if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) + return NULL; + + if (vi->vi_mask & VLAN_HAS_INGRESS_QOS) + return vi->vi_ingress_qos; + else + return NULL; +} + +int rtnl_link_vlan_set_egress_map(struct rtnl_link *link, uint32_t from, int to) +{ + struct vlan_info *vi = link->l_info; + + if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) + return -NLE_OPNOTSUPP; + + if (to < 0 || to > VLAN_PRIO_MAX) + return -NLE_INVAL; + + if (vi->vi_negress >= vi->vi_egress_size) { + int new_size = vi->vi_egress_size + 32; + void *ptr; + + ptr = realloc(vi->vi_egress_qos, new_size); + if (!ptr) + return -NLE_NOMEM; + + vi->vi_egress_qos = ptr; + vi->vi_egress_size = new_size; + } + + vi->vi_egress_qos[vi->vi_negress].vm_from = from; + vi->vi_egress_qos[vi->vi_negress].vm_to = to; + vi->vi_negress++; + vi->vi_mask |= VLAN_HAS_EGRESS_QOS; + + return 0; +} + +struct vlan_map *rtnl_link_vlan_get_egress_map(struct rtnl_link *link, + int *negress) +{ + struct vlan_info *vi = link->l_info; + + if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) + return NULL; + + if (negress == NULL) + return NULL; + + if (vi->vi_mask & VLAN_HAS_EGRESS_QOS) { + *negress = vi->vi_negress; + return vi->vi_egress_qos; + } else { + *negress = 0; + return NULL; + } +} + +/** @} */ + +static const struct trans_tbl vlan_flags[] = { + __ADD(VLAN_FLAG_REORDER_HDR, reorder_hdr) +}; + +/** + * @name Flag Translation + * @{ + */ + +char *rtnl_link_vlan_flags2str(int flags, char *buf, size_t len) +{ + return __flags2str(flags, buf, len, vlan_flags, ARRAY_SIZE(vlan_flags)); +} + +int rtnl_link_vlan_str2flags(const char *name) +{ + return __str2flags(name, vlan_flags, ARRAY_SIZE(vlan_flags)); +} + +/** @} */ + + +static void __init vlan_init(void) +{ + rtnl_link_register_info(&vlan_info_ops); +} + +static void __exit vlan_exit(void) +{ + rtnl_link_unregister_info(&vlan_info_ops); +} + +/** @} */ diff --git a/lib/route/neigh.c b/lib/route/neigh.c new file mode 100644 index 0000000..ad26b4d --- /dev/null +++ b/lib/route/neigh.c @@ -0,0 +1,962 @@ +/* + * lib/route/neigh.c Neighbours + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + */ + +/** + * @ingroup rtnl + * @defgroup neigh Neighbours + * @brief + * + * The neighbour table establishes bindings between protocol addresses and + * link layer addresses for hosts sharing the same physical link. This + * module allows you to access and manipulate the content of these tables. + * + * @par Neighbour States + * @code + * NUD_INCOMPLETE + * NUD_REACHABLE + * NUD_STALE + * NUD_DELAY + * NUD_PROBE + * NUD_FAILED + * NUD_NOARP + * NUD_PERMANENT + * @endcode + * + * @par Neighbour Flags + * @code + * NTF_USE + * NTF_PROXY + * NTF_ROUTER + * @endcode + * + * @par Neighbour Identification + * A neighbour is uniquely identified by the attributes listed below, whenever + * you refer to an existing neighbour all of the attributes must be set. + * Neighbours from caches automatically have all required attributes set. + * - interface index (rtnl_neigh_set_ifindex()) + * - destination address (rtnl_neigh_set_dst()) + * + * @par Changeable Attributes + * \anchor neigh_changeable + * - state (rtnl_neigh_set_state()) + * - link layer address (rtnl_neigh_set_lladdr()) + * + * @par Required Caches for Dumping + * In order to dump neighbour attributes you must provide the following + * caches via nl_cache_provide() + * - link cache holding all links + * + * @par TODO + * - Document proxy settings + * - Document states and their influence + * + * @par 1) Retrieving information about configured neighbours + * @code + * // The first step is to retrieve a list of all available neighbour within + * // the kernel and put them into a cache. + * struct nl_cache *cache = rtnl_neigh_alloc_cache(sk); + * + * // Neighbours can then be looked up by the interface and destination + * // address: + * struct rtnl_neigh *neigh = rtnl_neigh_get(cache, ifindex, dst_addr); + * + * // After successful usage, the object must be given back to the cache + * rtnl_neigh_put(neigh); + * @endcode + * + * @par 2) Adding new neighbours + * @code + * // Allocate an empty neighbour handle to be filled out with the attributes + * // of the new neighbour. + * struct rtnl_neigh *neigh = rtnl_neigh_alloc(); + * + * // Fill out the attributes of the new neighbour + * rtnl_neigh_set_ifindex(neigh, ifindex); + * rtnl_neigh_set_dst(neigh, dst_addr); + * rtnl_neigh_set_state(neigh, rtnl_neigh_str2state("permanent")); + * + * // Build the netlink message and send it to the kernel, the operation will + * // block until the operation has been completed. Alternatively the required + * // netlink message can be built using rtnl_neigh_build_add_request() + * // to be sent out using nl_send_auto_complete(). + * rtnl_neigh_add(sk, neigh, NLM_F_CREATE); + * + * // Free the memory + * rtnl_neigh_put(neigh); + * @endcode + * + * @par 3) Deleting an existing neighbour + * @code + * // Allocate an empty neighbour object to be filled out with the attributes + * // matching the neighbour to be deleted. Alternatively a fully equipped + * // neighbour object out of a cache can be used instead. + * struct rtnl_neigh *neigh = rtnl_neigh_alloc(); + * + * // Neighbours are uniquely identified by their interface index and + * // destination address, you may fill out other attributes but they + * // will have no influence. + * rtnl_neigh_set_ifindex(neigh, ifindex); + * rtnl_neigh_set_dst(neigh, dst_addr); + * + * // Build the netlink message and send it to the kernel, the operation will + * // block until the operation has been completed. Alternatively the required + * // netlink message can be built using rtnl_neigh_build_delete_request() + * // to be sent out using nl_send_auto_complete(). + * rtnl_neigh_delete(sk, neigh, 0); + * + * // Free the memory + * rtnl_neigh_put(neigh); + * @endcode + * + * @par 4) Changing neighbour attributes + * @code + * // Allocate an empty neighbour object to be filled out with the attributes + * // matching the neighbour to be changed and the new parameters. Alternatively + * // a fully equipped modified neighbour object out of a cache can be used. + * struct rtnl_neigh *neigh = rtnl_neigh_alloc(); + * + * // Identify the neighbour to be changed by its interface index and + * // destination address + * rtnl_neigh_set_ifindex(neigh, ifindex); + * rtnl_neigh_set_dst(neigh, dst_addr); + * + * // The link layer address may be modified, if so it is wise to change + * // its state to "permanent" in order to avoid having it overwritten. + * rtnl_neigh_set_lladdr(neigh, lladdr); + * + * // Secondly the state can be modified allowing normal neighbours to be + * // converted into permanent entries or to manually confirm a neighbour. + * rtnl_neigh_set_state(neigh, state); + * + * // Build the netlink message and send it to the kernel, the operation will + * // block until the operation has been completed. Alternatively the required + * // netlink message can be built using rtnl_neigh_build_change_request() + * // to be sent out using nl_send_auto_complete(). + * rtnl_neigh_add(sk, neigh, NLM_F_REPLACE); + * + * // Free the memory + * rtnl_neigh_put(neigh); + * @endcode + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define NEIGH_ATTR_FLAGS 0x01 +#define NEIGH_ATTR_STATE 0x02 +#define NEIGH_ATTR_LLADDR 0x04 +#define NEIGH_ATTR_DST 0x08 +#define NEIGH_ATTR_CACHEINFO 0x10 +#define NEIGH_ATTR_IFINDEX 0x20 +#define NEIGH_ATTR_FAMILY 0x40 +#define NEIGH_ATTR_TYPE 0x80 +#define NEIGH_ATTR_PROBES 0x100 +#define NEIGH_ATTR_MASTER 0x200 + +static struct nl_cache_ops rtnl_neigh_ops; +static struct nl_object_ops neigh_obj_ops; +/** @endcond */ + +static void neigh_free_data(struct nl_object *c) +{ + struct rtnl_neigh *neigh = nl_object_priv(c); + + if (!neigh) + return; + + nl_addr_put(neigh->n_lladdr); + nl_addr_put(neigh->n_dst); +} + +static int neigh_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct rtnl_neigh *dst = nl_object_priv(_dst); + struct rtnl_neigh *src = nl_object_priv(_src); + + if (src->n_lladdr) + if (!(dst->n_lladdr = nl_addr_clone(src->n_lladdr))) + return -NLE_NOMEM; + + if (src->n_dst) + if (!(dst->n_dst = nl_addr_clone(src->n_dst))) + return -NLE_NOMEM; + + return 0; +} + +static void neigh_keygen(struct nl_object *obj, uint32_t *hashkey, + uint32_t table_sz) +{ + struct rtnl_neigh *neigh = (struct rtnl_neigh *) obj; + unsigned int nkey_sz; + struct nl_addr *addr = NULL; + struct neigh_hash_key { + uint32_t n_family; + uint32_t n_ifindex; + char n_addr[0]; + } __attribute__((packed)) *nkey; +#ifdef NL_DEBUG + char buf[INET6_ADDRSTRLEN+5]; +#endif + + if (neigh->n_family == AF_BRIDGE) { + if (neigh->n_lladdr) + addr = neigh->n_lladdr; + } else if (neigh->n_dst) { + addr = neigh->n_dst; + } + + nkey_sz = sizeof(*nkey); + if (addr) + nkey_sz += nl_addr_get_len(addr); + + nkey = calloc(1, nkey_sz); + if (!nkey) { + *hashkey = 0; + return; + } + nkey->n_family = neigh->n_family; + if (neigh->n_family == AF_BRIDGE) + nkey->n_ifindex = neigh->n_master; + else + nkey->n_ifindex = neigh->n_ifindex; + if (addr) + memcpy(nkey->n_addr, + nl_addr_get_binary_addr(addr), + nl_addr_get_len(addr)); + + *hashkey = nl_hash(nkey, nkey_sz, 0) % table_sz; + + NL_DBG(5, "neigh %p key (fam %d dev %d addr %s) keysz %d hash 0x%x\n", + neigh, nkey->n_family, nkey->n_ifindex, + nl_addr2str(addr, buf, sizeof(buf)), + nkey_sz, *hashkey); + + free(nkey); + + return; +} + +static int neigh_compare(struct nl_object *_a, struct nl_object *_b, + uint32_t attrs, int flags) +{ + struct rtnl_neigh *a = (struct rtnl_neigh *) _a; + struct rtnl_neigh *b = (struct rtnl_neigh *) _b; + int diff = 0; + +#define NEIGH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGH_ATTR_##ATTR, a, b, EXPR) + + diff |= NEIGH_DIFF(IFINDEX, a->n_ifindex != b->n_ifindex); + diff |= NEIGH_DIFF(FAMILY, a->n_family != b->n_family); + diff |= NEIGH_DIFF(TYPE, a->n_type != b->n_type); + diff |= NEIGH_DIFF(LLADDR, nl_addr_cmp(a->n_lladdr, b->n_lladdr)); + diff |= NEIGH_DIFF(DST, nl_addr_cmp(a->n_dst, b->n_dst)); + diff |= NEIGH_DIFF(MASTER, a->n_master != b->n_master); + + if (flags & LOOSE_COMPARISON) { + diff |= NEIGH_DIFF(STATE, + (a->n_state ^ b->n_state) & b->n_state_mask); + diff |= NEIGH_DIFF(FLAGS, + (a->n_flags ^ b->n_flags) & b->n_flag_mask); + } else { + diff |= NEIGH_DIFF(STATE, a->n_state != b->n_state); + diff |= NEIGH_DIFF(FLAGS, a->n_flags != b->n_flags); + } + +#undef NEIGH_DIFF + + return diff; +} + +static const struct trans_tbl neigh_attrs[] = { + __ADD(NEIGH_ATTR_FLAGS, flags) + __ADD(NEIGH_ATTR_STATE, state) + __ADD(NEIGH_ATTR_LLADDR, lladdr) + __ADD(NEIGH_ATTR_DST, dst) + __ADD(NEIGH_ATTR_CACHEINFO, cacheinfo) + __ADD(NEIGH_ATTR_IFINDEX, ifindex) + __ADD(NEIGH_ATTR_FAMILY, family) + __ADD(NEIGH_ATTR_TYPE, type) + __ADD(NEIGH_ATTR_PROBES, probes) +}; + +static char *neigh_attrs2str(int attrs, char *buf, size_t len) +{ + return __flags2str(attrs, buf, len, neigh_attrs, + ARRAY_SIZE(neigh_attrs)); +} + +static uint32_t neigh_id_attrs_get(struct nl_object *obj) +{ + struct rtnl_neigh *neigh = (struct rtnl_neigh *)obj; + + if (neigh->n_family == AF_BRIDGE) + return (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY | NEIGH_ATTR_MASTER); + else + return (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY); +} + +static struct nla_policy neigh_policy[NDA_MAX+1] = { + [NDA_CACHEINFO] = { .minlen = sizeof(struct nda_cacheinfo) }, + [NDA_PROBES] = { .type = NLA_U32 }, +}; + +static int neigh_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *n, struct nl_parser_param *pp) +{ + struct rtnl_neigh *neigh; + int err; + + if ((err = rtnl_neigh_parse(n, &neigh)) < 0) + return err; + + err = pp->pp_cb((struct nl_object *) neigh, pp); + + rtnl_neigh_put(neigh); + return err; +} + + +int rtnl_neigh_parse(struct nlmsghdr *n, struct rtnl_neigh **result) +{ + struct rtnl_neigh *neigh; + struct nlattr *tb[NDA_MAX + 1]; + struct ndmsg *nm; + int err; + + neigh = rtnl_neigh_alloc(); + if (!neigh) { + err = -NLE_NOMEM; + goto errout; + } + + neigh->ce_msgtype = n->nlmsg_type; + nm = nlmsg_data(n); + + err = nlmsg_parse(n, sizeof(*nm), tb, NDA_MAX, neigh_policy); + if (err < 0) + goto errout; + + neigh->n_family = nm->ndm_family; + neigh->n_ifindex = nm->ndm_ifindex; + neigh->n_state = nm->ndm_state; + neigh->n_flags = nm->ndm_flags; + neigh->n_type = nm->ndm_type; + + neigh->ce_mask |= (NEIGH_ATTR_FAMILY | NEIGH_ATTR_IFINDEX | + NEIGH_ATTR_STATE | NEIGH_ATTR_FLAGS | + NEIGH_ATTR_TYPE); + + if (tb[NDA_LLADDR]) { + neigh->n_lladdr = nl_addr_alloc_attr(tb[NDA_LLADDR], AF_UNSPEC); + if (!neigh->n_lladdr) { + err = -NLE_NOMEM; + goto errout; + } + nl_addr_set_family(neigh->n_lladdr, + nl_addr_guess_family(neigh->n_lladdr)); + neigh->ce_mask |= NEIGH_ATTR_LLADDR; + } + + if (tb[NDA_DST]) { + neigh->n_dst = nl_addr_alloc_attr(tb[NDA_DST], neigh->n_family); + if (!neigh->n_dst) { + err = -NLE_NOMEM; + goto errout; + } + neigh->ce_mask |= NEIGH_ATTR_DST; + } + + if (tb[NDA_CACHEINFO]) { + struct nda_cacheinfo *ci = nla_data(tb[NDA_CACHEINFO]); + + neigh->n_cacheinfo.nci_confirmed = ci->ndm_confirmed; + neigh->n_cacheinfo.nci_used = ci->ndm_used; + neigh->n_cacheinfo.nci_updated = ci->ndm_updated; + neigh->n_cacheinfo.nci_refcnt = ci->ndm_refcnt; + + neigh->ce_mask |= NEIGH_ATTR_CACHEINFO; + } + + if (tb[NDA_PROBES]) { + neigh->n_probes = nla_get_u32(tb[NDA_PROBES]); + neigh->ce_mask |= NEIGH_ATTR_PROBES; + } + + /* + * Get the bridge index for AF_BRIDGE family entries + */ + if (neigh->n_family == AF_BRIDGE) { + struct nl_cache *lcache = nl_cache_mngt_require_safe("route/link"); + if (lcache ) { + struct rtnl_link *link = rtnl_link_get(lcache, + neigh->n_ifindex); + if (link) { + neigh->n_master = link->l_master; + rtnl_link_put(link); + neigh->ce_mask |= NEIGH_ATTR_MASTER; + } + + nl_cache_put(lcache); + } + } + + *result = neigh; + return 0; + +errout: + rtnl_neigh_put(neigh); + return err; +} + +static int neigh_request_update(struct nl_cache *c, struct nl_sock *h) +{ + int family = c->c_iarg1; + + return nl_rtgen_request(h, RTM_GETNEIGH, family, NLM_F_DUMP); +} + + +static void neigh_dump_line(struct nl_object *a, struct nl_dump_params *p) +{ + char dst[INET6_ADDRSTRLEN+5], lladdr[INET6_ADDRSTRLEN+5]; + struct rtnl_neigh *n = (struct rtnl_neigh *) a; + struct nl_cache *link_cache; + char state[128], flags[64]; + + link_cache = nl_cache_mngt_require_safe("route/link"); + + if (n->n_family != AF_BRIDGE) + nl_dump_line(p, "%s ", nl_addr2str(n->n_dst, dst, sizeof(dst))); + + if (link_cache) + nl_dump(p, "dev %s ", + rtnl_link_i2name(link_cache, n->n_ifindex, + state, sizeof(state))); + else + nl_dump(p, "dev %d ", n->n_ifindex); + + if (n->ce_mask & NEIGH_ATTR_LLADDR) + nl_dump(p, "lladdr %s ", + nl_addr2str(n->n_lladdr, lladdr, sizeof(lladdr))); + + rtnl_neigh_state2str(n->n_state, state, sizeof(state)); + rtnl_neigh_flags2str(n->n_flags, flags, sizeof(flags)); + + if (state[0]) + nl_dump(p, "<%s", state); + if (flags[0]) + nl_dump(p, "%s%s", state[0] ? "," : "<", flags); + if (state[0] || flags[0]) + nl_dump(p, ">"); + nl_dump(p, "\n"); + + if (link_cache) + nl_cache_put(link_cache); +} + +static void neigh_dump_details(struct nl_object *a, struct nl_dump_params *p) +{ + char rtn_type[32]; + struct rtnl_neigh *n = (struct rtnl_neigh *) a; + int hz = nl_get_user_hz(); + + neigh_dump_line(a, p); + + nl_dump_line(p, " refcnt %u type %s confirmed %u used " + "%u updated %u\n", + n->n_cacheinfo.nci_refcnt, + nl_rtntype2str(n->n_type, rtn_type, sizeof(rtn_type)), + n->n_cacheinfo.nci_confirmed/hz, + n->n_cacheinfo.nci_used/hz, n->n_cacheinfo.nci_updated/hz); +} + +static void neigh_dump_stats(struct nl_object *a, struct nl_dump_params *p) +{ + neigh_dump_details(a, p); +} + +/** + * @name Neighbour Object Allocation/Freeage + * @{ + */ + +struct rtnl_neigh *rtnl_neigh_alloc(void) +{ + return (struct rtnl_neigh *) nl_object_alloc(&neigh_obj_ops); +} + +void rtnl_neigh_put(struct rtnl_neigh *neigh) +{ + nl_object_put((struct nl_object *) neigh); +} + +/** @} */ + +/** + * @name Neighbour Cache Managament + * @{ + */ + +/** + * Build a neighbour cache including all neighbours currently configured in the kernel. + * @arg sock Netlink socket. + * @arg result Pointer to store resulting cache. + * + * Allocates a new neighbour cache, initializes it properly and updates it + * to include all neighbours currently configured in the kernel. + * + * @return 0 on success or a negative error code. + */ +int rtnl_neigh_alloc_cache(struct nl_sock *sock, struct nl_cache **result) +{ + return nl_cache_alloc_and_fill(&rtnl_neigh_ops, sock, result); +} + +/** + * Look up a neighbour by interface index and destination address + * @arg cache neighbour cache + * @arg ifindex interface index the neighbour is on + * @arg dst destination address of the neighbour + * + * @return neighbour handle or NULL if no match was found. + */ +struct rtnl_neigh * rtnl_neigh_get(struct nl_cache *cache, int ifindex, + struct nl_addr *dst) +{ + struct rtnl_neigh *neigh; + + nl_list_for_each_entry(neigh, &cache->c_items, ce_list) { + if (neigh->n_ifindex == ifindex && + !nl_addr_cmp(neigh->n_dst, dst)) { + nl_object_get((struct nl_object *) neigh); + return neigh; + } + } + + return NULL; +} + +/** @} */ + +/** + * @name Neighbour Addition + * @{ + */ + +static int build_neigh_msg(struct rtnl_neigh *tmpl, int cmd, int flags, + struct nl_msg **result) +{ + struct nl_msg *msg; + struct ndmsg nhdr = { + .ndm_ifindex = tmpl->n_ifindex, + .ndm_state = NUD_PERMANENT, + }; + + if (tmpl->n_family != AF_BRIDGE) { + if (!(tmpl->ce_mask & NEIGH_ATTR_DST)) + return -NLE_MISSING_ATTR; + nhdr.ndm_family = nl_addr_get_family(tmpl->n_dst); + } + else + nhdr.ndm_family = AF_BRIDGE; + + if (tmpl->ce_mask & NEIGH_ATTR_FLAGS) + nhdr.ndm_flags = tmpl->n_flags; + + if (tmpl->ce_mask & NEIGH_ATTR_STATE) + nhdr.ndm_state = tmpl->n_state; + + msg = nlmsg_alloc_simple(cmd, flags); + if (!msg) + return -NLE_NOMEM; + + if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if (tmpl->n_family != AF_BRIDGE) + NLA_PUT_ADDR(msg, NDA_DST, tmpl->n_dst); + + if (tmpl->ce_mask & NEIGH_ATTR_LLADDR) + NLA_PUT_ADDR(msg, NDA_LLADDR, tmpl->n_lladdr); + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +/** + * Build netlink request message to add a new neighbour + * @arg tmpl template with data of new neighbour + * @arg flags additional netlink message flags + * @arg result Pointer to store resulting message. + * + * Builds a new netlink message requesting a addition of a new + * neighbour. The netlink message header isn't fully equipped with + * all relevant fields and must thus be sent out via nl_send_auto_complete() + * or supplemented as needed. \a tmpl must contain the attributes of the new + * neighbour set via \c rtnl_neigh_set_* functions. + * + * The following attributes must be set in the template: + * - Interface index (rtnl_neigh_set_ifindex()) + * - State (rtnl_neigh_set_state()) + * - Destination address (rtnl_neigh_set_dst()) + * - Link layer address (rtnl_neigh_set_lladdr()) + * + * @return 0 on success or a negative error code. + */ +int rtnl_neigh_build_add_request(struct rtnl_neigh *tmpl, int flags, + struct nl_msg **result) +{ + return build_neigh_msg(tmpl, RTM_NEWNEIGH, flags, result); +} + +/** + * Add a new neighbour + * @arg sk Netlink socket. + * @arg tmpl template with requested changes + * @arg flags additional netlink message flags + * + * Builds a netlink message by calling rtnl_neigh_build_add_request(), + * sends the request to the kernel and waits for the next ACK to be + * received and thus blocks until the request has been fullfilled. + * + * The following attributes must be set in the template: + * - Interface index (rtnl_neigh_set_ifindex()) + * - State (rtnl_neigh_set_state()) + * - Destination address (rtnl_neigh_set_dst()) + * - Link layer address (rtnl_neigh_set_lladdr()) + * + * @return 0 on sucess or a negative error if an error occured. + */ +int rtnl_neigh_add(struct nl_sock *sk, struct rtnl_neigh *tmpl, int flags) +{ + int err; + struct nl_msg *msg; + + if ((err = rtnl_neigh_build_add_request(tmpl, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +/** @} */ + +/** + * @name Neighbour Deletion + * @{ + */ + +/** + * Build a netlink request message to delete a neighbour + * @arg neigh neighbour to delete + * @arg flags additional netlink message flags + * @arg result Pointer to store resulting message. + * + * Builds a new netlink message requesting a deletion of a neighbour. + * The netlink message header isn't fully equipped with all relevant + * fields and must thus be sent out via nl_send_auto_complete() + * or supplemented as needed. \a neigh must point to an existing + * neighbour. + * + * @return 0 on success or a negative error code. + */ +int rtnl_neigh_build_delete_request(struct rtnl_neigh *neigh, int flags, + struct nl_msg **result) +{ + return build_neigh_msg(neigh, RTM_DELNEIGH, flags, result); +} + +/** + * Delete a neighbour + * @arg sk Netlink socket. + * @arg neigh neighbour to delete + * @arg flags additional netlink message flags + * + * Builds a netlink message by calling rtnl_neigh_build_delete_request(), + * sends the request to the kernel and waits for the next ACK to be + * received and thus blocks until the request has been fullfilled. + * + * @return 0 on sucess or a negative error if an error occured. + */ +int rtnl_neigh_delete(struct nl_sock *sk, struct rtnl_neigh *neigh, + int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_neigh_build_delete_request(neigh, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +/** @} */ + +/** + * @name Neighbour States Translations + * @{ + */ + +static const struct trans_tbl neigh_states[] = { + __ADD(NUD_INCOMPLETE, incomplete) + __ADD(NUD_REACHABLE, reachable) + __ADD(NUD_STALE, stale) + __ADD(NUD_DELAY, delay) + __ADD(NUD_PROBE, probe) + __ADD(NUD_FAILED, failed) + __ADD(NUD_NOARP, norarp) + __ADD(NUD_PERMANENT, permanent) +}; + +char * rtnl_neigh_state2str(int state, char *buf, size_t len) +{ + return __flags2str(state, buf, len, neigh_states, + ARRAY_SIZE(neigh_states)); +} + +int rtnl_neigh_str2state(const char *name) +{ + return __str2type(name, neigh_states, ARRAY_SIZE(neigh_states)); +} + +/** @} */ + +/** + * @name Neighbour Flags Translations + * @{ + */ + +static const struct trans_tbl neigh_flags[] = { + __ADD(NTF_USE, use) + __ADD(NTF_PROXY, proxy) + __ADD(NTF_ROUTER, router) +}; + +char * rtnl_neigh_flags2str(int flags, char *buf, size_t len) +{ + return __flags2str(flags, buf, len, neigh_flags, + ARRAY_SIZE(neigh_flags)); +} + +int rtnl_neigh_str2flag(const char *name) +{ + return __str2type(name, neigh_flags, ARRAY_SIZE(neigh_flags)); +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ + +void rtnl_neigh_set_state(struct rtnl_neigh *neigh, int state) +{ + neigh->n_state_mask |= state; + neigh->n_state |= state; + neigh->ce_mask |= NEIGH_ATTR_STATE; +} + +int rtnl_neigh_get_state(struct rtnl_neigh *neigh) +{ + if (neigh->ce_mask & NEIGH_ATTR_STATE) + return neigh->n_state; + else + return -1; +} + +void rtnl_neigh_unset_state(struct rtnl_neigh *neigh, int state) +{ + neigh->n_state_mask |= state; + neigh->n_state &= ~state; + neigh->ce_mask |= NEIGH_ATTR_STATE; +} + +void rtnl_neigh_set_flags(struct rtnl_neigh *neigh, unsigned int flags) +{ + neigh->n_flag_mask |= flags; + neigh->n_flags |= flags; + neigh->ce_mask |= NEIGH_ATTR_FLAGS; +} + +unsigned int rtnl_neigh_get_flags(struct rtnl_neigh *neigh) +{ + return neigh->n_flags; +} + +void rtnl_neigh_unset_flags(struct rtnl_neigh *neigh, unsigned int flags) +{ + neigh->n_flag_mask |= flags; + neigh->n_flags &= ~flags; + neigh->ce_mask |= NEIGH_ATTR_FLAGS; +} + +void rtnl_neigh_set_ifindex(struct rtnl_neigh *neigh, int ifindex) +{ + neigh->n_ifindex = ifindex; + neigh->ce_mask |= NEIGH_ATTR_IFINDEX; +} + +int rtnl_neigh_get_ifindex(struct rtnl_neigh *neigh) +{ + return neigh->n_ifindex; +} + +static inline int __assign_addr(struct rtnl_neigh *neigh, struct nl_addr **pos, + struct nl_addr *new, int flag, int nocheck) +{ + if (!nocheck) { + if (neigh->ce_mask & NEIGH_ATTR_FAMILY) { + if (new->a_family != neigh->n_family) + return -NLE_AF_MISMATCH; + } else { + neigh->n_family = new->a_family; + neigh->ce_mask |= NEIGH_ATTR_FAMILY; + } + } + + if (*pos) + nl_addr_put(*pos); + + nl_addr_get(new); + *pos = new; + + neigh->ce_mask |= flag; + + return 0; +} + +void rtnl_neigh_set_lladdr(struct rtnl_neigh *neigh, struct nl_addr *addr) +{ + __assign_addr(neigh, &neigh->n_lladdr, addr, NEIGH_ATTR_LLADDR, 1); +} + +struct nl_addr *rtnl_neigh_get_lladdr(struct rtnl_neigh *neigh) +{ + if (neigh->ce_mask & NEIGH_ATTR_LLADDR) + return neigh->n_lladdr; + else + return NULL; +} + +int rtnl_neigh_set_dst(struct rtnl_neigh *neigh, struct nl_addr *addr) +{ + return __assign_addr(neigh, &neigh->n_dst, addr, + NEIGH_ATTR_DST, 0); +} + +struct nl_addr *rtnl_neigh_get_dst(struct rtnl_neigh *neigh) +{ + if (neigh->ce_mask & NEIGH_ATTR_DST) + return neigh->n_dst; + else + return NULL; +} + +void rtnl_neigh_set_family(struct rtnl_neigh *neigh, int family) +{ + neigh->n_family = family; + neigh->ce_mask |= NEIGH_ATTR_FAMILY; +} + +int rtnl_neigh_get_family(struct rtnl_neigh *neigh) +{ + return neigh->n_family; +} + +void rtnl_neigh_set_type(struct rtnl_neigh *neigh, int type) +{ + neigh->n_type = type; + neigh->ce_mask = NEIGH_ATTR_TYPE; +} + +int rtnl_neigh_get_type(struct rtnl_neigh *neigh) +{ + if (neigh->ce_mask & NEIGH_ATTR_TYPE) + return neigh->n_type; + else + return -1; +} + +/** @} */ + +static struct nl_object_ops neigh_obj_ops = { + .oo_name = "route/neigh", + .oo_size = sizeof(struct rtnl_neigh), + .oo_free_data = neigh_free_data, + .oo_clone = neigh_clone, + .oo_dump = { + [NL_DUMP_LINE] = neigh_dump_line, + [NL_DUMP_DETAILS] = neigh_dump_details, + [NL_DUMP_STATS] = neigh_dump_stats, + }, + .oo_compare = neigh_compare, + .oo_keygen = neigh_keygen, + .oo_attrs2str = neigh_attrs2str, + .oo_id_attrs = (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY), + .oo_id_attrs_get = neigh_id_attrs_get +}; + +static struct nl_af_group neigh_groups[] = { + { AF_UNSPEC, RTNLGRP_NEIGH }, + { AF_BRIDGE, RTNLGRP_NEIGH }, + { END_OF_GROUP_LIST }, +}; + +static struct nl_cache_ops rtnl_neigh_ops = { + .co_name = "route/neigh", + .co_hdrsize = sizeof(struct ndmsg), + .co_msgtypes = { + { RTM_NEWNEIGH, NL_ACT_NEW, "new" }, + { RTM_DELNEIGH, NL_ACT_DEL, "del" }, + { RTM_GETNEIGH, NL_ACT_GET, "get" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_ROUTE, + .co_groups = neigh_groups, + .co_request_update = neigh_request_update, + .co_msg_parser = neigh_msg_parser, + .co_obj_ops = &neigh_obj_ops, +}; + +static void __init neigh_init(void) +{ + nl_cache_mngt_register(&rtnl_neigh_ops); +} + +static void __exit neigh_exit(void) +{ + nl_cache_mngt_unregister(&rtnl_neigh_ops); +} + +/** @} */ diff --git a/lib/route/neightbl.c b/lib/route/neightbl.c new file mode 100644 index 0000000..f9c9c27 --- /dev/null +++ b/lib/route/neightbl.c @@ -0,0 +1,827 @@ +/* + * lib/route/neightbl.c neighbour tables + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + */ + +/** + * @ingroup rtnl + * @defgroup neightbl Neighbour Tables + * @brief + * @{ + */ + +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define NEIGHTBL_ATTR_FAMILY 0x001 +#define NEIGHTBL_ATTR_STATS 0x002 +#define NEIGHTBL_ATTR_NAME 0x004 +#define NEIGHTBL_ATTR_THRESH1 0x008 +#define NEIGHTBL_ATTR_THRESH2 0x010 +#define NEIGHTBL_ATTR_THRESH3 0x020 +#define NEIGHTBL_ATTR_CONFIG 0x040 +#define NEIGHTBL_ATTR_PARMS 0x080 +#define NEIGHTBL_ATTR_GC_INTERVAL 0x100 + +#define NEIGHTBLPARM_ATTR_IFINDEX 0x0001 +#define NEIGHTBLPARM_ATTR_REFCNT 0x0002 +#define NEIGHTBLPARM_ATTR_QUEUE_LEN 0x0004 +#define NEIGHTBLPARM_ATTR_APP_PROBES 0x0008 +#define NEIGHTBLPARM_ATTR_UCAST_PROBES 0x0010 +#define NEIGHTBLPARM_ATTR_MCAST_PROBES 0x0020 +#define NEIGHTBLPARM_ATTR_PROXY_QLEN 0x0040 +#define NEIGHTBLPARM_ATTR_REACHABLE_TIME 0x0080 +#define NEIGHTBLPARM_ATTR_BASE_REACHABLE_TIME 0x0100 +#define NEIGHTBLPARM_ATTR_RETRANS_TIME 0x0200 +#define NEIGHTBLPARM_ATTR_GC_STALETIME 0x0400 +#define NEIGHTBLPARM_ATTR_DELAY_PROBE_TIME 0x0800 +#define NEIGHTBLPARM_ATTR_ANYCAST_DELAY 0x1000 +#define NEIGHTBLPARM_ATTR_PROXY_DELAY 0x2000 +#define NEIGHTBLPARM_ATTR_LOCKTIME 0x4000 + +static struct nl_cache_ops rtnl_neightbl_ops; +static struct nl_object_ops neightbl_obj_ops; +/** @endcond */ + +static int neightbl_compare(struct nl_object *_a, struct nl_object *_b, + uint32_t attrs, int flags) +{ + struct rtnl_neightbl *a = (struct rtnl_neightbl *) _a; + struct rtnl_neightbl *b = (struct rtnl_neightbl *) _b; + int diff = 0; + +#define NT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGHTBL_ATTR_##ATTR, a, b, EXPR) + + diff |= NT_DIFF(FAMILY, a->nt_family != b->nt_family); + diff |= NT_DIFF(NAME, strcmp(a->nt_name, b->nt_name)); + diff |= NT_DIFF(THRESH1, a->nt_gc_thresh1 != b->nt_gc_thresh1); + diff |= NT_DIFF(THRESH2, a->nt_gc_thresh2 != b->nt_gc_thresh2); + diff |= NT_DIFF(THRESH3, a->nt_gc_thresh3 != b->nt_gc_thresh3); + diff |= NT_DIFF(GC_INTERVAL, a->nt_gc_interval != b->nt_gc_interval); + +#undef NT_DIFF + + if (!(a->ce_mask & NEIGHTBL_ATTR_PARMS) && + !(b->ce_mask & NEIGHTBL_ATTR_PARMS)) + return diff; + + /* XXX: FIXME: Compare parameter table */ + + +#if 0 +#define REQ(F) (fp->ntp_mask & NEIGHTBLPARM_ATTR_##F) +#define AVAIL(F) (op->ntp_mask & NEIGHTBLPARM_ATTR_##F) +#define _C(F, N) (REQ(F) && (!AVAIL(F) || (op->N != fp->N))) + if (_C(IFINDEX, ntp_ifindex) || + _C(QUEUE_LEN, ntp_queue_len) || + _C(APP_PROBES, ntp_app_probes) || + _C(UCAST_PROBES, ntp_ucast_probes) || + _C(MCAST_PROBES, ntp_mcast_probes) || + _C(PROXY_QLEN, ntp_proxy_qlen) || + _C(LOCKTIME, ntp_locktime) || + _C(RETRANS_TIME, ntp_retrans_time) || + _C(BASE_REACHABLE_TIME, ntp_base_reachable_time) || + _C(GC_STALETIME, ntp_gc_stale_time) || + _C(DELAY_PROBE_TIME, ntp_probe_delay) || + _C(ANYCAST_DELAY, ntp_anycast_delay) || + _C(PROXY_DELAY, ntp_proxy_delay)) + return 0; +#undef REQ +#undef AVAIL +#undef _C +#endif + + return diff; +} + + +static struct nla_policy neightbl_policy[NDTA_MAX+1] = { + [NDTA_NAME] = { .type = NLA_STRING, + .maxlen = NTBLNAMSIZ }, + [NDTA_THRESH1] = { .type = NLA_U32 }, + [NDTA_THRESH2] = { .type = NLA_U32 }, + [NDTA_THRESH3] = { .type = NLA_U32 }, + [NDTA_GC_INTERVAL] = { .type = NLA_U32 }, + [NDTA_CONFIG] = { .minlen = sizeof(struct ndt_config) }, + [NDTA_STATS] = { .minlen = sizeof(struct ndt_stats) }, + [NDTA_PARMS] = { .type = NLA_NESTED }, +}; + +static int neightbl_msg_parser(struct nl_cache_ops *ops, + struct sockaddr_nl *who, struct nlmsghdr *n, + struct nl_parser_param *pp) +{ + struct rtnl_neightbl *ntbl; + struct nlattr *tb[NDTA_MAX + 1]; + struct rtgenmsg *rtmsg; + int err; + + ntbl = rtnl_neightbl_alloc(); + if (!ntbl) { + err = -NLE_NOMEM; + goto errout; + } + + ntbl->ce_msgtype = n->nlmsg_type; + rtmsg = nlmsg_data(n); + + err = nlmsg_parse(n, sizeof(*rtmsg), tb, NDTA_MAX, neightbl_policy); + if (err < 0) + goto errout; + + ntbl->nt_family = rtmsg->rtgen_family; + + if (tb[NDTA_NAME] == NULL) { + err = -NLE_MISSING_ATTR; + goto errout; + } + + nla_strlcpy(ntbl->nt_name, tb[NDTA_NAME], NTBLNAMSIZ); + ntbl->ce_mask |= NEIGHTBL_ATTR_NAME; + + if (tb[NDTA_THRESH1]) { + ntbl->nt_gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]); + ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH1; + } + + if (tb[NDTA_THRESH2]) { + ntbl->nt_gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]); + ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH2; + } + + if (tb[NDTA_THRESH3]) { + ntbl->nt_gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]); + ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH3; + } + + if (tb[NDTA_GC_INTERVAL]) { + ntbl->nt_gc_interval = nla_get_u32(tb[NDTA_GC_INTERVAL]); + ntbl->ce_mask |= NEIGHTBL_ATTR_GC_INTERVAL; + } + + if (tb[NDTA_CONFIG]) { + nla_memcpy(&ntbl->nt_config, tb[NDTA_CONFIG], + sizeof(ntbl->nt_config)); + ntbl->ce_mask |= NEIGHTBL_ATTR_CONFIG; + } + + if (tb[NDTA_STATS]) { + nla_memcpy(&ntbl->nt_stats, tb[NDTA_STATS], + sizeof(ntbl->nt_stats)); + ntbl->ce_mask |= NEIGHTBL_ATTR_STATS; + } + + if (tb[NDTA_PARMS]) { + struct nlattr *tbp[NDTPA_MAX + 1]; + struct rtnl_neightbl_parms *p = &ntbl->nt_parms; + + err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS], NULL); + if (err < 0) + goto errout; + +#define COPY_ENTRY(name, var) \ + if (tbp[NDTPA_ ##name]) { \ + p->ntp_ ##var = nla_get_u32(tbp[NDTPA_ ##name]); \ + p->ntp_mask |= NEIGHTBLPARM_ATTR_ ##name; \ + } + + COPY_ENTRY(IFINDEX, ifindex); + COPY_ENTRY(REFCNT, refcnt); + COPY_ENTRY(QUEUE_LEN, queue_len); + COPY_ENTRY(APP_PROBES, app_probes); + COPY_ENTRY(UCAST_PROBES, ucast_probes); + COPY_ENTRY(MCAST_PROBES, mcast_probes); + COPY_ENTRY(PROXY_QLEN, proxy_qlen); + COPY_ENTRY(PROXY_DELAY, proxy_delay); + COPY_ENTRY(ANYCAST_DELAY, anycast_delay); + COPY_ENTRY(LOCKTIME, locktime); + COPY_ENTRY(REACHABLE_TIME, reachable_time); + COPY_ENTRY(BASE_REACHABLE_TIME, base_reachable_time); + COPY_ENTRY(RETRANS_TIME, retrans_time); + COPY_ENTRY(GC_STALETIME, gc_stale_time); + COPY_ENTRY(DELAY_PROBE_TIME, probe_delay); +#undef COPY_ENTRY + + ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; + } + + err = pp->pp_cb((struct nl_object *) ntbl, pp); +errout: + rtnl_neightbl_put(ntbl); + return err; +} + +static int neightbl_request_update(struct nl_cache *c, struct nl_sock *h) +{ + return nl_rtgen_request(h, RTM_GETNEIGHTBL, AF_UNSPEC, NLM_F_DUMP); +} + + +static void neightbl_dump_line(struct nl_object *arg, struct nl_dump_params *p) +{ + struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *) arg; + + nl_dump_line(p, "%s", ntbl->nt_name); + + if (ntbl->nt_parms.ntp_mask & NEIGHTBLPARM_ATTR_IFINDEX) { + struct nl_cache *link_cache; + + link_cache = nl_cache_mngt_require_safe("route/link"); + + if (link_cache) { + char buf[32]; + nl_dump(p, "<%s> ", + rtnl_link_i2name(link_cache, + ntbl->nt_parms.ntp_ifindex, + buf, sizeof(buf))); + nl_cache_put(link_cache); + } else + nl_dump(p, "<%u> ", ntbl->nt_parms.ntp_ifindex); + } else + nl_dump(p, " "); + + if (ntbl->ce_mask & NEIGHTBL_ATTR_CONFIG) + nl_dump(p, "entries %u ", ntbl->nt_config.ndtc_entries); + + if (ntbl->ce_mask & NEIGHTBL_ATTR_PARMS) { + char rt[32], rt2[32]; + struct rtnl_neightbl_parms *pa = &ntbl->nt_parms; + + nl_dump(p, "reachable-time %s retransmit-time %s", + nl_msec2str(pa->ntp_reachable_time, rt, sizeof(rt)), + nl_msec2str(pa->ntp_retrans_time, rt2, sizeof(rt2))); + } + + nl_dump(p, "\n"); +} + +static void neightbl_dump_details(struct nl_object *arg, struct nl_dump_params *p) +{ + char x[32], y[32], z[32]; + struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *) arg; + + neightbl_dump_line(arg, p); + + if (ntbl->ce_mask & NEIGHTBL_ATTR_CONFIG) { + nl_dump_line(p, " key-len %u entry-size %u last-flush %s\n", + ntbl->nt_config.ndtc_key_len, + ntbl->nt_config.ndtc_entry_size, + nl_msec2str(ntbl->nt_config.ndtc_last_flush, + x, sizeof(x))); + + nl_dump_line(p, " gc threshold %u/%u/%u interval %s " \ + "chain-position %u\n", + ntbl->nt_gc_thresh1, ntbl->nt_gc_thresh2, + ntbl->nt_gc_thresh3, + nl_msec2str(ntbl->nt_gc_interval, x, sizeof(x)), + ntbl->nt_config.ndtc_hash_chain_gc); + + nl_dump_line(p, " hash-rand 0x%08X/0x%08X last-rand %s\n", + ntbl->nt_config.ndtc_hash_rnd, + ntbl->nt_config.ndtc_hash_mask, + nl_msec2str(ntbl->nt_config.ndtc_last_rand, + x, sizeof(x))); + } + + if (ntbl->ce_mask & NEIGHTBL_ATTR_PARMS) { + struct rtnl_neightbl_parms *pa = &ntbl->nt_parms; + + nl_dump_line(p, " refcnt %u pending-queue-limit %u " \ + "proxy-delayed-queue-limit %u\n", + pa->ntp_refcnt, + pa->ntp_queue_len, + pa->ntp_proxy_qlen); + + nl_dump_line(p, " num-userspace-probes %u num-unicast-probes " \ + "%u num-multicast-probes %u\n", + pa->ntp_app_probes, + pa->ntp_ucast_probes, + pa->ntp_mcast_probes); + + nl_dump_line(p, " min-age %s base-reachable-time %s " \ + "stale-check-interval %s\n", + nl_msec2str(pa->ntp_locktime, x, sizeof(x)), + nl_msec2str(pa->ntp_base_reachable_time, + y, sizeof(y)), + nl_msec2str(pa->ntp_gc_stale_time, z, sizeof(z))); + + nl_dump_line(p, " initial-probe-delay %s answer-delay %s " \ + "proxy-answer-delay %s\n", + nl_msec2str(pa->ntp_probe_delay, x, sizeof(x)), + nl_msec2str(pa->ntp_anycast_delay, y, sizeof(y)), + nl_msec2str(pa->ntp_proxy_delay, z, sizeof(z))); + } +} + +static void neightbl_dump_stats(struct nl_object *arg, struct nl_dump_params *p) +{ + struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *) arg; + + neightbl_dump_details(arg, p); + + if (!(ntbl->ce_mask & NEIGHTBL_ATTR_STATS)) + return; + + nl_dump_line(p, " " \ + " lookups %" PRIu64 \ + " hits %" PRIu64 \ + " failed %" PRIu64 \ + " allocations %" PRIu64 \ + " destroys %" PRIu64 \ + "\n", + ntbl->nt_stats.ndts_lookups, + ntbl->nt_stats.ndts_hits, + ntbl->nt_stats.ndts_res_failed, + ntbl->nt_stats.ndts_allocs, + ntbl->nt_stats.ndts_destroys); + + nl_dump_line(p, " " \ + " hash-grows %" PRIu64 \ + " forced-gc-runs %" PRIu64 \ + " periodic-gc-runs %" PRIu64 \ + "\n", + ntbl->nt_stats.ndts_hash_grows, + ntbl->nt_stats.ndts_forced_gc_runs, + ntbl->nt_stats.ndts_periodic_gc_runs); + + nl_dump_line(p, " " \ + " rcv-unicast-probes %" PRIu64 \ + " rcv-multicast-probes %" PRIu64 \ + "\n", + ntbl->nt_stats.ndts_rcv_probes_ucast, + ntbl->nt_stats.ndts_rcv_probes_mcast); +} + +/** + * @name Allocation/Freeing + * @{ + */ + +struct rtnl_neightbl *rtnl_neightbl_alloc(void) +{ + return (struct rtnl_neightbl *) nl_object_alloc(&neightbl_obj_ops); +} + +void rtnl_neightbl_put(struct rtnl_neightbl *neightbl) +{ + nl_object_put((struct nl_object *) neightbl); +} + +/** @} */ + +/** + * @name Neighbour Table Cache Management + * @{ + */ + +/** + * Build a neighbour table cache including all neighbour tables currently configured in the kernel. + * @arg sk Netlink socket. + * @arg result Pointer to store resulting cache. + * + * Allocates a new neighbour table cache, initializes it properly and + * updates it to include all neighbour tables currently configured in + * the kernel. + * + * @return 0 on success or a negative error code. + */ +int rtnl_neightbl_alloc_cache(struct nl_sock *sk, struct nl_cache **result) +{ + return nl_cache_alloc_and_fill(&rtnl_neightbl_ops, sk, result); +} + +/** + * Lookup neighbour table by name and optional interface index + * @arg cache neighbour table cache + * @arg name name of table + * @arg ifindex optional interface index + * + * Looks up the neighbour table matching the specified name and + * optionally the specified ifindex to retrieve device specific + * parameter sets. + * + * @return ptr to neighbour table inside the cache or NULL if no + * match was found. + */ +struct rtnl_neightbl *rtnl_neightbl_get(struct nl_cache *cache, + const char *name, int ifindex) +{ + struct rtnl_neightbl *nt; + + if (cache->c_ops != &rtnl_neightbl_ops) + return NULL; + + nl_list_for_each_entry(nt, &cache->c_items, ce_list) { + if (!strcasecmp(nt->nt_name, name) && + ((!ifindex && !nt->nt_parms.ntp_ifindex) || + (ifindex && ifindex == nt->nt_parms.ntp_ifindex))) { + nl_object_get((struct nl_object *) nt); + return nt; + } + } + + return NULL; +} + +/** @} */ + +/** + * @name Neighbour Table Modifications + * @{ + */ + +/** + * Builds a netlink change request message to change neighbour table attributes + * @arg old neighbour table to change + * @arg tmpl template with requested changes + * @arg result Pointer to store resulting message. + * + * Builds a new netlink message requesting a change of neighbour table + * attributes. The netlink message header isn't fully equipped with all + * relevant fields and must be sent out via nl_send_auto_complete() or + * supplemented as needed. + * \a old must point to a neighbour table currently configured in the + * kernel and \a tmpl must contain the attributes to be changed set via + * \c rtnl_neightbl_set_* functions. + * + * @return 0 on success or a negative error code. + */ +int rtnl_neightbl_build_change_request(struct rtnl_neightbl *old, + struct rtnl_neightbl *tmpl, + struct nl_msg **result) +{ + struct nl_msg *m, *parms = NULL; + struct ndtmsg ndt = { + .ndtm_family = old->nt_family, + }; + + m = nlmsg_alloc_simple(RTM_SETNEIGHTBL, 0); + if (!m) + return -NLE_NOMEM; + + if (nlmsg_append(m, &ndt, sizeof(ndt), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + NLA_PUT_STRING(m, NDTA_NAME, old->nt_name); + + if (tmpl->ce_mask & NEIGHTBL_ATTR_THRESH1) + NLA_PUT_U32(m, NDTA_THRESH1, tmpl->nt_gc_thresh1); + + if (tmpl->ce_mask & NEIGHTBL_ATTR_THRESH2) + NLA_PUT_U32(m, NDTA_THRESH2, tmpl->nt_gc_thresh2); + + if (tmpl->ce_mask & NEIGHTBL_ATTR_THRESH2) + NLA_PUT_U32(m, NDTA_THRESH2, tmpl->nt_gc_thresh2); + + if (tmpl->ce_mask & NEIGHTBL_ATTR_GC_INTERVAL) + NLA_PUT_U64(m, NDTA_GC_INTERVAL, + tmpl->nt_gc_interval); + + if (tmpl->ce_mask & NEIGHTBL_ATTR_PARMS) { + struct rtnl_neightbl_parms *p = &tmpl->nt_parms; + + parms = nlmsg_alloc(); + if (!parms) + goto nla_put_failure; + + if (old->nt_parms.ntp_mask & NEIGHTBLPARM_ATTR_IFINDEX) + NLA_PUT_U32(parms, NDTPA_IFINDEX, + old->nt_parms.ntp_ifindex); + + + if (p->ntp_mask & NEIGHTBLPARM_ATTR_QUEUE_LEN) + NLA_PUT_U32(parms, NDTPA_QUEUE_LEN, p->ntp_queue_len); + + if (p->ntp_mask & NEIGHTBLPARM_ATTR_APP_PROBES) + NLA_PUT_U32(parms, NDTPA_APP_PROBES, p->ntp_app_probes); + + if (p->ntp_mask & NEIGHTBLPARM_ATTR_UCAST_PROBES) + NLA_PUT_U32(parms, NDTPA_UCAST_PROBES, + p->ntp_ucast_probes); + + if (p->ntp_mask & NEIGHTBLPARM_ATTR_MCAST_PROBES) + NLA_PUT_U32(parms, NDTPA_MCAST_PROBES, + p->ntp_mcast_probes); + + if (p->ntp_mask & NEIGHTBLPARM_ATTR_PROXY_QLEN) + NLA_PUT_U32(parms, NDTPA_PROXY_QLEN, + p->ntp_proxy_qlen); + + if (p->ntp_mask & NEIGHTBLPARM_ATTR_BASE_REACHABLE_TIME) + NLA_PUT_U64(parms, NDTPA_BASE_REACHABLE_TIME, + p->ntp_base_reachable_time); + + if (p->ntp_mask & NEIGHTBLPARM_ATTR_RETRANS_TIME) + NLA_PUT_U64(parms, NDTPA_RETRANS_TIME, + p->ntp_retrans_time); + + if (p->ntp_mask & NEIGHTBLPARM_ATTR_GC_STALETIME) + NLA_PUT_U64(parms, NDTPA_GC_STALETIME, + p->ntp_gc_stale_time); + + if (p->ntp_mask & NEIGHTBLPARM_ATTR_DELAY_PROBE_TIME) + NLA_PUT_U64(parms, NDTPA_DELAY_PROBE_TIME, + p->ntp_proxy_delay); + + if (p->ntp_mask & NEIGHTBLPARM_ATTR_ANYCAST_DELAY) + NLA_PUT_U64(parms, NDTPA_ANYCAST_DELAY, + p->ntp_anycast_delay); + + if (p->ntp_mask & NEIGHTBLPARM_ATTR_PROXY_DELAY) + NLA_PUT_U64(parms, NDTPA_PROXY_DELAY, + p->ntp_proxy_delay); + + if (p->ntp_mask & NEIGHTBLPARM_ATTR_LOCKTIME) + NLA_PUT_U64(parms, NDTPA_LOCKTIME, p->ntp_locktime); + + if (nla_put_nested(m, NDTA_PARMS, parms) < 0) + goto nla_put_failure; + + nlmsg_free(parms); + } + + *result = m; + return 0; + +nla_put_failure: + if (parms) + nlmsg_free(parms); + nlmsg_free(m); + return -NLE_MSGSIZE; +} + +/** + * Change neighbour table attributes + * @arg sk Netlink socket. + * @arg old neighbour table to be changed + * @arg tmpl template with requested changes + * + * Builds a new netlink message by calling + * rtnl_neightbl_build_change_request(), sends the request to the + * kernel and waits for the next ACK to be received, i.e. blocks + * until the request has been processed. + * + * @return 0 on success or a negative error code + */ +int rtnl_neightbl_change(struct nl_sock *sk, struct rtnl_neightbl *old, + struct rtnl_neightbl *tmpl) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_neightbl_build_change_request(old, tmpl, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +/** @} */ + +/** + * @name Attribute Modification + * @{ + */ + +void rtnl_neightbl_set_family(struct rtnl_neightbl *ntbl, int family) +{ + ntbl->nt_family = family; + ntbl->ce_mask |= NEIGHTBL_ATTR_FAMILY; +} + +void rtnl_neightbl_set_gc_interval(struct rtnl_neightbl *ntbl, uint64_t ms) +{ + ntbl->nt_gc_interval = ms; + ntbl->ce_mask |= NEIGHTBL_ATTR_GC_INTERVAL; +} + +void rtnl_neightbl_set_gc_tresh1(struct rtnl_neightbl *ntbl, int thresh) +{ + ntbl->nt_gc_thresh1 = thresh; + ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH1; +} + +void rtnl_neightbl_set_gc_tresh2(struct rtnl_neightbl *ntbl, int thresh) +{ + ntbl->nt_gc_thresh2 = thresh; + ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH2; +} + +void rtnl_neightbl_set_gc_tresh3(struct rtnl_neightbl *ntbl, int thresh) +{ + ntbl->nt_gc_thresh3 = thresh; + ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH3; +} + +void rtnl_neightbl_set_name(struct rtnl_neightbl *ntbl, const char *name) +{ + strncpy(ntbl->nt_name, name, sizeof(ntbl->nt_name) - 1); + ntbl->ce_mask |= NEIGHTBL_ATTR_NAME; +} + +void rtnl_neightbl_set_dev(struct rtnl_neightbl *ntbl, int ifindex) +{ + ntbl->nt_parms.ntp_ifindex = ifindex; + ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_IFINDEX; + ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; +} + +/** + * Set the queue length for pending requests of a neighbour table to the specified value + * @arg ntbl neighbour table to change + * @arg len new queue len + */ +void rtnl_neightbl_set_queue_len(struct rtnl_neightbl *ntbl, int len) +{ + ntbl->nt_parms.ntp_queue_len = len; + ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_QUEUE_LEN; + ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; +} + +/** + * Set the queue length for delay proxy arp requests of a neighbour table to the specified value + * @arg ntbl neighbour table to change + * @arg len new queue len + */ +void rtnl_neightbl_set_proxy_queue_len(struct rtnl_neightbl *ntbl, int len) +{ + ntbl->nt_parms.ntp_proxy_qlen = len; + ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_PROXY_QLEN; + ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; +} + +/** + * Set the number of application probes of a neighbour table to the specified value + * @arg ntbl neighbour table to change + * @arg probes new probes value + */ +void rtnl_neightbl_set_app_probes(struct rtnl_neightbl *ntbl, int probes) +{ + ntbl->nt_parms.ntp_app_probes = probes; + ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_APP_PROBES; + ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; +} + +/** + * Set the number of unicast probes of a neighbour table to the specified value + * @arg ntbl neighbour table to change + * @arg probes new probes value + */ +void rtnl_neightbl_set_ucast_probes(struct rtnl_neightbl *ntbl, int probes) +{ + ntbl->nt_parms.ntp_ucast_probes = probes; + ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_UCAST_PROBES; + ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; +} + +/** + * Set the number of multicast probes of a neighbour table to the specified value + * @arg ntbl neighbour table to change + * @arg probes new probes value + */ +void rtnl_neightbl_set_mcast_probes(struct rtnl_neightbl *ntbl, int probes) +{ + ntbl->nt_parms.ntp_mcast_probes = probes; + ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_MCAST_PROBES; + ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; +} + +/** + * Set the base reachable time of a neighbour table to the specified value + * @arg ntbl neighbour table to change + * @arg ms new base reachable time in milliseconds + */ +void rtnl_neightbl_set_base_reachable_time(struct rtnl_neightbl *ntbl, + uint64_t ms) +{ + ntbl->nt_parms.ntp_base_reachable_time = ms; + ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_BASE_REACHABLE_TIME; + ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; +} + +/** + * Set the retransmit time of a neighbour table to the specified value + * @arg ntbl neighbour table to change + * @arg ms new retransmit time + */ +void rtnl_neightbl_set_retrans_time(struct rtnl_neightbl *ntbl, uint64_t ms) +{ + ntbl->nt_parms.ntp_retrans_time = ms; + ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_RETRANS_TIME; + ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; +} + +/** + * Set the gc stale time of a neighbour table to the specified value + * @arg ntbl neighbour table to change + * @arg ms new gc stale time in milliseconds + */ +void rtnl_neightbl_set_gc_stale_time(struct rtnl_neightbl *ntbl, uint64_t ms) +{ + ntbl->nt_parms.ntp_gc_stale_time = ms; + ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_GC_STALETIME; + ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; +} + +/** + * Set the first probe delay time of a neighbour table to the specified value + * @arg ntbl neighbour table to change + * @arg ms new first probe delay time in milliseconds + */ +void rtnl_neightbl_set_delay_probe_time(struct rtnl_neightbl *ntbl, uint64_t ms) +{ + ntbl->nt_parms.ntp_probe_delay = ms; + ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_DELAY_PROBE_TIME; + ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; +} + +/** + * Set the anycast delay of a neighbour table to the specified value + * @arg ntbl neighbour table to change + * @arg ms new anycast delay in milliseconds + */ +void rtnl_neightbl_set_anycast_delay(struct rtnl_neightbl *ntbl, uint64_t ms) +{ + ntbl->nt_parms.ntp_anycast_delay = ms; + ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_ANYCAST_DELAY; + ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; +} + +/** + * Set the proxy delay of a neighbour table to the specified value + * @arg ntbl neighbour table to change + * @arg ms new proxy delay in milliseconds + */ +void rtnl_neightbl_set_proxy_delay(struct rtnl_neightbl *ntbl, uint64_t ms) +{ + ntbl->nt_parms.ntp_proxy_delay = ms; + ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_PROXY_DELAY; + ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; +} + +/** + * Set the locktime of a neighbour table to the specified value + * @arg ntbl neighbour table to change + * @arg ms new locktime in milliseconds + */ +void rtnl_neightbl_set_locktime(struct rtnl_neightbl *ntbl, uint64_t ms) +{ + ntbl->nt_parms.ntp_locktime = ms; + ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_LOCKTIME; + ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; +} + +/** @} */ + +static struct nl_object_ops neightbl_obj_ops = { + .oo_name = "route/neightbl", + .oo_size = sizeof(struct rtnl_neightbl), + .oo_dump = { + [NL_DUMP_LINE] = neightbl_dump_line, + [NL_DUMP_DETAILS] = neightbl_dump_details, + [NL_DUMP_STATS] = neightbl_dump_stats, + }, + .oo_compare = neightbl_compare, +}; + +static struct nl_cache_ops rtnl_neightbl_ops = { + .co_name = "route/neightbl", + .co_hdrsize = sizeof(struct rtgenmsg), + .co_msgtypes = { + { RTM_NEWNEIGHTBL, NL_ACT_NEW, "new" }, + { RTM_SETNEIGHTBL, NL_ACT_SET, "set" }, + { RTM_GETNEIGHTBL, NL_ACT_GET, "get" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_ROUTE, + .co_request_update = neightbl_request_update, + .co_msg_parser = neightbl_msg_parser, + .co_obj_ops = &neightbl_obj_ops, +}; + +static void __init neightbl_init(void) +{ + nl_cache_mngt_register(&rtnl_neightbl_ops); +} + +static void __exit neightbl_exit(void) +{ + nl_cache_mngt_unregister(&rtnl_neightbl_ops); +} + +/** @} */ diff --git a/lib/route/nexthop.c b/lib/route/nexthop.c new file mode 100644 index 0000000..d3ca499 --- /dev/null +++ b/lib/route/nexthop.c @@ -0,0 +1,297 @@ +/* + * lib/route/nexthop.c Routing Nexthop + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + */ + +/** + * @ingroup route_obj + * @defgroup nexthop Nexthop + * @{ + */ + +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define NH_ATTR_FLAGS 0x000001 +#define NH_ATTR_WEIGHT 0x000002 +#define NH_ATTR_IFINDEX 0x000004 +#define NH_ATTR_GATEWAY 0x000008 +#define NH_ATTR_REALMS 0x000010 +/** @endcond */ + +/** + * @name Allocation/Freeing + * @{ + */ + +struct rtnl_nexthop *rtnl_route_nh_alloc(void) +{ + struct rtnl_nexthop *nh; + + nh = calloc(1, sizeof(*nh)); + if (!nh) + return NULL; + + nl_init_list_head(&nh->rtnh_list); + + return nh; +} + +struct rtnl_nexthop *rtnl_route_nh_clone(struct rtnl_nexthop *src) +{ + struct rtnl_nexthop *nh; + + nh = rtnl_route_nh_alloc(); + if (!nh) + return NULL; + + nh->rtnh_flags = src->rtnh_flags; + nh->rtnh_flag_mask = src->rtnh_flag_mask; + nh->rtnh_weight = src->rtnh_weight; + nh->rtnh_ifindex = src->rtnh_ifindex; + nh->ce_mask = src->ce_mask; + + if (src->rtnh_gateway) { + nh->rtnh_gateway = nl_addr_clone(src->rtnh_gateway); + if (!nh->rtnh_gateway) { + free(nh); + return NULL; + } + } + + return nh; +} + +void rtnl_route_nh_free(struct rtnl_nexthop *nh) +{ + nl_addr_put(nh->rtnh_gateway); + free(nh); +} + +/** @} */ + +int rtnl_route_nh_compare(struct rtnl_nexthop *a, struct rtnl_nexthop *b, + uint32_t attrs, int loose) +{ + int diff = 0; + +#define NH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NH_ATTR_##ATTR, a, b, EXPR) + + diff |= NH_DIFF(IFINDEX, a->rtnh_ifindex != b->rtnh_ifindex); + diff |= NH_DIFF(WEIGHT, a->rtnh_weight != b->rtnh_weight); + diff |= NH_DIFF(REALMS, a->rtnh_realms != b->rtnh_realms); + diff |= NH_DIFF(GATEWAY, nl_addr_cmp(a->rtnh_gateway, + b->rtnh_gateway)); + + if (loose) + diff |= NH_DIFF(FLAGS, + (a->rtnh_flags ^ b->rtnh_flags) & b->rtnh_flag_mask); + else + diff |= NH_DIFF(FLAGS, a->rtnh_flags != b->rtnh_flags); + +#undef NH_DIFF + + return diff; +} + +static void nh_dump_line(struct rtnl_nexthop *nh, struct nl_dump_params *dp) +{ + struct nl_cache *link_cache; + char buf[128]; + + link_cache = nl_cache_mngt_require_safe("route/link"); + + nl_dump(dp, "via"); + + if (nh->ce_mask & NH_ATTR_GATEWAY) + nl_dump(dp, " %s", nl_addr2str(nh->rtnh_gateway, + buf, sizeof(buf))); + + if(nh->ce_mask & NH_ATTR_IFINDEX) { + if (link_cache) { + nl_dump(dp, " dev %s", + rtnl_link_i2name(link_cache, + nh->rtnh_ifindex, + buf, sizeof(buf))); + } else + nl_dump(dp, " dev %d", nh->rtnh_ifindex); + } + + nl_dump(dp, " "); + + if (link_cache) + nl_cache_put(link_cache); +} + +static void nh_dump_details(struct rtnl_nexthop *nh, struct nl_dump_params *dp) +{ + struct nl_cache *link_cache; + char buf[128]; + + link_cache = nl_cache_mngt_require_safe("route/link"); + + nl_dump(dp, "nexthop"); + + if (nh->ce_mask & NH_ATTR_GATEWAY) + nl_dump(dp, " via %s", nl_addr2str(nh->rtnh_gateway, + buf, sizeof(buf))); + + if(nh->ce_mask & NH_ATTR_IFINDEX) { + if (link_cache) { + nl_dump(dp, " dev %s", + rtnl_link_i2name(link_cache, + nh->rtnh_ifindex, + buf, sizeof(buf))); + } else + nl_dump(dp, " dev %d", nh->rtnh_ifindex); + } + + if (nh->ce_mask & NH_ATTR_WEIGHT) + nl_dump(dp, " weight %u", nh->rtnh_weight); + + if (nh->ce_mask & NH_ATTR_REALMS) + nl_dump(dp, " realm %04x:%04x", + RTNL_REALM_FROM(nh->rtnh_realms), + RTNL_REALM_TO(nh->rtnh_realms)); + + if (nh->ce_mask & NH_ATTR_FLAGS) + nl_dump(dp, " <%s>", rtnl_route_nh_flags2str(nh->rtnh_flags, + buf, sizeof(buf))); + + if (link_cache) + nl_cache_put(link_cache); +} + +void rtnl_route_nh_dump(struct rtnl_nexthop *nh, struct nl_dump_params *dp) +{ + switch (dp->dp_type) { + case NL_DUMP_LINE: + nh_dump_line(nh, dp); + break; + + case NL_DUMP_DETAILS: + case NL_DUMP_STATS: + if (dp->dp_ivar == NH_DUMP_FROM_DETAILS) + nh_dump_details(nh, dp); + break; + + default: + break; + } +} + +/** + * @name Attributes + * @{ + */ + +void rtnl_route_nh_set_weight(struct rtnl_nexthop *nh, uint8_t weight) +{ + nh->rtnh_weight = weight; + nh->ce_mask |= NH_ATTR_WEIGHT; +} + +uint8_t rtnl_route_nh_get_weight(struct rtnl_nexthop *nh) +{ + return nh->rtnh_weight; +} + +void rtnl_route_nh_set_ifindex(struct rtnl_nexthop *nh, int ifindex) +{ + nh->rtnh_ifindex = ifindex; + nh->ce_mask |= NH_ATTR_IFINDEX; +} + +int rtnl_route_nh_get_ifindex(struct rtnl_nexthop *nh) +{ + return nh->rtnh_ifindex; +} + +/* FIXME: Convert to return an int */ +void rtnl_route_nh_set_gateway(struct rtnl_nexthop *nh, struct nl_addr *addr) +{ + struct nl_addr *old = nh->rtnh_gateway; + + if (addr) { + nh->rtnh_gateway = nl_addr_get(addr); + nh->ce_mask |= NH_ATTR_GATEWAY; + } else { + nh->ce_mask &= ~NH_ATTR_GATEWAY; + nh->rtnh_gateway = NULL; + } + + if (old) + nl_addr_put(old); +} + +struct nl_addr *rtnl_route_nh_get_gateway(struct rtnl_nexthop *nh) +{ + return nh->rtnh_gateway; +} + +void rtnl_route_nh_set_flags(struct rtnl_nexthop *nh, unsigned int flags) +{ + nh->rtnh_flag_mask |= flags; + nh->rtnh_flags |= flags; + nh->ce_mask |= NH_ATTR_FLAGS; +} + +void rtnl_route_nh_unset_flags(struct rtnl_nexthop *nh, unsigned int flags) +{ + nh->rtnh_flag_mask |= flags; + nh->rtnh_flags &= ~flags; + nh->ce_mask |= NH_ATTR_FLAGS; +} + +unsigned int rtnl_route_nh_get_flags(struct rtnl_nexthop *nh) +{ + return nh->rtnh_flags; +} + +void rtnl_route_nh_set_realms(struct rtnl_nexthop *nh, uint32_t realms) +{ + nh->rtnh_realms = realms; + nh->ce_mask |= NH_ATTR_REALMS; +} + +uint32_t rtnl_route_nh_get_realms(struct rtnl_nexthop *nh) +{ + return nh->rtnh_realms; +} + +/** @} */ + +/** + * @name Nexthop Flags Translations + * @{ + */ + +static const struct trans_tbl nh_flags[] = { + __ADD(RTNH_F_DEAD, dead) + __ADD(RTNH_F_PERVASIVE, pervasive) + __ADD(RTNH_F_ONLINK, onlink) +}; + +char *rtnl_route_nh_flags2str(int flags, char *buf, size_t len) +{ + return __flags2str(flags, buf, len, nh_flags, ARRAY_SIZE(nh_flags)); +} + +int rtnl_route_nh_str2flags(const char *name) +{ + return __str2flags(name, nh_flags, ARRAY_SIZE(nh_flags)); +} + +/** @} */ + +/** @} */ diff --git a/lib/route/pktloc.c b/lib/route/pktloc.c new file mode 100644 index 0000000..9fcf4a4 --- /dev/null +++ b/lib/route/pktloc.c @@ -0,0 +1,260 @@ +/* + * lib/route/pktloc.c Packet Location Aliasing + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2008-2013 Thomas Graf + */ + +/** + * @ingroup tc + * @defgroup pktloc Packet Location Aliasing + * Packet Location Aliasing + * + * The packet location aliasing interface eases the use of offset definitions + * inside packets by allowing them to be referenced by name. Known positions + * of protocol fields are stored in a configuration file and associated with + * a name for later reference. The configuration file is distributed with the + * library and provides a well defined set of definitions for most common + * protocol fields. + * + * @section pktloc_examples Examples + * @par Example 1.1 Looking up a packet location + * @code + * struct rtnl_pktloc *loc; + * + * rtnl_pktloc_lookup("ip.src", &loc); + * @endcode + * @{ + */ + +#include +#include +#include +#include +#include + +#include "pktloc_syntax.h" +#include "pktloc_grammar.h" + +/** @cond SKIP */ +#define PKTLOC_NAME_HT_SIZ 256 + +static struct nl_list_head pktloc_name_ht[PKTLOC_NAME_HT_SIZ]; + +/* djb2 */ +static unsigned int pktloc_hash(const char *str) +{ + unsigned long hash = 5381; + int c; + + while ((c = *str++)) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + return hash % PKTLOC_NAME_HT_SIZ; +} + +static int __pktloc_lookup(const char *name, struct rtnl_pktloc **result) +{ + struct rtnl_pktloc *loc; + int hash; + + hash = pktloc_hash(name); + nl_list_for_each_entry(loc, &pktloc_name_ht[hash], list) { + if (!strcasecmp(loc->name, name)) { + loc->refcnt++; + *result = loc; + return 0; + } + } + + return -NLE_OBJ_NOTFOUND; +} + +extern int pktloc_parse(void *scanner); + +static void rtnl_pktloc_free(struct rtnl_pktloc *loc) +{ + if (!loc) + return; + + free(loc->name); + free(loc); +} + +static int read_pktlocs(void) +{ + YY_BUFFER_STATE buf = NULL; + yyscan_t scanner = NULL; + static time_t last_read; + struct stat st; + char *path; + int i, err; + FILE *fd; + + if (build_sysconf_path(&path, "pktloc") < 0) + return -NLE_NOMEM; + + /* if stat fails, just try to read the file */ + if (stat(path, &st) == 0) { + /* Don't re-read file if file is unchanged */ + if (last_read == st.st_mtime) + return 0; + } + + NL_DBG(2, "Reading packet location file \"%s\"\n", path); + + if (!(fd = fopen(path, "r"))) { + err = -NLE_PKTLOC_FILE; + goto errout; + } + + for (i = 0; i < PKTLOC_NAME_HT_SIZ; i++) { + struct rtnl_pktloc *loc, *n; + + nl_list_for_each_entry_safe(loc, n, &pktloc_name_ht[i], list) + rtnl_pktloc_put(loc); + + nl_init_list_head(&pktloc_name_ht[i]); + } + + if ((err = pktloc_lex_init(&scanner)) < 0) { + err = -NLE_FAILURE; + goto errout_close; + } + + buf = pktloc__create_buffer(fd, YY_BUF_SIZE, scanner); + pktloc__switch_to_buffer(buf, scanner); + + if ((err = pktloc_parse(scanner)) != 0) { + pktloc__delete_buffer(buf, scanner); + err = -NLE_PARSE_ERR; + goto errout_scanner; + } + + last_read = st.st_mtime; + +errout_scanner: + if (scanner) + pktloc_lex_destroy(scanner); +errout_close: + fclose(fd); +errout: + free(path); + + return 0; +} + +/** @endcond */ + +/** + * Lookup packet location alias + * @arg name Name of packet location. + * @arg result Result pointer + * + * Tries to find a matching packet location alias for the supplied + * packet location name. + * + * The file containing the packet location definitions is automatically + * re-read if its modification time has changed since the last call. + * + * The returned packet location has to be returned after use by calling + * rtnl_pktloc_put() in order to allow freeing its memory after the last + * user has abandoned it. + * + * @return 0 on success or a negative error code. + * @retval NLE_PKTLOC_FILE Unable to open packet location file. + * @retval NLE_OBJ_NOTFOUND No matching packet location alias found. + */ +int rtnl_pktloc_lookup(const char *name, struct rtnl_pktloc **result) +{ + int err; + + if ((err = read_pktlocs()) < 0) + return err; + + return __pktloc_lookup(name, result); +} + +/** + * Allocate packet location object + */ +struct rtnl_pktloc *rtnl_pktloc_alloc(void) +{ + struct rtnl_pktloc *loc; + + if (!(loc = calloc(1, sizeof(*loc)))) + return NULL; + + loc->refcnt = 1; + nl_init_list_head(&loc->list); + + return loc; +} + +/** + * Return reference of a packet location + * @arg loc packet location object. + */ +void rtnl_pktloc_put(struct rtnl_pktloc *loc) +{ + if (!loc) + return; + + loc->refcnt--; + if (loc->refcnt <= 0) + rtnl_pktloc_free(loc); +} + +/** + * Add a packet location to the hash table + * @arg loc packet location object + * + * @return 0 on success or a negative error code. + */ +int rtnl_pktloc_add(struct rtnl_pktloc *loc) +{ + struct rtnl_pktloc *l; + + if (__pktloc_lookup(loc->name, &l) == 0) { + rtnl_pktloc_put(l); + return -NLE_EXIST; + } + + NL_DBG(2, "New packet location entry \"%s\" align=%u layer=%u " + "offset=%u mask=%#x shift=%u refnt=%u\n", + loc->name, loc->align, loc->layer, loc->offset, + loc->mask, loc->shift, loc->refcnt); + + nl_list_add_tail(&loc->list, &pktloc_name_ht[pktloc_hash(loc->name)]); + + return 0; +} + +void rtnl_pktloc_foreach(void (*cb)(struct rtnl_pktloc *, void *), void *arg) +{ + struct rtnl_pktloc *loc; + int i; + + /* ignore errors */ + read_pktlocs(); + + for (i = 0; i < PKTLOC_NAME_HT_SIZ; i++) + nl_list_for_each_entry(loc, &pktloc_name_ht[i], list) + cb(loc, arg); +} + +static int __init pktloc_init(void) +{ + int i; + + for (i = 0; i < PKTLOC_NAME_HT_SIZ; i++) + nl_init_list_head(&pktloc_name_ht[i]); + + return 0; +} + +/** @} */ diff --git a/lib/route/pktloc_grammar.l b/lib/route/pktloc_grammar.l new file mode 100644 index 0000000..cbb42b3 --- /dev/null +++ b/lib/route/pktloc_grammar.l @@ -0,0 +1,51 @@ +%{ + #include + #include + #include + #include + #include + #include "pktloc_syntax.h" +%} + +%option 8bit +%option reentrant +%option warn +%option noyywrap +%option noinput +%option nounput +%option bison-bridge +%option bison-locations +%option prefix="pktloc_" + +%% + +[ \t\r\n]+ + +"#".* + +[[:digit:]]+ | +0[xX][[:xdigit:]]+ { + yylval->i = strtoul(yytext, NULL, 0); + return NUMBER; + } + +"+" { return yylval->i = yytext[0]; } + +[uU]8 { yylval->i = TCF_EM_ALIGN_U8; return ALIGN; } +[uU]16 { yylval->i = TCF_EM_ALIGN_U16; return ALIGN; } +[uU]32 { yylval->i = TCF_EM_ALIGN_U32; return ALIGN; } + +[lL][iI][nN][kK] | +[eE][tT][hH] { yylval->i = TCF_LAYER_LINK; return LAYER; } +[nN][eE][tT] | +[iI][pP] { yylval->i = TCF_LAYER_NETWORK; return LAYER; } +[tT][rR][aA][nN][sS][pP][oO][rR][tT] | +[tT][cC][pP] { yylval->i = TCF_LAYER_TRANSPORT; return LAYER; } + + +[^ \t\r\n+]+ { + yylval->s = strdup(yytext); + if (yylval->s == NULL) + return ERROR; + return NAME; + } diff --git a/lib/route/pktloc_syntax.y b/lib/route/pktloc_syntax.y new file mode 100644 index 0000000..25d8710 --- /dev/null +++ b/lib/route/pktloc_syntax.y @@ -0,0 +1,103 @@ +%{ +#include +#include +#include +#include +#include +%} + +%locations +%error-verbose +%define api.pure +%name-prefix "pktloc_" + +%parse-param {void *scanner} +%lex-param {void *scanner} +%expect 1 + +%union { + struct rtnl_pktloc *l; + uint32_t i; + char *s; +} + +%{ +extern int pktloc_lex(YYSTYPE *, YYLTYPE *, void *); + +static void yyerror(YYLTYPE *locp, void *scanner, const char *msg) +{ + NL_DBG(1, "Error while parsing packet location file: %s\n", msg); +} +%} + +%token ERROR NUMBER LAYER ALIGN +%token NAME + +%type mask layer align shift +%type location + +%destructor { free($$); } NAME + +%start input + +%% + +input: + /* empty */ + | location input + ; + +location: + NAME align layer NUMBER mask shift + { + struct rtnl_pktloc *loc; + + if (!(loc = rtnl_pktloc_alloc())) { + NL_DBG(1, "Allocating a packet location " + "object failed.\n"); + YYABORT; + } + + loc->name = $1; + loc->align = $2; + loc->layer = $3; + loc->offset = $4; + loc->mask = $5; + loc->shift = $6; + + if (rtnl_pktloc_add(loc) < 0) { + NL_DBG(1, "Duplicate packet location entry " + "\"%s\"\n", $1); + } + + $$ = loc; + } + ; + +align: + ALIGN + { $$ = $1; } + | NUMBER + { $$ = $1; } + ; + +layer: + /* empty */ + { $$ = TCF_LAYER_NETWORK; } + | LAYER '+' + { $$ = $1; } + ; + +mask: + /* empty */ + { $$ = 0; } + | NUMBER + { $$ = $1; } + ; + +shift: + /* empty */ + { $$ = 0; } + | NUMBER + { $$ = $1; } + ; diff --git a/lib/route/qdisc.c b/lib/route/qdisc.c new file mode 100644 index 0000000..250d191 --- /dev/null +++ b/lib/route/qdisc.c @@ -0,0 +1,575 @@ +/* + * lib/route/qdisc.c 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-2011 Thomas Graf + */ + +/** + * @ingroup tc + * @defgroup qdisc Queueing Disciplines + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct nl_cache_ops rtnl_qdisc_ops; +static struct nl_object_ops qdisc_obj_ops; + +static int qdisc_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *n, struct nl_parser_param *pp) +{ + struct rtnl_qdisc *qdisc; + int err; + + if (!(qdisc = rtnl_qdisc_alloc())) + return -NLE_NOMEM; + + if ((err = rtnl_tc_msg_parse(n, TC_CAST(qdisc))) < 0) + goto errout; + + err = pp->pp_cb(OBJ_CAST(qdisc), pp); +errout: + rtnl_qdisc_put(qdisc); + + return err; +} + +static int qdisc_request_update(struct nl_cache *c, struct nl_sock *sk) +{ + struct tcmsg tchdr = { + .tcm_family = AF_UNSPEC, + .tcm_ifindex = c->c_iarg1, + }; + + return nl_send_simple(sk, RTM_GETQDISC, NLM_F_DUMP, &tchdr, + sizeof(tchdr)); +} + +/** + * @name Allocation/Freeing + * @{ + */ + +struct rtnl_qdisc *rtnl_qdisc_alloc(void) +{ + struct rtnl_tc *tc; + + tc = TC_CAST(nl_object_alloc(&qdisc_obj_ops)); + if (tc) + tc->tc_type = RTNL_TC_TYPE_QDISC; + + return (struct rtnl_qdisc *) tc; +} + +void rtnl_qdisc_put(struct rtnl_qdisc *qdisc) +{ + nl_object_put((struct nl_object *) qdisc); +} + +/** @} */ + +/** + * @name Addition / Modification / Deletion + * @{ + */ + +static int build_qdisc_msg(struct rtnl_qdisc *qdisc, int type, int flags, + struct nl_msg **result) +{ + if (!(qdisc->ce_mask & TCA_ATTR_IFINDEX)) { + APPBUG("ifindex must be specified"); + return -NLE_MISSING_ATTR; + } + + return rtnl_tc_msg_build(TC_CAST(qdisc), type, flags, result); +} + +/** + * Build a netlink message requesting the addition of a qdisc + * @arg qdisc Qdisc to add + * @arg flags Additional netlink message flags + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_qdisc_add() with + * the exception that it will not send the message but return it int the + * provided return pointer instead. + * + * @see rtnl_qdisc_add() + * + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_build_add_request(struct rtnl_qdisc *qdisc, int flags, + struct nl_msg **result) +{ + if (!(qdisc->ce_mask & (TCA_ATTR_HANDLE | TCA_ATTR_PARENT))) { + APPBUG("handle or parent must be specified"); + return -NLE_MISSING_ATTR; + } + + return build_qdisc_msg(qdisc, RTM_NEWQDISC, flags, result); +} + +/** + * Add qdisc + * @arg sk Netlink socket + * @arg qdisc Qdisc to add + * @arg flags Additional netlink message flags + * + * Builds a \c RTM_NEWQDISC netlink message requesting the addition + * of a new qdisc and sends the message to the kernel. The configuration + * of the qdisc is derived from the attributes of the specified qdisc. + * + * The following flags may be specified: + * - \c NLM_F_CREATE: Create qdisc if it does not exist, otherwise + * -NLE_OBJ_NOTFOUND is returned. + * - \c NLM_F_REPLACE: If another qdisc is already attached to the + * parent, replace it even if the handles mismatch. + * - \c NLM_F_EXCL: Return -NLE_EXISTS if a qdisc with matching + * handle exists already. + * + * Existing qdiscs with matching handles will be updated, unless the + * flag \c NLM_F_EXCL is specified. If their handles do not match, the + * error -NLE_EXISTS is returned unless the flag \c NLM_F_REPLACE is + * specified in which case the existing qdisc is replaced with the new + * one. If no matching qdisc exists, it will be created if the flag + * \c NLM_F_CREATE is set, otherwise the error -NLE_OBJ_NOTFOUND is + * returned. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_add(struct nl_sock *sk, struct rtnl_qdisc *qdisc, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_qdisc_build_add_request(qdisc, flags, &msg)) < 0) + return err; + + return nl_send_sync(sk, msg); +} + +/** + * Build netlink message requesting the update of a qdisc + * @arg qdisc Qdisc to update + * @arg new Qdisc with updated attributes + * @arg flags Additional netlink message flags + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_qdisc_update() with + * the exception that it will not send the message but return it in the + * provided return pointer instead. + * + * @see rtnl_qdisc_update() + * + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_build_update_request(struct rtnl_qdisc *qdisc, + struct rtnl_qdisc *new, int flags, + struct nl_msg **result) +{ + if (flags & (NLM_F_CREATE | NLM_F_EXCL)) { + APPBUG("NLM_F_CREATE and NLM_F_EXCL may not be used here, " + "use rtnl_qdisc_add()"); + return -NLE_INVAL; + } + + if (!(qdisc->ce_mask & TCA_ATTR_IFINDEX)) { + APPBUG("ifindex must be specified"); + return -NLE_MISSING_ATTR; + } + + if (!(qdisc->ce_mask & (TCA_ATTR_HANDLE | TCA_ATTR_PARENT))) { + APPBUG("handle or parent must be specified"); + return -NLE_MISSING_ATTR; + } + + rtnl_tc_set_ifindex(TC_CAST(new), qdisc->q_ifindex); + + if (qdisc->ce_mask & TCA_ATTR_HANDLE) + rtnl_tc_set_handle(TC_CAST(new), qdisc->q_handle); + + if (qdisc->ce_mask & TCA_ATTR_PARENT) + rtnl_tc_set_parent(TC_CAST(new), qdisc->q_parent); + + return build_qdisc_msg(new, RTM_NEWQDISC, flags, result); +} + +/** + * Update qdisc + * @arg sk Netlink socket + * @arg qdisc Qdisc to update + * @arg new Qdisc with updated attributes + * @arg flags Additional netlink message flags + * + * Builds a \c RTM_NEWQDISC netlink message requesting the update + * of an existing qdisc and sends the message to the kernel. + * + * This function is a varation of rtnl_qdisc_add() to update qdiscs + * if the qdisc to be updated is available as qdisc object. The + * behaviour is identical to the one of rtnl_qdisc_add except that + * before constructing the message, it copies the \c ifindex, + * \c handle, and \c parent from the original \p qdisc to the \p new + * qdisc. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_update(struct nl_sock *sk, struct rtnl_qdisc *qdisc, + struct rtnl_qdisc *new, int flags) +{ + struct nl_msg *msg; + int err; + + err = rtnl_qdisc_build_update_request(qdisc, new, flags, &msg); + if (err < 0) + return err; + + return nl_send_sync(sk, msg); +} + +/** + * Build netlink message requesting the deletion of a qdisc + * @arg qdisc Qdisc to delete + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_qdisc_delete() with + * the exception that it will not send the message but return it in the + * provided return pointer instead. + * + * @see rtnl_qdisc_delete() + * + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_build_delete_request(struct rtnl_qdisc *qdisc, + struct nl_msg **result) +{ + struct nl_msg *msg; + struct tcmsg tchdr; + uint32_t required = TCA_ATTR_IFINDEX | TCA_ATTR_PARENT; + + if ((qdisc->ce_mask & required) != required) { + APPBUG("ifindex and parent must be specified"); + return -NLE_MISSING_ATTR; + } + + if (!(msg = nlmsg_alloc_simple(RTM_DELQDISC, 0))) + return -NLE_NOMEM; + + memset(&tchdr, 0, sizeof(tchdr)); + + tchdr.tcm_family = AF_UNSPEC; + tchdr.tcm_ifindex = qdisc->q_ifindex; + tchdr.tcm_parent = qdisc->q_parent; + + if (qdisc->ce_mask & TCA_ATTR_HANDLE) + tchdr.tcm_handle = qdisc->q_handle; + + if (nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if (qdisc->ce_mask & TCA_ATTR_KIND) + NLA_PUT_STRING(msg, TCA_KIND, qdisc->q_kind); + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +/** + * Delete qdisc + * @arg sk Netlink socket + * @arg qdisc Qdisc to add + * + * Builds a \c RTM_NEWQDISC netlink message requesting the deletion + * of a qdisc and sends the message to the kernel. + * + * The message is constructed out of the following attributes: + * - \c ifindex and \c parent + * - \c handle (optional, must match if provided) + * - \c kind (optional, must match if provided) + * + * All other qdisc attributes including all qdisc type specific + * attributes are ignored. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note It is not possible to delete default qdiscs. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_delete(struct nl_sock *sk, struct rtnl_qdisc *qdisc) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_qdisc_build_delete_request(qdisc, &msg)) < 0) + return err; + + return nl_send_sync(sk, msg); +} + +/** @} */ + +/** + * @name Cache Related Functions + * @{ + */ + +/** + * Allocate a cache and fill it with all configured qdiscs + * @arg sk Netlink socket + * @arg result Pointer to store the created cache + * + * Allocates a new qdisc cache and fills it with a list of all configured + * qdiscs on all network devices. Release the cache with nl_cache_free(). + * + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_alloc_cache(struct nl_sock *sk, struct nl_cache **result) +{ + return nl_cache_alloc_and_fill(&rtnl_qdisc_ops, sk, result); +} + +/** + * Search qdisc by interface index and parent + * @arg cache Qdisc cache + * @arg ifindex Interface index + * @arg parent Handle of parent qdisc + * + * Searches a qdisc cache previously allocated with rtnl_qdisc_alloc_cache() + * and searches for a qdisc matching the interface index and parent qdisc. + * + * The reference counter is incremented before returning the qdisc, therefore + * the reference must be given back with rtnl_qdisc_put() after usage. + * + * @return pointer to qdisc inside the cache or NULL if no match was found. + */ +struct rtnl_qdisc *rtnl_qdisc_get_by_parent(struct nl_cache *cache, + int ifindex, uint32_t parent) +{ + struct rtnl_qdisc *q; + + if (cache->c_ops != &rtnl_qdisc_ops) + return NULL; + + nl_list_for_each_entry(q, &cache->c_items, ce_list) { + if (q->q_parent == parent && q->q_ifindex == ifindex) { + nl_object_get((struct nl_object *) q); + return q; + } + } + + return NULL; +} + +/** + * Search qdisc by interface index and handle + * @arg cache Qdisc cache + * @arg ifindex Interface index + * @arg handle Handle + * + * Searches a qdisc cache previously allocated with rtnl_qdisc_alloc_cache() + * and searches for a qdisc matching the interface index and handle. + * + * The reference counter is incremented before returning the qdisc, therefore + * the reference must be given back with rtnl_qdisc_put() after usage. + * + * @return Qdisc or NULL if no match was found. + */ +struct rtnl_qdisc *rtnl_qdisc_get(struct nl_cache *cache, int ifindex, + uint32_t handle) +{ + struct rtnl_qdisc *q; + + if (cache->c_ops != &rtnl_qdisc_ops) + return NULL; + + nl_list_for_each_entry(q, &cache->c_items, ce_list) { + if (q->q_handle == handle && q->q_ifindex == ifindex) { + nl_object_get((struct nl_object *) q); + return q; + } + } + + return NULL; +} + +/** @} */ + +/** + * @name Deprecated Functions + * @{ + */ + +/** + * Call a callback for each child class of a qdisc (deprecated) + * + * @deprecated Use of this function is deprecated, it does not allow + * to handle the out of memory situation that can occur. + */ +void rtnl_qdisc_foreach_child(struct rtnl_qdisc *qdisc, struct nl_cache *cache, + void (*cb)(struct nl_object *, void *), void *arg) +{ + struct rtnl_class *filter; + + filter = rtnl_class_alloc(); + if (!filter) + return; + + rtnl_tc_set_parent(TC_CAST(filter), qdisc->q_handle); + rtnl_tc_set_ifindex(TC_CAST(filter), qdisc->q_ifindex); + rtnl_tc_set_kind(TC_CAST(filter), qdisc->q_kind); + + nl_cache_foreach_filter(cache, OBJ_CAST(filter), cb, arg); + + rtnl_class_put(filter); +} + +/** + * Call a callback for each filter attached to the qdisc (deprecated) + * + * @deprecated Use of this function is deprecated, it does not allow + * to handle the out of memory situation that can occur. + */ +void rtnl_qdisc_foreach_cls(struct rtnl_qdisc *qdisc, struct nl_cache *cache, + void (*cb)(struct nl_object *, void *), void *arg) +{ + struct rtnl_cls *filter; + + if (!(filter = rtnl_cls_alloc())) + return; + + rtnl_tc_set_ifindex(TC_CAST(filter), qdisc->q_ifindex); + rtnl_tc_set_parent(TC_CAST(filter), qdisc->q_parent); + + nl_cache_foreach_filter(cache, OBJ_CAST(filter), cb, arg); + rtnl_cls_put(filter); +} + +/** + * Build a netlink message requesting the update of a qdisc + * + * @deprecated Use of this function is deprecated in favour of + * rtnl_qdisc_build_update_request() due to the missing + * possibility of specifying additional flags. + */ +int rtnl_qdisc_build_change_request(struct rtnl_qdisc *qdisc, + struct rtnl_qdisc *new, + struct nl_msg **result) +{ + return rtnl_qdisc_build_update_request(qdisc, new, NLM_F_REPLACE, + result); +} + +/** + * Change attributes of a qdisc + * + * @deprecated Use of this function is deprecated in favour of + * rtnl_qdisc_update() due to the missing possibility of + * specifying additional flags. + */ +int rtnl_qdisc_change(struct nl_sock *sk, struct rtnl_qdisc *qdisc, + struct rtnl_qdisc *new) +{ + return rtnl_qdisc_update(sk, qdisc, new, NLM_F_REPLACE); +} + +/** @} */ + +static void qdisc_dump_details(struct rtnl_tc *tc, struct nl_dump_params *p) +{ + struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc; + + nl_dump(p, "refcnt %u ", qdisc->q_info); +} + +static struct rtnl_tc_type_ops qdisc_ops = { + .tt_type = RTNL_TC_TYPE_QDISC, + .tt_dump_prefix = "qdisc", + .tt_dump = { + [NL_DUMP_DETAILS] = qdisc_dump_details, + }, +}; + +static struct nl_cache_ops rtnl_qdisc_ops = { + .co_name = "route/qdisc", + .co_hdrsize = sizeof(struct tcmsg), + .co_msgtypes = { + { RTM_NEWQDISC, NL_ACT_NEW, "new" }, + { RTM_DELQDISC, NL_ACT_DEL, "del" }, + { RTM_GETQDISC, NL_ACT_GET, "get" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_ROUTE, + .co_request_update = qdisc_request_update, + .co_msg_parser = qdisc_msg_parser, + .co_obj_ops = &qdisc_obj_ops, +}; + +static struct nl_object_ops qdisc_obj_ops = { + .oo_name = "route/qdisc", + .oo_size = sizeof(struct rtnl_qdisc), + .oo_free_data = rtnl_tc_free_data, + .oo_clone = rtnl_tc_clone, + .oo_dump = { + [NL_DUMP_LINE] = rtnl_tc_dump_line, + [NL_DUMP_DETAILS] = rtnl_tc_dump_details, + [NL_DUMP_STATS] = rtnl_tc_dump_stats, + }, + .oo_compare = rtnl_tc_compare, + .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE), +}; + +static void __init qdisc_init(void) +{ + rtnl_tc_type_register(&qdisc_ops); + nl_cache_mngt_register(&rtnl_qdisc_ops); +} + +static void __exit qdisc_exit(void) +{ + nl_cache_mngt_unregister(&rtnl_qdisc_ops); + rtnl_tc_type_unregister(&qdisc_ops); +} + +/** @} */ diff --git a/lib/route/qdisc/blackhole.c b/lib/route/qdisc/blackhole.c new file mode 100644 index 0000000..339cf78 --- /dev/null +++ b/lib/route/qdisc/blackhole.c @@ -0,0 +1,37 @@ +/* + * lib/route/qdisc/blackhole.c Blackhole Qdisc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + */ + +/** + * @ingroup qdisc + * @defgroup qdisc_blackhole Blackhole + * @{ + */ + +#include +#include +#include + +static struct rtnl_tc_ops blackhole_ops = { + .to_kind = "blackhole", + .to_type = RTNL_TC_TYPE_QDISC, +}; + +static void __init blackhole_init(void) +{ + rtnl_tc_register(&blackhole_ops); +} + +static void __exit blackhole_exit(void) +{ + rtnl_tc_unregister(&blackhole_ops); +} + +/** @} */ diff --git a/lib/route/qdisc/cbq.c b/lib/route/qdisc/cbq.c new file mode 100644 index 0000000..95f1761 --- /dev/null +++ b/lib/route/qdisc/cbq.c @@ -0,0 +1,204 @@ +/* + * lib/route/qdisc/cbq.c Class Based Queueing + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @ingroup qdisc + * @ingroup class + * @defgroup qdisc_cbq Class Based Queueing (CBQ) + * @{ + */ + +static const struct trans_tbl ovl_strategies[] = { + __ADD(TC_CBQ_OVL_CLASSIC,classic) + __ADD(TC_CBQ_OVL_DELAY,delay) + __ADD(TC_CBQ_OVL_LOWPRIO,lowprio) + __ADD(TC_CBQ_OVL_DROP,drop) + __ADD(TC_CBQ_OVL_RCLASSIC,rclassic) +}; + +/** + * Convert a CBQ OVL strategy to a character string + * @arg type CBQ OVL strategy + * @arg buf destination buffer + * @arg len length of destination buffer + * + * Converts a CBQ OVL strategy to a character string and stores in the + * provided buffer. Returns the destination buffer or the type + * encoded in hex if no match was found. + */ +char *nl_ovl_strategy2str(int type, char *buf, size_t len) +{ + return __type2str(type, buf, len, ovl_strategies, + ARRAY_SIZE(ovl_strategies)); +} + +/** + * Convert a string to a CBQ OVL strategy + * @arg name CBQ OVL stragegy name + * + * Converts a CBQ OVL stragegy name to it's corresponding CBQ OVL strategy + * type. Returns the type or -1 if none was found. + */ +int nl_str2ovl_strategy(const char *name) +{ + return __str2type(name, ovl_strategies, ARRAY_SIZE(ovl_strategies)); +} + +static struct nla_policy cbq_policy[TCA_CBQ_MAX+1] = { + [TCA_CBQ_LSSOPT] = { .minlen = sizeof(struct tc_cbq_lssopt) }, + [TCA_CBQ_RATE] = { .minlen = sizeof(struct tc_ratespec) }, + [TCA_CBQ_WRROPT] = { .minlen = sizeof(struct tc_cbq_wrropt) }, + [TCA_CBQ_OVL_STRATEGY] = { .minlen = sizeof(struct tc_cbq_ovl) }, + [TCA_CBQ_FOPT] = { .minlen = sizeof(struct tc_cbq_fopt) }, + [TCA_CBQ_POLICE] = { .minlen = sizeof(struct tc_cbq_police) }, +}; + +static int cbq_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct nlattr *tb[TCA_CBQ_MAX + 1]; + struct rtnl_cbq *cbq = data; + int err; + + err = tca_parse(tb, TCA_CBQ_MAX, tc, cbq_policy); + if (err < 0) + return err; + + nla_memcpy(&cbq->cbq_lss, tb[TCA_CBQ_LSSOPT], sizeof(cbq->cbq_lss)); + nla_memcpy(&cbq->cbq_rate, tb[TCA_CBQ_RATE], sizeof(cbq->cbq_rate)); + nla_memcpy(&cbq->cbq_wrr, tb[TCA_CBQ_WRROPT], sizeof(cbq->cbq_wrr)); + nla_memcpy(&cbq->cbq_fopt, tb[TCA_CBQ_FOPT], sizeof(cbq->cbq_fopt)); + nla_memcpy(&cbq->cbq_ovl, tb[TCA_CBQ_OVL_STRATEGY], + sizeof(cbq->cbq_ovl)); + nla_memcpy(&cbq->cbq_police, tb[TCA_CBQ_POLICE], + sizeof(cbq->cbq_police)); + + return 0; +} + +static void cbq_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_cbq *cbq = data; + double r, rbit; + char *ru, *rubit; + + if (!cbq) + return; + + r = nl_cancel_down_bytes(cbq->cbq_rate.rate, &ru); + rbit = nl_cancel_down_bits(cbq->cbq_rate.rate * 8, &rubit); + + nl_dump(p, " rate %.2f%s/s (%.0f%s) prio %u", + r, ru, rbit, rubit, cbq->cbq_wrr.priority); +} + +static void cbq_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_cbq *cbq = data; + char *unit, buf[32]; + double w; + uint32_t el; + + if (!cbq) + return; + + w = nl_cancel_down_bits(cbq->cbq_wrr.weight * 8, &unit); + + nl_dump(p, "avgpkt %u mpu %u cell %u allot %u weight %.0f%s\n", + cbq->cbq_lss.avpkt, + cbq->cbq_rate.mpu, + 1 << cbq->cbq_rate.cell_log, + cbq->cbq_wrr.allot, w, unit); + + el = cbq->cbq_lss.ewma_log; + nl_dump_line(p, " minidle %uus maxidle %uus offtime " + "%uus level %u ewma_log %u\n", + nl_ticks2us(cbq->cbq_lss.minidle >> el), + nl_ticks2us(cbq->cbq_lss.maxidle >> el), + nl_ticks2us(cbq->cbq_lss.offtime >> el), + cbq->cbq_lss.level, + cbq->cbq_lss.ewma_log); + + nl_dump_line(p, " penalty %uus strategy %s ", + nl_ticks2us(cbq->cbq_ovl.penalty), + nl_ovl_strategy2str(cbq->cbq_ovl.strategy, buf, sizeof(buf))); + + nl_dump(p, "split %s defmap 0x%08x ", + rtnl_tc_handle2str(cbq->cbq_fopt.split, buf, sizeof(buf)), + cbq->cbq_fopt.defmap); + + nl_dump(p, "police %s", + nl_police2str(cbq->cbq_police.police, buf, sizeof(buf))); +} + +static void cbq_dump_stats(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct tc_cbq_xstats *x; + + if (!(x = tca_xstats(tc))) + return; + + nl_dump_line(p, " borrows overact " + " avgidle undertime\n"); + nl_dump_line(p, " %10u %10u %10u %10u\n", + x->borrows, x->overactions, x->avgidle, x->undertime); +} + +static struct rtnl_tc_ops cbq_qdisc_ops = { + .to_kind = "cbq", + .to_type = RTNL_TC_TYPE_QDISC, + .to_size = sizeof(struct rtnl_cbq), + .to_msg_parser = cbq_msg_parser, + .to_dump = { + [NL_DUMP_LINE] = cbq_dump_line, + [NL_DUMP_DETAILS] = cbq_dump_details, + [NL_DUMP_STATS] = cbq_dump_stats, + }, +}; + +static struct rtnl_tc_ops cbq_class_ops = { + .to_kind = "cbq", + .to_type = RTNL_TC_TYPE_CLASS, + .to_size = sizeof(struct rtnl_cbq), + .to_msg_parser = cbq_msg_parser, + .to_dump = { + [NL_DUMP_LINE] = cbq_dump_line, + [NL_DUMP_DETAILS] = cbq_dump_details, + [NL_DUMP_STATS] = cbq_dump_stats, + }, +}; + +static void __init cbq_init(void) +{ + rtnl_tc_register(&cbq_qdisc_ops); + rtnl_tc_register(&cbq_class_ops); +} + +static void __exit cbq_exit(void) +{ + rtnl_tc_unregister(&cbq_qdisc_ops); + rtnl_tc_unregister(&cbq_class_ops); +} + +/** @} */ diff --git a/lib/route/qdisc/dsmark.c b/lib/route/qdisc/dsmark.c new file mode 100644 index 0000000..fd9553d --- /dev/null +++ b/lib/route/qdisc/dsmark.c @@ -0,0 +1,413 @@ +/* + * lib/route/qdisc/dsmark.c DSMARK + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + */ + +/** + * @ingroup qdisc + * @ingroup class + * @defgroup qdisc_dsmark Differentiated Services Marker (DSMARK) + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define SCH_DSMARK_ATTR_INDICES 0x1 +#define SCH_DSMARK_ATTR_DEFAULT_INDEX 0x2 +#define SCH_DSMARK_ATTR_SET_TC_INDEX 0x4 + +#define SCH_DSMARK_ATTR_MASK 0x1 +#define SCH_DSMARK_ATTR_VALUE 0x2 +/** @endcond */ + +static struct nla_policy dsmark_policy[TCA_DSMARK_MAX+1] = { + [TCA_DSMARK_INDICES] = { .type = NLA_U16 }, + [TCA_DSMARK_DEFAULT_INDEX] = { .type = NLA_U16 }, + [TCA_DSMARK_SET_TC_INDEX] = { .type = NLA_FLAG }, + [TCA_DSMARK_VALUE] = { .type = NLA_U8 }, + [TCA_DSMARK_MASK] = { .type = NLA_U8 }, +}; + +static int dsmark_qdisc_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct rtnl_dsmark_qdisc *dsmark = data; + struct nlattr *tb[TCA_DSMARK_MAX + 1]; + int err; + + err = tca_parse(tb, TCA_DSMARK_MAX, tc, dsmark_policy); + if (err < 0) + return err; + + if (tb[TCA_DSMARK_INDICES]) { + dsmark->qdm_indices = nla_get_u16(tb[TCA_DSMARK_INDICES]); + dsmark->qdm_mask |= SCH_DSMARK_ATTR_INDICES; + } + + if (tb[TCA_DSMARK_DEFAULT_INDEX]) { + dsmark->qdm_default_index = + nla_get_u16(tb[TCA_DSMARK_DEFAULT_INDEX]); + dsmark->qdm_mask |= SCH_DSMARK_ATTR_DEFAULT_INDEX; + } + + if (tb[TCA_DSMARK_SET_TC_INDEX]) { + dsmark->qdm_set_tc_index = 1; + dsmark->qdm_mask |= SCH_DSMARK_ATTR_SET_TC_INDEX; + } + + return 0; +} + +static int dsmark_class_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct rtnl_dsmark_class *dsmark = data; + struct nlattr *tb[TCA_DSMARK_MAX + 1]; + int err; + + err = tca_parse(tb, TCA_DSMARK_MAX, tc, dsmark_policy); + if (err < 0) + return err; + + if (tb[TCA_DSMARK_MASK]) { + dsmark->cdm_bmask = nla_get_u8(tb[TCA_DSMARK_MASK]); + dsmark->cdm_mask |= SCH_DSMARK_ATTR_MASK; + } + + if (tb[TCA_DSMARK_VALUE]) { + dsmark->cdm_value = nla_get_u8(tb[TCA_DSMARK_VALUE]); + dsmark->cdm_mask |= SCH_DSMARK_ATTR_VALUE; + } + + return 0; +} + +static void dsmark_qdisc_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_dsmark_qdisc *dsmark = data; + + if (dsmark && (dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES)) + nl_dump(p, " indices 0x%04x", dsmark->qdm_indices); +} + +static void dsmark_qdisc_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_dsmark_qdisc *dsmark = data; + + if (!dsmark) + return; + + if (dsmark->qdm_mask & SCH_DSMARK_ATTR_DEFAULT_INDEX) + nl_dump(p, " default index 0x%04x", dsmark->qdm_default_index); + + if (dsmark->qdm_mask & SCH_DSMARK_ATTR_SET_TC_INDEX) + nl_dump(p, " set-tc-index"); +} + +static void dsmark_class_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_dsmark_class *dsmark = data; + + if (!dsmark) + return; + + if (dsmark->cdm_mask & SCH_DSMARK_ATTR_VALUE) + nl_dump(p, " value 0x%02x", dsmark->cdm_value); + + if (dsmark->cdm_mask & SCH_DSMARK_ATTR_MASK) + nl_dump(p, " mask 0x%02x", dsmark->cdm_bmask); +} + +static int dsmark_qdisc_msg_fill(struct rtnl_tc *tc, void *data, + struct nl_msg *msg) +{ + struct rtnl_dsmark_qdisc *dsmark = data; + + if (!dsmark) + return 0; + + if (dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES) + NLA_PUT_U16(msg, TCA_DSMARK_INDICES, dsmark->qdm_indices); + + if (dsmark->qdm_mask & SCH_DSMARK_ATTR_DEFAULT_INDEX) + NLA_PUT_U16(msg, TCA_DSMARK_DEFAULT_INDEX, + dsmark->qdm_default_index); + + if (dsmark->qdm_mask & SCH_DSMARK_ATTR_SET_TC_INDEX) + NLA_PUT_FLAG(msg, TCA_DSMARK_SET_TC_INDEX); + + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +static int dsmark_class_msg_fill(struct rtnl_tc *tc, void *data, + struct nl_msg *msg) +{ + struct rtnl_dsmark_class *dsmark = data; + + if (!dsmark) + return 0; + + if (dsmark->cdm_mask & SCH_DSMARK_ATTR_MASK) + NLA_PUT_U8(msg, TCA_DSMARK_MASK, dsmark->cdm_bmask); + + if (dsmark->cdm_mask & SCH_DSMARK_ATTR_VALUE) + NLA_PUT_U8(msg, TCA_DSMARK_VALUE, dsmark->cdm_value); + + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +/** + * @name Class Attribute Access + * @{ + */ + +/** + * Set bitmask of DSMARK class. + * @arg class DSMARK class to be modified. + * @arg mask New bitmask. + * @return 0 on success or a negative error code. + */ +int rtnl_class_dsmark_set_bitmask(struct rtnl_class *class, uint8_t mask) +{ + struct rtnl_dsmark_class *dsmark; + + if (!(dsmark = rtnl_tc_data(TC_CAST(class)))) + return -NLE_NOMEM; + + dsmark->cdm_bmask = mask; + dsmark->cdm_mask |= SCH_DSMARK_ATTR_MASK; + + return 0; +} + +/** + * Get bitmask of DSMARK class. + * @arg class DSMARK class. + * @return Bitmask or a negative error code. + */ +int rtnl_class_dsmark_get_bitmask(struct rtnl_class *class) +{ + struct rtnl_dsmark_class *dsmark; + + if (!(dsmark = rtnl_tc_data(TC_CAST(class)))) + return -NLE_NOMEM; + + if (dsmark->cdm_mask & SCH_DSMARK_ATTR_MASK) + return dsmark->cdm_bmask; + else + return -NLE_NOATTR; +} + +/** + * Set value of DSMARK class. + * @arg class DSMARK class to be modified. + * @arg value New value. + * @return 0 on success or a negative errror code. + */ +int rtnl_class_dsmark_set_value(struct rtnl_class *class, uint8_t value) +{ + struct rtnl_dsmark_class *dsmark; + + if (!(dsmark = rtnl_tc_data(TC_CAST(class)))) + return -NLE_NOMEM; + + dsmark->cdm_value = value; + dsmark->cdm_mask |= SCH_DSMARK_ATTR_VALUE; + + return 0; +} + +/** + * Get value of DSMARK class. + * @arg class DSMARK class. + * @return Value or a negative error code. + */ +int rtnl_class_dsmark_get_value(struct rtnl_class *class) +{ + struct rtnl_dsmark_class *dsmark; + + if (!(dsmark = rtnl_tc_data(TC_CAST(class)))) + return -NLE_NOMEM; + + if (dsmark->cdm_mask & SCH_DSMARK_ATTR_VALUE) + return dsmark->cdm_value; + else + return -NLE_NOATTR; +} + +/** @} */ + +/** + * @name Qdisc Attribute Access + * @{ + */ + +/** + * Set indices of DSMARK qdisc. + * @arg qdisc DSMARK qdisc to be modified. + * @arg indices New indices. + */ +int rtnl_qdisc_dsmark_set_indices(struct rtnl_qdisc *qdisc, uint16_t indices) +{ + struct rtnl_dsmark_qdisc *dsmark; + + if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + dsmark->qdm_indices = indices; + dsmark->qdm_mask |= SCH_DSMARK_ATTR_INDICES; + + return 0; +} + +/** + * Get indices of DSMARK qdisc. + * @arg qdisc DSMARK qdisc. + * @return Indices or a negative error code. + */ +int rtnl_qdisc_dsmark_get_indices(struct rtnl_qdisc *qdisc) +{ + struct rtnl_dsmark_qdisc *dsmark; + + if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + if (dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES) + return dsmark->qdm_indices; + else + return -NLE_NOATTR; +} + +/** + * Set default index of DSMARK qdisc. + * @arg qdisc DSMARK qdisc to be modified. + * @arg default_index New default index. + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_dsmark_set_default_index(struct rtnl_qdisc *qdisc, + uint16_t default_index) +{ + struct rtnl_dsmark_qdisc *dsmark; + + if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + dsmark->qdm_default_index = default_index; + dsmark->qdm_mask |= SCH_DSMARK_ATTR_DEFAULT_INDEX; + + return 0; +} + +/** + * Get default index of DSMARK qdisc. + * @arg qdisc DSMARK qdisc. + * @return Default index or a negative error code. + */ +int rtnl_qdisc_dsmark_get_default_index(struct rtnl_qdisc *qdisc) +{ + struct rtnl_dsmark_qdisc *dsmark; + + if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + if (dsmark->qdm_mask & SCH_DSMARK_ATTR_DEFAULT_INDEX) + return dsmark->qdm_default_index; + else + return -NLE_NOATTR; +} + +/** + * Set set-tc-index flag of DSMARK qdisc. + * @arg qdisc DSMARK qdisc to be modified. + * @arg flag Flag indicating whether to enable or disable. + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_dsmark_set_set_tc_index(struct rtnl_qdisc *qdisc, int flag) +{ + struct rtnl_dsmark_qdisc *dsmark; + + if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + dsmark->qdm_set_tc_index = !!flag; + dsmark->qdm_mask |= SCH_DSMARK_ATTR_SET_TC_INDEX; + + return 0; +} + +/** + * Get set-tc-index flag of DSMARK qdisc. + * @arg qdisc DSMARK qdisc to be modified. + * @return 1 or 0 to indicate wehther the flag is enabled or a negative + * error code. + */ +int rtnl_qdisc_dsmark_get_set_tc_index(struct rtnl_qdisc *qdisc) +{ + struct rtnl_dsmark_qdisc *dsmark; + + if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + if (dsmark->qdm_mask & SCH_DSMARK_ATTR_SET_TC_INDEX) + return dsmark->qdm_set_tc_index; + else + return -NLE_NOATTR; +} + +/** @} */ + +static struct rtnl_tc_ops dsmark_qdisc_ops = { + .to_kind = "dsmark", + .to_type = RTNL_TC_TYPE_QDISC, + .to_size = sizeof(struct rtnl_dsmark_qdisc), + .to_msg_parser = dsmark_qdisc_msg_parser, + .to_dump = { + [NL_DUMP_LINE] = dsmark_qdisc_dump_line, + [NL_DUMP_DETAILS] = dsmark_qdisc_dump_details, + }, + .to_msg_fill = dsmark_qdisc_msg_fill, +}; + +static struct rtnl_tc_ops dsmark_class_ops = { + .to_kind = "dsmark", + .to_type = RTNL_TC_TYPE_CLASS, + .to_size = sizeof(struct rtnl_dsmark_class), + .to_msg_parser = dsmark_class_msg_parser, + .to_dump[NL_DUMP_LINE] = dsmark_class_dump_line, + .to_msg_fill = dsmark_class_msg_fill, +}; + +static void __init dsmark_init(void) +{ + rtnl_tc_register(&dsmark_qdisc_ops); + rtnl_tc_register(&dsmark_class_ops); +} + +static void __exit dsmark_exit(void) +{ + rtnl_tc_unregister(&dsmark_qdisc_ops); + rtnl_tc_unregister(&dsmark_class_ops); +} + +/** @} */ diff --git a/lib/route/qdisc/fifo.c b/lib/route/qdisc/fifo.c new file mode 100644 index 0000000..d94c007 --- /dev/null +++ b/lib/route/qdisc/fifo.c @@ -0,0 +1,169 @@ +/* + * lib/route/qdisc/fifo.c (p|b)fifo + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + */ + +/** + * @ingroup qdisc + * @defgroup qdisc_fifo Packet/Bytes FIFO (pfifo/bfifo) + * @brief + * + * The FIFO qdisc comes in two flavours: + * @par bfifo (Byte FIFO) + * Allows enqueuing until the currently queued volume in bytes exceeds + * the configured limit.backlog contains currently enqueued volume in bytes. + * + * @par pfifo (Packet FIFO) + * Allows enquueing until the currently queued number of packets + * exceeds the configured limit. + * + * The configuration is exactly the same, the decision which of + * the two variations is going to be used is made based on the + * kind of the qdisc (rtnl_tc_set_kind()). + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define SCH_FIFO_ATTR_LIMIT 1 +/** @endcond */ + +static int fifo_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct rtnl_fifo *fifo = data; + struct tc_fifo_qopt *opt; + + if (tc->tc_opts->d_size < sizeof(struct tc_fifo_qopt)) + return -NLE_INVAL; + + opt = (struct tc_fifo_qopt *) tc->tc_opts->d_data; + fifo->qf_limit = opt->limit; + fifo->qf_mask = SCH_FIFO_ATTR_LIMIT; + + return 0; +} + +static void pfifo_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_fifo *fifo = data; + + if (fifo) + nl_dump(p, " limit %u packets", fifo->qf_limit); +} + +static void bfifo_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_fifo *fifo = data; + char *unit; + double r; + + if (!fifo) + return; + + r = nl_cancel_down_bytes(fifo->qf_limit, &unit); + nl_dump(p, " limit %.1f%s", r, unit); +} + +static int fifo_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + struct rtnl_fifo *fifo = data; + struct tc_fifo_qopt opts = {0}; + + if (!fifo || !(fifo->qf_mask & SCH_FIFO_ATTR_LIMIT)) + return -NLE_INVAL; + + opts.limit = fifo->qf_limit; + + return nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD); +} + +/** + * @name Attribute Modification + * @{ + */ + +/** + * Set limit of FIFO qdisc. + * @arg qdisc FIFO qdisc to be modified. + * @arg limit New limit. + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_fifo_set_limit(struct rtnl_qdisc *qdisc, int limit) +{ + struct rtnl_fifo *fifo; + + if (!(fifo = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + fifo->qf_limit = limit; + fifo->qf_mask |= SCH_FIFO_ATTR_LIMIT; + + return 0; +} + +/** + * Get limit of a FIFO qdisc. + * @arg qdisc FIFO qdisc. + * @return Numeric limit or a negative error code. + */ +int rtnl_qdisc_fifo_get_limit(struct rtnl_qdisc *qdisc) +{ + struct rtnl_fifo *fifo; + + if (!(fifo = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + if (fifo->qf_mask & SCH_FIFO_ATTR_LIMIT) + return fifo->qf_limit; + else + return -NLE_NOATTR; +} + +/** @} */ + +static struct rtnl_tc_ops pfifo_ops = { + .to_kind = "pfifo", + .to_type = RTNL_TC_TYPE_QDISC, + .to_size = sizeof(struct rtnl_fifo), + .to_msg_parser = fifo_msg_parser, + .to_dump[NL_DUMP_LINE] = pfifo_dump_line, + .to_msg_fill = fifo_msg_fill, +}; + +static struct rtnl_tc_ops bfifo_ops = { + .to_kind = "bfifo", + .to_type = RTNL_TC_TYPE_QDISC, + .to_size = sizeof(struct rtnl_fifo), + .to_msg_parser = fifo_msg_parser, + .to_dump[NL_DUMP_LINE] = bfifo_dump_line, + .to_msg_fill = fifo_msg_fill, +}; + +static void __init fifo_init(void) +{ + rtnl_tc_register(&pfifo_ops); + rtnl_tc_register(&bfifo_ops); +} + +static void __exit fifo_exit(void) +{ + rtnl_tc_unregister(&pfifo_ops); + rtnl_tc_unregister(&bfifo_ops); +} + +/** @} */ diff --git a/lib/route/qdisc/htb.c b/lib/route/qdisc/htb.c new file mode 100644 index 0000000..5a61a4e --- /dev/null +++ b/lib/route/qdisc/htb.c @@ -0,0 +1,643 @@ +/* + * lib/route/qdisc/htb.c HTB Qdisc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + * Copyright (c) 2005-2006 Petr Gotthard + * Copyright (c) 2005-2006 Siemens AG Oesterreich + */ + +/** + * @ingroup qdisc + * @ingroup class + * @defgroup qdisc_htb Hierachical Token Bucket (HTB) + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define SCH_HTB_HAS_RATE2QUANTUM 0x01 +#define SCH_HTB_HAS_DEFCLS 0x02 + +#define SCH_HTB_HAS_PRIO 0x001 +#define SCH_HTB_HAS_RATE 0x002 +#define SCH_HTB_HAS_CEIL 0x004 +#define SCH_HTB_HAS_RBUFFER 0x008 +#define SCH_HTB_HAS_CBUFFER 0x010 +#define SCH_HTB_HAS_QUANTUM 0x020 +#define SCH_HTB_HAS_LEVEL 0x040 +/** @endcond */ + +static struct nla_policy htb_policy[TCA_HTB_MAX+1] = { + [TCA_HTB_INIT] = { .minlen = sizeof(struct tc_htb_glob) }, + [TCA_HTB_PARMS] = { .minlen = sizeof(struct tc_htb_opt) }, +}; + +static int htb_qdisc_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct nlattr *tb[TCA_HTB_MAX + 1]; + struct rtnl_htb_qdisc *htb = data; + int err; + + if ((err = tca_parse(tb, TCA_HTB_MAX, tc, htb_policy)) < 0) + return err; + + if (tb[TCA_HTB_INIT]) { + struct tc_htb_glob opts; + + nla_memcpy(&opts, tb[TCA_HTB_INIT], sizeof(opts)); + htb->qh_rate2quantum = opts.rate2quantum; + htb->qh_defcls = opts.defcls; + htb->qh_direct_pkts = opts.direct_pkts; + + htb->qh_mask = (SCH_HTB_HAS_RATE2QUANTUM | SCH_HTB_HAS_DEFCLS); + } + + return 0; +} + +static int htb_class_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct nlattr *tb[TCA_HTB_MAX + 1]; + struct rtnl_htb_class *htb = data; + int err; + + if ((err = tca_parse(tb, TCA_HTB_MAX, tc, htb_policy)) < 0) + return err; + + if (tb[TCA_HTB_PARMS]) { + struct tc_htb_opt opts; + + nla_memcpy(&opts, tb[TCA_HTB_PARMS], sizeof(opts)); + htb->ch_prio = opts.prio; + rtnl_copy_ratespec(&htb->ch_rate, &opts.rate); + rtnl_copy_ratespec(&htb->ch_ceil, &opts.ceil); + htb->ch_rbuffer = rtnl_tc_calc_bufsize(nl_ticks2us(opts.buffer), + opts.rate.rate); + htb->ch_cbuffer = rtnl_tc_calc_bufsize(nl_ticks2us(opts.cbuffer), + opts.ceil.rate); + htb->ch_quantum = opts.quantum; + htb->ch_level = opts.level; + + rtnl_tc_set_mpu(tc, htb->ch_rate.rs_mpu); + rtnl_tc_set_overhead(tc, htb->ch_rate.rs_overhead); + + htb->ch_mask = (SCH_HTB_HAS_PRIO | SCH_HTB_HAS_RATE | + SCH_HTB_HAS_CEIL | SCH_HTB_HAS_RBUFFER | + SCH_HTB_HAS_CBUFFER | SCH_HTB_HAS_QUANTUM | + SCH_HTB_HAS_LEVEL); + } + + return 0; +} + +static void htb_qdisc_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_htb_qdisc *htb = data; + + if (!htb) + return; + + if (htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM) + nl_dump(p, " r2q %u", htb->qh_rate2quantum); + + if (htb->qh_mask & SCH_HTB_HAS_DEFCLS) { + char buf[64]; + nl_dump(p, " default-class %s", + rtnl_tc_handle2str(htb->qh_defcls, buf, sizeof(buf))); + } +} + +static void htb_class_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_htb_class *htb = data; + + if (!htb) + return; + + if (htb->ch_mask & SCH_HTB_HAS_RATE) { + double r, rbit; + char *ru, *rubit; + + r = nl_cancel_down_bytes(htb->ch_rate.rs_rate, &ru); + rbit = nl_cancel_down_bits(htb->ch_rate.rs_rate*8, &rubit); + + nl_dump(p, " rate %.2f%s/s (%.0f%s) log %u", + r, ru, rbit, rubit, 1<ch_rate.rs_cell_log); + } +} + +static void htb_class_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_htb_class *htb = data; + + if (!htb) + return; + + /* line 1 */ + if (htb->ch_mask & SCH_HTB_HAS_CEIL) { + double r, rbit; + char *ru, *rubit; + + r = nl_cancel_down_bytes(htb->ch_ceil.rs_rate, &ru); + rbit = nl_cancel_down_bits(htb->ch_ceil.rs_rate*8, &rubit); + + nl_dump(p, " ceil %.2f%s/s (%.0f%s) log %u", + r, ru, rbit, rubit, 1<ch_ceil.rs_cell_log); + } + + if (htb->ch_mask & SCH_HTB_HAS_PRIO) + nl_dump(p, " prio %u", htb->ch_prio); + + if (htb->ch_mask & SCH_HTB_HAS_RBUFFER) { + double b; + char *bu; + + b = nl_cancel_down_bytes(htb->ch_rbuffer, &bu); + nl_dump(p, " rbuffer %.2f%s", b, bu); + } + + if (htb->ch_mask & SCH_HTB_HAS_CBUFFER) { + double b; + char *bu; + + b = nl_cancel_down_bytes(htb->ch_cbuffer, &bu); + nl_dump(p, " cbuffer %.2f%s", b, bu); + } + + if (htb->ch_mask & SCH_HTB_HAS_QUANTUM) + nl_dump(p, " quantum %u", htb->ch_quantum); +} + +static int htb_qdisc_msg_fill(struct rtnl_tc *tc, void *data, + struct nl_msg *msg) +{ + struct rtnl_htb_qdisc *htb = data; + struct tc_htb_glob opts = { + .version = TC_HTB_PROTOVER, + .rate2quantum = 10, + }; + + if (htb) { + if (htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM) + opts.rate2quantum = htb->qh_rate2quantum; + + if (htb->qh_mask & SCH_HTB_HAS_DEFCLS) + opts.defcls = htb->qh_defcls; + } + + return nla_put(msg, TCA_HTB_INIT, sizeof(opts), &opts); +} + +static int htb_class_msg_fill(struct rtnl_tc *tc, void *data, + struct nl_msg *msg) +{ + struct rtnl_htb_class *htb = data; + uint32_t mtu, rtable[RTNL_TC_RTABLE_SIZE], ctable[RTNL_TC_RTABLE_SIZE]; + struct tc_htb_opt opts; + int buffer, cbuffer; + + if (!htb || !(htb->ch_mask & SCH_HTB_HAS_RATE)) + BUG(); + + memset(&opts, 0, sizeof(opts)); + + /* if not set, zero (0) is used as priority */ + if (htb->ch_mask & SCH_HTB_HAS_PRIO) + opts.prio = htb->ch_prio; + + mtu = rtnl_tc_get_mtu(tc); + + rtnl_tc_build_rate_table(tc, &htb->ch_rate, rtable); + rtnl_rcopy_ratespec(&opts.rate, &htb->ch_rate); + + if (htb->ch_mask & SCH_HTB_HAS_CEIL) { + rtnl_tc_build_rate_table(tc, &htb->ch_ceil, ctable); + rtnl_rcopy_ratespec(&opts.ceil, &htb->ch_ceil); + } else { + /* + * If not set, configured rate is used as ceil, which implies + * no borrowing. + */ + memcpy(&opts.ceil, &opts.rate, sizeof(struct tc_ratespec)); + } + + if (htb->ch_mask & SCH_HTB_HAS_RBUFFER) + buffer = htb->ch_rbuffer; + else + buffer = opts.rate.rate / nl_get_psched_hz() + mtu; /* XXX */ + + opts.buffer = nl_us2ticks(rtnl_tc_calc_txtime(buffer, opts.rate.rate)); + + if (htb->ch_mask & SCH_HTB_HAS_CBUFFER) + cbuffer = htb->ch_cbuffer; + else + cbuffer = opts.ceil.rate / nl_get_psched_hz() + mtu; /* XXX */ + + opts.cbuffer = nl_us2ticks(rtnl_tc_calc_txtime(cbuffer, opts.ceil.rate)); + + if (htb->ch_mask & SCH_HTB_HAS_QUANTUM) + opts.quantum = htb->ch_quantum; + + NLA_PUT(msg, TCA_HTB_PARMS, sizeof(opts), &opts); + NLA_PUT(msg, TCA_HTB_RTAB, sizeof(rtable), &rtable); + NLA_PUT(msg, TCA_HTB_CTAB, sizeof(ctable), &ctable); + + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +static struct rtnl_tc_ops htb_qdisc_ops; +static struct rtnl_tc_ops htb_class_ops; + +static struct rtnl_htb_qdisc *htb_qdisc_data(struct rtnl_qdisc *qdisc) +{ + return rtnl_tc_data_check(TC_CAST(qdisc), &htb_qdisc_ops); +} + +static struct rtnl_htb_class *htb_class_data(struct rtnl_class *class) +{ + return rtnl_tc_data_check(TC_CAST(class), &htb_class_ops); +} + +/** + * @name Attribute Modifications + * @{ + */ + +/** + * Return rate/quantum ratio of HTB qdisc + * @arg qdisc htb qdisc object + * + * @return rate/quantum ratio or 0 if unspecified + */ +uint32_t rtnl_htb_get_rate2quantum(struct rtnl_qdisc *qdisc) +{ + struct rtnl_htb_qdisc *htb; + + if ((htb = htb_qdisc_data(qdisc)) && + htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM) + return htb->qh_rate2quantum; + + return 0; +} + +int rtnl_htb_set_rate2quantum(struct rtnl_qdisc *qdisc, uint32_t rate2quantum) +{ + struct rtnl_htb_qdisc *htb; + + if (!(htb = htb_qdisc_data(qdisc))) + return -NLE_OPNOTSUPP; + + htb->qh_rate2quantum = rate2quantum; + htb->qh_mask |= SCH_HTB_HAS_RATE2QUANTUM; + + return 0; +} + +/** + * Return default class of HTB qdisc + * @arg qdisc htb qdisc object + * + * Returns the classid of the class where all unclassified traffic + * goes to. + * + * @return classid or TC_H_UNSPEC if unspecified. + */ +uint32_t rtnl_htb_get_defcls(struct rtnl_qdisc *qdisc) +{ + struct rtnl_htb_qdisc *htb; + + if ((htb = htb_qdisc_data(qdisc)) && + htb->qh_mask & SCH_HTB_HAS_DEFCLS) + return htb->qh_defcls; + + return TC_H_UNSPEC; +} + +/** + * Set default class of the htb qdisc to the specified value + * @arg qdisc qdisc to change + * @arg defcls new default class + */ +int rtnl_htb_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls) +{ + struct rtnl_htb_qdisc *htb; + + if (!(htb = htb_qdisc_data(qdisc))) + return -NLE_OPNOTSUPP; + + htb->qh_defcls = defcls; + htb->qh_mask |= SCH_HTB_HAS_DEFCLS; + + return 0; +} + +uint32_t rtnl_htb_get_prio(struct rtnl_class *class) +{ + struct rtnl_htb_class *htb; + + if ((htb = htb_class_data(class)) && htb->ch_mask & SCH_HTB_HAS_PRIO) + return htb->ch_prio; + + return 0; +} + +int rtnl_htb_set_prio(struct rtnl_class *class, uint32_t prio) +{ + struct rtnl_htb_class *htb; + + if (!(htb = htb_class_data(class))) + return -NLE_OPNOTSUPP; + + htb->ch_prio = prio; + htb->ch_mask |= SCH_HTB_HAS_PRIO; + + return 0; +} + +/** + * Return rate of HTB class + * @arg class htb class object + * + * @return Rate in bytes/s or 0 if unspecified. + */ +uint32_t rtnl_htb_get_rate(struct rtnl_class *class) +{ + struct rtnl_htb_class *htb; + + if ((htb = htb_class_data(class)) && htb->ch_mask & SCH_HTB_HAS_RATE) + return htb->ch_rate.rs_rate; + + return 0; +} + +/** + * Set rate of HTB class + * @arg class htb class object + * @arg rate new rate in bytes per second + * + * @return 0 on success or a negative error code. + */ +int rtnl_htb_set_rate(struct rtnl_class *class, uint32_t rate) +{ + struct rtnl_htb_class *htb; + + if (!(htb = htb_class_data(class))) + return -NLE_OPNOTSUPP; + + htb->ch_rate.rs_cell_log = UINT8_MAX; /* use default value */ + htb->ch_rate.rs_rate = rate; + htb->ch_mask |= SCH_HTB_HAS_RATE; + + return 0; +} + +/** + * Return ceil rate of HTB class + * @arg class htb class object + * + * @return Ceil rate in bytes/s or 0 if unspecified + */ +uint32_t rtnl_htb_get_ceil(struct rtnl_class *class) +{ + struct rtnl_htb_class *htb; + + if ((htb = htb_class_data(class)) && htb->ch_mask & SCH_HTB_HAS_CEIL) + return htb->ch_ceil.rs_rate; + + return 0; +} + +/** + * Set ceil rate of HTB class + * @arg class htb class object + * @arg ceil new ceil rate number of bytes per second + * + * @return 0 on success or a negative error code. + */ +int rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil) +{ + struct rtnl_htb_class *htb; + + if (!(htb = htb_class_data(class))) + return -NLE_OPNOTSUPP; + + htb->ch_ceil.rs_cell_log = UINT8_MAX; /* use default value */ + htb->ch_ceil.rs_rate = ceil; + htb->ch_mask |= SCH_HTB_HAS_CEIL; + + return 0; +} + +/** + * Return burst buffer size of HTB class + * @arg class htb class object + * + * @return Burst buffer size or 0 if unspecified + */ +uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *class) +{ + struct rtnl_htb_class *htb; + + if ((htb = htb_class_data(class)) && + htb->ch_mask & SCH_HTB_HAS_RBUFFER) + return htb->ch_rbuffer; + + return 0; +} + +/** + * Set size of the rate bucket of HTB class. + * @arg class HTB class to be modified. + * @arg rbuffer New size in bytes. + */ +int rtnl_htb_set_rbuffer(struct rtnl_class *class, uint32_t rbuffer) +{ + struct rtnl_htb_class *htb; + + if (!(htb = htb_class_data(class))) + return -NLE_OPNOTSUPP; + + htb->ch_rbuffer = rbuffer; + htb->ch_mask |= SCH_HTB_HAS_RBUFFER; + + return 0; +} + +/** + * Return ceil burst buffer size of HTB class + * @arg class htb class object + * + * @return Ceil burst buffer size or 0 if unspecified + */ +uint32_t rtnl_htb_get_cbuffer(struct rtnl_class *class) +{ + struct rtnl_htb_class *htb; + + if ((htb = htb_class_data(class)) && + htb->ch_mask & SCH_HTB_HAS_CBUFFER) + return htb->ch_cbuffer; + + return 0; +} + +/** + * Set size of the ceil bucket of HTB class. + * @arg class HTB class to be modified. + * @arg cbuffer New size in bytes. + */ +int rtnl_htb_set_cbuffer(struct rtnl_class *class, uint32_t cbuffer) +{ + struct rtnl_htb_class *htb; + + if (!(htb = htb_class_data(class))) + return -NLE_OPNOTSUPP; + + htb->ch_cbuffer = cbuffer; + htb->ch_mask |= SCH_HTB_HAS_CBUFFER; + + return 0; +} + +/** + * Return quantum of HTB class + * @arg class htb class object + * + * See XXX[quantum def] + * + * @return Quantum or 0 if unspecified. + */ +uint32_t rtnl_htb_get_quantum(struct rtnl_class *class) +{ + struct rtnl_htb_class *htb; + + if ((htb = htb_class_data(class)) && + htb->ch_mask & SCH_HTB_HAS_QUANTUM) + return htb->ch_quantum; + + return 0; +} + +/** + * Set quantum of HTB class (overwrites value calculated based on r2q) + * @arg class htb class object + * @arg quantum new quantum in number of bytes + * + * See XXX[quantum def] + * + * @return 0 on success or a negative error code. + */ +int rtnl_htb_set_quantum(struct rtnl_class *class, uint32_t quantum) +{ + struct rtnl_htb_class *htb; + + if (!(htb = htb_class_data(class))) + return -NLE_OPNOTSUPP; + + htb->ch_quantum = quantum; + htb->ch_mask |= SCH_HTB_HAS_QUANTUM; + + return 0; +} + +/** + * Return level of HTB class + * @arg class htb class object + * + * Returns the level of the HTB class. Leaf classes are assigned level + * 0, root classes have level (TC_HTB_MAXDEPTH - 1). Interior classes + * have a level of one less than their parent. + * + * @return Level or -NLE_OPNOTSUPP + */ +int rtnl_htb_get_level(struct rtnl_class *class) +{ + struct rtnl_htb_class *htb; + + if ((htb = htb_class_data(class)) && htb->ch_mask & SCH_HTB_HAS_LEVEL) + return htb->ch_level; + + return -NLE_OPNOTSUPP; +} + +/** + * Set level of HTB class + * @arg class htb class object + * @arg level new level of HTB class + * + * Sets the level of a HTB class. Note that changing the level of a HTB + * class does not change the level of its in kernel counterpart. This + * function is provided only to create HTB objects which can be compared + * against or filtered upon. + * + * @return 0 on success or a negative error code. + */ +int rtnl_htb_set_level(struct rtnl_class *class, int level) +{ + struct rtnl_htb_class *htb; + + if (!(htb = htb_class_data(class))) + return -NLE_OPNOTSUPP; + + htb->ch_level = level; + htb->ch_mask |= SCH_HTB_HAS_LEVEL; + + return 0; +} + +/** @} */ + +static struct rtnl_tc_ops htb_qdisc_ops = { + .to_kind = "htb", + .to_type = RTNL_TC_TYPE_QDISC, + .to_size = sizeof(struct rtnl_htb_qdisc), + .to_msg_parser = htb_qdisc_msg_parser, + .to_dump[NL_DUMP_LINE] = htb_qdisc_dump_line, + .to_msg_fill = htb_qdisc_msg_fill, +}; + +static struct rtnl_tc_ops htb_class_ops = { + .to_kind = "htb", + .to_type = RTNL_TC_TYPE_CLASS, + .to_size = sizeof(struct rtnl_htb_class), + .to_msg_parser = htb_class_msg_parser, + .to_dump = { + [NL_DUMP_LINE] = htb_class_dump_line, + [NL_DUMP_DETAILS] = htb_class_dump_details, + }, + .to_msg_fill = htb_class_msg_fill, +}; + +static void __init htb_init(void) +{ + rtnl_tc_register(&htb_qdisc_ops); + rtnl_tc_register(&htb_class_ops); +} + +static void __exit htb_exit(void) +{ + rtnl_tc_unregister(&htb_qdisc_ops); + rtnl_tc_unregister(&htb_class_ops); +} + +/** @} */ diff --git a/lib/route/qdisc/netem.c b/lib/route/qdisc/netem.c new file mode 100644 index 0000000..06d9fe8 --- /dev/null +++ b/lib/route/qdisc/netem.c @@ -0,0 +1,908 @@ +/* + * lib/route/qdisc/netem.c Network Emulator Qdisc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + */ + +/** + * @ingroup qdisc + * @defgroup qdisc_netem Network Emulator + * @brief + * + * For further documentation see http://linux-net.osdl.org/index.php/Netem + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define SCH_NETEM_ATTR_LATENCY 0x0001 +#define SCH_NETEM_ATTR_LIMIT 0x0002 +#define SCH_NETEM_ATTR_LOSS 0x0004 +#define SCH_NETEM_ATTR_GAP 0x0008 +#define SCH_NETEM_ATTR_DUPLICATE 0x0010 +#define SCH_NETEM_ATTR_JITTER 0x0020 +#define SCH_NETEM_ATTR_DELAY_CORR 0x0040 +#define SCH_NETEM_ATTR_LOSS_CORR 0x0080 +#define SCH_NETEM_ATTR_DUP_CORR 0x0100 +#define SCH_NETEM_ATTR_RO_PROB 0x0200 +#define SCH_NETEM_ATTR_RO_CORR 0x0400 +#define SCH_NETEM_ATTR_CORRUPT_PROB 0x0800 +#define SCH_NETEM_ATTR_CORRUPT_CORR 0x1000 +#define SCH_NETEM_ATTR_DIST 0x2000 +/** @endcond */ + +static struct nla_policy netem_policy[TCA_NETEM_MAX+1] = { + [TCA_NETEM_CORR] = { .minlen = sizeof(struct tc_netem_corr) }, + [TCA_NETEM_REORDER] = { .minlen = sizeof(struct tc_netem_reorder) }, + [TCA_NETEM_CORRUPT] = { .minlen = sizeof(struct tc_netem_corrupt) }, +}; + +static int netem_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct rtnl_netem *netem = data; + struct tc_netem_qopt *opts; + int len, err = 0; + + if (tc->tc_opts->d_size < sizeof(*opts)) + return -NLE_INVAL; + + opts = (struct tc_netem_qopt *) tc->tc_opts->d_data; + netem->qnm_latency = opts->latency; + netem->qnm_limit = opts->limit; + netem->qnm_loss = opts->loss; + netem->qnm_gap = opts->gap; + netem->qnm_duplicate = opts->duplicate; + netem->qnm_jitter = opts->jitter; + + netem->qnm_mask = (SCH_NETEM_ATTR_LATENCY | SCH_NETEM_ATTR_LIMIT | + SCH_NETEM_ATTR_LOSS | SCH_NETEM_ATTR_GAP | + SCH_NETEM_ATTR_DUPLICATE | SCH_NETEM_ATTR_JITTER); + + len = tc->tc_opts->d_size - sizeof(*opts); + + if (len > 0) { + struct nlattr *tb[TCA_NETEM_MAX+1]; + + err = nla_parse(tb, TCA_NETEM_MAX, (struct nlattr *) + (tc->tc_opts->d_data + sizeof(*opts)), + len, netem_policy); + if (err < 0) { + free(netem); + return err; + } + + if (tb[TCA_NETEM_CORR]) { + struct tc_netem_corr cor; + + nla_memcpy(&cor, tb[TCA_NETEM_CORR], sizeof(cor)); + netem->qnm_corr.nmc_delay = cor.delay_corr; + netem->qnm_corr.nmc_loss = cor.loss_corr; + netem->qnm_corr.nmc_duplicate = cor.dup_corr; + + netem->qnm_mask |= (SCH_NETEM_ATTR_DELAY_CORR | + SCH_NETEM_ATTR_LOSS_CORR | + SCH_NETEM_ATTR_DUP_CORR); + } + + if (tb[TCA_NETEM_REORDER]) { + struct tc_netem_reorder ro; + + nla_memcpy(&ro, tb[TCA_NETEM_REORDER], sizeof(ro)); + netem->qnm_ro.nmro_probability = ro.probability; + netem->qnm_ro.nmro_correlation = ro.correlation; + + netem->qnm_mask |= (SCH_NETEM_ATTR_RO_PROB | + SCH_NETEM_ATTR_RO_CORR); + } + + if (tb[TCA_NETEM_CORRUPT]) { + struct tc_netem_corrupt corrupt; + + nla_memcpy(&corrupt, tb[TCA_NETEM_CORRUPT], sizeof(corrupt)); + netem->qnm_crpt.nmcr_probability = corrupt.probability; + netem->qnm_crpt.nmcr_correlation = corrupt.correlation; + + netem->qnm_mask |= (SCH_NETEM_ATTR_CORRUPT_PROB | + SCH_NETEM_ATTR_CORRUPT_CORR); + } + + /* sch_netem does not currently dump TCA_NETEM_DELAY_DIST */ + netem->qnm_dist.dist_data = NULL; + netem->qnm_dist.dist_size = 0; + } + + return 0; +} + +static void netem_free_data(struct rtnl_tc *tc, void *data) +{ + struct rtnl_netem *netem = data; + + if (!netem) + return; + + free(netem->qnm_dist.dist_data); +} + +static void netem_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_netem *netem = data; + + if (netem) + nl_dump(p, "limit %d", netem->qnm_limit); +} + +static int netem_msg_fill_raw(struct rtnl_tc *tc, void *data, + struct nl_msg *msg) +{ + int err = 0; + struct tc_netem_qopt opts; + struct tc_netem_corr cor; + struct tc_netem_reorder reorder; + struct tc_netem_corrupt corrupt; + struct rtnl_netem *netem = data; + + unsigned char set_correlation = 0, set_reorder = 0, + set_corrupt = 0, set_dist = 0; + + if (!netem) + BUG(); + + memset(&opts, 0, sizeof(opts)); + memset(&cor, 0, sizeof(cor)); + memset(&reorder, 0, sizeof(reorder)); + memset(&corrupt, 0, sizeof(corrupt)); + + msg->nm_nlh->nlmsg_flags |= NLM_F_REQUEST; + + if ( netem->qnm_ro.nmro_probability != 0 ) { + if (netem->qnm_latency == 0) { + return -NLE_MISSING_ATTR; + } + if (netem->qnm_gap == 0) netem->qnm_gap = 1; + } + else if ( netem->qnm_gap ) { + return -NLE_MISSING_ATTR; + } + + if ( netem->qnm_corr.nmc_delay != 0 ) { + if ( netem->qnm_latency == 0 || netem->qnm_jitter == 0) { + return -NLE_MISSING_ATTR; + } + set_correlation = 1; + } + + if ( netem->qnm_corr.nmc_loss != 0 ) { + if ( netem->qnm_loss == 0 ) { + return -NLE_MISSING_ATTR; + } + set_correlation = 1; + } + + if ( netem->qnm_corr.nmc_duplicate != 0 ) { + if ( netem->qnm_duplicate == 0 ) { + return -NLE_MISSING_ATTR; + } + set_correlation = 1; + } + + if ( netem->qnm_ro.nmro_probability != 0 ) set_reorder = 1; + else if ( netem->qnm_ro.nmro_correlation != 0 ) { + return -NLE_MISSING_ATTR; + } + + if ( netem->qnm_crpt.nmcr_probability != 0 ) set_corrupt = 1; + else if ( netem->qnm_crpt.nmcr_correlation != 0 ) { + return -NLE_MISSING_ATTR; + } + + if ( netem->qnm_dist.dist_data && netem->qnm_dist.dist_size ) { + if (netem->qnm_latency == 0 || netem->qnm_jitter == 0) { + return -NLE_MISSING_ATTR; + } + else { + /* Resize to accomodate the large distribution table */ + int new_msg_len = msg->nm_size + netem->qnm_dist.dist_size * + sizeof(netem->qnm_dist.dist_data[0]); + + msg->nm_nlh = (struct nlmsghdr *) realloc(msg->nm_nlh, new_msg_len); + if ( msg->nm_nlh == NULL ) + return -NLE_NOMEM; + msg->nm_size = new_msg_len; + set_dist = 1; + } + } + + opts.latency = netem->qnm_latency; + opts.limit = netem->qnm_limit ? netem->qnm_limit : 1000; + opts.loss = netem->qnm_loss; + opts.gap = netem->qnm_gap; + opts.duplicate = netem->qnm_duplicate; + opts.jitter = netem->qnm_jitter; + + NLA_PUT(msg, TCA_OPTIONS, sizeof(opts), &opts); + + if ( set_correlation ) { + cor.delay_corr = netem->qnm_corr.nmc_delay; + cor.loss_corr = netem->qnm_corr.nmc_loss; + cor.dup_corr = netem->qnm_corr.nmc_duplicate; + + NLA_PUT(msg, TCA_NETEM_CORR, sizeof(cor), &cor); + } + + if ( set_reorder ) { + reorder.probability = netem->qnm_ro.nmro_probability; + reorder.correlation = netem->qnm_ro.nmro_correlation; + + NLA_PUT(msg, TCA_NETEM_REORDER, sizeof(reorder), &reorder); + } + + if ( set_corrupt ) { + corrupt.probability = netem->qnm_crpt.nmcr_probability; + corrupt.correlation = netem->qnm_crpt.nmcr_correlation; + + NLA_PUT(msg, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt); + } + + if ( set_dist ) { + NLA_PUT(msg, TCA_NETEM_DELAY_DIST, + netem->qnm_dist.dist_size * sizeof(netem->qnm_dist.dist_data[0]), + netem->qnm_dist.dist_data); + } + + /* Length specified in the TCA_OPTIONS section must span the entire + * remainder of the message. That's just the way that sch_netem expects it. + * Maybe there's a more succinct way to do this at a higher level. + */ + struct nlattr* head = (struct nlattr *)(NLMSG_DATA(msg->nm_nlh) + + NLMSG_LENGTH(sizeof(struct tcmsg)) - NLMSG_ALIGNTO); + + struct nlattr* tail = (struct nlattr *)(((void *) (msg->nm_nlh)) + + NLMSG_ALIGN(msg->nm_nlh->nlmsg_len)); + + int old_len = head->nla_len; + head->nla_len = (void *)tail - (void *)head; + msg->nm_nlh->nlmsg_len += (head->nla_len - old_len); + + return err; +nla_put_failure: + return -NLE_MSGSIZE; +} + +/** + * @name Queue Limit + * @{ + */ + +/** + * Set limit of netem qdisc. + * @arg qdisc Netem qdisc to be modified. + * @arg limit New limit in bytes. + * @return 0 on success or a negative error code. + */ +void rtnl_netem_set_limit(struct rtnl_qdisc *qdisc, int limit) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + netem->qnm_limit = limit; + netem->qnm_mask |= SCH_NETEM_ATTR_LIMIT; +} + +/** + * Get limit of netem qdisc. + * @arg qdisc Netem qdisc. + * @return Limit in bytes or a negative error code. + */ +int rtnl_netem_get_limit(struct rtnl_qdisc *qdisc) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + if (netem->qnm_mask & SCH_NETEM_ATTR_LIMIT) + return netem->qnm_limit; + else + return -NLE_NOATTR; +} + +/** @} */ + +/** + * @name Packet Re-ordering + * @{ + */ + +/** + * Set re-ordering gap of netem qdisc. + * @arg qdisc Netem qdisc to be modified. + * @arg gap New gap in number of packets. + * @return 0 on success or a negative error code. + */ +void rtnl_netem_set_gap(struct rtnl_qdisc *qdisc, int gap) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + netem->qnm_gap = gap; + netem->qnm_mask |= SCH_NETEM_ATTR_GAP; +} + +/** + * Get re-ordering gap of netem qdisc. + * @arg qdisc Netem qdisc. + * @return Re-ordering gap in packets or a negative error code. + */ +int rtnl_netem_get_gap(struct rtnl_qdisc *qdisc) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + if (netem->qnm_mask & SCH_NETEM_ATTR_GAP) + return netem->qnm_gap; + else + return -NLE_NOATTR; +} + +/** + * Set re-ordering probability of netem qdisc. + * @arg qdisc Netem qdisc to be modified. + * @arg prob New re-ordering probability. + * @return 0 on success or a negative error code. + */ +void rtnl_netem_set_reorder_probability(struct rtnl_qdisc *qdisc, int prob) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + netem->qnm_ro.nmro_probability = prob; + netem->qnm_mask |= SCH_NETEM_ATTR_RO_PROB; +} + +/** + * Get re-ordering probability of netem qdisc. + * @arg qdisc Netem qdisc. + * @return Re-ordering probability or a negative error code. + */ +int rtnl_netem_get_reorder_probability(struct rtnl_qdisc *qdisc) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + if (netem->qnm_mask & SCH_NETEM_ATTR_RO_PROB) + return netem->qnm_ro.nmro_probability; + else + return -NLE_NOATTR; +} + +/** + * Set re-order correlation probability of netem qdisc. + * @arg qdisc Netem qdisc to be modified. + * @arg prob New re-ordering correlation probability. + * @return 0 on success or a negative error code. + */ +void rtnl_netem_set_reorder_correlation(struct rtnl_qdisc *qdisc, int prob) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + netem->qnm_ro.nmro_correlation = prob; + netem->qnm_mask |= SCH_NETEM_ATTR_RO_CORR; +} + +/** + * Get re-ordering correlation probability of netem qdisc. + * @arg qdisc Netem qdisc. + * @return Re-ordering correlation probability or a negative error code. + */ +int rtnl_netem_get_reorder_correlation(struct rtnl_qdisc *qdisc) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + if (netem->qnm_mask & SCH_NETEM_ATTR_RO_CORR) + return netem->qnm_ro.nmro_correlation; + else + return -NLE_NOATTR; +} + +/** @} */ + +/** + * @name Corruption + * @{ + */ + +/** + * Set corruption probability of netem qdisc. + * @arg qdisc Netem qdisc to be modified. + * @arg prob New corruption probability. + * @return 0 on success or a negative error code. + */ +void rtnl_netem_set_corruption_probability(struct rtnl_qdisc *qdisc, int prob) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + netem->qnm_crpt.nmcr_probability = prob; + netem->qnm_mask |= SCH_NETEM_ATTR_CORRUPT_PROB; +} + +/** + * Get corruption probability of netem qdisc. + * @arg qdisc Netem qdisc. + * @return Corruption probability or a negative error code. + */ +int rtnl_netem_get_corruption_probability(struct rtnl_qdisc *qdisc) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (netem->qnm_mask & SCH_NETEM_ATTR_CORRUPT_PROB) + return netem->qnm_crpt.nmcr_probability; + else + return -NLE_NOATTR; +} + +/** + * Set corruption correlation probability of netem qdisc. + * @arg qdisc Netem qdisc to be modified. + * @arg prob New corruption correlation probability. + * @return 0 on success or a negative error code. + */ +void rtnl_netem_set_corruption_correlation(struct rtnl_qdisc *qdisc, int prob) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + netem->qnm_crpt.nmcr_correlation = prob; + netem->qnm_mask |= SCH_NETEM_ATTR_CORRUPT_CORR; +} + +/** + * Get corruption correlation probability of netem qdisc. + * @arg qdisc Netem qdisc. + * @return Corruption correlation probability or a negative error code. + */ +int rtnl_netem_get_corruption_correlation(struct rtnl_qdisc *qdisc) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (netem->qnm_mask & SCH_NETEM_ATTR_CORRUPT_CORR) + return netem->qnm_crpt.nmcr_correlation; + else + return -NLE_NOATTR; +} + +/** @} */ + +/** + * @name Packet Loss + * @{ + */ + +/** + * Set packet loss probability of netem qdisc. + * @arg qdisc Netem qdisc to be modified. + * @arg prob New packet loss probability. + * @return 0 on success or a negative error code. + */ +void rtnl_netem_set_loss(struct rtnl_qdisc *qdisc, int prob) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + netem->qnm_loss = prob; + netem->qnm_mask |= SCH_NETEM_ATTR_LOSS; +} + +/** + * Get packet loss probability of netem qdisc. + * @arg qdisc Netem qdisc. + * @return Packet loss probability or a negative error code. + */ +int rtnl_netem_get_loss(struct rtnl_qdisc *qdisc) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (netem->qnm_mask & SCH_NETEM_ATTR_LOSS) + return netem->qnm_loss; + else + return -NLE_NOATTR; +} + +/** + * Set packet loss correlation probability of netem qdisc. + * @arg qdisc Netem qdisc to be modified. + * @arg prob New packet loss correlation. + * @return 0 on success or a negative error code. + */ +void rtnl_netem_set_loss_correlation(struct rtnl_qdisc *qdisc, int prob) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + netem->qnm_corr.nmc_loss = prob; + netem->qnm_mask |= SCH_NETEM_ATTR_LOSS_CORR; +} + +/** + * Get packet loss correlation probability of netem qdisc. + * @arg qdisc Netem qdisc. + * @return Packet loss correlation probability or a negative error code. + */ +int rtnl_netem_get_loss_correlation(struct rtnl_qdisc *qdisc) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (netem->qnm_mask & SCH_NETEM_ATTR_LOSS_CORR) + return netem->qnm_corr.nmc_loss; + else + return -NLE_NOATTR; +} + +/** @} */ + +/** + * @name Packet Duplication + * @{ + */ + +/** + * Set packet duplication probability of netem qdisc. + * @arg qdisc Netem qdisc to be modified. + * @arg prob New packet duplication probability. + * @return 0 on success or a negative error code. + */ +void rtnl_netem_set_duplicate(struct rtnl_qdisc *qdisc, int prob) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + netem->qnm_duplicate = prob; + netem->qnm_mask |= SCH_NETEM_ATTR_DUPLICATE; +} + +/** + * Get packet duplication probability of netem qdisc. + * @arg qdisc Netem qdisc. + * @return Packet duplication probability or a negative error code. + */ +int rtnl_netem_get_duplicate(struct rtnl_qdisc *qdisc) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (netem->qnm_mask & SCH_NETEM_ATTR_DUPLICATE) + return netem->qnm_duplicate; + else + return -NLE_NOATTR; +} + +/** + * Set packet duplication correlation probability of netem qdisc. + * @arg qdisc Netem qdisc to be modified. + * @arg prob New packet duplication correlation probability. + * @return 0 on sucess or a negative error code. + */ +void rtnl_netem_set_duplicate_correlation(struct rtnl_qdisc *qdisc, int prob) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + netem->qnm_corr.nmc_duplicate = prob; + netem->qnm_mask |= SCH_NETEM_ATTR_DUP_CORR; +} + +/** + * Get packet duplication correlation probability of netem qdisc. + * @arg qdisc Netem qdisc. + * @return Packet duplication correlation probability or a negative error code. + */ +int rtnl_netem_get_duplicate_correlation(struct rtnl_qdisc *qdisc) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (netem->qnm_mask & SCH_NETEM_ATTR_DUP_CORR) + return netem->qnm_corr.nmc_duplicate; + else + return -NLE_NOATTR; +} + +/** @} */ + +/** + * @name Packet Delay + * @{ + */ + +/** + * Set packet delay of netem qdisc. + * @arg qdisc Netem qdisc to be modified. + * @arg delay New packet delay in micro seconds. + * @return 0 on success or a negative error code. + */ +void rtnl_netem_set_delay(struct rtnl_qdisc *qdisc, int delay) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + netem->qnm_latency = nl_us2ticks(delay); + netem->qnm_mask |= SCH_NETEM_ATTR_LATENCY; +} + +/** + * Get packet delay of netem qdisc. + * @arg qdisc Netem qdisc. + * @return Packet delay in micro seconds or a negative error code. + */ +int rtnl_netem_get_delay(struct rtnl_qdisc *qdisc) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (netem->qnm_mask & SCH_NETEM_ATTR_LATENCY) + return nl_ticks2us(netem->qnm_latency); + else + return -NLE_NOATTR; +} + +/** + * Set packet delay jitter of netem qdisc. + * @arg qdisc Netem qdisc to be modified. + * @arg jitter New packet delay jitter in micro seconds. + * @return 0 on success or a negative error code. + */ +void rtnl_netem_set_jitter(struct rtnl_qdisc *qdisc, int jitter) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + netem->qnm_jitter = nl_us2ticks(jitter); + netem->qnm_mask |= SCH_NETEM_ATTR_JITTER; +} + +/** + * Get packet delay jitter of netem qdisc. + * @arg qdisc Netem qdisc. + * @return Packet delay jitter in micro seconds or a negative error code. + */ +int rtnl_netem_get_jitter(struct rtnl_qdisc *qdisc) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (netem->qnm_mask & SCH_NETEM_ATTR_JITTER) + return nl_ticks2us(netem->qnm_jitter); + else + return -NLE_NOATTR; +} + +/** + * Set packet delay correlation probability of netem qdisc. + * @arg qdisc Netem qdisc to be modified. + * @arg prob New packet delay correlation probability. + */ +void rtnl_netem_set_delay_correlation(struct rtnl_qdisc *qdisc, int prob) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + netem->qnm_corr.nmc_delay = prob; + netem->qnm_mask |= SCH_NETEM_ATTR_DELAY_CORR; +} + +/** + * Get packet delay correlation probability of netem qdisc. + * @arg qdisc Netem qdisc. + * @return Packet delay correlation probability or a negative error code. + */ +int rtnl_netem_get_delay_correlation(struct rtnl_qdisc *qdisc) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (netem->qnm_mask & SCH_NETEM_ATTR_DELAY_CORR) + return netem->qnm_corr.nmc_delay; + else + return -NLE_NOATTR; +} + +/** + * Get the size of the distribution table. + * @arg qdisc Netem qdisc. + * @return Distribution table size or a negative error code. + */ +int rtnl_netem_get_delay_distribution_size(struct rtnl_qdisc *qdisc) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (netem->qnm_mask & SCH_NETEM_ATTR_DIST) + return netem->qnm_dist.dist_size; + else + return -NLE_NOATTR; +} + +/** + * Get a pointer to the distribution table. + * @arg qdisc Netem qdisc. + * @arg dist_ptr The pointer to set. + * @return Negative error code on failure or 0 on success. + */ +int rtnl_netem_get_delay_distribution(struct rtnl_qdisc *qdisc, int16_t **dist_ptr) +{ + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (netem->qnm_mask & SCH_NETEM_ATTR_DIST) { + *dist_ptr = netem->qnm_dist.dist_data; + return 0; + } else + return -NLE_NOATTR; +} + +/** + * Set the delay distribution. Latency/jitter must be set before applying. + * @arg qdisc Netem qdisc. + * @arg dist_type The name of the distribution (type, file, path/file). + * @return 0 on success, error code on failure. + */ +int rtnl_netem_set_delay_distribution(struct rtnl_qdisc *qdisc, const char *dist_type) { + struct rtnl_netem *netem; + + if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + FILE *f; + int n = 0; + size_t i; + size_t len = 2048; + char *line; + char name[NAME_MAX]; + char dist_suffix[] = ".dist"; + + /* If the given filename already ends in .dist, don't append it later */ + char *test_suffix = strstr(dist_type, dist_suffix); + if (test_suffix != NULL && strlen(test_suffix) == 5) + strcpy(dist_suffix, ""); + + /* Check several locations for the dist file */ + char *test_path[] = { "", "./", "/usr/lib/tc/", "/usr/local/lib/tc/" }; + + for (i = 0; i < ARRAY_SIZE(test_path); i++) { + snprintf(name, NAME_MAX, "%s%s%s", test_path[i], dist_type, dist_suffix); + if ((f = fopen(name, "r"))) + break; + } + + if ( f == NULL ) + return -nl_syserr2nlerr(errno); + + netem->qnm_dist.dist_data = (int16_t *) calloc (MAXDIST, sizeof(int16_t)); + + line = (char *) calloc (sizeof(char), len + 1); + + while (getline(&line, &len, f) != -1) { + char *p, *endp; + + if (*line == '\n' || *line == '#') + continue; + + for (p = line; ; p = endp) { + long x = strtol(p, &endp, 0); + if (endp == p) break; + + if (n >= MAXDIST) { + free(line); + fclose(f); + return -NLE_INVAL; + } + netem->qnm_dist.dist_data[n++] = x; + } + } + + free(line); + + netem->qnm_dist.dist_size = n; + netem->qnm_mask |= SCH_NETEM_ATTR_DIST; + + fclose(f); + return 0; +} + +/** @} */ + +static struct rtnl_tc_ops netem_ops = { + .to_kind = "netem", + .to_type = RTNL_TC_TYPE_QDISC, + .to_size = sizeof(struct rtnl_netem), + .to_msg_parser = netem_msg_parser, + .to_free_data = netem_free_data, + .to_dump[NL_DUMP_LINE] = netem_dump_line, + .to_msg_fill_raw = netem_msg_fill_raw, +}; + +static void __init netem_init(void) +{ + rtnl_tc_register(&netem_ops); +} + +static void __exit netem_exit(void) +{ + rtnl_tc_unregister(&netem_ops); +} + +/** @} */ diff --git a/lib/route/qdisc/plug.c b/lib/route/qdisc/plug.c new file mode 100644 index 0000000..9f53637 --- /dev/null +++ b/lib/route/qdisc/plug.c @@ -0,0 +1,177 @@ +/* + * lib/route/qdisc/plug.c PLUG Qdisc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2012 Shriram Rajagopalan + */ + +/** + * @ingroup qdisc + * @defgroup qdisc_plug Plug/Unplug Traffic (PLUG) + * @brief + * + * Queue traffic until an explicit release command. + * + * There are two ways to use this qdisc: + * 1. A simple "instantaneous" plug/unplug operation, by issuing an alternating + * sequence of TCQ_PLUG_BUFFER & TCQ_PLUG_RELEASE_INDEFINITE commands. + * + * 2. For network output buffering (a.k.a output commit) functionality. + * Output commit property is commonly used by applications using checkpoint + * based fault-tolerance to ensure that the checkpoint from which a system + * is being restored is consistent w.r.t outside world. + * + * Consider for e.g. Remus - a Virtual Machine checkpointing system, + * wherein a VM is checkpointed, say every 50ms. The checkpoint is replicated + * asynchronously to the backup host, while the VM continues executing the + * next epoch speculatively. + * + * The following is a typical sequence of output buffer operations: + * 1.At epoch i, start_buffer(i) + * 2. At end of epoch i (i.e. after 50ms): + * 2.1 Stop VM and take checkpoint(i). + * 2.2 start_buffer(i+1) and Resume VM + * 3. While speculatively executing epoch(i+1), asynchronously replicate + * checkpoint(i) to backup host. + * 4. When checkpoint_ack(i) is received from backup, release_buffer(i) + * Thus, this Qdisc would receive the following sequence of commands: + * TCQ_PLUG_BUFFER (epoch i) + * .. TCQ_PLUG_BUFFER (epoch i+1) + * ....TCQ_PLUG_RELEASE_ONE (epoch i) + * ......TCQ_PLUG_BUFFER (epoch i+2) + * ........ + * + * + * State of the queue, when used for network output buffering: + * + * plug(i+1) plug(i) head + * ------------------+--------------------+----------------> + * | | + * | | + * pkts_current_epoch| pkts_last_epoch |pkts_to_release + * ----------------->|<--------+--------->|+---------------> + * v v + * + * + * @{ + */ + +#include +#include +#include +#include +#include +#include + +static int plug_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + struct rtnl_plug *plug = data; + struct tc_plug_qopt opts; + + if (!plug) + return -NLE_INVAL; + + opts.action = plug->action; + opts.limit = plug->limit; + + return nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD); +} + +/** + * @name Attribute Modification + * @{ + */ + +/** + * Insert a plug into the qdisc and buffer any incoming + * network traffic. + * @arg qdisc PLUG qdisc to be modified. + */ +int rtnl_qdisc_plug_buffer(struct rtnl_qdisc *qdisc) +{ + struct rtnl_plug *plug; + + if (!(plug = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + plug->action = TCQ_PLUG_BUFFER; + return 0; +} + +/** + * Unplug the qdisc, releasing packets from queue head + * to the last complete buffer, while new traffic + * continues to be buffered. + * @arg qdisc PLUG qdisc to be modified. + */ +int rtnl_qdisc_plug_release_one(struct rtnl_qdisc *qdisc) +{ + struct rtnl_plug *plug; + + if (!(plug = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + plug->action = TCQ_PLUG_RELEASE_ONE; + return 0; +} + +/** + * Indefinitely unplug the qdisc, releasing all packets. + * Network traffic will not be buffered until the next + * buffer command is issued. + * @arg qdisc PLUG qdisc to be modified. + */ +int rtnl_qdisc_plug_release_indefinite(struct rtnl_qdisc *qdisc) +{ + struct rtnl_plug *plug; + + if (!(plug = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + plug->action = TCQ_PLUG_RELEASE_INDEFINITE; + return 0; +} + +/** + * Set limit of PLUG qdisc. + * @arg qdisc PLUG qdisc to be modified. + * @arg limit New limit. + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_plug_set_limit(struct rtnl_qdisc *qdisc, int limit) +{ + struct rtnl_plug *plug; + + if (!(plug = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + plug->action = TCQ_PLUG_LIMIT; + plug->limit = limit; + + return 0; +} + +/** @} */ + +static struct rtnl_tc_ops plug_ops = { + .to_kind = "plug", + .to_type = RTNL_TC_TYPE_QDISC, + .to_size = sizeof(struct rtnl_plug), + .to_msg_fill = plug_msg_fill, +}; + +static void __init plug_init(void) +{ + rtnl_tc_register(&plug_ops); +} + +static void __exit plug_exit(void) +{ + rtnl_tc_unregister(&plug_ops); +} + +/** @} */ diff --git a/lib/route/qdisc/prio.c b/lib/route/qdisc/prio.c new file mode 100644 index 0000000..54a46f0 --- /dev/null +++ b/lib/route/qdisc/prio.c @@ -0,0 +1,294 @@ +/* + * lib/route/qdisc/prio.c PRIO Qdisc/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) 2003-2011 Thomas Graf + */ + +/** + * @ingroup qdisc + * @defgroup qdisc_prio (Fast) Prio + * @brief + * + * @par 1) Typical PRIO configuration + * @code + * // Specify the maximal number of bands to be used for this PRIO qdisc. + * rtnl_qdisc_prio_set_bands(qdisc, QDISC_PRIO_DEFAULT_BANDS); + * + * // Provide a map assigning each priority to a band number. + * uint8_t map[] = QDISC_PRIO_DEFAULT_PRIOMAP; + * rtnl_qdisc_prio_set_priomap(qdisc, map, sizeof(map)); + * @endcode + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define SCH_PRIO_ATTR_BANDS 1 +#define SCH_PRIO_ATTR_PRIOMAP 2 +/** @endcond */ + +static int prio_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct rtnl_prio *prio = data; + struct tc_prio_qopt *opt; + + if (tc->tc_opts->d_size < sizeof(*opt)) + return -NLE_INVAL; + + opt = (struct tc_prio_qopt *) tc->tc_opts->d_data; + prio->qp_bands = opt->bands; + memcpy(prio->qp_priomap, opt->priomap, sizeof(prio->qp_priomap)); + prio->qp_mask = (SCH_PRIO_ATTR_BANDS | SCH_PRIO_ATTR_PRIOMAP); + + return 0; +} + +static void prio_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_prio *prio = data; + + if (prio) + nl_dump(p, " bands %u", prio->qp_bands); +} + +static void prio_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_prio *prio = data; + int i, hp; + + if (!prio) + return; + + nl_dump(p, "priomap ["); + + for (i = 0; i <= TC_PRIO_MAX; i++) + nl_dump(p, "%u%s", prio->qp_priomap[i], + i < TC_PRIO_MAX ? " " : ""); + + nl_dump(p, "]\n"); + nl_new_line(p); + + hp = (((TC_PRIO_MAX/2) + 1) & ~1); + + for (i = 0; i < hp; i++) { + char a[32]; + nl_dump(p, " %18s => %u", + rtnl_prio2str(i, a, sizeof(a)), + prio->qp_priomap[i]); + if (hp+i <= TC_PRIO_MAX) { + nl_dump(p, " %18s => %u", + rtnl_prio2str(hp+i, a, sizeof(a)), + prio->qp_priomap[hp+i]); + if (i < (hp - 1)) { + nl_dump(p, "\n"); + nl_new_line(p); + } + } + } +} + +static int prio_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + struct rtnl_prio *prio = data; + struct tc_prio_qopt opts; + + if (!prio || !(prio->qp_mask & SCH_PRIO_ATTR_PRIOMAP)) + BUG(); + + opts.bands = prio->qp_bands; + memcpy(opts.priomap, prio->qp_priomap, sizeof(opts.priomap)); + + return nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD); +} + +/** + * @name Attribute Modification + * @{ + */ + +/** + * Set number of bands of PRIO qdisc. + * @arg qdisc PRIO qdisc to be modified. + * @arg bands New number of bands. + * @return 0 on success or a negative error code. + */ +void rtnl_qdisc_prio_set_bands(struct rtnl_qdisc *qdisc, int bands) +{ + struct rtnl_prio *prio; + + if (!(prio = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + prio->qp_bands = bands; + prio->qp_mask |= SCH_PRIO_ATTR_BANDS; +} + +/** + * Get number of bands of PRIO qdisc. + * @arg qdisc PRIO qdisc. + * @return Number of bands or a negative error code. + */ +int rtnl_qdisc_prio_get_bands(struct rtnl_qdisc *qdisc) +{ + struct rtnl_prio *prio; + + if (!(prio = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (prio->qp_mask & SCH_PRIO_ATTR_BANDS) + return prio->qp_bands; + else + return -NLE_NOMEM; +} + +/** + * Set priomap of the PRIO qdisc. + * @arg qdisc PRIO qdisc to be modified. + * @arg priomap New priority mapping. + * @arg len Length of priomap (# of elements). + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_prio_set_priomap(struct rtnl_qdisc *qdisc, uint8_t priomap[], + int len) +{ + struct rtnl_prio *prio; + int i; + + if (!(prio = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (!(prio->qp_mask & SCH_PRIO_ATTR_BANDS)) + return -NLE_MISSING_ATTR; + + if ((len / sizeof(uint8_t)) > (TC_PRIO_MAX+1)) + return -NLE_RANGE; + + for (i = 0; i <= TC_PRIO_MAX; i++) { + if (priomap[i] > prio->qp_bands) + return -NLE_RANGE; + } + + memcpy(prio->qp_priomap, priomap, len); + prio->qp_mask |= SCH_PRIO_ATTR_PRIOMAP; + + return 0; +} + +/** + * Get priomap of a PRIO qdisc. + * @arg qdisc PRIO qdisc. + * @return Priority mapping as array of size TC_PRIO_MAX+1 + * or NULL if an error occured. + */ +uint8_t *rtnl_qdisc_prio_get_priomap(struct rtnl_qdisc *qdisc) +{ + struct rtnl_prio *prio; + + if (!(prio = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (prio->qp_mask & SCH_PRIO_ATTR_PRIOMAP) + return prio->qp_priomap; + else + return NULL; +} + +/** @} */ + +/** + * @name Priority Band Translations + * @{ + */ + +static const struct trans_tbl prios[] = { + __ADD(TC_PRIO_BESTEFFORT,besteffort) + __ADD(TC_PRIO_FILLER,filler) + __ADD(TC_PRIO_BULK,bulk) + __ADD(TC_PRIO_INTERACTIVE_BULK,interactive_bulk) + __ADD(TC_PRIO_INTERACTIVE,interactive) + __ADD(TC_PRIO_CONTROL,control) +}; + +/** + * Convert priority to character string. + * @arg prio Priority. + * @arg buf Destination buffer + * @arg size Size of destination buffer. + * + * Converts a priority to a character string and stores the result in + * the specified destination buffer. + * + * @return Name of priority as character string. + */ +char * rtnl_prio2str(int prio, char *buf, size_t size) +{ + return __type2str(prio, buf, size, prios, ARRAY_SIZE(prios)); +} + +/** + * Convert character string to priority. + * @arg name Name of priority. + * + * Converts the provided character string specifying a priority + * to the corresponding numeric value. + * + * @return Numeric priority or a negative value if no match was found. + */ +int rtnl_str2prio(const char *name) +{ + return __str2type(name, prios, ARRAY_SIZE(prios)); +} + +/** @} */ + +static struct rtnl_tc_ops prio_ops = { + .to_kind = "prio", + .to_type = RTNL_TC_TYPE_QDISC, + .to_size = sizeof(struct rtnl_prio), + .to_msg_parser = prio_msg_parser, + .to_dump = { + [NL_DUMP_LINE] = prio_dump_line, + [NL_DUMP_DETAILS] = prio_dump_details, + }, + .to_msg_fill = prio_msg_fill, +}; + +static struct rtnl_tc_ops pfifo_fast_ops = { + .to_kind = "pfifo_fast", + .to_type = RTNL_TC_TYPE_QDISC, + .to_size = sizeof(struct rtnl_prio), + .to_msg_parser = prio_msg_parser, + .to_dump = { + [NL_DUMP_LINE] = prio_dump_line, + [NL_DUMP_DETAILS] = prio_dump_details, + }, + .to_msg_fill = prio_msg_fill, +}; + +static void __init prio_init(void) +{ + rtnl_tc_register(&prio_ops); + rtnl_tc_register(&pfifo_fast_ops); +} + +static void __exit prio_exit(void) +{ + rtnl_tc_unregister(&prio_ops); + rtnl_tc_unregister(&pfifo_fast_ops); +} + +/** @} */ diff --git a/lib/route/qdisc/red.c b/lib/route/qdisc/red.c new file mode 100644 index 0000000..f05626e --- /dev/null +++ b/lib/route/qdisc/red.c @@ -0,0 +1,190 @@ +/* + * lib/route/qdisc/red.c RED Qdisc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + */ + +/** + * @ingroup qdisc + * @defgroup qdisc_red Random Early Detection (RED) + * @brief + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define RED_ATTR_LIMIT 0x01 +#define RED_ATTR_QTH_MIN 0x02 +#define RED_ATTR_QTH_MAX 0x04 +#define RED_ATTR_FLAGS 0x08 +#define RED_ATTR_WLOG 0x10 +#define RED_ATTR_PLOG 0x20 +#define RED_ATTR_SCELL_LOG 0x40 +/** @endcond */ + +static struct nla_policy red_policy[TCA_RED_MAX+1] = { + [TCA_RED_PARMS] = { .minlen = sizeof(struct tc_red_qopt) }, +}; + +static int red_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct nlattr *tb[TCA_RED_MAX+1]; + struct rtnl_red *red = data; + struct tc_red_qopt *opts; + int err; + + if (!(tc->ce_mask & TCA_ATTR_OPTS)) + return 0; + + err = tca_parse(tb, TCA_RED_MAX, tc, red_policy); + if (err < 0) + return err; + + if (!tb[TCA_RED_PARMS]) + return -NLE_MISSING_ATTR; + + opts = nla_data(tb[TCA_RED_PARMS]); + + red->qr_limit = opts->limit; + red->qr_qth_min = opts->qth_min; + red->qr_qth_max = opts->qth_max; + red->qr_flags = opts->flags; + red->qr_wlog = opts->Wlog; + red->qr_plog = opts->Plog; + red->qr_scell_log = opts->Scell_log; + + red->qr_mask = (RED_ATTR_LIMIT | RED_ATTR_QTH_MIN | RED_ATTR_QTH_MAX | + RED_ATTR_FLAGS | RED_ATTR_WLOG | RED_ATTR_PLOG | + RED_ATTR_SCELL_LOG); + + return 0; +} + +static void red_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_red *red = data; + + if (red) { + /* XXX: limit, min, max, flags */ + } +} + +static void red_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_red *red = data; + + if (red) { + /* XXX: wlog, plog, scell_log */ + } +} + +static void red_dump_stats(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_red *red = data; + + if (red) { + /* XXX: xstats */ + } +} + +static int red_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + struct rtnl_red *red = data; + + if (!red) + BUG(); + +#if 0 + memset(&opts, 0, sizeof(opts)); + opts.quantum = sfq->qs_quantum; + opts.perturb_period = sfq->qs_perturb; + opts.limit = sfq->qs_limit; + + if (nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD) < 0) + goto errout; +#endif + + return -NLE_OPNOTSUPP; +} + +/** + * @name Attribute Access + * @{ + */ + +/** + * Set limit of RED qdisc. + * @arg qdisc RED qdisc to be modified. + * @arg limit New limit in number of packets. + * @return 0 on success or a negative error code. + */ +void rtnl_red_set_limit(struct rtnl_qdisc *qdisc, int limit) +{ + struct rtnl_red *red; + + if (!(red = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + red->qr_limit = limit; + red->qr_mask |= RED_ATTR_LIMIT; +} + +/** + * Get limit of RED qdisc. + * @arg qdisc RED qdisc. + * @return Limit or a negative error code. + */ +int rtnl_red_get_limit(struct rtnl_qdisc *qdisc) +{ + struct rtnl_red *red; + + if (!(red = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (red->qr_mask & RED_ATTR_LIMIT) + return red->qr_limit; + else + return -NLE_NOATTR; +} + +/** @} */ + +static struct rtnl_tc_ops red_ops = { + .to_kind = "red", + .to_type = RTNL_TC_TYPE_QDISC, + .to_size = sizeof(struct rtnl_red), + .to_msg_parser = red_msg_parser, + .to_dump = { + [NL_DUMP_LINE] = red_dump_line, + [NL_DUMP_DETAILS] = red_dump_details, + [NL_DUMP_STATS] = red_dump_stats, + }, + .to_msg_fill = red_msg_fill, +}; + +static void __init red_init(void) +{ + rtnl_tc_register(&red_ops); +} + +static void __exit red_exit(void) +{ + rtnl_tc_unregister(&red_ops); +} + +/** @} */ diff --git a/lib/route/qdisc/sfq.c b/lib/route/qdisc/sfq.c new file mode 100644 index 0000000..acbb4ef --- /dev/null +++ b/lib/route/qdisc/sfq.c @@ -0,0 +1,256 @@ +/* + * lib/route/qdisc/sfq.c SFQ Qdisc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + */ + +/** + * @ingroup qdisc + * @defgroup qdisc_sfq Stochastic Fairness Queueing (SFQ) + * @brief + * + * @par Parameter Description + * - \b Quantum: Number of bytes to send out per slot and round. + * - \b Perturbation: Timer period between changing the hash function. + * - \b Limit: Upper limit of queue in number of packets before SFQ starts + * dropping packets. + * - \b Divisor: Hash table divisor, i.e. size of hash table. + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define SCH_SFQ_ATTR_QUANTUM 0x01 +#define SCH_SFQ_ATTR_PERTURB 0x02 +#define SCH_SFQ_ATTR_LIMIT 0x04 +#define SCH_SFQ_ATTR_DIVISOR 0x08 +#define SCH_SFQ_ATTR_FLOWS 0x10 +/** @endcond */ + +static int sfq_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct rtnl_sfq *sfq = data; + struct tc_sfq_qopt *opts; + + if (!(tc->ce_mask & TCA_ATTR_OPTS)) + return 0; + + if (tc->tc_opts->d_size < sizeof(*opts)) + return -NLE_INVAL; + + opts = (struct tc_sfq_qopt *) tc->tc_opts->d_data; + + sfq->qs_quantum = opts->quantum; + sfq->qs_perturb = opts->perturb_period; + sfq->qs_limit = opts->limit; + sfq->qs_divisor = opts->divisor; + sfq->qs_flows = opts->flows; + + sfq->qs_mask = (SCH_SFQ_ATTR_QUANTUM | SCH_SFQ_ATTR_PERTURB | + SCH_SFQ_ATTR_LIMIT | SCH_SFQ_ATTR_DIVISOR | + SCH_SFQ_ATTR_FLOWS); + + return 0; +} + +static void sfq_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_sfq *sfq = data; + + if (sfq) + nl_dump(p, " quantum %u perturb %us", sfq->qs_quantum, + sfq->qs_perturb); +} + +static void sfq_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_sfq *sfq = data; + + if (sfq) + nl_dump(p, "limit %u divisor %u", + sfq->qs_limit, sfq->qs_divisor); +} + +static int sfq_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + struct rtnl_sfq *sfq = data; + struct tc_sfq_qopt opts = {0}; + + if (!sfq) + BUG(); + + opts.quantum = sfq->qs_quantum; + opts.perturb_period = sfq->qs_perturb; + opts.limit = sfq->qs_limit; + + return nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD); +} + +/** + * @name Attribute Access + * @{ + */ + +/** + * Set quantum of SFQ qdisc. + * @arg qdisc SFQ qdisc to be modified. + * @arg quantum New quantum in bytes. + * @return 0 on success or a negative error code. + */ +void rtnl_sfq_set_quantum(struct rtnl_qdisc *qdisc, int quantum) +{ + struct rtnl_sfq *sfq; + + if (!(sfq = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + sfq->qs_quantum = quantum; + sfq->qs_mask |= SCH_SFQ_ATTR_QUANTUM; +} + +/** + * Get quantum of SFQ qdisc. + * @arg qdisc SFQ qdisc. + * @return Quantum in bytes or a negative error code. + */ +int rtnl_sfq_get_quantum(struct rtnl_qdisc *qdisc) +{ + struct rtnl_sfq *sfq; + + if (!(sfq = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (sfq->qs_mask & SCH_SFQ_ATTR_QUANTUM) + return sfq->qs_quantum; + else + return -NLE_NOATTR; +} + +/** + * Set limit of SFQ qdisc. + * @arg qdisc SFQ qdisc to be modified. + * @arg limit New limit in number of packets. + * @return 0 on success or a negative error code. + */ +void rtnl_sfq_set_limit(struct rtnl_qdisc *qdisc, int limit) +{ + struct rtnl_sfq *sfq; + + if (!(sfq = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + sfq->qs_limit = limit; + sfq->qs_mask |= SCH_SFQ_ATTR_LIMIT; +} + +/** + * Get limit of SFQ qdisc. + * @arg qdisc SFQ qdisc. + * @return Limit or a negative error code. + */ +int rtnl_sfq_get_limit(struct rtnl_qdisc *qdisc) +{ + struct rtnl_sfq *sfq; + + if (!(sfq = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (sfq->qs_mask & SCH_SFQ_ATTR_LIMIT) + return sfq->qs_limit; + else + return -NLE_NOATTR; +} + +/** + * Set perturbation interval of SFQ qdisc. + * @arg qdisc SFQ qdisc to be modified. + * @arg perturb New perturbation interval in seconds. + * @note A value of 0 disables perturbation altogether. + * @return 0 on success or a negative error code. + */ +void rtnl_sfq_set_perturb(struct rtnl_qdisc *qdisc, int perturb) +{ + struct rtnl_sfq *sfq; + + if (!(sfq = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + sfq->qs_perturb = perturb; + sfq->qs_mask |= SCH_SFQ_ATTR_PERTURB; +} + +/** + * Get perturbation interval of SFQ qdisc. + * @arg qdisc SFQ qdisc. + * @return Perturbation interval in seconds or a negative error code. + */ +int rtnl_sfq_get_perturb(struct rtnl_qdisc *qdisc) +{ + struct rtnl_sfq *sfq; + + if (!(sfq = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (sfq->qs_mask & SCH_SFQ_ATTR_PERTURB) + return sfq->qs_perturb; + else + return -NLE_NOATTR; +} + +/** + * Get divisor of SFQ qdisc. + * @arg qdisc SFQ qdisc. + * @return Divisor in number of entries or a negative error code. + */ +int rtnl_sfq_get_divisor(struct rtnl_qdisc *qdisc) +{ + struct rtnl_sfq *sfq; + + if (!(sfq = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (sfq->qs_mask & SCH_SFQ_ATTR_DIVISOR) + return sfq->qs_divisor; + else + return -NLE_NOATTR; +} + +/** @} */ + +static struct rtnl_tc_ops sfq_ops = { + .to_kind = "sfq", + .to_type = RTNL_TC_TYPE_QDISC, + .to_size = sizeof(struct rtnl_sfq), + .to_msg_parser = sfq_msg_parser, + .to_dump = { + [NL_DUMP_LINE] = sfq_dump_line, + [NL_DUMP_DETAILS] = sfq_dump_details, + }, + .to_msg_fill = sfq_msg_fill, +}; + +static void __init sfq_init(void) +{ + rtnl_tc_register(&sfq_ops); +} + +static void __exit sfq_exit(void) +{ + rtnl_tc_unregister(&sfq_ops); +} + +/** @} */ diff --git a/lib/route/qdisc/tbf.c b/lib/route/qdisc/tbf.c new file mode 100644 index 0000000..eb574d9 --- /dev/null +++ b/lib/route/qdisc/tbf.c @@ -0,0 +1,460 @@ +/* + * lib/route/qdisc/tbf.c TBF Qdisc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + */ + +/** + * @ingroup qdisc + * @defgroup qdisc_tbf Token Bucket Filter (TBF) + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define TBF_ATTR_LIMIT 0x01 +#define TBF_ATTR_RATE 0x02 +#define TBF_ATTR_PEAKRATE 0x10 +/** @endcond */ + +static struct nla_policy tbf_policy[TCA_TBF_MAX+1] = { + [TCA_TBF_PARMS] = { .minlen = sizeof(struct tc_tbf_qopt) }, +}; + +static int tbf_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct nlattr *tb[TCA_TBF_MAX + 1]; + struct rtnl_tbf *tbf = data; + int err; + + if ((err = tca_parse(tb, TCA_TBF_MAX, tc, tbf_policy)) < 0) + return err; + + if (tb[TCA_TBF_PARMS]) { + struct tc_tbf_qopt opts; + int bufsize; + + nla_memcpy(&opts, tb[TCA_TBF_PARMS], sizeof(opts)); + tbf->qt_limit = opts.limit; + + rtnl_copy_ratespec(&tbf->qt_rate, &opts.rate); + tbf->qt_rate_txtime = opts.buffer; + bufsize = rtnl_tc_calc_bufsize(nl_ticks2us(opts.buffer), + opts.rate.rate); + tbf->qt_rate_bucket = bufsize; + + rtnl_copy_ratespec(&tbf->qt_peakrate, &opts.peakrate); + tbf->qt_peakrate_txtime = opts.mtu; + bufsize = rtnl_tc_calc_bufsize(nl_ticks2us(opts.mtu), + opts.peakrate.rate); + tbf->qt_peakrate_bucket = bufsize; + + rtnl_tc_set_mpu(tc, tbf->qt_rate.rs_mpu); + rtnl_tc_set_overhead(tc, tbf->qt_rate.rs_overhead); + + tbf->qt_mask = (TBF_ATTR_LIMIT | TBF_ATTR_RATE | TBF_ATTR_PEAKRATE); + } + + return 0; +} + +static void tbf_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + double r, rbit, lim; + char *ru, *rubit, *limu; + struct rtnl_tbf *tbf = data; + + if (!tbf) + return; + + r = nl_cancel_down_bytes(tbf->qt_rate.rs_rate, &ru); + rbit = nl_cancel_down_bits(tbf->qt_rate.rs_rate*8, &rubit); + lim = nl_cancel_down_bytes(tbf->qt_limit, &limu); + + nl_dump(p, " rate %.2f%s/s (%.0f%s) limit %.2f%s", + r, ru, rbit, rubit, lim, limu); +} + +static void tbf_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_tbf *tbf = data; + + if (!tbf) + return; + + if (1) { + char *bu, *cu; + double bs = nl_cancel_down_bytes(tbf->qt_rate_bucket, &bu); + double cl = nl_cancel_down_bytes(1 << tbf->qt_rate.rs_cell_log, + &cu); + + nl_dump(p, "rate-bucket-size %1.f%s " + "rate-cell-size %.1f%s\n", + bs, bu, cl, cu); + + } + + if (tbf->qt_mask & TBF_ATTR_PEAKRATE) { + char *pru, *prbu, *bsu, *clu; + double pr, prb, bs, cl; + + pr = nl_cancel_down_bytes(tbf->qt_peakrate.rs_rate, &pru); + prb = nl_cancel_down_bits(tbf->qt_peakrate.rs_rate * 8, &prbu); + bs = nl_cancel_down_bits(tbf->qt_peakrate_bucket, &bsu); + cl = nl_cancel_down_bits(1 << tbf->qt_peakrate.rs_cell_log, + &clu); + + nl_dump_line(p, " peak-rate %.2f%s/s (%.0f%s) " + "bucket-size %.1f%s cell-size %.1f%s" + "latency %.1f%s", + pr, pru, prb, prbu, bs, bsu, cl, clu); + } +} + +static int tbf_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + uint32_t rtab[RTNL_TC_RTABLE_SIZE], ptab[RTNL_TC_RTABLE_SIZE]; + struct tc_tbf_qopt opts; + struct rtnl_tbf *tbf = data; + int required = TBF_ATTR_RATE | TBF_ATTR_LIMIT; + + if ((tbf->qt_mask & required) != required) + return -NLE_MISSING_ATTR; + + memset(&opts, 0, sizeof(opts)); + opts.limit = tbf->qt_limit; + opts.buffer = tbf->qt_rate_txtime; + + rtnl_tc_build_rate_table(tc, &tbf->qt_rate, rtab); + rtnl_rcopy_ratespec(&opts.rate, &tbf->qt_rate); + + if (tbf->qt_mask & TBF_ATTR_PEAKRATE) { + opts.mtu = tbf->qt_peakrate_txtime; + rtnl_tc_build_rate_table(tc, &tbf->qt_peakrate, ptab); + rtnl_rcopy_ratespec(&opts.peakrate, &tbf->qt_peakrate); + + } + + NLA_PUT(msg, TCA_TBF_PARMS, sizeof(opts), &opts); + NLA_PUT(msg, TCA_TBF_RTAB, sizeof(rtab), rtab); + + if (tbf->qt_mask & TBF_ATTR_PEAKRATE) + NLA_PUT(msg, TCA_TBF_PTAB, sizeof(ptab), ptab); + + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +/** + * @name Attribute Access + * @{ + */ + +/** + * Set limit of TBF qdisc. + * @arg qdisc TBF qdisc to be modified. + * @arg limit New limit in bytes. + * @return 0 on success or a negative error code. + */ +void rtnl_qdisc_tbf_set_limit(struct rtnl_qdisc *qdisc, int limit) +{ + struct rtnl_tbf *tbf; + + if (!(tbf = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + tbf->qt_limit = limit; + tbf->qt_mask |= TBF_ATTR_LIMIT; +} + +static inline double calc_limit(struct rtnl_ratespec *spec, int latency, + int bucket) +{ + double limit; + + limit = (double) spec->rs_rate * ((double) latency / 1000000.); + limit += bucket; + + return limit; +} + +/** + * Set limit of TBF qdisc by latency. + * @arg qdisc TBF qdisc to be modified. + * @arg latency Latency in micro seconds. + * + * Calculates and sets the limit based on the desired latency and the + * configured rate and peak rate. In order for this operation to succeed, + * the rate and if required the peak rate must have been set in advance. + * + * @f[ + * limit_n = \frac{{rate_n} \times {latency}}{10^6}+{bucketsize}_n + * @f] + * @f[ + * limit = min(limit_{rate},limit_{peak}) + * @f] + * + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_tbf_set_limit_by_latency(struct rtnl_qdisc *qdisc, int latency) +{ + struct rtnl_tbf *tbf; + double limit, limit2; + + if (!(tbf = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (!(tbf->qt_mask & TBF_ATTR_RATE)) + return -NLE_MISSING_ATTR; + + limit = calc_limit(&tbf->qt_rate, latency, tbf->qt_rate_bucket); + + if (tbf->qt_mask & TBF_ATTR_PEAKRATE) { + limit2 = calc_limit(&tbf->qt_peakrate, latency, + tbf->qt_peakrate_bucket); + + if (limit2 < limit) + limit = limit2; + } + + rtnl_qdisc_tbf_set_limit(qdisc, (int) limit); + + return 0; +} + +/** + * Get limit of TBF qdisc. + * @arg qdisc TBF qdisc. + * @return Limit in bytes or a negative error code. + */ +int rtnl_qdisc_tbf_get_limit(struct rtnl_qdisc *qdisc) +{ + struct rtnl_tbf *tbf; + + if (!(tbf = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (tbf->qt_mask & TBF_ATTR_LIMIT) + return tbf->qt_limit; + else + return -NLE_NOATTR; +} + +static inline int calc_cell_log(int cell, int bucket) +{ + cell = rtnl_tc_calc_cell_log(cell); + return cell; +} + +/** + * Set rate of TBF qdisc. + * @arg qdisc TBF qdisc to be modified. + * @arg rate New rate in bytes per second. + * @arg bucket Size of bucket in bytes. + * @arg cell Size of a rate cell or 0 to get default value. + * @return 0 on success or a negative error code. + */ +void rtnl_qdisc_tbf_set_rate(struct rtnl_qdisc *qdisc, int rate, int bucket, + int cell) +{ + struct rtnl_tbf *tbf; + int cell_log; + + if (!(tbf = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (!cell) + cell_log = UINT8_MAX; + else + cell_log = rtnl_tc_calc_cell_log(cell); + + tbf->qt_rate.rs_rate = rate; + tbf->qt_rate_bucket = bucket; + tbf->qt_rate.rs_cell_log = cell_log; + tbf->qt_rate_txtime = nl_us2ticks(rtnl_tc_calc_txtime(bucket, rate)); + tbf->qt_mask |= TBF_ATTR_RATE; +} + +/** + * Get rate of TBF qdisc. + * @arg qdisc TBF qdisc. + * @return Rate in bytes per seconds or a negative error code. + */ +int rtnl_qdisc_tbf_get_rate(struct rtnl_qdisc *qdisc) +{ + struct rtnl_tbf *tbf; + + if (!(tbf = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (tbf->qt_mask & TBF_ATTR_RATE) + return tbf->qt_rate.rs_rate; + else + return -1; +} + +/** + * Get rate bucket size of TBF qdisc. + * @arg qdisc TBF qdisc. + * @return Size of rate bucket or a negative error code. + */ +int rtnl_qdisc_tbf_get_rate_bucket(struct rtnl_qdisc *qdisc) +{ + struct rtnl_tbf *tbf; + + if (!(tbf = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (tbf->qt_mask & TBF_ATTR_RATE) + return tbf->qt_rate_bucket; + else + return -1; +} + +/** + * Get rate cell size of TBF qdisc. + * @arg qdisc TBF qdisc. + * @return Size of rate cell in bytes or a negative error code. + */ +int rtnl_qdisc_tbf_get_rate_cell(struct rtnl_qdisc *qdisc) +{ + struct rtnl_tbf *tbf; + + if (!(tbf = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (tbf->qt_mask & TBF_ATTR_RATE) + return (1 << tbf->qt_rate.rs_cell_log); + else + return -1; +} + +/** + * Set peak rate of TBF qdisc. + * @arg qdisc TBF qdisc to be modified. + * @arg rate New peak rate in bytes per second. + * @arg bucket Size of peakrate bucket. + * @arg cell Size of a peakrate cell or 0 to get default value. + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_tbf_set_peakrate(struct rtnl_qdisc *qdisc, int rate, int bucket, + int cell) +{ + struct rtnl_tbf *tbf; + int cell_log; + + if (!(tbf = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + cell_log = calc_cell_log(cell, bucket); + if (cell_log < 0) + return cell_log; + + tbf->qt_peakrate.rs_rate = rate; + tbf->qt_peakrate_bucket = bucket; + tbf->qt_peakrate.rs_cell_log = cell_log; + tbf->qt_peakrate_txtime = nl_us2ticks(rtnl_tc_calc_txtime(bucket, rate)); + + tbf->qt_mask |= TBF_ATTR_PEAKRATE; + + return 0; +} + +/** + * Get peak rate of TBF qdisc. + * @arg qdisc TBF qdisc. + * @return Peak rate in bytes per seconds or a negative error code. + */ +int rtnl_qdisc_tbf_get_peakrate(struct rtnl_qdisc *qdisc) +{ + struct rtnl_tbf *tbf; + + if (!(tbf = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (tbf->qt_mask & TBF_ATTR_PEAKRATE) + return tbf->qt_peakrate.rs_rate; + else + return -1; +} + +/** + * Get peak rate bucket size of TBF qdisc. + * @arg qdisc TBF qdisc. + * @return Size of peak rate bucket or a negative error code. + */ +int rtnl_qdisc_tbf_get_peakrate_bucket(struct rtnl_qdisc *qdisc) +{ + struct rtnl_tbf *tbf; + + if (!(tbf = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (tbf->qt_mask & TBF_ATTR_PEAKRATE) + return tbf->qt_peakrate_bucket; + else + return -1; +} + +/** + * Get peak rate cell size of TBF qdisc. + * @arg qdisc TBF qdisc. + * @return Size of peak rate cell in bytes or a negative error code. + */ +int rtnl_qdisc_tbf_get_peakrate_cell(struct rtnl_qdisc *qdisc) +{ + struct rtnl_tbf *tbf; + + if (!(tbf = rtnl_tc_data(TC_CAST(qdisc)))) + BUG(); + + if (tbf->qt_mask & TBF_ATTR_PEAKRATE) + return (1 << tbf->qt_peakrate.rs_cell_log); + else + return -1; +} + +/** @} */ + +static struct rtnl_tc_ops tbf_tc_ops = { + .to_kind = "tbf", + .to_type = RTNL_TC_TYPE_QDISC, + .to_size = sizeof(struct rtnl_tbf), + .to_msg_parser = tbf_msg_parser, + .to_dump = { + [NL_DUMP_LINE] = tbf_dump_line, + [NL_DUMP_DETAILS] = tbf_dump_details, + }, + .to_msg_fill = tbf_msg_fill, +}; + +static void __init tbf_init(void) +{ + rtnl_tc_register(&tbf_tc_ops); +} + +static void __exit tbf_exit(void) +{ + rtnl_tc_unregister(&tbf_tc_ops); +} + +/** @} */ diff --git a/lib/route/route.c b/lib/route/route.c new file mode 100644 index 0000000..2985187 --- /dev/null +++ b/lib/route/route.c @@ -0,0 +1,206 @@ +/* + * lib/route/route.c Routes + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + */ + +/** + * @ingroup rtnl + * @defgroup route Routing + * @brief + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct nl_cache_ops rtnl_route_ops; + +static int route_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *nlh, struct nl_parser_param *pp) +{ + struct rtnl_route *route; + int err; + + if ((err = rtnl_route_parse(nlh, &route)) < 0) + return err; + + err = pp->pp_cb((struct nl_object *) route, pp); + + rtnl_route_put(route); + return err; +} + +static int route_request_update(struct nl_cache *c, struct nl_sock *h) +{ + struct rtmsg rhdr = { + .rtm_family = c->c_iarg1, + }; + + if (c->c_iarg2 & ROUTE_CACHE_CONTENT) + rhdr.rtm_flags |= RTM_F_CLONED; + + return nl_send_simple(h, RTM_GETROUTE, NLM_F_DUMP, &rhdr, sizeof(rhdr)); +} + +/** + * @name Cache Management + * @{ + */ + +/** + * Build a route cache holding all routes currently configured in the kernel + * @arg sk Netlink socket. + * @arg family Address family of routes to cover or AF_UNSPEC + * @arg flags Flags + * @arg result Result pointer + * + * Allocates a new cache, initializes it properly and updates it to + * contain all routes currently configured in the kernel. + * + * Valid flags: + * * ROUTE_CACHE_CONTENT - Cache will contain contents of routing cache + * instead of actual routes. + * + * @note The caller is responsible for destroying and freeing the + * cache after using it. + * @return 0 on success or a negative error code. + */ +int rtnl_route_alloc_cache(struct nl_sock *sk, int family, int flags, + struct nl_cache **result) +{ + struct nl_cache *cache; + int err; + + if (!(cache = nl_cache_alloc(&rtnl_route_ops))) + return -NLE_NOMEM; + + cache->c_iarg1 = family; + cache->c_iarg2 = flags; + + if (sk && (err = nl_cache_refill(sk, cache)) < 0) { + free(cache); + return err; + } + + *result = cache; + return 0; +} + +/** @} */ + +/** + * @name Route Addition + * @{ + */ + +static int build_route_msg(struct rtnl_route *tmpl, int cmd, int flags, + struct nl_msg **result) +{ + struct nl_msg *msg; + int err; + + if (!(msg = nlmsg_alloc_simple(cmd, flags))) + return -NLE_NOMEM; + + if ((err = rtnl_route_build_msg(msg, tmpl)) < 0) { + nlmsg_free(msg); + return err; + } + + *result = msg; + return 0; +} + +int rtnl_route_build_add_request(struct rtnl_route *tmpl, int flags, + struct nl_msg **result) +{ + return build_route_msg(tmpl, RTM_NEWROUTE, NLM_F_CREATE | flags, + result); +} + +int rtnl_route_add(struct nl_sock *sk, struct rtnl_route *route, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_route_build_add_request(route, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +int rtnl_route_build_del_request(struct rtnl_route *tmpl, int flags, + struct nl_msg **result) +{ + return build_route_msg(tmpl, RTM_DELROUTE, flags, result); +} + +int rtnl_route_delete(struct nl_sock *sk, struct rtnl_route *route, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_route_build_del_request(route, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +/** @} */ + +static struct nl_af_group route_groups[] = { + { AF_INET, RTNLGRP_IPV4_ROUTE }, + { AF_INET6, RTNLGRP_IPV6_ROUTE }, + { AF_DECnet, RTNLGRP_DECnet_ROUTE }, + { END_OF_GROUP_LIST }, +}; + +static struct nl_cache_ops rtnl_route_ops = { + .co_name = "route/route", + .co_hdrsize = sizeof(struct rtmsg), + .co_msgtypes = { + { RTM_NEWROUTE, NL_ACT_NEW, "new" }, + { RTM_DELROUTE, NL_ACT_DEL, "del" }, + { RTM_GETROUTE, NL_ACT_GET, "get" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_ROUTE, + .co_groups = route_groups, + .co_request_update = route_request_update, + .co_msg_parser = route_msg_parser, + .co_obj_ops = &route_obj_ops, +}; + +static void __init route_init(void) +{ + nl_cache_mngt_register(&rtnl_route_ops); +} + +static void __exit route_exit(void) +{ + nl_cache_mngt_unregister(&rtnl_route_ops); +} + +/** @} */ diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c new file mode 100644 index 0000000..f2de523 --- /dev/null +++ b/lib/route/route_obj.c @@ -0,0 +1,1315 @@ +/* + * lib/route/route_obj.c Route Object + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + */ + +/** + * @ingroup route + * @defgroup route_obj Route Object + * + * @par Attributes + * @code + * Name Default + * ------------------------------------------------------------- + * routing table RT_TABLE_MAIN + * scope RT_SCOPE_NOWHERE + * tos 0 + * protocol RTPROT_STATIC + * prio 0 + * family AF_UNSPEC + * type RTN_UNICAST + * iif NULL + * @endcode + * + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define ROUTE_ATTR_FAMILY 0x000001 +#define ROUTE_ATTR_TOS 0x000002 +#define ROUTE_ATTR_TABLE 0x000004 +#define ROUTE_ATTR_PROTOCOL 0x000008 +#define ROUTE_ATTR_SCOPE 0x000010 +#define ROUTE_ATTR_TYPE 0x000020 +#define ROUTE_ATTR_FLAGS 0x000040 +#define ROUTE_ATTR_DST 0x000080 +#define ROUTE_ATTR_SRC 0x000100 +#define ROUTE_ATTR_IIF 0x000200 +#define ROUTE_ATTR_OIF 0x000400 +#define ROUTE_ATTR_GATEWAY 0x000800 +#define ROUTE_ATTR_PRIO 0x001000 +#define ROUTE_ATTR_PREF_SRC 0x002000 +#define ROUTE_ATTR_METRICS 0x004000 +#define ROUTE_ATTR_MULTIPATH 0x008000 +#define ROUTE_ATTR_REALMS 0x010000 +#define ROUTE_ATTR_CACHEINFO 0x020000 +/** @endcond */ + +static void route_constructor(struct nl_object *c) +{ + struct rtnl_route *r = (struct rtnl_route *) c; + + r->rt_family = AF_UNSPEC; + r->rt_scope = RT_SCOPE_NOWHERE; + r->rt_table = RT_TABLE_MAIN; + r->rt_protocol = RTPROT_STATIC; + r->rt_type = RTN_UNICAST; + r->rt_prio = 0; + + nl_init_list_head(&r->rt_nexthops); +} + +static void route_free_data(struct nl_object *c) +{ + struct rtnl_route *r = (struct rtnl_route *) c; + struct rtnl_nexthop *nh, *tmp; + + if (r == NULL) + return; + + nl_addr_put(r->rt_dst); + nl_addr_put(r->rt_src); + nl_addr_put(r->rt_pref_src); + + nl_list_for_each_entry_safe(nh, tmp, &r->rt_nexthops, rtnh_list) { + rtnl_route_remove_nexthop(r, nh); + rtnl_route_nh_free(nh); + } +} + +static int route_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct rtnl_route *dst = (struct rtnl_route *) _dst; + struct rtnl_route *src = (struct rtnl_route *) _src; + struct rtnl_nexthop *nh, *new; + + if (src->rt_dst) + if (!(dst->rt_dst = nl_addr_clone(src->rt_dst))) + return -NLE_NOMEM; + + if (src->rt_src) + if (!(dst->rt_src = nl_addr_clone(src->rt_src))) + return -NLE_NOMEM; + + if (src->rt_pref_src) + if (!(dst->rt_pref_src = nl_addr_clone(src->rt_pref_src))) + return -NLE_NOMEM; + + /* Will be inc'ed again while adding the nexthops of the source */ + dst->rt_nr_nh = 0; + + nl_init_list_head(&dst->rt_nexthops); + nl_list_for_each_entry(nh, &src->rt_nexthops, rtnh_list) { + new = rtnl_route_nh_clone(nh); + if (!new) + return -NLE_NOMEM; + + rtnl_route_add_nexthop(dst, new); + } + + return 0; +} + +static void route_dump_line(struct nl_object *a, struct nl_dump_params *p) +{ + struct rtnl_route *r = (struct rtnl_route *) a; + int cache = 0, flags; + char buf[64]; + + if (r->rt_flags & RTM_F_CLONED) + cache = 1; + + nl_dump_line(p, "%s ", nl_af2str(r->rt_family, buf, sizeof(buf))); + + if (cache) + nl_dump(p, "cache "); + + if (!(r->ce_mask & ROUTE_ATTR_DST) || + nl_addr_get_len(r->rt_dst) == 0) + nl_dump(p, "default "); + else + nl_dump(p, "%s ", nl_addr2str(r->rt_dst, buf, sizeof(buf))); + + if (r->ce_mask & ROUTE_ATTR_TABLE && !cache) + nl_dump(p, "table %s ", + rtnl_route_table2str(r->rt_table, buf, sizeof(buf))); + + if (r->ce_mask & ROUTE_ATTR_TYPE) + nl_dump(p, "type %s ", + nl_rtntype2str(r->rt_type, buf, sizeof(buf))); + + if (r->ce_mask & ROUTE_ATTR_TOS && r->rt_tos != 0) + nl_dump(p, "tos %#x ", r->rt_tos); + + if (r->ce_mask & ROUTE_ATTR_MULTIPATH) { + struct rtnl_nexthop *nh; + + nl_list_for_each_entry(nh, &r->rt_nexthops, rtnh_list) { + p->dp_ivar = NH_DUMP_FROM_ONELINE; + rtnl_route_nh_dump(nh, p); + } + } + + flags = r->rt_flags & ~(RTM_F_CLONED); + if (r->ce_mask & ROUTE_ATTR_FLAGS && flags) { + + nl_dump(p, "<"); + +#define PRINT_FLAG(f) if (flags & RTNH_F_##f) { \ + flags &= ~RTNH_F_##f; nl_dump(p, #f "%s", flags ? "," : ""); } + PRINT_FLAG(DEAD); + PRINT_FLAG(ONLINK); + PRINT_FLAG(PERVASIVE); +#undef PRINT_FLAG + +#define PRINT_FLAG(f) if (flags & RTM_F_##f) { \ + flags &= ~RTM_F_##f; nl_dump(p, #f "%s", flags ? "," : ""); } + PRINT_FLAG(NOTIFY); + PRINT_FLAG(EQUALIZE); + PRINT_FLAG(PREFIX); +#undef PRINT_FLAG + +#define PRINT_FLAG(f) if (flags & RTCF_##f) { \ + flags &= ~RTCF_##f; nl_dump(p, #f "%s", flags ? "," : ""); } + PRINT_FLAG(NOTIFY); + PRINT_FLAG(REDIRECTED); + PRINT_FLAG(DOREDIRECT); + PRINT_FLAG(DIRECTSRC); + PRINT_FLAG(DNAT); + PRINT_FLAG(BROADCAST); + PRINT_FLAG(MULTICAST); + PRINT_FLAG(LOCAL); +#undef PRINT_FLAG + + nl_dump(p, ">"); + } + + nl_dump(p, "\n"); +} + +static void route_dump_details(struct nl_object *a, struct nl_dump_params *p) +{ + struct rtnl_route *r = (struct rtnl_route *) a; + struct nl_cache *link_cache; + char buf[256]; + int i; + + link_cache = nl_cache_mngt_require_safe("route/link"); + + route_dump_line(a, p); + nl_dump_line(p, " "); + + if (r->ce_mask & ROUTE_ATTR_PREF_SRC) + nl_dump(p, "preferred-src %s ", + nl_addr2str(r->rt_pref_src, buf, sizeof(buf))); + + if (r->ce_mask & ROUTE_ATTR_SCOPE && r->rt_scope != RT_SCOPE_NOWHERE) + nl_dump(p, "scope %s ", + rtnl_scope2str(r->rt_scope, buf, sizeof(buf))); + + if (r->ce_mask & ROUTE_ATTR_PRIO) + nl_dump(p, "priority %#x ", r->rt_prio); + + if (r->ce_mask & ROUTE_ATTR_PROTOCOL) + nl_dump(p, "protocol %s ", + rtnl_route_proto2str(r->rt_protocol, buf, sizeof(buf))); + + if (r->ce_mask & ROUTE_ATTR_IIF) { + if (link_cache) { + nl_dump(p, "iif %s ", + rtnl_link_i2name(link_cache, r->rt_iif, + buf, sizeof(buf))); + } else + nl_dump(p, "iif %d ", r->rt_iif); + } + + if (r->ce_mask & ROUTE_ATTR_SRC) + nl_dump(p, "src %s ", nl_addr2str(r->rt_src, buf, sizeof(buf))); + + nl_dump(p, "\n"); + + if (r->ce_mask & ROUTE_ATTR_MULTIPATH) { + struct rtnl_nexthop *nh; + + nl_list_for_each_entry(nh, &r->rt_nexthops, rtnh_list) { + nl_dump_line(p, " "); + p->dp_ivar = NH_DUMP_FROM_DETAILS; + rtnl_route_nh_dump(nh, p); + nl_dump(p, "\n"); + } + } + + if ((r->ce_mask & ROUTE_ATTR_CACHEINFO) && r->rt_cacheinfo.rtci_error) { + nl_dump_line(p, " cacheinfo error %d (%s)\n", + r->rt_cacheinfo.rtci_error, + strerror_r(-r->rt_cacheinfo.rtci_error, buf, sizeof(buf))); + } + + if (r->ce_mask & ROUTE_ATTR_METRICS) { + nl_dump_line(p, " metrics ["); + for (i = 0; i < RTAX_MAX; i++) + if (r->rt_metrics_mask & (1 << i)) + nl_dump(p, "%s %u ", + rtnl_route_metric2str(i+1, + buf, sizeof(buf)), + r->rt_metrics[i]); + nl_dump(p, "]\n"); + } + + if (link_cache) + nl_cache_put(link_cache); +} + +static void route_dump_stats(struct nl_object *obj, struct nl_dump_params *p) +{ + struct rtnl_route *route = (struct rtnl_route *) obj; + + route_dump_details(obj, p); + + if (route->ce_mask & ROUTE_ATTR_CACHEINFO) { + struct rtnl_rtcacheinfo *ci = &route->rt_cacheinfo; + + nl_dump_line(p, " used %u refcnt %u last-use %us " + "expires %us\n", + ci->rtci_used, ci->rtci_clntref, + ci->rtci_last_use / nl_get_user_hz(), + ci->rtci_expires / nl_get_user_hz()); + } +} + +static void route_keygen(struct nl_object *obj, uint32_t *hashkey, + uint32_t table_sz) +{ + struct rtnl_route *route = (struct rtnl_route *) obj; + unsigned int rkey_sz; + struct nl_addr *addr = NULL; + struct route_hash_key { + uint8_t rt_family; + uint8_t rt_tos; + uint32_t rt_table; + uint32_t rt_prio; + char rt_addr[0]; + } __attribute__((packed)) *rkey; +#ifdef NL_DEBUG + char buf[INET6_ADDRSTRLEN+5]; +#endif + + if (route->rt_dst) + addr = route->rt_dst; + + rkey_sz = sizeof(*rkey); + if (addr) + rkey_sz += nl_addr_get_len(addr); + rkey = calloc(1, rkey_sz); + if (!rkey) { + NL_DBG(2, "Warning: calloc failed for %d bytes...\n", rkey_sz); + *hashkey = 0; + return; + } + rkey->rt_family = route->rt_family; + rkey->rt_tos = route->rt_tos; + rkey->rt_table = route->rt_table; + rkey->rt_prio = route->rt_prio; + if (addr) + memcpy(rkey->rt_addr, nl_addr_get_binary_addr(addr), + nl_addr_get_len(addr)); + + *hashkey = nl_hash(rkey, rkey_sz, 0) % table_sz; + + NL_DBG(5, "route %p key (fam %d tos %d table %d addr %s) keysz %d " + "hash 0x%x\n", route, rkey->rt_family, rkey->rt_tos, + rkey->rt_table, nl_addr2str(addr, buf, sizeof(buf)), + rkey_sz, *hashkey); + + free(rkey); + + return; +} + +static int route_compare(struct nl_object *_a, struct nl_object *_b, + uint32_t attrs, int flags) +{ + struct rtnl_route *a = (struct rtnl_route *) _a; + struct rtnl_route *b = (struct rtnl_route *) _b; + struct rtnl_nexthop *nh_a, *nh_b; + int i, diff = 0, found; + +#define ROUTE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ROUTE_ATTR_##ATTR, a, b, EXPR) + + diff |= ROUTE_DIFF(FAMILY, a->rt_family != b->rt_family); + diff |= ROUTE_DIFF(TOS, a->rt_tos != b->rt_tos); + diff |= ROUTE_DIFF(TABLE, a->rt_table != b->rt_table); + diff |= ROUTE_DIFF(PROTOCOL, a->rt_protocol != b->rt_protocol); + diff |= ROUTE_DIFF(SCOPE, a->rt_scope != b->rt_scope); + diff |= ROUTE_DIFF(TYPE, a->rt_type != b->rt_type); + diff |= ROUTE_DIFF(PRIO, a->rt_prio != b->rt_prio); + diff |= ROUTE_DIFF(DST, nl_addr_cmp(a->rt_dst, b->rt_dst)); + diff |= ROUTE_DIFF(SRC, nl_addr_cmp(a->rt_src, b->rt_src)); + diff |= ROUTE_DIFF(IIF, a->rt_iif != b->rt_iif); + diff |= ROUTE_DIFF(PREF_SRC, nl_addr_cmp(a->rt_pref_src, + b->rt_pref_src)); + + if (flags & LOOSE_COMPARISON) { + nl_list_for_each_entry(nh_b, &b->rt_nexthops, rtnh_list) { + found = 0; + nl_list_for_each_entry(nh_a, &a->rt_nexthops, + rtnh_list) { + if (!rtnl_route_nh_compare(nh_a, nh_b, + nh_b->ce_mask, 1)) { + found = 1; + break; + } + } + + if (!found) + goto nh_mismatch; + } + + for (i = 0; i < RTAX_MAX - 1; i++) { + if (a->rt_metrics_mask & (1 << i) && + (!(b->rt_metrics_mask & (1 << i)) || + a->rt_metrics[i] != b->rt_metrics[i])) + diff |= ROUTE_DIFF(METRICS, 1); + } + + diff |= ROUTE_DIFF(FLAGS, + (a->rt_flags ^ b->rt_flags) & b->rt_flag_mask); + } else { + if (a->rt_nr_nh != b->rt_nr_nh) + goto nh_mismatch; + + /* search for a dup in each nh of a */ + nl_list_for_each_entry(nh_a, &a->rt_nexthops, rtnh_list) { + found = 0; + nl_list_for_each_entry(nh_b, &b->rt_nexthops, + rtnh_list) { + if (!rtnl_route_nh_compare(nh_a, nh_b, ~0, 0)) { + found = 1; + break; + } + } + if (!found) + goto nh_mismatch; + } + + /* search for a dup in each nh of b, covers case where a has + * dupes itself */ + nl_list_for_each_entry(nh_b, &b->rt_nexthops, rtnh_list) { + found = 0; + nl_list_for_each_entry(nh_a, &a->rt_nexthops, + rtnh_list) { + if (!rtnl_route_nh_compare(nh_a, nh_b, ~0, 0)) { + found = 1; + break; + } + } + if (!found) + goto nh_mismatch; + } + + for (i = 0; i < RTAX_MAX - 1; i++) { + if ((a->rt_metrics_mask & (1 << i)) ^ + (b->rt_metrics_mask & (1 << i))) + diff |= ROUTE_DIFF(METRICS, 1); + else + diff |= ROUTE_DIFF(METRICS, + a->rt_metrics[i] != b->rt_metrics[i]); + } + + diff |= ROUTE_DIFF(FLAGS, a->rt_flags != b->rt_flags); + } + +out: + return diff; + +nh_mismatch: + diff |= ROUTE_DIFF(MULTIPATH, 1); + goto out; + +#undef ROUTE_DIFF +} + +static int route_update(struct nl_object *old_obj, struct nl_object *new_obj) +{ + struct rtnl_route *new_route = (struct rtnl_route *) new_obj; + struct rtnl_route *old_route = (struct rtnl_route *) old_obj; + struct rtnl_nexthop *new_nh; + int action = new_obj->ce_msgtype; +#ifdef NL_DEBUG + char buf[INET6_ADDRSTRLEN+5]; +#endif + + /* + * ipv6 ECMP route notifications from the kernel come as + * separate notifications, one for every nexthop. This update + * function collapses such route msgs into a single + * route with multiple nexthops. The resulting object looks + * similar to a ipv4 ECMP route + */ + if (new_route->rt_family != AF_INET6 || + new_route->rt_table == RT_TABLE_LOCAL) + return -NLE_OPNOTSUPP; + + /* + * For routes that are already multipath, + * or dont have a nexthop dont do anything + */ + if (rtnl_route_get_nnexthops(new_route) != 1) + return -NLE_OPNOTSUPP; + + /* + * Get the only nexthop entry from the new route. For + * IPv6 we always get a route with a 0th NH + * filled or nothing at all + */ + new_nh = rtnl_route_nexthop_n(new_route, 0); + if (!new_nh || !rtnl_route_nh_get_gateway(new_nh)) + return -NLE_OPNOTSUPP; + + switch(action) { + case RTM_NEWROUTE : { + struct rtnl_nexthop *cloned_nh; + + /* + * Add the nexthop to old route + */ + cloned_nh = rtnl_route_nh_clone(new_nh); + if (!cloned_nh) + return -NLE_NOMEM; + rtnl_route_add_nexthop(old_route, cloned_nh); + + NL_DBG(2, "Route obj %p updated. Added " + "nexthop %p via %s\n", old_route, cloned_nh, + nl_addr2str(cloned_nh->rtnh_gateway, buf, + sizeof(buf))); + } + break; + case RTM_DELROUTE : { + struct rtnl_nexthop *old_nh; + + /* + * Only take care of nexthop deletes and not + * route deletes. So, if there is only one nexthop + * quite likely we did not update it. So dont do + * anything and return + */ + if (rtnl_route_get_nnexthops(old_route) <= 1) + return -NLE_OPNOTSUPP; + + /* + * Find the next hop in old route and delete it + */ + nl_list_for_each_entry(old_nh, &old_route->rt_nexthops, + rtnh_list) { + if (!rtnl_route_nh_compare(old_nh, new_nh, ~0, 0)) { + + rtnl_route_remove_nexthop(old_route, old_nh); + + NL_DBG(2, "Route obj %p updated. Removed " + "nexthop %p via %s\n", old_route, + old_nh, + nl_addr2str(old_nh->rtnh_gateway, buf, + sizeof(buf))); + + rtnl_route_nh_free(old_nh); + break; + } + } + } + break; + default: + NL_DBG(2, "Unknown action associated " + "to object %p during route update\n", new_obj); + return -NLE_OPNOTSUPP; + } + + return NLE_SUCCESS; +} + +static const struct trans_tbl route_attrs[] = { + __ADD(ROUTE_ATTR_FAMILY, family) + __ADD(ROUTE_ATTR_TOS, tos) + __ADD(ROUTE_ATTR_TABLE, table) + __ADD(ROUTE_ATTR_PROTOCOL, protocol) + __ADD(ROUTE_ATTR_SCOPE, scope) + __ADD(ROUTE_ATTR_TYPE, type) + __ADD(ROUTE_ATTR_FLAGS, flags) + __ADD(ROUTE_ATTR_DST, dst) + __ADD(ROUTE_ATTR_SRC, src) + __ADD(ROUTE_ATTR_IIF, iif) + __ADD(ROUTE_ATTR_OIF, oif) + __ADD(ROUTE_ATTR_GATEWAY, gateway) + __ADD(ROUTE_ATTR_PRIO, prio) + __ADD(ROUTE_ATTR_PREF_SRC, pref_src) + __ADD(ROUTE_ATTR_METRICS, metrics) + __ADD(ROUTE_ATTR_MULTIPATH, multipath) + __ADD(ROUTE_ATTR_REALMS, realms) + __ADD(ROUTE_ATTR_CACHEINFO, cacheinfo) +}; + +static char *route_attrs2str(int attrs, char *buf, size_t len) +{ + return __flags2str(attrs, buf, len, route_attrs, + ARRAY_SIZE(route_attrs)); +} + +/** + * @name Allocation/Freeing + * @{ + */ + +struct rtnl_route *rtnl_route_alloc(void) +{ + return (struct rtnl_route *) nl_object_alloc(&route_obj_ops); +} + +void rtnl_route_get(struct rtnl_route *route) +{ + nl_object_get((struct nl_object *) route); +} + +void rtnl_route_put(struct rtnl_route *route) +{ + nl_object_put((struct nl_object *) route); +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ + +void rtnl_route_set_table(struct rtnl_route *route, uint32_t table) +{ + route->rt_table = table; + route->ce_mask |= ROUTE_ATTR_TABLE; +} + +uint32_t rtnl_route_get_table(struct rtnl_route *route) +{ + return route->rt_table; +} + +void rtnl_route_set_scope(struct rtnl_route *route, uint8_t scope) +{ + route->rt_scope = scope; + route->ce_mask |= ROUTE_ATTR_SCOPE; +} + +uint8_t rtnl_route_get_scope(struct rtnl_route *route) +{ + return route->rt_scope; +} + +void rtnl_route_set_tos(struct rtnl_route *route, uint8_t tos) +{ + route->rt_tos = tos; + route->ce_mask |= ROUTE_ATTR_TOS; +} + +uint8_t rtnl_route_get_tos(struct rtnl_route *route) +{ + return route->rt_tos; +} + +void rtnl_route_set_protocol(struct rtnl_route *route, uint8_t protocol) +{ + route->rt_protocol = protocol; + route->ce_mask |= ROUTE_ATTR_PROTOCOL; +} + +uint8_t rtnl_route_get_protocol(struct rtnl_route *route) +{ + return route->rt_protocol; +} + +void rtnl_route_set_priority(struct rtnl_route *route, uint32_t prio) +{ + route->rt_prio = prio; + route->ce_mask |= ROUTE_ATTR_PRIO; +} + +uint32_t rtnl_route_get_priority(struct rtnl_route *route) +{ + return route->rt_prio; +} + +int rtnl_route_set_family(struct rtnl_route *route, uint8_t family) +{ + if (family != AF_INET && family != AF_INET6 && family != AF_DECnet) + return -NLE_AF_NOSUPPORT; + + route->rt_family = family; + route->ce_mask |= ROUTE_ATTR_FAMILY; + + return 0; +} + +uint8_t rtnl_route_get_family(struct rtnl_route *route) +{ + return route->rt_family; +} + +int rtnl_route_set_dst(struct rtnl_route *route, struct nl_addr *addr) +{ + if (route->ce_mask & ROUTE_ATTR_FAMILY) { + if (addr->a_family != route->rt_family) + return -NLE_AF_MISMATCH; + } else + route->rt_family = addr->a_family; + + if (route->rt_dst) + nl_addr_put(route->rt_dst); + + nl_addr_get(addr); + route->rt_dst = addr; + + route->ce_mask |= (ROUTE_ATTR_DST | ROUTE_ATTR_FAMILY); + + return 0; +} + +struct nl_addr *rtnl_route_get_dst(struct rtnl_route *route) +{ + return route->rt_dst; +} + +int rtnl_route_set_src(struct rtnl_route *route, struct nl_addr *addr) +{ + if (addr->a_family == AF_INET) + return -NLE_SRCRT_NOSUPPORT; + + if (route->ce_mask & ROUTE_ATTR_FAMILY) { + if (addr->a_family != route->rt_family) + return -NLE_AF_MISMATCH; + } else + route->rt_family = addr->a_family; + + if (route->rt_src) + nl_addr_put(route->rt_src); + + nl_addr_get(addr); + route->rt_src = addr; + route->ce_mask |= (ROUTE_ATTR_SRC | ROUTE_ATTR_FAMILY); + + return 0; +} + +struct nl_addr *rtnl_route_get_src(struct rtnl_route *route) +{ + return route->rt_src; +} + +int rtnl_route_set_type(struct rtnl_route *route, uint8_t type) +{ + if (type > RTN_MAX) + return -NLE_RANGE; + + route->rt_type = type; + route->ce_mask |= ROUTE_ATTR_TYPE; + + return 0; +} + +uint8_t rtnl_route_get_type(struct rtnl_route *route) +{ + return route->rt_type; +} + +void rtnl_route_set_flags(struct rtnl_route *route, uint32_t flags) +{ + route->rt_flag_mask |= flags; + route->rt_flags |= flags; + route->ce_mask |= ROUTE_ATTR_FLAGS; +} + +void rtnl_route_unset_flags(struct rtnl_route *route, uint32_t flags) +{ + route->rt_flag_mask |= flags; + route->rt_flags &= ~flags; + route->ce_mask |= ROUTE_ATTR_FLAGS; +} + +uint32_t rtnl_route_get_flags(struct rtnl_route *route) +{ + return route->rt_flags; +} + +int rtnl_route_set_metric(struct rtnl_route *route, int metric, uint32_t value) +{ + if (metric > RTAX_MAX || metric < 1) + return -NLE_RANGE; + + route->rt_metrics[metric - 1] = value; + + if (!(route->rt_metrics_mask & (1 << (metric - 1)))) { + route->rt_nmetrics++; + route->rt_metrics_mask |= (1 << (metric - 1)); + } + + route->ce_mask |= ROUTE_ATTR_METRICS; + + return 0; +} + +int rtnl_route_unset_metric(struct rtnl_route *route, int metric) +{ + if (metric > RTAX_MAX || metric < 1) + return -NLE_RANGE; + + if (route->rt_metrics_mask & (1 << (metric - 1))) { + route->rt_nmetrics--; + route->rt_metrics_mask &= ~(1 << (metric - 1)); + } + + return 0; +} + +int rtnl_route_get_metric(struct rtnl_route *route, int metric, uint32_t *value) +{ + if (metric > RTAX_MAX || metric < 1) + return -NLE_RANGE; + + if (!(route->rt_metrics_mask & (1 << (metric - 1)))) + return -NLE_OBJ_NOTFOUND; + + if (value) + *value = route->rt_metrics[metric - 1]; + + return 0; +} + +int rtnl_route_set_pref_src(struct rtnl_route *route, struct nl_addr *addr) +{ + if (route->ce_mask & ROUTE_ATTR_FAMILY) { + if (addr->a_family != route->rt_family) + return -NLE_AF_MISMATCH; + } else + route->rt_family = addr->a_family; + + if (route->rt_pref_src) + nl_addr_put(route->rt_pref_src); + + nl_addr_get(addr); + route->rt_pref_src = addr; + route->ce_mask |= (ROUTE_ATTR_PREF_SRC | ROUTE_ATTR_FAMILY); + + return 0; +} + +struct nl_addr *rtnl_route_get_pref_src(struct rtnl_route *route) +{ + return route->rt_pref_src; +} + +void rtnl_route_set_iif(struct rtnl_route *route, int ifindex) +{ + route->rt_iif = ifindex; + route->ce_mask |= ROUTE_ATTR_IIF; +} + +int rtnl_route_get_iif(struct rtnl_route *route) +{ + return route->rt_iif; +} + +void rtnl_route_add_nexthop(struct rtnl_route *route, struct rtnl_nexthop *nh) +{ + nl_list_add_tail(&nh->rtnh_list, &route->rt_nexthops); + route->rt_nr_nh++; + route->ce_mask |= ROUTE_ATTR_MULTIPATH; +} + +void rtnl_route_remove_nexthop(struct rtnl_route *route, struct rtnl_nexthop *nh) +{ + if (route->ce_mask & ROUTE_ATTR_MULTIPATH) { + route->rt_nr_nh--; + nl_list_del(&nh->rtnh_list); + } +} + +struct nl_list_head *rtnl_route_get_nexthops(struct rtnl_route *route) +{ + if (route->ce_mask & ROUTE_ATTR_MULTIPATH) + return &route->rt_nexthops; + + return NULL; +} + +int rtnl_route_get_nnexthops(struct rtnl_route *route) +{ + if (route->ce_mask & ROUTE_ATTR_MULTIPATH) + return route->rt_nr_nh; + + return 0; +} + +void rtnl_route_foreach_nexthop(struct rtnl_route *r, + void (*cb)(struct rtnl_nexthop *, void *), + void *arg) +{ + struct rtnl_nexthop *nh; + + if (r->ce_mask & ROUTE_ATTR_MULTIPATH) { + nl_list_for_each_entry(nh, &r->rt_nexthops, rtnh_list) { + cb(nh, arg); + } + } +} + +struct rtnl_nexthop *rtnl_route_nexthop_n(struct rtnl_route *r, int n) +{ + struct rtnl_nexthop *nh; + uint32_t i; + + if (r->ce_mask & ROUTE_ATTR_MULTIPATH && r->rt_nr_nh > n) { + i = 0; + nl_list_for_each_entry(nh, &r->rt_nexthops, rtnh_list) { + if (i == n) return nh; + i++; + } + } + return NULL; +} + +/** @} */ + +/** + * @name Utilities + * @{ + */ + +/** + * Guess scope of a route object. + * @arg route Route object. + * + * Guesses the scope of a route object, based on the following rules: + * @code + * 1) Local route -> local scope + * 2) At least one nexthop not directly connected -> universe scope + * 3) All others -> link scope + * @endcode + * + * @return Scope value. + */ +int rtnl_route_guess_scope(struct rtnl_route *route) +{ + if (route->rt_type == RTN_LOCAL) + return RT_SCOPE_HOST; + + if (!nl_list_empty(&route->rt_nexthops)) { + struct rtnl_nexthop *nh; + + /* + * Use scope uiniverse if there is at least one nexthop which + * is not directly connected + */ + nl_list_for_each_entry(nh, &route->rt_nexthops, rtnh_list) { + if (nh->rtnh_gateway) + return RT_SCOPE_UNIVERSE; + } + } + + return RT_SCOPE_LINK; +} + +/** @} */ + +static struct nla_policy route_policy[RTA_MAX+1] = { + [RTA_IIF] = { .type = NLA_U32 }, + [RTA_OIF] = { .type = NLA_U32 }, + [RTA_PRIORITY] = { .type = NLA_U32 }, + [RTA_FLOW] = { .type = NLA_U32 }, + [RTA_CACHEINFO] = { .minlen = sizeof(struct rta_cacheinfo) }, + [RTA_METRICS] = { .type = NLA_NESTED }, + [RTA_MULTIPATH] = { .type = NLA_NESTED }, +}; + +static int parse_multipath(struct rtnl_route *route, struct nlattr *attr) +{ + struct rtnl_nexthop *nh = NULL; + struct rtnexthop *rtnh = nla_data(attr); + size_t tlen = nla_len(attr); + int err; + + while (tlen >= sizeof(*rtnh) && tlen >= rtnh->rtnh_len) { + nh = rtnl_route_nh_alloc(); + if (!nh) + return -NLE_NOMEM; + + rtnl_route_nh_set_weight(nh, rtnh->rtnh_hops); + rtnl_route_nh_set_ifindex(nh, rtnh->rtnh_ifindex); + rtnl_route_nh_set_flags(nh, rtnh->rtnh_flags); + + if (rtnh->rtnh_len > sizeof(*rtnh)) { + struct nlattr *ntb[RTA_MAX + 1]; + + err = nla_parse(ntb, RTA_MAX, (struct nlattr *) + RTNH_DATA(rtnh), + rtnh->rtnh_len - sizeof(*rtnh), + route_policy); + if (err < 0) + goto errout; + + if (ntb[RTA_GATEWAY]) { + struct nl_addr *addr; + + addr = nl_addr_alloc_attr(ntb[RTA_GATEWAY], + route->rt_family); + if (!addr) { + err = -NLE_NOMEM; + goto errout; + } + + rtnl_route_nh_set_gateway(nh, addr); + nl_addr_put(addr); + } + + if (ntb[RTA_FLOW]) { + uint32_t realms; + + realms = nla_get_u32(ntb[RTA_FLOW]); + rtnl_route_nh_set_realms(nh, realms); + } + } + + rtnl_route_add_nexthop(route, nh); + tlen -= RTNH_ALIGN(rtnh->rtnh_len); + rtnh = RTNH_NEXT(rtnh); + } + + err = 0; +errout: + if (err && nh) + rtnl_route_nh_free(nh); + + return err; +} + +int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) +{ + struct rtmsg *rtm; + struct rtnl_route *route; + struct nlattr *tb[RTA_MAX + 1]; + struct nl_addr *src = NULL, *dst = NULL, *addr; + struct rtnl_nexthop *old_nh = NULL; + int err, family; + + route = rtnl_route_alloc(); + if (!route) { + err = -NLE_NOMEM; + goto errout; + } + + route->ce_msgtype = nlh->nlmsg_type; + + err = nlmsg_parse(nlh, sizeof(struct rtmsg), tb, RTA_MAX, route_policy); + if (err < 0) + goto errout; + + rtm = nlmsg_data(nlh); + route->rt_family = family = rtm->rtm_family; + route->rt_tos = rtm->rtm_tos; + route->rt_table = rtm->rtm_table; + route->rt_type = rtm->rtm_type; + route->rt_scope = rtm->rtm_scope; + route->rt_protocol = rtm->rtm_protocol; + route->rt_flags = rtm->rtm_flags; + route->rt_prio = 0; + + route->ce_mask |= ROUTE_ATTR_FAMILY | ROUTE_ATTR_TOS | + ROUTE_ATTR_TABLE | ROUTE_ATTR_TYPE | + ROUTE_ATTR_SCOPE | ROUTE_ATTR_PROTOCOL | + ROUTE_ATTR_FLAGS | ROUTE_ATTR_PRIO; + + if (tb[RTA_DST]) { + if (!(dst = nl_addr_alloc_attr(tb[RTA_DST], family))) + goto errout_nomem; + } else { + if (!(dst = nl_addr_alloc(0))) + goto errout_nomem; + nl_addr_set_family(dst, rtm->rtm_family); + } + + nl_addr_set_prefixlen(dst, rtm->rtm_dst_len); + err = rtnl_route_set_dst(route, dst); + if (err < 0) + goto errout; + + nl_addr_put(dst); + + if (tb[RTA_SRC]) { + if (!(src = nl_addr_alloc_attr(tb[RTA_SRC], family))) + goto errout_nomem; + } else if (rtm->rtm_src_len) + if (!(src = nl_addr_alloc(0))) + goto errout_nomem; + + if (src) { + nl_addr_set_prefixlen(src, rtm->rtm_src_len); + rtnl_route_set_src(route, src); + nl_addr_put(src); + } + + if (tb[RTA_TABLE]) + rtnl_route_set_table(route, nla_get_u32(tb[RTA_TABLE])); + + if (tb[RTA_IIF]) + rtnl_route_set_iif(route, nla_get_u32(tb[RTA_IIF])); + + if (tb[RTA_PRIORITY]) + rtnl_route_set_priority(route, nla_get_u32(tb[RTA_PRIORITY])); + + if (tb[RTA_PREFSRC]) { + if (!(addr = nl_addr_alloc_attr(tb[RTA_PREFSRC], family))) + goto errout_nomem; + rtnl_route_set_pref_src(route, addr); + nl_addr_put(addr); + } + + if (tb[RTA_METRICS]) { + struct nlattr *mtb[RTAX_MAX + 1]; + int i; + + err = nla_parse_nested(mtb, RTAX_MAX, tb[RTA_METRICS], NULL); + if (err < 0) + goto errout; + + for (i = 1; i <= RTAX_MAX; i++) { + if (mtb[i] && nla_len(mtb[i]) >= sizeof(uint32_t)) { + uint32_t m = nla_get_u32(mtb[i]); + if (rtnl_route_set_metric(route, i, m) < 0) + goto errout; + } + } + } + + if (tb[RTA_MULTIPATH]) + if ((err = parse_multipath(route, tb[RTA_MULTIPATH])) < 0) + goto errout; + + if (tb[RTA_CACHEINFO]) { + nla_memcpy(&route->rt_cacheinfo, tb[RTA_CACHEINFO], + sizeof(route->rt_cacheinfo)); + route->ce_mask |= ROUTE_ATTR_CACHEINFO; + } + + if (tb[RTA_OIF]) { + if (!old_nh && !(old_nh = rtnl_route_nh_alloc())) + goto errout; + + rtnl_route_nh_set_ifindex(old_nh, nla_get_u32(tb[RTA_OIF])); + } + + if (tb[RTA_GATEWAY]) { + if (!old_nh && !(old_nh = rtnl_route_nh_alloc())) + goto errout; + + if (!(addr = nl_addr_alloc_attr(tb[RTA_GATEWAY], family))) + goto errout_nomem; + + rtnl_route_nh_set_gateway(old_nh, addr); + nl_addr_put(addr); + } + + if (tb[RTA_FLOW]) { + if (!old_nh && !(old_nh = rtnl_route_nh_alloc())) + goto errout; + + rtnl_route_nh_set_realms(old_nh, nla_get_u32(tb[RTA_FLOW])); + } + + if (old_nh) { + rtnl_route_nh_set_flags(old_nh, rtm->rtm_flags & 0xff); + if (route->rt_nr_nh == 0) { + /* If no nexthops have been provided via RTA_MULTIPATH + * we add it as regular nexthop to maintain backwards + * compatibility */ + rtnl_route_add_nexthop(route, old_nh); + } else { + /* Kernel supports new style nexthop configuration, + * verify that it is a duplicate and discard nexthop. */ + struct rtnl_nexthop *first; + + first = nl_list_first_entry(&route->rt_nexthops, + struct rtnl_nexthop, + rtnh_list); + if (!first) + BUG(); + + if (rtnl_route_nh_compare(old_nh, first, + old_nh->ce_mask, 0)) { + err = -NLE_INVAL; + goto errout; + } + + rtnl_route_nh_free(old_nh); + } + } + + *result = route; + return 0; + +errout: + rtnl_route_put(route); + return err; + +errout_nomem: + err = -NLE_NOMEM; + goto errout; +} + +int rtnl_route_build_msg(struct nl_msg *msg, struct rtnl_route *route) +{ + int i; + struct nlattr *metrics; + struct rtmsg rtmsg = { + .rtm_family = route->rt_family, + .rtm_tos = route->rt_tos, + .rtm_table = route->rt_table, + .rtm_protocol = route->rt_protocol, + .rtm_scope = route->rt_scope, + .rtm_type = route->rt_type, + .rtm_flags = route->rt_flags, + }; + + if (route->rt_dst == NULL) + return -NLE_MISSING_ATTR; + + rtmsg.rtm_dst_len = nl_addr_get_prefixlen(route->rt_dst); + if (route->rt_src) + rtmsg.rtm_src_len = nl_addr_get_prefixlen(route->rt_src); + + if (rtmsg.rtm_scope == RT_SCOPE_NOWHERE) + rtmsg.rtm_scope = rtnl_route_guess_scope(route); + + if (rtnl_route_get_nnexthops(route) == 1) { + struct rtnl_nexthop *nh; + nh = rtnl_route_nexthop_n(route, 0); + rtmsg.rtm_flags |= nh->rtnh_flags; + } + + if (nlmsg_append(msg, &rtmsg, sizeof(rtmsg), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + /* Additional table attribute replacing the 8bit in the header, was + * required to allow more than 256 tables. */ + NLA_PUT_U32(msg, RTA_TABLE, route->rt_table); + + if (nl_addr_get_len(route->rt_dst)) + NLA_PUT_ADDR(msg, RTA_DST, route->rt_dst); + NLA_PUT_U32(msg, RTA_PRIORITY, route->rt_prio); + + if (route->ce_mask & ROUTE_ATTR_SRC) + NLA_PUT_ADDR(msg, RTA_SRC, route->rt_src); + + if (route->ce_mask & ROUTE_ATTR_PREF_SRC) + NLA_PUT_ADDR(msg, RTA_PREFSRC, route->rt_pref_src); + + if (route->ce_mask & ROUTE_ATTR_IIF) + NLA_PUT_U32(msg, RTA_IIF, route->rt_iif); + + if (route->rt_nmetrics > 0) { + uint32_t val; + + metrics = nla_nest_start(msg, RTA_METRICS); + if (metrics == NULL) + goto nla_put_failure; + + for (i = 1; i <= RTAX_MAX; i++) { + if (!rtnl_route_get_metric(route, i, &val)) + NLA_PUT_U32(msg, i, val); + } + + nla_nest_end(msg, metrics); + } + + if (rtnl_route_get_nnexthops(route) == 1) { + struct rtnl_nexthop *nh; + + nh = rtnl_route_nexthop_n(route, 0); + if (nh->rtnh_gateway) + NLA_PUT_ADDR(msg, RTA_GATEWAY, nh->rtnh_gateway); + if (nh->rtnh_ifindex) + NLA_PUT_U32(msg, RTA_OIF, nh->rtnh_ifindex); + if (nh->rtnh_realms) + NLA_PUT_U32(msg, RTA_FLOW, nh->rtnh_realms); + } else if (rtnl_route_get_nnexthops(route) > 1) { + struct nlattr *multipath; + struct rtnl_nexthop *nh; + + if (!(multipath = nla_nest_start(msg, RTA_MULTIPATH))) + goto nla_put_failure; + + nl_list_for_each_entry(nh, &route->rt_nexthops, rtnh_list) { + struct rtnexthop *rtnh; + + rtnh = nlmsg_reserve(msg, sizeof(*rtnh), NLMSG_ALIGNTO); + if (!rtnh) + goto nla_put_failure; + + rtnh->rtnh_flags = nh->rtnh_flags; + rtnh->rtnh_hops = nh->rtnh_weight; + rtnh->rtnh_ifindex = nh->rtnh_ifindex; + + if (nh->rtnh_gateway) + NLA_PUT_ADDR(msg, RTA_GATEWAY, + nh->rtnh_gateway); + + if (nh->rtnh_realms) + NLA_PUT_U32(msg, RTA_FLOW, nh->rtnh_realms); + + rtnh->rtnh_len = nlmsg_tail(msg->nm_nlh) - + (void *) rtnh; + } + + nla_nest_end(msg, multipath); + } + + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +/** @cond SKIP */ +struct nl_object_ops route_obj_ops = { + .oo_name = "route/route", + .oo_size = sizeof(struct rtnl_route), + .oo_constructor = route_constructor, + .oo_free_data = route_free_data, + .oo_clone = route_clone, + .oo_dump = { + [NL_DUMP_LINE] = route_dump_line, + [NL_DUMP_DETAILS] = route_dump_details, + [NL_DUMP_STATS] = route_dump_stats, + }, + .oo_compare = route_compare, + .oo_keygen = route_keygen, + .oo_update = route_update, + .oo_attrs2str = route_attrs2str, + .oo_id_attrs = (ROUTE_ATTR_FAMILY | ROUTE_ATTR_TOS | + ROUTE_ATTR_TABLE | ROUTE_ATTR_DST | + ROUTE_ATTR_PRIO), +}; +/** @endcond */ + +/** @} */ diff --git a/lib/route/route_utils.c b/lib/route/route_utils.c new file mode 100644 index 0000000..a5b3966 --- /dev/null +++ b/lib/route/route_utils.c @@ -0,0 +1,171 @@ +/* + * lib/route/route_utils.c Routing Utilities + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2006 Thomas Graf + */ + +/** + * @ingroup route + * @defgroup route_utils Utilities + * @brief Routing Utility Functions + * + * + * @par 1) Translating Routing Table Names + * @code + * // libnl is only aware of the de facto standard routing table names. + * // Additional name <-> identifier associations have to be read in via + * // a configuration file, f.e. /etc/iproute2/rt_tables + * err = rtnl_route_read_table_names("/etc/iproute2/rt_tables"); + * + * // Translating a table name to its idenfier + * int table = rtnl_route_str2table("main"); + * + * // ... and the other way around. + * char buf[32]; + * printf("Name: %s\n", + * rtnl_route_table2str(table, buf, sizeof(buf))); + * @endcode + * + * + * + * + * @{ + */ + +#include +#include +#include +#include +#include + +/** + * @name Routing Table Identifier Translations + * @{ + */ + +static NL_LIST_HEAD(table_names); + +static int add_routing_table_name(long id, const char *name) +{ + return __trans_list_add(id, name, &table_names); +} + +static void __init init_routing_table_names(void) +{ + add_routing_table_name(RT_TABLE_UNSPEC, "unspec"); + add_routing_table_name(RT_TABLE_COMPAT, "compat"); + add_routing_table_name(RT_TABLE_DEFAULT, "default"); + add_routing_table_name(RT_TABLE_MAIN, "main"); + add_routing_table_name(RT_TABLE_LOCAL, "local"); +}; + +static void __exit release_routing_table_names(void) +{ + __trans_list_clear(&table_names); +} + +int rtnl_route_read_table_names(const char *path) +{ + __trans_list_clear(&table_names); + + return __nl_read_num_str_file(path, &add_routing_table_name); +} + +char *rtnl_route_table2str(int table, char *buf, size_t size) +{ + return __list_type2str(table, buf, size, &table_names); +} + +int rtnl_route_str2table(const char *name) +{ + return __list_str2type(name, &table_names); +} + + +/** @} */ + +/** + * @name Routing Protocol Translations + * @{ + */ + +static NL_LIST_HEAD(proto_names); + +static int add_proto_name(long id, const char *name) +{ + return __trans_list_add(id, name, &proto_names); +} + +static void __init init_proto_names(void) +{ + add_proto_name(RTPROT_UNSPEC, "unspec"); + add_proto_name(RTPROT_REDIRECT, "redirect"); + add_proto_name(RTPROT_KERNEL, "kernel"); + add_proto_name(RTPROT_BOOT, "boot"); + add_proto_name(RTPROT_STATIC, "static"); +}; + +static void __exit release_proto_names(void) +{ + __trans_list_clear(&proto_names); +} + +int rtnl_route_read_protocol_names(const char *path) +{ + __trans_list_clear(&proto_names); + + return __nl_read_num_str_file(path, &add_proto_name); +} + +char *rtnl_route_proto2str(int proto, char *buf, size_t size) +{ + return __list_type2str(proto, buf, size, &proto_names); +} + +int rtnl_route_str2proto(const char *name) +{ + return __list_str2type(name, &proto_names); +} + +/** @} */ + +/** + * @name Routing Metrices Translations + * @{ + */ + +static const struct trans_tbl route_metrices[] = { + __ADD(RTAX_UNSPEC, unspec) + __ADD(RTAX_LOCK, lock) + __ADD(RTAX_MTU, mtu) + __ADD(RTAX_WINDOW, window) + __ADD(RTAX_RTT, rtt) + __ADD(RTAX_RTTVAR, rttvar) + __ADD(RTAX_SSTHRESH, ssthresh) + __ADD(RTAX_CWND, cwnd) + __ADD(RTAX_ADVMSS, advmss) + __ADD(RTAX_REORDERING, reordering) + __ADD(RTAX_HOPLIMIT, hoplimit) + __ADD(RTAX_INITCWND, initcwnd) + __ADD(RTAX_FEATURES, features) +}; + +char *rtnl_route_metric2str(int metric, char *buf, size_t size) +{ + return __type2str(metric, buf, size, route_metrices, + ARRAY_SIZE(route_metrices)); +} + +int rtnl_route_str2metric(const char *name) +{ + return __str2type(name, route_metrices, ARRAY_SIZE(route_metrices)); +} + +/** @} */ + +/** @} */ diff --git a/lib/route/rtnl.c b/lib/route/rtnl.c new file mode 100644 index 0000000..82397e9 --- /dev/null +++ b/lib/route/rtnl.c @@ -0,0 +1,124 @@ +/* + * lib/route/rtnl.c Routing Netlink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +/** + * @defgroup rtnl Routing Library (libnl-route) + * @{ + */ + +#include +#include +#include +#include + +/** + * @name Sending + * @{ + */ + +/** + * Send routing netlink request message + * @arg sk Netlink socket. + * @arg type Netlink message type. + * @arg family Address family. + * @arg flags Additional netlink message flags. + * + * Fills out a routing netlink request message and sends it out + * using nl_send_simple(). + * + * @return 0 on success or a negative error code. + */ +int nl_rtgen_request(struct nl_sock *sk, int type, int family, int flags) +{ + struct rtgenmsg gmsg = { + .rtgen_family = family, + }; + + return nl_send_simple(sk, type, flags, &gmsg, sizeof(gmsg)); +} + +/** @} */ + +/** + * @name Routing Type Translations + * @{ + */ + +static const struct trans_tbl rtntypes[] = { + __ADD(RTN_UNSPEC,unspec) + __ADD(RTN_UNICAST,unicast) + __ADD(RTN_LOCAL,local) + __ADD(RTN_BROADCAST,broadcast) + __ADD(RTN_ANYCAST,anycast) + __ADD(RTN_MULTICAST,multicast) + __ADD(RTN_BLACKHOLE,blackhole) + __ADD(RTN_UNREACHABLE,unreachable) + __ADD(RTN_PROHIBIT,prohibit) + __ADD(RTN_THROW,throw) + __ADD(RTN_NAT,nat) + __ADD(RTN_XRESOLVE,xresolve) +}; + +char *nl_rtntype2str(int type, char *buf, size_t size) +{ + return __type2str(type, buf, size, rtntypes, ARRAY_SIZE(rtntypes)); +} + +int nl_str2rtntype(const char *name) +{ + return __str2type(name, rtntypes, ARRAY_SIZE(rtntypes)); +} + +/** @} */ + +/** + * @name Scope Translations + * @{ + */ + +static const struct trans_tbl scopes[] = { + __ADD(255,nowhere) + __ADD(254,host) + __ADD(253,link) + __ADD(200,site) + __ADD(0,global) +}; + +char *rtnl_scope2str(int scope, char *buf, size_t size) +{ + return __type2str(scope, buf, size, scopes, ARRAY_SIZE(scopes)); +} + +int rtnl_str2scope(const char *name) +{ + return __str2type(name, scopes, ARRAY_SIZE(scopes)); +} + +/** @} */ + +/** + * @name Realms Translations + * @{ + */ + +char * rtnl_realms2str(uint32_t realms, char *buf, size_t len) +{ + int from = RTNL_REALM_FROM(realms); + int to = RTNL_REALM_TO(realms); + + snprintf(buf, len, "%d/%d", from, to); + + return buf; +} + +/** @} */ + +/** @} */ diff --git a/lib/route/rule.c b/lib/route/rule.c new file mode 100644 index 0000000..b2161a2 --- /dev/null +++ b/lib/route/rule.c @@ -0,0 +1,757 @@ +/* + * lib/route/rule.c Routing Rules + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2010 Thomas Graf + */ + +/** + * @ingroup rtnl + * @defgroup rule Routing Rules + * @brief + * @{ + */ + +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define RULE_ATTR_FAMILY 0x0001 +#define RULE_ATTR_TABLE 0x0002 +#define RULE_ATTR_ACTION 0x0004 +#define RULE_ATTR_FLAGS 0x0008 +#define RULE_ATTR_IIFNAME 0x0010 +#define RULE_ATTR_OIFNAME 0x0020 +#define RULE_ATTR_PRIO 0x0040 +#define RULE_ATTR_MARK 0x0080 +#define RULE_ATTR_MASK 0x0100 +#define RULE_ATTR_GOTO 0x0200 +#define RULE_ATTR_SRC 0x0400 +#define RULE_ATTR_DST 0x0800 +#define RULE_ATTR_DSFIELD 0x1000 +#define RULE_ATTR_FLOW 0x2000 + +static struct nl_cache_ops rtnl_rule_ops; +static struct nl_object_ops rule_obj_ops; +/** @endcond */ + +static void rule_free_data(struct nl_object *c) +{ + struct rtnl_rule *rule = nl_object_priv(c); + + if (!rule) + return; + + nl_addr_put(rule->r_src); + nl_addr_put(rule->r_dst); +} + +static int rule_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct rtnl_rule *dst = nl_object_priv(_dst); + struct rtnl_rule *src = nl_object_priv(_src); + + if (src->r_src) + if (!(dst->r_src = nl_addr_clone(src->r_src))) + return -NLE_NOMEM; + + if (src->r_dst) + if (!(dst->r_dst = nl_addr_clone(src->r_dst))) + return -NLE_NOMEM; + + return 0; +} + +static struct nla_policy rule_policy[FRA_MAX+1] = { + [FRA_TABLE] = { .type = NLA_U32 }, + [FRA_IIFNAME] = { .type = NLA_STRING, .maxlen = IFNAMSIZ }, + [FRA_OIFNAME] = { .type = NLA_STRING, .maxlen = IFNAMSIZ }, + [FRA_PRIORITY] = { .type = NLA_U32 }, + [FRA_FWMARK] = { .type = NLA_U32 }, + [FRA_FWMASK] = { .type = NLA_U32 }, + [FRA_GOTO] = { .type = NLA_U32 }, + [FRA_FLOW] = { .type = NLA_U32 }, +}; + +static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *n, struct nl_parser_param *pp) +{ + struct rtnl_rule *rule; + struct fib_rule_hdr *frh; + struct nlattr *tb[FRA_MAX+1]; + int err = 1, family; + + rule = rtnl_rule_alloc(); + if (!rule) { + err = -NLE_NOMEM; + goto errout; + } + + rule->ce_msgtype = n->nlmsg_type; + frh = nlmsg_data(n); + + err = nlmsg_parse(n, sizeof(*frh), tb, FRA_MAX, rule_policy); + if (err < 0) + goto errout; + + rule->r_family = family = frh->family; + rule->r_table = frh->table; + rule->r_action = frh->action; + rule->r_flags = frh->flags; + + rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_TABLE | RULE_ATTR_ACTION | + RULE_ATTR_FLAGS); + + /* ipv4 only */ + if (frh->tos) { + rule->r_dsfield = frh->tos; + rule->ce_mask |= RULE_ATTR_DSFIELD; + } + + if (tb[FRA_TABLE]) { + rule->r_table = nla_get_u32(tb[FRA_TABLE]); + rule->ce_mask |= RULE_ATTR_TABLE; + } + + if (tb[FRA_IIFNAME]) { + nla_strlcpy(rule->r_iifname, tb[FRA_IIFNAME], IFNAMSIZ); + rule->ce_mask |= RULE_ATTR_IIFNAME; + } + + if (tb[FRA_OIFNAME]) { + nla_strlcpy(rule->r_oifname, tb[FRA_OIFNAME], IFNAMSIZ); + rule->ce_mask |= RULE_ATTR_OIFNAME; + } + + if (tb[FRA_PRIORITY]) { + rule->r_prio = nla_get_u32(tb[FRA_PRIORITY]); + rule->ce_mask |= RULE_ATTR_PRIO; + } + + if (tb[FRA_FWMARK]) { + rule->r_mark = nla_get_u32(tb[FRA_FWMARK]); + rule->ce_mask |= RULE_ATTR_MARK; + } + + if (tb[FRA_FWMASK]) { + rule->r_mask = nla_get_u32(tb[FRA_FWMASK]); + rule->ce_mask |= RULE_ATTR_MASK; + } + + if (tb[FRA_GOTO]) { + rule->r_goto = nla_get_u32(tb[FRA_GOTO]); + rule->ce_mask |= RULE_ATTR_GOTO; + } + + if (tb[FRA_SRC]) { + if (!(rule->r_src = nl_addr_alloc_attr(tb[FRA_SRC], family))) + goto errout_enomem; + + nl_addr_set_prefixlen(rule->r_src, frh->src_len); + rule->ce_mask |= RULE_ATTR_SRC; + } + + if (tb[FRA_DST]) { + if (!(rule->r_dst = nl_addr_alloc_attr(tb[FRA_DST], family))) + goto errout_enomem; + nl_addr_set_prefixlen(rule->r_dst, frh->dst_len); + rule->ce_mask |= RULE_ATTR_DST; + } + + /* ipv4 only */ + if (tb[FRA_FLOW]) { + rule->r_flow = nla_get_u32(tb[FRA_FLOW]); + rule->ce_mask |= RULE_ATTR_FLOW; + } + + err = pp->pp_cb((struct nl_object *) rule, pp); +errout: + rtnl_rule_put(rule); + return err; + +errout_enomem: + err = -NLE_NOMEM; + goto errout; +} + +static int rule_request_update(struct nl_cache *c, struct nl_sock *h) +{ + return nl_rtgen_request(h, RTM_GETRULE, AF_UNSPEC, NLM_F_DUMP); +} + +static void rule_dump_line(struct nl_object *o, struct nl_dump_params *p) +{ + struct rtnl_rule *r = (struct rtnl_rule *) o; + char buf[128]; + + nl_dump_line(p, "%8d ", (r->ce_mask & RULE_ATTR_PRIO) ? r->r_prio : 0); + nl_dump(p, "%s ", nl_af2str(r->r_family, buf, sizeof(buf))); + + if (r->ce_mask & RULE_ATTR_SRC) + nl_dump(p, "from %s ", + nl_addr2str(r->r_src, buf, sizeof(buf))); + + if (r->ce_mask & RULE_ATTR_DST) + nl_dump(p, "to %s ", + nl_addr2str(r->r_dst, buf, sizeof(buf))); + + if (r->ce_mask & RULE_ATTR_DSFIELD) + nl_dump(p, "tos %u ", r->r_dsfield); + + if (r->ce_mask & (RULE_ATTR_MARK | RULE_ATTR_MASK)) + nl_dump(p, "mark %#x/%#x", r->r_mark, r->r_mask); + + if (r->ce_mask & RULE_ATTR_IIFNAME) + nl_dump(p, "iif %s ", r->r_iifname); + + if (r->ce_mask & RULE_ATTR_OIFNAME) + nl_dump(p, "oif %s ", r->r_oifname); + + if (r->ce_mask & RULE_ATTR_TABLE) + nl_dump(p, "lookup %s ", + rtnl_route_table2str(r->r_table, buf, sizeof(buf))); + + if (r->ce_mask & RULE_ATTR_FLOW) + nl_dump(p, "flow %s ", + rtnl_realms2str(r->r_flow, buf, sizeof(buf))); + + if (r->ce_mask & RULE_ATTR_GOTO) + nl_dump(p, "goto %u ", r->r_goto); + + if (r->ce_mask & RULE_ATTR_ACTION) + nl_dump(p, "action %s", + nl_rtntype2str(r->r_action, buf, sizeof(buf))); + + nl_dump(p, "\n"); +} + +static void rule_dump_details(struct nl_object *obj, struct nl_dump_params *p) +{ + rule_dump_line(obj, p); +} + +static void rule_dump_stats(struct nl_object *obj, struct nl_dump_params *p) +{ + rule_dump_details(obj, p); +} + +#define RULE_ATTR_FLAGS 0x0008 + +static int rule_compare(struct nl_object *_a, struct nl_object *_b, + uint32_t attrs, int flags) +{ + struct rtnl_rule *a = (struct rtnl_rule *) _a; + struct rtnl_rule *b = (struct rtnl_rule *) _b; + int diff = 0; + +#define RULE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, RULE_ATTR_##ATTR, a, b, EXPR) + + diff |= RULE_DIFF(FAMILY, a->r_family != b->r_family); + diff |= RULE_DIFF(TABLE, a->r_table != b->r_table); + diff |= RULE_DIFF(ACTION, a->r_action != b->r_action); + diff |= RULE_DIFF(IIFNAME, strcmp(a->r_iifname, b->r_iifname)); + diff |= RULE_DIFF(OIFNAME, strcmp(a->r_oifname, b->r_oifname)); + diff |= RULE_DIFF(PRIO, a->r_prio != b->r_prio); + diff |= RULE_DIFF(MARK, a->r_mark != b->r_mark); + diff |= RULE_DIFF(MASK, a->r_mask != b->r_mask); + diff |= RULE_DIFF(GOTO, a->r_goto != b->r_goto); + diff |= RULE_DIFF(SRC, nl_addr_cmp(a->r_src, b->r_src)); + diff |= RULE_DIFF(DST, nl_addr_cmp(a->r_dst, b->r_dst)); + diff |= RULE_DIFF(DSFIELD, a->r_dsfield != b->r_dsfield); + diff |= RULE_DIFF(FLOW, a->r_flow != b->r_flow); + +#undef RULE_DIFF + + return diff; +} + +static const struct trans_tbl rule_attrs[] = { + __ADD(RULE_ATTR_FAMILY, family) + __ADD(RULE_ATTR_TABLE, table) + __ADD(RULE_ATTR_ACTION, action) + __ADD(RULE_ATTR_IIFNAME, iifname) + __ADD(RULE_ATTR_OIFNAME, oifname) + __ADD(RULE_ATTR_PRIO, prio) + __ADD(RULE_ATTR_MARK, mark) + __ADD(RULE_ATTR_MASK, mask) + __ADD(RULE_ATTR_GOTO, goto) + __ADD(RULE_ATTR_SRC, src) + __ADD(RULE_ATTR_DST, dst) + __ADD(RULE_ATTR_DSFIELD, dsfield) + __ADD(RULE_ATTR_FLOW, flow) +}; + +static char *rule_attrs2str(int attrs, char *buf, size_t len) +{ + return __flags2str(attrs, buf, len, rule_attrs, + ARRAY_SIZE(rule_attrs)); +} + +/** + * @name Allocation/Freeing + * @{ + */ + +struct rtnl_rule *rtnl_rule_alloc(void) +{ + return (struct rtnl_rule *) nl_object_alloc(&rule_obj_ops); +} + +void rtnl_rule_put(struct rtnl_rule *rule) +{ + nl_object_put((struct nl_object *) rule); +} + +/** @} */ + +/** + * @name Cache Management + * @{ + */ + +/** + * Build a rule cache including all rules currently configured in the kernel. + * @arg sock Netlink socket. + * @arg family Address family or AF_UNSPEC. + * @arg result Pointer to store resulting cache. + * + * Allocates a new rule cache, initializes it properly and updates it + * to include all rules currently configured in the kernel. + * + * @return 0 on success or a negative error code. + */ +int rtnl_rule_alloc_cache(struct nl_sock *sock, int family, + struct nl_cache **result) +{ + struct nl_cache * cache; + int err; + + if (!(cache = nl_cache_alloc(&rtnl_rule_ops))) + return -NLE_NOMEM; + + cache->c_iarg1 = family; + + if (sock && (err = nl_cache_refill(sock, cache)) < 0) { + free(cache); + return err; + } + + *result = cache; + return 0; +} + +/** @} */ + +/** + * @name Rule Addition + * @{ + */ + +static int build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags, + struct nl_msg **result) +{ + struct nl_msg *msg; + struct fib_rule_hdr frh = { + .family = tmpl->r_family, + .table = tmpl->r_table, + .action = tmpl->r_action, + .flags = tmpl->r_flags, + .tos = tmpl->r_dsfield, + }; + + if (!(tmpl->ce_mask & RULE_ATTR_FAMILY)) + return -NLE_MISSING_ATTR; + + msg = nlmsg_alloc_simple(cmd, flags); + if (!msg) + return -NLE_NOMEM; + + if (tmpl->ce_mask & RULE_ATTR_SRC) + frh.src_len = nl_addr_get_prefixlen(tmpl->r_src); + + if (tmpl->ce_mask & RULE_ATTR_DST) + frh.dst_len = nl_addr_get_prefixlen(tmpl->r_dst); + + if (nlmsg_append(msg, &frh, sizeof(frh), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + /* Additional table attribute replacing the 8bit in the header, was + * required to allow more than 256 tables. */ + NLA_PUT_U32(msg, FRA_TABLE, tmpl->r_table); + + if (tmpl->ce_mask & RULE_ATTR_SRC) + NLA_PUT_ADDR(msg, FRA_SRC, tmpl->r_src); + + if (tmpl->ce_mask & RULE_ATTR_DST) + NLA_PUT_ADDR(msg, FRA_DST, tmpl->r_dst); + + if (tmpl->ce_mask & RULE_ATTR_IIFNAME) + NLA_PUT_STRING(msg, FRA_IIFNAME, tmpl->r_iifname); + + if (tmpl->ce_mask & RULE_ATTR_OIFNAME) + NLA_PUT_STRING(msg, FRA_OIFNAME, tmpl->r_oifname); + + if (tmpl->ce_mask & RULE_ATTR_PRIO) + NLA_PUT_U32(msg, FRA_PRIORITY, tmpl->r_prio); + + if (tmpl->ce_mask & RULE_ATTR_MARK) + NLA_PUT_U32(msg, FRA_FWMARK, tmpl->r_mark); + + if (tmpl->ce_mask & RULE_ATTR_MASK) + NLA_PUT_U32(msg, FRA_FWMASK, tmpl->r_mask); + + if (tmpl->ce_mask & RULE_ATTR_GOTO) + NLA_PUT_U32(msg, FRA_GOTO, tmpl->r_goto); + + if (tmpl->ce_mask & RULE_ATTR_FLOW) + NLA_PUT_U32(msg, FRA_FLOW, tmpl->r_flow); + + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +/** + * Build netlink request message to add a new rule + * @arg tmpl template with data of new rule + * @arg flags additional netlink message flags + * @arg result Result pointer + * + * Builds a new netlink message requesting a addition of a new + * rule. The netlink message header isn't fully equipped with + * all relevant fields and must thus be sent out via nl_send_auto_complete() + * or supplemented as needed. \a tmpl must contain the attributes of the new + * address set via \c rtnl_rule_set_* functions. + * + * @return 0 on success or a negative error code. + */ +int rtnl_rule_build_add_request(struct rtnl_rule *tmpl, int flags, + struct nl_msg **result) +{ + return build_rule_msg(tmpl, RTM_NEWRULE, NLM_F_CREATE | flags, + result); +} + +/** + * Add a new rule + * @arg sk Netlink socket. + * @arg tmpl template with requested changes + * @arg flags additional netlink message flags + * + * Builds a netlink message by calling rtnl_rule_build_add_request(), + * sends the request to the kernel and waits for the next ACK to be + * received and thus blocks until the request has been fullfilled. + * + * @return 0 on sucess or a negative error if an error occured. + */ +int rtnl_rule_add(struct nl_sock *sk, struct rtnl_rule *tmpl, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_rule_build_add_request(tmpl, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +/** @} */ + +/** + * @name Rule Deletion + * @{ + */ + +/** + * Build a netlink request message to delete a rule + * @arg rule rule to delete + * @arg flags additional netlink message flags + * @arg result Result pointer + * + * Builds a new netlink message requesting a deletion of a rule. + * The netlink message header isn't fully equipped with all relevant + * fields and must thus be sent out via nl_send_auto_complete() + * or supplemented as needed. \a rule must point to an existing + * address. + * + * @return 0 on success or a negative error code. + */ +int rtnl_rule_build_delete_request(struct rtnl_rule *rule, int flags, + struct nl_msg **result) +{ + return build_rule_msg(rule, RTM_DELRULE, flags, result); +} + +/** + * Delete a rule + * @arg sk Netlink socket. + * @arg rule rule to delete + * @arg flags additional netlink message flags + * + * Builds a netlink message by calling rtnl_rule_build_delete_request(), + * sends the request to the kernel and waits for the next ACK to be + * received and thus blocks until the request has been fullfilled. + * + * @return 0 on sucess or a negative error if an error occured. + */ +int rtnl_rule_delete(struct nl_sock *sk, struct rtnl_rule *rule, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_rule_build_delete_request(rule, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return wait_for_ack(sk); +} + +/** @} */ + +/** + * @name Attribute Modification + * @{ + */ + +void rtnl_rule_set_family(struct rtnl_rule *rule, int family) +{ + rule->r_family = family; + rule->ce_mask |= RULE_ATTR_FAMILY; +} + +int rtnl_rule_get_family(struct rtnl_rule *rule) +{ + if (rule->ce_mask & RULE_ATTR_FAMILY) + return rule->r_family; + else + return AF_UNSPEC; +} + +void rtnl_rule_set_prio(struct rtnl_rule *rule, uint32_t prio) +{ + rule->r_prio = prio; + rule->ce_mask |= RULE_ATTR_PRIO; +} + +uint32_t rtnl_rule_get_prio(struct rtnl_rule *rule) +{ + return rule->r_prio; +} + +void rtnl_rule_set_mark(struct rtnl_rule *rule, uint32_t mark) +{ + rule->r_mark = mark; + rule->ce_mask |= RULE_ATTR_MARK; +} + +uint32_t rtnl_rule_get_mark(struct rtnl_rule *rule) +{ + return rule->r_mark; +} + +void rtnl_rule_set_mask(struct rtnl_rule *rule, uint32_t mask) +{ + rule->r_mask = mask; + rule->ce_mask |= RULE_ATTR_MASK; +} + +uint32_t rtnl_rule_get_mask(struct rtnl_rule *rule) +{ + return rule->r_mask; +} + +void rtnl_rule_set_table(struct rtnl_rule *rule, uint32_t table) +{ + rule->r_table = table; + rule->ce_mask |= RULE_ATTR_TABLE; +} + +uint32_t rtnl_rule_get_table(struct rtnl_rule *rule) +{ + return rule->r_table; +} + +void rtnl_rule_set_dsfield(struct rtnl_rule *rule, uint8_t dsfield) +{ + rule->r_dsfield = dsfield; + rule->ce_mask |= RULE_ATTR_DSFIELD; +} + +uint8_t rtnl_rule_get_dsfield(struct rtnl_rule *rule) +{ + return rule->r_dsfield; +} + +static inline int __assign_addr(struct rtnl_rule *rule, struct nl_addr **pos, + struct nl_addr *new, int flag) +{ + if (rule->ce_mask & RULE_ATTR_FAMILY) { + if (new->a_family != rule->r_family) + return -NLE_AF_MISMATCH; + } else + rule->r_family = new->a_family; + + if (*pos) + nl_addr_put(*pos); + + nl_addr_get(new); + *pos = new; + + rule->ce_mask |= (flag | RULE_ATTR_FAMILY); + + return 0; +} + +int rtnl_rule_set_src(struct rtnl_rule *rule, struct nl_addr *src) +{ + return __assign_addr(rule, &rule->r_src, src, RULE_ATTR_SRC); +} + +struct nl_addr *rtnl_rule_get_src(struct rtnl_rule *rule) +{ + return rule->r_src; +} + +int rtnl_rule_set_dst(struct rtnl_rule *rule, struct nl_addr *dst) +{ + return __assign_addr(rule, &rule->r_dst, dst, RULE_ATTR_DST); +} + +struct nl_addr *rtnl_rule_get_dst(struct rtnl_rule *rule) +{ + return rule->r_dst; +} + +int rtnl_rule_set_iif(struct rtnl_rule *rule, const char *dev) +{ + if (strlen(dev) > IFNAMSIZ-1) + return -NLE_RANGE; + + strcpy(rule->r_iifname, dev); + rule->ce_mask |= RULE_ATTR_IIFNAME; + return 0; +} + +char *rtnl_rule_get_iif(struct rtnl_rule *rule) +{ + if (rule->ce_mask & RULE_ATTR_IIFNAME) + return rule->r_iifname; + else + return NULL; +} + +int rtnl_rule_set_oif(struct rtnl_rule *rule, const char *dev) +{ + if (strlen(dev) > IFNAMSIZ-1) + return -NLE_RANGE; + + strcpy(rule->r_oifname, dev); + rule->ce_mask |= RULE_ATTR_OIFNAME; + return 0; +} + +char *rtnl_rule_get_oif(struct rtnl_rule *rule) +{ + if (rule->ce_mask & RULE_ATTR_OIFNAME) + return rule->r_oifname; + else + return NULL; +} + +void rtnl_rule_set_action(struct rtnl_rule *rule, uint8_t action) +{ + rule->r_action = action; + rule->ce_mask |= RULE_ATTR_ACTION; +} + +uint8_t rtnl_rule_get_action(struct rtnl_rule *rule) +{ + return rule->r_action; +} + +void rtnl_rule_set_realms(struct rtnl_rule *rule, uint32_t realms) +{ + rule->r_flow = realms; + rule->ce_mask |= RULE_ATTR_FLOW; +} + +uint32_t rtnl_rule_get_realms(struct rtnl_rule *rule) +{ + return rule->r_flow; +} + +void rtnl_rule_set_goto(struct rtnl_rule *rule, uint32_t ref) +{ + rule->r_goto = ref; + rule->ce_mask |= RULE_ATTR_GOTO; +} + +uint32_t rtnl_rule_get_goto(struct rtnl_rule *rule) +{ + return rule->r_goto; +} + +/** @} */ + +static struct nl_object_ops rule_obj_ops = { + .oo_name = "route/rule", + .oo_size = sizeof(struct rtnl_rule), + .oo_free_data = rule_free_data, + .oo_clone = rule_clone, + .oo_dump = { + [NL_DUMP_LINE] = rule_dump_line, + [NL_DUMP_DETAILS] = rule_dump_details, + [NL_DUMP_STATS] = rule_dump_stats, + }, + .oo_compare = rule_compare, + .oo_attrs2str = rule_attrs2str, + .oo_id_attrs = ~0, +}; + +static struct nl_cache_ops rtnl_rule_ops = { + .co_name = "route/rule", + .co_hdrsize = sizeof(struct fib_rule_hdr), + .co_msgtypes = { + { RTM_NEWRULE, NL_ACT_NEW, "new" }, + { RTM_DELRULE, NL_ACT_DEL, "del" }, + { RTM_GETRULE, NL_ACT_GET, "get" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_ROUTE, + .co_request_update = rule_request_update, + .co_msg_parser = rule_msg_parser, + .co_obj_ops = &rule_obj_ops, +}; + +static void __init rule_init(void) +{ + nl_cache_mngt_register(&rtnl_rule_ops); +} + +static void __exit rule_exit(void) +{ + nl_cache_mngt_unregister(&rtnl_rule_ops); +} + +/** @} */ diff --git a/lib/route/tc.c b/lib/route/tc.c new file mode 100644 index 0000000..29954fd --- /dev/null +++ b/lib/route/tc.c @@ -0,0 +1,1072 @@ +/* + * lib/route/tc.c Traffic Control + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2011 Thomas Graf + */ + +/** + * @ingroup rtnl + * @defgroup tc Traffic Control + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ + +static struct nl_list_head tc_ops_list[__RTNL_TC_TYPE_MAX]; +static struct rtnl_tc_type_ops *tc_type_ops[__RTNL_TC_TYPE_MAX]; + +static struct nla_policy tc_policy[TCA_MAX+1] = { + [TCA_KIND] = { .type = NLA_STRING, + .maxlen = TCKINDSIZ }, + [TCA_STATS] = { .minlen = sizeof(struct tc_stats) }, + [TCA_STATS2] = { .type = NLA_NESTED }, +}; + +int tca_parse(struct nlattr **tb, int maxattr, struct rtnl_tc *g, + struct nla_policy *policy) +{ + + if (g->ce_mask & TCA_ATTR_OPTS) + return nla_parse(tb, maxattr, + (struct nlattr *) g->tc_opts->d_data, + g->tc_opts->d_size, policy); + else { + /* Ugly but tb[] must be in a defined state even if no + * attributes can be found. */ + memset(tb, 0, sizeof(struct nlattr *) * (maxattr + 1)); + return 0; + } +} + +static struct nla_policy tc_stats2_policy[TCA_STATS_MAX+1] = { + [TCA_STATS_BASIC] = { .minlen = sizeof(struct gnet_stats_basic) }, + [TCA_STATS_RATE_EST] = { .minlen = sizeof(struct gnet_stats_rate_est) }, + [TCA_STATS_QUEUE] = { .minlen = sizeof(struct gnet_stats_queue) }, +}; + +int rtnl_tc_msg_parse(struct nlmsghdr *n, struct rtnl_tc *tc) +{ + struct nl_cache *link_cache; + struct rtnl_tc_ops *ops; + struct nlattr *tb[TCA_MAX + 1]; + char kind[TCKINDSIZ]; + struct tcmsg *tm; + int err; + + tc->ce_msgtype = n->nlmsg_type; + + err = nlmsg_parse(n, sizeof(*tm), tb, TCA_MAX, tc_policy); + if (err < 0) + return err; + + if (tb[TCA_KIND] == NULL) + return -NLE_MISSING_ATTR; + + nla_strlcpy(kind, tb[TCA_KIND], sizeof(kind)); + rtnl_tc_set_kind(tc, kind); + + tm = nlmsg_data(n); + tc->tc_family = tm->tcm_family; + tc->tc_ifindex = tm->tcm_ifindex; + tc->tc_handle = tm->tcm_handle; + tc->tc_parent = tm->tcm_parent; + tc->tc_info = tm->tcm_info; + + tc->ce_mask |= (TCA_ATTR_FAMILY | TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE| + TCA_ATTR_PARENT | TCA_ATTR_INFO); + + if (tb[TCA_OPTIONS]) { + tc->tc_opts = nl_data_alloc_attr(tb[TCA_OPTIONS]); + if (!tc->tc_opts) + return -NLE_NOMEM; + tc->ce_mask |= TCA_ATTR_OPTS; + } + + if (tb[TCA_STATS2]) { + struct nlattr *tbs[TCA_STATS_MAX + 1]; + + err = nla_parse_nested(tbs, TCA_STATS_MAX, tb[TCA_STATS2], + tc_stats2_policy); + if (err < 0) + return err; + + if (tbs[TCA_STATS_BASIC]) { + struct gnet_stats_basic *bs; + + bs = nla_data(tbs[TCA_STATS_BASIC]); + tc->tc_stats[RTNL_TC_BYTES] = bs->bytes; + tc->tc_stats[RTNL_TC_PACKETS] = bs->packets; + } + + if (tbs[TCA_STATS_RATE_EST]) { + struct gnet_stats_rate_est *re; + + re = nla_data(tbs[TCA_STATS_RATE_EST]); + tc->tc_stats[RTNL_TC_RATE_BPS] = re->bps; + tc->tc_stats[RTNL_TC_RATE_PPS] = re->pps; + } + + if (tbs[TCA_STATS_QUEUE]) { + struct gnet_stats_queue *q; + + q = nla_data(tbs[TCA_STATS_QUEUE]); + tc->tc_stats[RTNL_TC_QLEN] = q->qlen; + tc->tc_stats[RTNL_TC_BACKLOG] = q->backlog; + tc->tc_stats[RTNL_TC_DROPS] = q->drops; + tc->tc_stats[RTNL_TC_REQUEUES] = q->requeues; + tc->tc_stats[RTNL_TC_OVERLIMITS] = q->overlimits; + } + + tc->ce_mask |= TCA_ATTR_STATS; + + if (tbs[TCA_STATS_APP]) { + tc->tc_xstats = nl_data_alloc_attr(tbs[TCA_STATS_APP]); + if (tc->tc_xstats == NULL) + return -NLE_NOMEM; + } else + goto compat_xstats; + } else { + if (tb[TCA_STATS]) { + struct tc_stats *st = nla_data(tb[TCA_STATS]); + + tc->tc_stats[RTNL_TC_BYTES] = st->bytes; + tc->tc_stats[RTNL_TC_PACKETS] = st->packets; + tc->tc_stats[RTNL_TC_RATE_BPS] = st->bps; + tc->tc_stats[RTNL_TC_RATE_PPS] = st->pps; + tc->tc_stats[RTNL_TC_QLEN] = st->qlen; + tc->tc_stats[RTNL_TC_BACKLOG] = st->backlog; + tc->tc_stats[RTNL_TC_DROPS] = st->drops; + tc->tc_stats[RTNL_TC_OVERLIMITS]= st->overlimits; + + tc->ce_mask |= TCA_ATTR_STATS; + } + +compat_xstats: + if (tb[TCA_XSTATS]) { + tc->tc_xstats = nl_data_alloc_attr(tb[TCA_XSTATS]); + if (tc->tc_xstats == NULL) + return -NLE_NOMEM; + tc->ce_mask |= TCA_ATTR_XSTATS; + } + } + + ops = rtnl_tc_get_ops(tc); + if (ops && ops->to_msg_parser) { + void *data = rtnl_tc_data(tc); + + if (!data) + return -NLE_NOMEM; + + err = ops->to_msg_parser(tc, data); + if (err < 0) + return err; + } + + if ((link_cache = __nl_cache_mngt_require("route/link"))) { + struct rtnl_link *link; + + if ((link = rtnl_link_get(link_cache, tc->tc_ifindex))) { + rtnl_tc_set_link(tc, link); + + /* rtnl_tc_set_link incs refcnt */ + rtnl_link_put(link); + } + } + + return 0; +} + +int rtnl_tc_msg_build(struct rtnl_tc *tc, int type, int flags, + struct nl_msg **result) +{ + struct nl_msg *msg; + struct rtnl_tc_ops *ops; + struct tcmsg tchdr = { + .tcm_family = AF_UNSPEC, + .tcm_ifindex = tc->tc_ifindex, + .tcm_handle = tc->tc_handle, + .tcm_parent = tc->tc_parent, + }; + int err = -NLE_MSGSIZE; + + msg = nlmsg_alloc_simple(type, flags); + if (!msg) + return -NLE_NOMEM; + + if (nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if (tc->ce_mask & TCA_ATTR_KIND) + NLA_PUT_STRING(msg, TCA_KIND, tc->tc_kind); + + ops = rtnl_tc_get_ops(tc); + if (ops && ops->to_msg_fill) { + struct nlattr *opts; + void *data = rtnl_tc_data(tc); + + if (!(opts = nla_nest_start(msg, TCA_OPTIONS))) + goto nla_put_failure; + + if ((err = ops->to_msg_fill(tc, data, msg)) < 0) + goto nla_put_failure; + + nla_nest_end(msg, opts); + } + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return err; +} + +void tca_set_kind(struct rtnl_tc *t, const char *kind) +{ + strncpy(t->tc_kind, kind, sizeof(t->tc_kind) - 1); + t->ce_mask |= TCA_ATTR_KIND; +} + + +/** @endcond */ + +/** + * @name Attributes + * @{ + */ + +/** + * Set interface index of traffic control object + * @arg tc traffic control object + * @arg ifindex interface index. + * + * Sets the interface index of a traffic control object. The interface + * index defines the network device which this tc object is attached to. + * This function will overwrite any network device assigned with previous + * calls to rtnl_tc_set_ifindex() or rtnl_tc_set_link(). + */ +void rtnl_tc_set_ifindex(struct rtnl_tc *tc, int ifindex) +{ + /* Obsolete possible old link reference */ + rtnl_link_put(tc->tc_link); + tc->tc_link = NULL; + tc->ce_mask &= ~TCA_ATTR_LINK; + + tc->tc_ifindex = ifindex; + tc->ce_mask |= TCA_ATTR_IFINDEX; +} + +/** + * Return interface index of traffic control object + * @arg tc traffic control object + */ +int rtnl_tc_get_ifindex(struct rtnl_tc *tc) +{ + return tc->tc_ifindex; +} + +/** + * Set link of traffic control object + * @arg tc traffic control object + * @arg link link object + * + * Sets the link of a traffic control object. This function serves + * the same purpose as rtnl_tc_set_ifindex() but due to the continued + * allowed access to the link object it gives it the possibility to + * retrieve sane default values for the the MTU and the linktype. + * Always prefer this function over rtnl_tc_set_ifindex() if you can + * spare to have an additional link object around. + */ +void rtnl_tc_set_link(struct rtnl_tc *tc, struct rtnl_link *link) +{ + rtnl_link_put(tc->tc_link); + + if (!link) + return; + + nl_object_get(OBJ_CAST(link)); + tc->tc_link = link; + tc->tc_ifindex = link->l_index; + tc->ce_mask |= TCA_ATTR_LINK | TCA_ATTR_IFINDEX; +} + +/** + * Get link of traffic control object + * @arg tc traffic control object + * + * Returns the link of a traffic control object. The link is only + * returned if it has been set before via rtnl_tc_set_link() or + * if a link cache was available while parsing the tc object. This + * function may still return NULL even if an ifindex is assigned to + * the tc object. It will _not_ look up the link by itself. + * + * @note The returned link will have its reference counter incremented. + * It is in the responsibility of the caller to return the + * reference. + * + * @return link object or NULL if not set. + */ +struct rtnl_link *rtnl_tc_get_link(struct rtnl_tc *tc) +{ + if (tc->tc_link) { + nl_object_get(OBJ_CAST(tc->tc_link)); + return tc->tc_link; + } + + return NULL; +} + +/** + * Set the Maximum Transmission Unit (MTU) of traffic control object + * @arg tc traffic control object + * @arg mtu largest packet size expected + * + * Sets the MTU of a traffic control object. Not all traffic control + * objects will make use of this but it helps while calculating rate + * tables. This value is typically derived directly from the link + * the tc object is attached to if the link has been assigned via + * rtnl_tc_set_link(). It is usually not necessary to set the MTU + * manually, this function is provided to allow overwriting the derived + * value. + */ +void rtnl_tc_set_mtu(struct rtnl_tc *tc, uint32_t mtu) +{ + tc->tc_mtu = mtu; + tc->ce_mask |= TCA_ATTR_MTU; +} + +/** + * Return the MTU of traffic control object + * @arg tc traffic control object + * + * Returns the MTU of a traffic control object which has been set via: + * -# User specified value set via rtnl_tc_set_mtu() + * -# Dervied from link set via rtnl_tc_set_link() + * -# Fall back to default: ethernet = 1500 + */ +uint32_t rtnl_tc_get_mtu(struct rtnl_tc *tc) +{ + if (tc->ce_mask & TCA_ATTR_MTU) + return tc->tc_mtu; + else if (tc->ce_mask & TCA_ATTR_LINK) + return tc->tc_link->l_mtu; + else + return 1500; /* default to ethernet */ +} + +/** + * Set the Minimum Packet Unit (MPU) of a traffic control object + * @arg tc traffic control object + * @arg mpu minimum packet size expected + * + * Sets the MPU of a traffic contorl object. It specifies the minimum + * packet size to ever hit this traffic control object. Not all traffic + * control objects will make use of this but it helps while calculating + * rate tables. + */ +void rtnl_tc_set_mpu(struct rtnl_tc *tc, uint32_t mpu) +{ + tc->tc_mpu = mpu; + tc->ce_mask |= TCA_ATTR_MPU; +} + +/** + * Return the Minimum Packet Unit (MPU) of a traffic control object + * @arg tc traffic control object + * + * @return The MPU previously set via rtnl_tc_set_mpu() or 0. + */ +uint32_t rtnl_tc_get_mpu(struct rtnl_tc *tc) +{ + return tc->tc_mpu; +} + +/** + * Set per packet overhead of a traffic control object + * @arg tc traffic control object + * @arg overhead overhead per packet in bytes + * + * Sets the per packet overhead in bytes occuring on the link not seen + * by the kernel. This value can be used to correct size calculations + * if the packet size on the wire does not match the packet sizes seen + * in the network stack. Not all traffic control objects will make use + * this but it helps while calculating accurate packet sizes in the + * kernel. + */ +void rtnl_tc_set_overhead(struct rtnl_tc *tc, uint32_t overhead) +{ + tc->tc_overhead = overhead; + tc->ce_mask |= TCA_ATTR_OVERHEAD; +} + +/** + * Return per packet overhead of a traffic control object + * @arg tc traffic control object + * + * @return The overhead previously set by rtnl_tc_set_overhead() or 0. + */ +uint32_t rtnl_tc_get_overhead(struct rtnl_tc *tc) +{ + return tc->tc_overhead; +} + +/** + * Set the linktype of a traffic control object + * @arg tc traffic control object + * @arg type type of link (e.g. ARPHRD_ATM, ARPHRD_ETHER) + * + * Overwrites the type of link this traffic control object is attached to. + * This value is typically derived from the link this tc object is attached + * if the link has been assigned via rtnl_tc_set_link(). It is usually not + * necessary to set the linktype manually. This function is provided to + * allow overwriting the linktype. + */ +void rtnl_tc_set_linktype(struct rtnl_tc *tc, uint32_t type) +{ + tc->tc_linktype = type; + tc->ce_mask |= TCA_ATTR_LINKTYPE; +} + +/** + * Return the linktype of a traffic control object + * @arg tc traffic control object + * + * Returns the linktype of the link the traffic control object is attached to: + * -# User specified value via rtnl_tc_set_linktype() + * -# Value derived from link set via rtnl_tc_set_link() + * -# Default fall-back: ARPHRD_ETHER + */ +uint32_t rtnl_tc_get_linktype(struct rtnl_tc *tc) +{ + if (tc->ce_mask & TCA_ATTR_LINKTYPE) + return tc->tc_linktype; + else if (tc->ce_mask & TCA_ATTR_LINK) + return tc->tc_link->l_arptype; + else + return ARPHRD_ETHER; /* default to ethernet */ +} + +/** + * Set identifier of traffic control object + * @arg tc traffic control object + * @arg id unique identifier + */ +void rtnl_tc_set_handle(struct rtnl_tc *tc, uint32_t id) +{ + tc->tc_handle = id; + tc->ce_mask |= TCA_ATTR_HANDLE; +} + +/** + * Return identifier of a traffic control object + * @arg tc traffic control object + */ +uint32_t rtnl_tc_get_handle(struct rtnl_tc *tc) +{ + return tc->tc_handle; +} + +/** + * Set the parent identifier of a traffic control object + * @arg tc traffic control object + * @arg parent identifier of parent traffif control object + * + */ +void rtnl_tc_set_parent(struct rtnl_tc *tc, uint32_t parent) +{ + tc->tc_parent = parent; + tc->ce_mask |= TCA_ATTR_PARENT; +} + +/** + * Return parent identifier of a traffic control object + * @arg tc traffic control object + */ +uint32_t rtnl_tc_get_parent(struct rtnl_tc *tc) +{ + return tc->tc_parent; +} + +/** + * Define the type of traffic control object + * @arg tc traffic control object + * @arg kind name of the tc object type + * + * @return 0 on success or a negative error code + */ +int rtnl_tc_set_kind(struct rtnl_tc *tc, const char *kind) +{ + if (tc->ce_mask & TCA_ATTR_KIND) + return -NLE_EXIST; + + strncpy(tc->tc_kind, kind, sizeof(tc->tc_kind) - 1); + tc->ce_mask |= TCA_ATTR_KIND; + + /* Force allocation of data */ + rtnl_tc_data(tc); + + return 0; +} + +/** + * Return kind of traffic control object + * @arg tc traffic control object + * + * @return Kind of traffic control object or NULL if not set. + */ +char *rtnl_tc_get_kind(struct rtnl_tc *tc) +{ + if (tc->ce_mask & TCA_ATTR_KIND) + return tc->tc_kind; + else + return NULL; +} + +/** + * Return value of a statistical counter of a traffic control object + * @arg tc traffic control object + * @arg id identifier of statistical counter + * + * @return Value of requested statistic counter or 0. + */ +uint64_t rtnl_tc_get_stat(struct rtnl_tc *tc, enum rtnl_tc_stat id) +{ + if (id < 0 || id > RTNL_TC_STATS_MAX) + return 0; + + return tc->tc_stats[id]; +} + +/** @} */ + +/** + * @name Utilities + * @{ + */ + +/** + * Calculate time required to transmit buffer at a specific rate + * @arg bufsize Size of buffer to be transmited in bytes. + * @arg rate Transmit rate in bytes per second. + * + * Calculates the number of micro seconds required to transmit a + * specific buffer at a specific transmit rate. + * + * @f[ + * txtime=\frac{bufsize}{rate}10^6 + * @f] + * + * @return Required transmit time in micro seconds. + */ +int rtnl_tc_calc_txtime(int bufsize, int rate) +{ + double tx_time_secs; + + tx_time_secs = (double) bufsize / (double) rate; + + return tx_time_secs * 1000000.; +} + +/** + * Calculate buffer size able to transmit in a specific time and rate. + * @arg txtime Available transmit time in micro seconds. + * @arg rate Transmit rate in bytes per second. + * + * Calculates the size of the buffer that can be transmitted in a + * specific time period at a specific transmit rate. + * + * @f[ + * bufsize=\frac{{txtime} \times {rate}}{10^6} + * @f] + * + * @return Size of buffer in bytes. + */ +int rtnl_tc_calc_bufsize(int txtime, int rate) +{ + double bufsize; + + bufsize = (double) txtime * (double) rate; + + return bufsize / 1000000.; +} + +/** + * Calculate the binary logarithm for a specific cell size + * @arg cell_size Size of cell, must be a power of two. + * @return Binary logirhtm of cell size or a negative error code. + */ +int rtnl_tc_calc_cell_log(int cell_size) +{ + int i; + + for (i = 0; i < 32; i++) + if ((1 << i) == cell_size) + return i; + + return -NLE_INVAL; +} + + +/** @} */ + +/** + * @name Rate Tables + * @{ + */ + +/* + * COPYRIGHT NOTE: + * align_to_atm() and adjust_size() derived/coped from iproute2 source. + */ + +/* + * The align to ATM cells is used for determining the (ATM) SAR + * alignment overhead at the ATM layer. (SAR = Segmentation And + * Reassembly). This is for example needed when scheduling packet on + * an ADSL connection. Note that the extra ATM-AAL overhead is _not_ + * included in this calculation. This overhead is added in the kernel + * before doing the rate table lookup, as this gives better precision + * (as the table will always be aligned for 48 bytes). + * --Hawk, d.7/11-2004. + */ +static unsigned int align_to_atm(unsigned int size) +{ + int linksize, cells; + cells = size / ATM_CELL_PAYLOAD; + if ((size % ATM_CELL_PAYLOAD) > 0) + cells++; + + linksize = cells * ATM_CELL_SIZE; /* Use full cell size to add ATM tax */ + return linksize; +} + +static unsigned int adjust_size(unsigned int size, unsigned int mpu, + uint32_t linktype) +{ + if (size < mpu) + size = mpu; + + switch (linktype) { + case ARPHRD_ATM: + return align_to_atm(size); + + case ARPHRD_ETHER: + default: + return size; + } +} + +/** + * Compute a transmission time lookup table + * @arg tc traffic control object + * @arg spec Rate specification + * @arg dst Destination buffer of RTNL_TC_RTABLE_SIZE uint32_t[]. + * + * Computes a table of RTNL_TC_RTABLE_SIZE entries specyfing the + * transmission times for various packet sizes, e.g. the transmission + * time for a packet of size \c pktsize could be looked up: + * @code + * txtime = table[pktsize >> log2(mtu)]; + * @endcode + */ +int rtnl_tc_build_rate_table(struct rtnl_tc *tc, struct rtnl_ratespec *spec, + uint32_t *dst) +{ + uint32_t mtu = rtnl_tc_get_mtu(tc); + uint32_t linktype = rtnl_tc_get_linktype(tc); + uint8_t cell_log = spec->rs_cell_log; + unsigned int size, i; + + spec->rs_mpu = rtnl_tc_get_mpu(tc); + spec->rs_overhead = rtnl_tc_get_overhead(tc); + + if (mtu == 0) + mtu = 2047; + + if (cell_log == UINT8_MAX) { + /* + * cell_log not specified, calculate it. It has to specify the + * minimum number of rshifts required to break the MTU to below + * RTNL_TC_RTABLE_SIZE. + */ + cell_log = 0; + while ((mtu >> cell_log) >= RTNL_TC_RTABLE_SIZE) + cell_log++; + } + + for (i = 0; i < RTNL_TC_RTABLE_SIZE; i++) { + size = adjust_size((i + 1) << cell_log, spec->rs_mpu, linktype); + dst[i] = nl_us2ticks(rtnl_tc_calc_txtime(size, spec->rs_rate)); + } + + spec->rs_cell_align = -1; + spec->rs_cell_log = cell_log; + + return 0; +} + +/** @} */ + +/** + * @name TC implementation of cache functions + */ + +void rtnl_tc_free_data(struct nl_object *obj) +{ + struct rtnl_tc *tc = TC_CAST(obj); + struct rtnl_tc_ops *ops; + + rtnl_link_put(tc->tc_link); + nl_data_free(tc->tc_opts); + nl_data_free(tc->tc_xstats); + + if (tc->tc_subdata) { + ops = rtnl_tc_get_ops(tc); + if (ops && ops->to_free_data) + ops->to_free_data(tc, nl_data_get(tc->tc_subdata)); + + nl_data_free(tc->tc_subdata); + } +} + +int rtnl_tc_clone(struct nl_object *dstobj, struct nl_object *srcobj) +{ + struct rtnl_tc *dst = TC_CAST(dstobj); + struct rtnl_tc *src = TC_CAST(srcobj); + struct rtnl_tc_ops *ops; + + if (src->tc_link) { + nl_object_get(OBJ_CAST(src->tc_link)); + dst->tc_link = src->tc_link; + } + + if (src->tc_opts) { + dst->tc_opts = nl_data_clone(src->tc_opts); + if (!dst->tc_opts) + return -NLE_NOMEM; + } + + if (src->tc_xstats) { + dst->tc_xstats = nl_data_clone(src->tc_xstats); + if (!dst->tc_xstats) + return -NLE_NOMEM; + } + + if (src->tc_subdata) { + if (!(dst->tc_subdata = nl_data_clone(src->tc_subdata))) { + return -NLE_NOMEM; + } + } + + ops = rtnl_tc_get_ops(src); + if (ops && ops->to_clone) { + void *a = rtnl_tc_data(dst), *b = rtnl_tc_data(src); + + if (!a) + return 0; + else if (!b) + return -NLE_NOMEM; + + return ops->to_clone(a, b); + } + + return 0; +} + +static int tc_dump(struct rtnl_tc *tc, enum nl_dump_type type, + struct nl_dump_params *p) +{ + struct rtnl_tc_type_ops *type_ops; + struct rtnl_tc_ops *ops; + void *data = rtnl_tc_data(tc); + + type_ops = tc_type_ops[tc->tc_type]; + if (type_ops && type_ops->tt_dump[type]) + type_ops->tt_dump[type](tc, p); + + ops = rtnl_tc_get_ops(tc); + if (ops && ops->to_dump[type]) { + ops->to_dump[type](tc, data, p); + return 1; + } + + return 0; +} + +void rtnl_tc_dump_line(struct nl_object *obj, struct nl_dump_params *p) +{ + struct rtnl_tc_type_ops *type_ops; + struct rtnl_tc *tc = TC_CAST(obj); + struct nl_cache *link_cache; + char buf[32]; + + nl_new_line(p); + + type_ops = tc_type_ops[tc->tc_type]; + if (type_ops && type_ops->tt_dump_prefix) + nl_dump(p, "%s ", type_ops->tt_dump_prefix); + + nl_dump(p, "%s ", tc->tc_kind); + + if ((link_cache = nl_cache_mngt_require_safe("route/link"))) { + nl_dump(p, "dev %s ", + rtnl_link_i2name(link_cache, tc->tc_ifindex, + buf, sizeof(buf))); + } else + nl_dump(p, "dev %u ", tc->tc_ifindex); + + nl_dump(p, "id %s ", + rtnl_tc_handle2str(tc->tc_handle, buf, sizeof(buf))); + + nl_dump(p, "parent %s", + rtnl_tc_handle2str(tc->tc_parent, buf, sizeof(buf))); + + tc_dump(tc, NL_DUMP_LINE, p); + nl_dump(p, "\n"); + + if (link_cache) + nl_cache_put(link_cache); +} + +void rtnl_tc_dump_details(struct nl_object *obj, struct nl_dump_params *p) +{ + struct rtnl_tc *tc = TC_CAST(obj); + + rtnl_tc_dump_line(OBJ_CAST(tc), p); + + nl_dump_line(p, " "); + + if (tc->ce_mask & TCA_ATTR_MTU) + nl_dump(p, " mtu %u", tc->tc_mtu); + + if (tc->ce_mask & TCA_ATTR_MPU) + nl_dump(p, " mpu %u", tc->tc_mpu); + + if (tc->ce_mask & TCA_ATTR_OVERHEAD) + nl_dump(p, " overhead %u", tc->tc_overhead); + + if (!tc_dump(tc, NL_DUMP_DETAILS, p)) + nl_dump(p, "no options"); + nl_dump(p, "\n"); +} + +void rtnl_tc_dump_stats(struct nl_object *obj, struct nl_dump_params *p) +{ + struct rtnl_tc *tc = TC_CAST(obj); + char *unit, fmt[64]; + float res; + + rtnl_tc_dump_details(OBJ_CAST(tc), p); + + strcpy(fmt, " %7.2f %s %10u %10u %10u %10u %10u\n"); + + nl_dump_line(p, + " Stats: bytes packets drops overlimits" \ + " qlen backlog\n"); + + res = nl_cancel_down_bytes(tc->tc_stats[RTNL_TC_BYTES], &unit); + if (*unit == 'B') + fmt[11] = '9'; + + nl_dump_line(p, fmt, res, unit, + tc->tc_stats[RTNL_TC_PACKETS], + tc->tc_stats[RTNL_TC_DROPS], + tc->tc_stats[RTNL_TC_OVERLIMITS], + tc->tc_stats[RTNL_TC_QLEN], + tc->tc_stats[RTNL_TC_BACKLOG]); + + res = nl_cancel_down_bytes(tc->tc_stats[RTNL_TC_RATE_BPS], &unit); + + strcpy(fmt, " %7.2f %s/s%9u pps"); + + if (*unit == 'B') + fmt[11] = '9'; + + nl_dump_line(p, fmt, res, unit, tc->tc_stats[RTNL_TC_RATE_PPS]); + + tc_dump(tc, NL_DUMP_LINE, p); + nl_dump(p, "\n"); +} + +int rtnl_tc_compare(struct nl_object *aobj, struct nl_object *bobj, + uint32_t attrs, int flags) +{ + struct rtnl_tc *a = TC_CAST(aobj); + struct rtnl_tc *b = TC_CAST(bobj); + int diff = 0; + +#define TC_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, TCA_ATTR_##ATTR, a, b, EXPR) + + diff |= TC_DIFF(HANDLE, a->tc_handle != b->tc_handle); + diff |= TC_DIFF(PARENT, a->tc_parent != b->tc_parent); + diff |= TC_DIFF(IFINDEX, a->tc_ifindex != b->tc_ifindex); + diff |= TC_DIFF(KIND, strcmp(a->tc_kind, b->tc_kind)); + +#undef TC_DIFF + + return diff; +} + +/** @} */ + +/** + * @name Modules API + */ + +struct rtnl_tc_ops *rtnl_tc_lookup_ops(enum rtnl_tc_type type, const char *kind) +{ + struct rtnl_tc_ops *ops; + + nl_list_for_each_entry(ops, &tc_ops_list[type], to_list) + if (!strcmp(kind, ops->to_kind)) + return ops; + + return NULL; +} + +struct rtnl_tc_ops *rtnl_tc_get_ops(struct rtnl_tc *tc) +{ + if (!tc->tc_ops) + tc->tc_ops = rtnl_tc_lookup_ops(tc->tc_type, tc->tc_kind); + + return tc->tc_ops; +} + +/** + * Register a traffic control module + * @arg ops traffic control module operations + */ +int rtnl_tc_register(struct rtnl_tc_ops *ops) +{ + static int init = 0; + + /* + * Initialiation hack, make sure list is initialized when + * the first tc module registers. Putting this in a + * separate __init would required correct ordering of init + * functions + */ + if (!init) { + int i; + + for (i = 0; i < __RTNL_TC_TYPE_MAX; i++) + nl_init_list_head(&tc_ops_list[i]); + + init = 1; + } + + if (!ops->to_kind || ops->to_type > RTNL_TC_TYPE_MAX) + BUG(); + + if (rtnl_tc_lookup_ops(ops->to_type, ops->to_kind)) + return -NLE_EXIST; + + nl_list_add_tail(&ops->to_list, &tc_ops_list[ops->to_type]); + + return 0; +} + +/** + * Unregister a traffic control module + * @arg ops traffic control module operations + */ +void rtnl_tc_unregister(struct rtnl_tc_ops *ops) +{ + nl_list_del(&ops->to_list); +} + +/** + * Return pointer to private data of traffic control object + * @arg tc traffic control object + * + * Allocates the private traffic control object data section + * as necessary and returns it. + * + * @return Pointer to private tc data or NULL if allocation failed. + */ +void *rtnl_tc_data(struct rtnl_tc *tc) +{ + if (!tc->tc_subdata) { + size_t size; + + if (!tc->tc_ops) { + if (!tc->tc_kind) + BUG(); + + if (!rtnl_tc_get_ops(tc)) + return NULL; + } + + if (!(size = tc->tc_ops->to_size)) + BUG(); + + if (!(tc->tc_subdata = nl_data_alloc(NULL, size))) + return NULL; + } + + return nl_data_get(tc->tc_subdata); +} + +/** + * Check traffic control object type and return private data section + * @arg tc traffic control object + * @arg ops expected traffic control object operations + * + * Checks whether the traffic control object matches the type + * specified with the traffic control object operations. If the + * type matches, the private tc object data is returned. If type + * mismatches, APPBUG() will print a application bug warning. + * + * @see rtnl_tc_data() + * + * @return Pointer to private tc data or NULL if type mismatches. + */ +void *rtnl_tc_data_check(struct rtnl_tc *tc, struct rtnl_tc_ops *ops) +{ + if (tc->tc_ops != ops) { + char buf[64]; + + snprintf(buf, sizeof(buf), + "tc object %p used in %s context but is of type %s", + tc, ops->to_kind, tc->tc_ops->to_kind); + APPBUG(buf); + + return NULL; + } + + return rtnl_tc_data(tc); +} + +void rtnl_tc_type_register(struct rtnl_tc_type_ops *ops) +{ + if (ops->tt_type > RTNL_TC_TYPE_MAX) + BUG(); + + tc_type_ops[ops->tt_type] = ops; +} + +void rtnl_tc_type_unregister(struct rtnl_tc_type_ops *ops) +{ + if (ops->tt_type > RTNL_TC_TYPE_MAX) + BUG(); + + tc_type_ops[ops->tt_type] = NULL; +} + +/** @} */ + +/** @} */ diff --git a/lib/socket.c b/lib/socket.c new file mode 100644 index 0000000..1ca7783 --- /dev/null +++ b/lib/socket.c @@ -0,0 +1,696 @@ +/* + * lib/socket.c Netlink Socket + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +/** + * @ingroup core_types + * @defgroup socket Socket + * + * Representation of a netlink socket + * + * Related sections in the development guide: + * - @core_doc{core_sockets, Netlink Sockets} + * + * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ + */ + +#include "defs.h" + +#include +#include +#include +#include +#include +#include + +static int default_cb = NL_CB_DEFAULT; + +static void __init init_default_cb(void) +{ + char *nlcb; + + if ((nlcb = getenv("NLCB"))) { + if (!strcasecmp(nlcb, "default")) + default_cb = NL_CB_DEFAULT; + else if (!strcasecmp(nlcb, "verbose")) + default_cb = NL_CB_VERBOSE; + else if (!strcasecmp(nlcb, "debug")) + default_cb = NL_CB_DEBUG; + else { + fprintf(stderr, "Unknown value for NLCB, valid values: " + "{default | verbose | debug}\n"); + } + } +} + +static uint32_t used_ports_map[32]; +static NL_RW_LOCK(port_map_lock); + +static uint32_t generate_local_port(void) +{ + int i, n; + uint32_t pid = getpid() & 0x3FFFFF; + + nl_write_lock(&port_map_lock); + + for (i = 0; i < 32; i++) { + if (used_ports_map[i] == 0xFFFFFFFF) + continue; + + for (n = 0; n < 32; n++) { + if (1UL & (used_ports_map[i] >> n)) + continue; + + used_ports_map[i] |= (1UL << n); + n += (i * 32); + + /* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit + * to, i.e. 1024 unique ports per application. */ + + nl_write_unlock(&port_map_lock); + + return pid + (n << 22); + } + } + + nl_write_unlock(&port_map_lock); + + /* Out of sockets in our own PID namespace, what to do? FIXME */ + return UINT_MAX; +} + +static void release_local_port(uint32_t port) +{ + int nr; + + if (port == UINT_MAX) + return; + + nr = port >> 22; + + nl_write_lock(&port_map_lock); + used_ports_map[nr / 32] &= ~(1 << (nr % 32)); + nl_write_unlock(&port_map_lock); +} + +/** + * @name Allocation + * @{ + */ + +static struct nl_sock *__alloc_socket(struct nl_cb *cb) +{ + struct nl_sock *sk; + + sk = calloc(1, sizeof(*sk)); + if (!sk) + return NULL; + + sk->s_fd = -1; + sk->s_cb = nl_cb_get(cb); + sk->s_local.nl_family = AF_NETLINK; + sk->s_peer.nl_family = AF_NETLINK; + sk->s_seq_expect = sk->s_seq_next = time(0); + sk->s_local.nl_pid = generate_local_port(); + if (sk->s_local.nl_pid == UINT_MAX) { + nl_socket_free(sk); + return NULL; + } + + return sk; +} + +/** + * Allocate new netlink socket + * + * @return Newly allocated netlink socket or NULL. + */ +struct nl_sock *nl_socket_alloc(void) +{ + struct nl_cb *cb; + struct nl_sock *sk; + + cb = nl_cb_alloc(default_cb); + if (!cb) + return NULL; + + /* will increment cb reference count on success */ + sk = __alloc_socket(cb); + + nl_cb_put(cb); + + return sk; +} + +/** + * Allocate new socket with custom callbacks + * @arg cb Callback handler + * + * The reference to the callback handler is taken into account + * automatically, it is released again upon calling nl_socket_free(). + * + *@return Newly allocted socket handle or NULL. + */ +struct nl_sock *nl_socket_alloc_cb(struct nl_cb *cb) +{ + if (cb == NULL) + BUG(); + + return __alloc_socket(cb); +} + +/** + * Free a netlink socket. + * @arg sk Netlink socket. + */ +void nl_socket_free(struct nl_sock *sk) +{ + if (!sk) + return; + + if (sk->s_fd >= 0) + close(sk->s_fd); + + if (!(sk->s_flags & NL_OWN_PORT)) + release_local_port(sk->s_local.nl_pid); + + nl_cb_put(sk->s_cb); + free(sk); +} + +/** @} */ + +/** + * @name Sequence Numbers + * @{ + */ + +static int noop_seq_check(struct nl_msg *msg, void *arg) +{ + return NL_OK; +} + + +/** + * Disable sequence number checking. + * @arg sk Netlink socket. + * + * Disables checking of sequence numbers on the netlink socket This is + * required to allow messages to be processed which were not requested by + * a preceding request message, e.g. netlink events. + * + * @note This function modifies the NL_CB_SEQ_CHECK configuration in + * the callback handle associated with the socket. + */ +void nl_socket_disable_seq_check(struct nl_sock *sk) +{ + nl_cb_set(sk->s_cb, NL_CB_SEQ_CHECK, + NL_CB_CUSTOM, noop_seq_check, NULL); +} + +/** + * Use next sequence number + * @arg sk Netlink socket. + * + * Uses the next available sequence number and increases the counter + * by one for subsequent calls. + * + * @return Unique serial sequence number + */ +unsigned int nl_socket_use_seq(struct nl_sock *sk) +{ + return sk->s_seq_next++; +} + +/** + * Disable automatic request for ACK + * @arg sk Netlink socket. + * + * The default behaviour of a socket is to request an ACK for + * each message sent to allow for the caller to synchronize to + * the completion of the netlink operation. This function + * disables this behaviour and will result in requests being + * sent which will not have the NLM_F_ACK flag set automatically. + * However, it is still possible for the caller to set the + * NLM_F_ACK flag explicitely. + */ +void nl_socket_disable_auto_ack(struct nl_sock *sk) +{ + sk->s_flags |= NL_NO_AUTO_ACK; +} + +/** + * Enable automatic request for ACK (default) + * @arg sk Netlink socket. + * @see nl_socket_disable_auto_ack + */ +void nl_socket_enable_auto_ack(struct nl_sock *sk) +{ + sk->s_flags &= ~NL_NO_AUTO_ACK; +} + +/** @} */ + +/** + * @name Source Idenficiation + * @{ + */ + +uint32_t nl_socket_get_local_port(const struct nl_sock *sk) +{ + return sk->s_local.nl_pid; +} + +/** + * Set local port of socket + * @arg sk Netlink socket. + * @arg port Local port identifier + * + * Assigns a local port identifier to the socket. If port is 0 + * a unique port identifier will be generated automatically. + */ +void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port) +{ + if (port == 0) { + port = generate_local_port(); + /* + * Release local port after generation of a new one to be + * able to change local port using nl_socket_set_local_port(, 0) + */ + if (!(sk->s_flags & NL_OWN_PORT)) + release_local_port(sk->s_local.nl_pid); + else + sk->s_flags &= ~NL_OWN_PORT; + } else { + if (!(sk->s_flags & NL_OWN_PORT)) + release_local_port(sk->s_local.nl_pid); + sk->s_flags |= NL_OWN_PORT; + } + + sk->s_local.nl_pid = port; +} + +/** @} */ + +/** + * @name Group Subscriptions + * @{ + */ + +/** + * Join groups + * @arg sk Netlink socket + * @arg group Group identifier + * + * Joins the specified groups using the modern socket option which + * is available since kernel version 2.6.14. It allows joining an + * almost arbitary number of groups without limitation. The list + * of groups has to be terminated by 0 (%NFNLGRP_NONE). + * + * Make sure to use the correct group definitions as the older + * bitmask definitions for nl_join_groups() are likely to still + * be present for backward compatibility reasons. + * + * @return 0 on sucess or a negative error code. + */ +int nl_socket_add_memberships(struct nl_sock *sk, int group, ...) +{ + int err; + va_list ap; + + if (sk->s_fd == -1) + return -NLE_BAD_SOCK; + + va_start(ap, group); + + while (group != 0) { + if (group < 0) { + va_end(ap); + return -NLE_INVAL; + } + + err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, + &group, sizeof(group)); + if (err < 0) { + va_end(ap); + return -nl_syserr2nlerr(errno); + } + + group = va_arg(ap, int); + } + + va_end(ap); + + return 0; +} + +int nl_socket_add_membership(struct nl_sock *sk, int group) +{ + return nl_socket_add_memberships(sk, group, 0); +} + +/** + * Leave groups + * @arg sk Netlink socket + * @arg group Group identifier + * + * Leaves the specified groups using the modern socket option + * which is available since kernel version 2.6.14. The list of groups + * has to terminated by 0 (%NFNLGRP_NONE). + * + * @see nl_socket_add_membership + * @return 0 on success or a negative error code. + */ +int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...) +{ + int err; + va_list ap; + + if (sk->s_fd == -1) + return -NLE_BAD_SOCK; + + va_start(ap, group); + + while (group != 0) { + if (group < 0) { + va_end(ap); + return -NLE_INVAL; + } + + err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP, + &group, sizeof(group)); + if (err < 0) { + va_end(ap); + return -nl_syserr2nlerr(errno); + } + + group = va_arg(ap, int); + } + + va_end(ap); + + return 0; +} + +int nl_socket_drop_membership(struct nl_sock *sk, int group) +{ + return nl_socket_drop_memberships(sk, group, 0); +} + + +/** + * Join multicast groups (deprecated) + * @arg sk Netlink socket. + * @arg groups Bitmask of groups to join. + * + * This function defines the old way of joining multicast group which + * has to be done prior to calling nl_connect(). It works on any kernel + * version but is very limited as only 32 groups can be joined. + */ +void nl_join_groups(struct nl_sock *sk, int groups) +{ + sk->s_local.nl_groups |= groups; +} + + +/** @} */ + +/** + * @name Peer Identfication + * @{ + */ + +uint32_t nl_socket_get_peer_port(const struct nl_sock *sk) +{ + return sk->s_peer.nl_pid; +} + +void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port) +{ + sk->s_peer.nl_pid = port; +} + +uint32_t nl_socket_get_peer_groups(const struct nl_sock *sk) +{ + return sk->s_peer.nl_groups; +} + +void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups) +{ + sk->s_peer.nl_groups = groups; +} + + + +/** @} */ + +/** + * @name File Descriptor + * @{ + */ + +/** + * Return the file descriptor of the backing socket + * @arg sk Netlink socket + * + * Only valid after calling nl_connect() to create and bind the respective + * socket. + * + * @return File descriptor or -1 if not available. + */ +int nl_socket_get_fd(const struct nl_sock *sk) +{ + return sk->s_fd; +} + +/** + * Set file descriptor of socket to non-blocking state + * @arg sk Netlink socket. + * + * @return 0 on success or a negative error code. + */ +int nl_socket_set_nonblocking(const struct nl_sock *sk) +{ + if (sk->s_fd == -1) + return -NLE_BAD_SOCK; + + if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0) + return -nl_syserr2nlerr(errno); + + return 0; +} + +/** + * Enable use of MSG_PEEK when reading from socket + * @arg sk Netlink socket. + */ +void nl_socket_enable_msg_peek(struct nl_sock *sk) +{ + sk->s_flags |= NL_MSG_PEEK; +} + +/** + * Disable use of MSG_PEEK when reading from socket + * @arg sk Netlink socket. + */ +void nl_socket_disable_msg_peek(struct nl_sock *sk) +{ + sk->s_flags &= ~NL_MSG_PEEK; +} + +/** @} */ + +/** + * @name Callback Handler + * @{ + */ + +struct nl_cb *nl_socket_get_cb(const struct nl_sock *sk) +{ + return nl_cb_get(sk->s_cb); +} + +void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb) +{ + if (cb == NULL) + BUG(); + + nl_cb_put(sk->s_cb); + sk->s_cb = nl_cb_get(cb); +} + +/** + * Modify the callback handler associated with the socket + * @arg sk Netlink socket. + * @arg type which type callback to set + * @arg kind kind of callback + * @arg func callback function + * @arg arg argument to be passed to callback function + * + * @see nl_cb_set + */ +int nl_socket_modify_cb(struct nl_sock *sk, enum nl_cb_type type, + enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func, + void *arg) +{ + return nl_cb_set(sk->s_cb, type, kind, func, arg); +} + +/** + * Modify the error callback handler associated with the socket + * @arg sk Netlink socket. + * @arg kind kind of callback + * @arg func callback function + * @arg arg argument to be passed to callback function + * + * @see nl_cb_err + */ +int nl_socket_modify_err_cb(struct nl_sock *sk, enum nl_cb_kind kind, + nl_recvmsg_err_cb_t func, void *arg) +{ + return nl_cb_err(sk->s_cb, kind, func, arg); +} + +/** @} */ + +/** + * @name Utilities + * @{ + */ + +/** + * Set socket buffer size of netlink socket. + * @arg sk Netlink socket. + * @arg rxbuf New receive socket buffer size in bytes. + * @arg txbuf New transmit socket buffer size in bytes. + * + * Sets the socket buffer size of a netlink socket to the specified + * values \c rxbuf and \c txbuf. Providing a value of \c 0 assumes a + * good default value. + * + * @note It is not required to call this function prior to nl_connect(). + * @return 0 on sucess or a negative error code. + */ +int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf) +{ + int err; + + if (rxbuf <= 0) + rxbuf = 32768; + + if (txbuf <= 0) + txbuf = 32768; + + if (sk->s_fd == -1) + return -NLE_BAD_SOCK; + + err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF, + &txbuf, sizeof(txbuf)); + if (err < 0) + return -nl_syserr2nlerr(errno); + + err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF, + &rxbuf, sizeof(rxbuf)); + if (err < 0) + return -nl_syserr2nlerr(errno); + + sk->s_flags |= NL_SOCK_BUFSIZE_SET; + + return 0; +} + +/** + * Set default message buffer size of netlink socket. + * @arg sk Netlink socket. + * @arg bufsize Default message buffer size in bytes. + * + * Sets the default message buffer size to the specified length in bytes. + * The default message buffer size limits the maximum message size the + * socket will be able to receive. It is generally recommneded to specify + * a buffer size no less than the size of a memory page. + * + * @return 0 on success or a negative error code. + */ +int nl_socket_set_msg_buf_size(struct nl_sock *sk, size_t bufsize) +{ + sk->s_bufsize = bufsize; + + return 0; +} + +/** + * Get default message buffer size of netlink socket. + * @arg sk Netlink socket. + * + * @return Size of default message buffer. + */ +size_t nl_socket_get_msg_buf_size(struct nl_sock *sk) +{ + return sk->s_bufsize; +} + +/** + * Enable/disable credential passing on netlink socket. + * @arg sk Netlink socket. + * @arg state New state (0 - disabled, 1 - enabled) + * + * @return 0 on success or a negative error code + */ +int nl_socket_set_passcred(struct nl_sock *sk, int state) +{ + int err; + + if (sk->s_fd == -1) + return -NLE_BAD_SOCK; + + err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED, + &state, sizeof(state)); + if (err < 0) + return -nl_syserr2nlerr(errno); + + if (state) + sk->s_flags |= NL_SOCK_PASSCRED; + else + sk->s_flags &= ~NL_SOCK_PASSCRED; + + return 0; +} + +/** + * Enable/disable receival of additional packet information + * @arg sk Netlink socket. + * @arg state New state (0 - disabled, 1 - enabled) + * + * @return 0 on success or a negative error code + */ +int nl_socket_recv_pktinfo(struct nl_sock *sk, int state) +{ + int err; + + if (sk->s_fd == -1) + return -NLE_BAD_SOCK; + + err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_PKTINFO, + &state, sizeof(state)); + if (err < 0) + return -nl_syserr2nlerr(errno); + + return 0; +} + +/** @} */ + +/** @} */ diff --git a/lib/utils.c b/lib/utils.c new file mode 100644 index 0000000..4457b1f --- /dev/null +++ b/lib/utils.c @@ -0,0 +1,1106 @@ +/* + * lib/utils.c Utility Functions + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +/** + * @ingroup core + * @defgroup utils Utilities + * + * Collection of helper functions + * + * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ + */ + +#include +#include +#include +#include +#include /* exit() */ + +/** + * Global variable indicating the desired level of debugging output. + * + * Level | Messages Printed + * ----- | --------------------------------------------------------- + * 0 | Debugging output disabled + * 1 | Warnings, important events and notifications + * 2 | More or less important debugging messages + * 3 | Repetitive events causing a flood of debugging messages + * 4 | Even less important messages + * + * If available, the variable will be initialized to the value of the + * environment variable `NLDBG`. The default value is 0 (disabled). + * + * For more information, see section @core_doc{_debugging, Debugging}. + */ +int nl_debug = 0; + +/** @cond SKIP */ +#ifdef NL_DEBUG +struct nl_dump_params nl_debug_dp = { + .dp_type = NL_DUMP_DETAILS, +}; + +static void __init nl_debug_init(void) +{ + char *nldbg, *end; + + if ((nldbg = getenv("NLDBG"))) { + long level = strtol(nldbg, &end, 0); + if (nldbg != end) + nl_debug = level; + } + + nl_debug_dp.dp_fd = stderr; +} +#endif + +int __nl_read_num_str_file(const char *path, int (*cb)(long, const char *)) +{ + FILE *fd; + char buf[128]; + + fd = fopen(path, "r"); + if (fd == NULL) + return -nl_syserr2nlerr(errno); + + while (fgets(buf, sizeof(buf), fd)) { + int goodlen, err; + long num; + char *end; + + if (*buf == '#' || *buf == '\n' || *buf == '\r') + continue; + + num = strtol(buf, &end, 0); + if (end == buf) { + fclose(fd); + return -NLE_INVAL; + } + + if (num == LONG_MIN || num == LONG_MAX) { + fclose(fd); + return -NLE_RANGE; + } + + while (*end == ' ' || *end == '\t') + end++; + + goodlen = strcspn(end, "#\r\n\t "); + if (goodlen == 0) { + fclose(fd); + return -NLE_INVAL; + } + + end[goodlen] = '\0'; + + err = cb(num, end); + if (err < 0) { + fclose(fd); + return err; + } + } + + fclose(fd); + + return 0; +} +/** @endcond */ + +/** + * @name Pretty Printing of Numbers + * @{ + */ + +/** + * Cancel down a byte counter + * @arg l byte counter + * @arg unit destination unit pointer + * + * Cancels down a byte counter until it reaches a reasonable + * unit. The chosen unit is assigned to \a unit. + * This function assume 1024 bytes in one kilobyte + * + * @return The cancelled down byte counter in the new unit. + */ +double nl_cancel_down_bytes(unsigned long long l, char **unit) +{ + if (l >= 1099511627776LL) { + *unit = "TiB"; + return ((double) l) / 1099511627776LL; + } else if (l >= 1073741824) { + *unit = "GiB"; + return ((double) l) / 1073741824; + } else if (l >= 1048576) { + *unit = "MiB"; + return ((double) l) / 1048576; + } else if (l >= 1024) { + *unit = "KiB"; + return ((double) l) / 1024; + } else { + *unit = "B"; + return (double) l; + } +} + +/** + * Cancel down a bit counter + * @arg l bit counter + * @arg unit destination unit pointer + * + * Cancels down bit counter until it reaches a reasonable + * unit. The chosen unit is assigned to \a unit. + * This function assume 1000 bits in one kilobit + * + * @return The cancelled down bit counter in the new unit. + */ +double nl_cancel_down_bits(unsigned long long l, char **unit) +{ + if (l >= 1000000000000ULL) { + *unit = "Tbit"; + return ((double) l) / 1000000000000ULL; + } + + if (l >= 1000000000) { + *unit = "Gbit"; + return ((double) l) / 1000000000; + } + + if (l >= 1000000) { + *unit = "Mbit"; + return ((double) l) / 1000000; + } + + if (l >= 1000) { + *unit = "Kbit"; + return ((double) l) / 1000; + } + + *unit = "bit"; + return (double) l; +} + +int nl_rate2str(unsigned long long rate, int type, char *buf, size_t len) +{ + char *unit; + double frac; + + switch (type) { + case NL_BYTE_RATE: + frac = nl_cancel_down_bytes(rate, &unit); + break; + + case NL_BIT_RATE: + frac = nl_cancel_down_bits(rate, &unit); + break; + + default: + BUG(); + } + + return snprintf(buf, len, "%.2f%s/s", frac, unit); +} + +/** + * Cancel down a micro second value + * @arg l micro seconds + * @arg unit destination unit pointer + * + * Cancels down a microsecond counter until it reaches a + * reasonable unit. The chosen unit is assigned to \a unit. + * + * @return The cancelled down microsecond in the new unit + */ +double nl_cancel_down_us(uint32_t l, char **unit) +{ + if (l >= 1000000) { + *unit = "s"; + return ((double) l) / 1000000; + } else if (l >= 1000) { + *unit = "ms"; + return ((double) l) / 1000; + } else { + *unit = "us"; + return (double) l; + } +} + +/** @} */ + +/** + * @name Generic Unit Translations + * @{ + */ + +/** + * Convert a character string to a size + * @arg str size encoded as character string + * + * Converts the specified size as character to the corresponding + * number of bytes. + * + * Supported formats are: + * - b,kb/k,m/mb,gb/g for bytes + * - bit,kbit/mbit/gbit + * + * This function assume 1000 bits in one kilobit and + * 1024 bytes in one kilobyte + * + * @return The number of bytes or -1 if the string is unparseable + */ +long nl_size2int(const char *str) +{ + char *p; + long l = strtol(str, &p, 0); + if (p == str) + return -NLE_INVAL; + + if (*p) { + if (!strcasecmp(p, "kb") || !strcasecmp(p, "k")) + l *= 1024; + else if (!strcasecmp(p, "gb") || !strcasecmp(p, "g")) + l *= 1024*1024*1024; + else if (!strcasecmp(p, "gbit")) + l *= 1000000000L/8; + else if (!strcasecmp(p, "mb") || !strcasecmp(p, "m")) + l *= 1024*1024; + else if (!strcasecmp(p, "mbit")) + l *= 1000000/8; + else if (!strcasecmp(p, "kbit")) + l *= 1000/8; + else if (!strcasecmp(p, "bit")) + l /= 8; + else if (strcasecmp(p, "b") != 0) + return -NLE_INVAL; + } + + return l; +} + +static const struct { + double limit; + const char *unit; +} size_units[] = { + { 1024. * 1024. * 1024. * 1024. * 1024., "EiB" }, + { 1024. * 1024. * 1024. * 1024., "TiB" }, + { 1024. * 1024. * 1024., "GiB" }, + { 1024. * 1024., "MiB" }, + { 1024., "KiB" }, + { 0., "B" }, +}; + +/** + * Convert a size toa character string + * @arg size Size in number of bytes + * @arg buf Buffer to write character string to + * @arg len Size of buf + * + * This function converts a value in bytes to a human readable representation + * of it. The function uses IEC prefixes: + * + * @code + * 1024 bytes => 1 KiB + * 1048576 bytes => 1 MiB + * @endcode + * + * The highest prefix is used which ensures a result of >= 1.0, the result + * is provided as floating point number with a maximum precision of 2 digits: + * @code + * 965176 bytes => 942.55 KiB + * @endcode + * + * @return pointer to buf + */ +char *nl_size2str(const size_t size, char *buf, const size_t len) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(size_units); i++) { + if (size >= size_units[i].limit) { + snprintf(buf, len, "%.2g%s", + (double) size / size_units[i].limit, + size_units[i].unit); + return buf; + } + } + + BUG(); +} + +/** + * Convert a character string to a probability + * @arg str probability encoded as character string + * + * Converts the specified probability as character to the + * corresponding probability number. + * + * Supported formats are: + * - 0.0-1.0 + * - 0%-100% + * + * @return The probability relative to NL_PROB_MIN and NL_PROB_MAX + */ +long nl_prob2int(const char *str) +{ + char *p; + double d = strtod(str, &p); + + if (p == str) + return -NLE_INVAL; + + if (d > 1.0) + d /= 100.0f; + + if (d > 1.0f || d < 0.0f) + return -NLE_RANGE; + + if (*p && strcmp(p, "%") != 0) + return -NLE_INVAL; + + return rint(d * NL_PROB_MAX); +} + +/** @} */ + +/** + * @name Time Translations + * @{ + */ + +#ifndef USER_HZ +#define USER_HZ 100 +#endif + +static uint32_t user_hz = USER_HZ; +static uint32_t psched_hz = USER_HZ; + +static double ticks_per_usec = 1.0f; + +/* Retrieves the configured HZ and ticks/us value in the kernel. + * The value is cached. Supported ways of getting it: + * + * 1) environment variable + * 2) /proc/net/psched and sysconf + * + * Supports the environment variables: + * PROC_NET_PSCHED - may point to psched file in /proc + * PROC_ROOT - may point to /proc fs */ +static void __init get_psched_settings(void) +{ + char name[FILENAME_MAX]; + FILE *fd; + int got_hz = 0; + + if (getenv("HZ")) { + long hz = strtol(getenv("HZ"), NULL, 0); + + if (LONG_MIN != hz && LONG_MAX != hz) { + user_hz = hz; + got_hz = 1; + } + } + + if (!got_hz) + user_hz = sysconf(_SC_CLK_TCK); + + psched_hz = user_hz; + + if (getenv("TICKS_PER_USEC")) { + double t = strtod(getenv("TICKS_PER_USEC"), NULL); + ticks_per_usec = t; + } + else { + if (getenv("PROC_NET_PSCHED")) + snprintf(name, sizeof(name), "%s", getenv("PROC_NET_PSCHED")); + else if (getenv("PROC_ROOT")) + snprintf(name, sizeof(name), "%s/net/psched", + getenv("PROC_ROOT")); + else + strncpy(name, "/proc/net/psched", sizeof(name) - 1); + + if ((fd = fopen(name, "r"))) { + unsigned int ns_per_usec, ns_per_tick, nom, denom; + + if (fscanf(fd, "%08x %08x %08x %08x", + &ns_per_usec, &ns_per_tick, &nom, &denom) != 4) { + NL_DBG(1, "Fatal error: can not read psched settings from \"%s\". " \ + "Try to set TICKS_PER_USEC, PROC_NET_PSCHED or PROC_ROOT " \ + "environment variables\n", name); + exit(1); + } + + ticks_per_usec = (double) ns_per_usec / + (double) ns_per_tick; + + if (nom == 1000000) + psched_hz = denom; + + fclose(fd); + } + } +} + + +/** + * Return the value of HZ + */ +int nl_get_user_hz(void) +{ + return user_hz; +} + +/** + * Return the value of packet scheduler HZ + */ +int nl_get_psched_hz(void) +{ + return psched_hz; +} + +/** + * Convert micro seconds to ticks + * @arg us micro seconds + * @return number of ticks + */ +uint32_t nl_us2ticks(uint32_t us) +{ + return us * ticks_per_usec; +} + + +/** + * Convert ticks to micro seconds + * @arg ticks number of ticks + * @return microseconds + */ +uint32_t nl_ticks2us(uint32_t ticks) +{ + return ticks / ticks_per_usec; +} + +int nl_str2msec(const char *str, uint64_t *result) +{ + uint64_t total = 0, l; + int plen; + char *p; + + do { + l = strtoul(str, &p, 0); + if (p == str) + return -NLE_INVAL; + else if (*p) { + plen = strcspn(p, " \t"); + + if (!plen) + total += l; + else if (!strncasecmp(p, "sec", plen)) + total += (l * 1000); + else if (!strncasecmp(p, "min", plen)) + total += (l * 1000*60); + else if (!strncasecmp(p, "hour", plen)) + total += (l * 1000*60*60); + else if (!strncasecmp(p, "day", plen)) + total += (l * 1000*60*60*24); + else + return -NLE_INVAL; + + str = p + plen; + } else + total += l; + } while (*str && *p); + + *result = total; + + return 0; +} + +/** + * Convert milliseconds to a character string + * @arg msec number of milliseconds + * @arg buf destination buffer + * @arg len buffer length + * + * Converts milliseconds to a character string split up in days, hours, + * minutes, seconds, and milliseconds and stores it in the specified + * destination buffer. + * + * @return The destination buffer. + */ +char * nl_msec2str(uint64_t msec, char *buf, size_t len) +{ + uint64_t split[5]; + size_t i; + static const char *units[5] = {"d", "h", "m", "s", "msec"}; + char * const buf_orig = buf; + +#define _SPLIT(idx, unit) if ((split[idx] = msec / unit)) msec %= unit + _SPLIT(0, 86400000); /* days */ + _SPLIT(1, 3600000); /* hours */ + _SPLIT(2, 60000); /* minutes */ + _SPLIT(3, 1000); /* seconds */ +#undef _SPLIT + split[4] = msec; + + for (i = 0; i < ARRAY_SIZE(split) && len; i++) { + int l; + if (split[i] == 0) + continue; + l = snprintf(buf, len, "%s%" PRIu64 "%s", + (buf==buf_orig) ? "" : " ", split[i], units[i]); + buf += l; + len -= l; + } + + return buf_orig; +} + +/** @} */ + +/** + * @name Netlink Family Translations + * @{ + */ + +static const struct trans_tbl nlfamilies[] = { + __ADD(NETLINK_ROUTE,route) + __ADD(NETLINK_USERSOCK,usersock) + __ADD(NETLINK_FIREWALL,firewall) + __ADD(NETLINK_INET_DIAG,inetdiag) + __ADD(NETLINK_NFLOG,nflog) + __ADD(NETLINK_XFRM,xfrm) + __ADD(NETLINK_SELINUX,selinux) + __ADD(NETLINK_ISCSI,iscsi) + __ADD(NETLINK_AUDIT,audit) + __ADD(NETLINK_FIB_LOOKUP,fib_lookup) + __ADD(NETLINK_CONNECTOR,connector) + __ADD(NETLINK_NETFILTER,netfilter) + __ADD(NETLINK_IP6_FW,ip6_fw) + __ADD(NETLINK_DNRTMSG,dnrtmsg) + __ADD(NETLINK_KOBJECT_UEVENT,kobject_uevent) + __ADD(NETLINK_GENERIC,generic) + __ADD(NETLINK_SCSITRANSPORT,scsitransport) + __ADD(NETLINK_ECRYPTFS,ecryptfs) +}; + +char * nl_nlfamily2str(int family, char *buf, size_t size) +{ + return __type2str(family, buf, size, nlfamilies, + ARRAY_SIZE(nlfamilies)); +} + +int nl_str2nlfamily(const char *name) +{ + return __str2type(name, nlfamilies, ARRAY_SIZE(nlfamilies)); +} + +/** + * @} + */ + +/** + * @name Link Layer Protocol Translations + * @{ + */ + +static const struct trans_tbl llprotos[] = { + {0, "generic"}, + __ADD(ARPHRD_ETHER,ether) + __ADD(ARPHRD_EETHER,eether) + __ADD(ARPHRD_AX25,ax25) + __ADD(ARPHRD_PRONET,pronet) + __ADD(ARPHRD_CHAOS,chaos) + __ADD(ARPHRD_IEEE802,ieee802) + __ADD(ARPHRD_ARCNET,arcnet) + __ADD(ARPHRD_APPLETLK,atalk) + __ADD(ARPHRD_DLCI,dlci) + __ADD(ARPHRD_ATM,atm) + __ADD(ARPHRD_METRICOM,metricom) + __ADD(ARPHRD_IEEE1394,ieee1394) +#ifdef ARPHRD_EUI64 + __ADD(ARPHRD_EUI64,eui64) +#endif + __ADD(ARPHRD_INFINIBAND,infiniband) + __ADD(ARPHRD_SLIP,slip) + __ADD(ARPHRD_CSLIP,cslip) + __ADD(ARPHRD_SLIP6,slip6) + __ADD(ARPHRD_CSLIP6,cslip6) + __ADD(ARPHRD_RSRVD,rsrvd) + __ADD(ARPHRD_ADAPT,adapt) + __ADD(ARPHRD_ROSE,rose) + __ADD(ARPHRD_X25,x25) +#ifdef ARPHRD_HWX25 + __ADD(ARPHRD_HWX25,hwx25) +#endif + __ADD(ARPHRD_CAN,can) + __ADD(ARPHRD_PPP,ppp) + __ADD(ARPHRD_HDLC,hdlc) + __ADD(ARPHRD_LAPB,lapb) + __ADD(ARPHRD_DDCMP,ddcmp) + __ADD(ARPHRD_RAWHDLC,rawhdlc) + __ADD(ARPHRD_TUNNEL,ipip) + __ADD(ARPHRD_TUNNEL6,tunnel6) + __ADD(ARPHRD_FRAD,frad) + __ADD(ARPHRD_SKIP,skip) + __ADD(ARPHRD_LOOPBACK,loopback) + __ADD(ARPHRD_LOCALTLK,localtlk) + __ADD(ARPHRD_FDDI,fddi) + __ADD(ARPHRD_BIF,bif) + __ADD(ARPHRD_SIT,sit) + __ADD(ARPHRD_IPDDP,ip/ddp) + __ADD(ARPHRD_IPGRE,gre) + __ADD(ARPHRD_PIMREG,pimreg) + __ADD(ARPHRD_HIPPI,hippi) + __ADD(ARPHRD_ASH,ash) + __ADD(ARPHRD_ECONET,econet) + __ADD(ARPHRD_IRDA,irda) + __ADD(ARPHRD_FCPP,fcpp) + __ADD(ARPHRD_FCAL,fcal) + __ADD(ARPHRD_FCPL,fcpl) + __ADD(ARPHRD_FCFABRIC,fcfb_0) + __ADD(ARPHRD_FCFABRIC+1,fcfb_1) + __ADD(ARPHRD_FCFABRIC+2,fcfb_2) + __ADD(ARPHRD_FCFABRIC+3,fcfb_3) + __ADD(ARPHRD_FCFABRIC+4,fcfb_4) + __ADD(ARPHRD_FCFABRIC+5,fcfb_5) + __ADD(ARPHRD_FCFABRIC+6,fcfb_6) + __ADD(ARPHRD_FCFABRIC+7,fcfb_7) + __ADD(ARPHRD_FCFABRIC+8,fcfb_8) + __ADD(ARPHRD_FCFABRIC+9,fcfb_9) + __ADD(ARPHRD_FCFABRIC+10,fcfb_10) + __ADD(ARPHRD_FCFABRIC+11,fcfb_11) + __ADD(ARPHRD_FCFABRIC+12,fcfb_12) + __ADD(ARPHRD_IEEE802_TR,tr) + __ADD(ARPHRD_IEEE80211,ieee802.11) + __ADD(ARPHRD_PHONET,phonet) +#ifdef ARPHRD_CAIF + __ADD(ARPHRD_CAIF, caif) +#endif +#ifdef ARPHRD_IEEE80211_PRISM + __ADD(ARPHRD_IEEE80211_PRISM, ieee802.11_prism) +#endif +#ifdef ARPHRD_VOID + __ADD(ARPHRD_VOID,void) +#endif +#ifdef ARPHRD_NONE + __ADD(ARPHRD_NONE,nohdr) +#endif +}; + +char * nl_llproto2str(int llproto, char *buf, size_t len) +{ + return __type2str(llproto, buf, len, llprotos, ARRAY_SIZE(llprotos)); +} + +int nl_str2llproto(const char *name) +{ + return __str2type(name, llprotos, ARRAY_SIZE(llprotos)); +} + +/** @} */ + + +/** + * @name Ethernet Protocol Translations + * @{ + */ + +static const struct trans_tbl ether_protos[] = { + __ADD(ETH_P_LOOP,loop) + __ADD(ETH_P_PUP,pup) + __ADD(ETH_P_PUPAT,pupat) + __ADD(ETH_P_IP,ip) + __ADD(ETH_P_X25,x25) + __ADD(ETH_P_ARP,arp) + __ADD(ETH_P_BPQ,bpq) + __ADD(ETH_P_IEEEPUP,ieeepup) + __ADD(ETH_P_IEEEPUPAT,ieeepupat) + __ADD(ETH_P_DEC,dec) + __ADD(ETH_P_DNA_DL,dna_dl) + __ADD(ETH_P_DNA_RC,dna_rc) + __ADD(ETH_P_DNA_RT,dna_rt) + __ADD(ETH_P_LAT,lat) + __ADD(ETH_P_DIAG,diag) + __ADD(ETH_P_CUST,cust) + __ADD(ETH_P_SCA,sca) + __ADD(ETH_P_TEB,teb) + __ADD(ETH_P_RARP,rarp) + __ADD(ETH_P_ATALK,atalk) + __ADD(ETH_P_AARP,aarp) +#ifdef ETH_P_8021Q + __ADD(ETH_P_8021Q,802.1q) +#endif + __ADD(ETH_P_IPX,ipx) + __ADD(ETH_P_IPV6,ipv6) + __ADD(ETH_P_PAUSE,pause) + __ADD(ETH_P_SLOW,slow) +#ifdef ETH_P_WCCP + __ADD(ETH_P_WCCP,wccp) +#endif + __ADD(ETH_P_PPP_DISC,ppp_disc) + __ADD(ETH_P_PPP_SES,ppp_ses) + __ADD(ETH_P_MPLS_UC,mpls_uc) + __ADD(ETH_P_MPLS_MC,mpls_mc) + __ADD(ETH_P_ATMMPOA,atmmpoa) + __ADD(ETH_P_LINK_CTL,link_ctl) + __ADD(ETH_P_ATMFATE,atmfate) + __ADD(ETH_P_PAE,pae) + __ADD(ETH_P_AOE,aoe) + __ADD(ETH_P_TIPC,tipc) + __ADD(ETH_P_1588,ieee1588) + __ADD(ETH_P_FCOE,fcoe) + __ADD(ETH_P_FIP,fip) + __ADD(ETH_P_EDSA,edsa) + __ADD(ETH_P_EDP2,edp2) + __ADD(ETH_P_802_3,802.3) + __ADD(ETH_P_AX25,ax25) + __ADD(ETH_P_ALL,all) + __ADD(ETH_P_802_2,802.2) + __ADD(ETH_P_SNAP,snap) + __ADD(ETH_P_DDCMP,ddcmp) + __ADD(ETH_P_WAN_PPP,wan_ppp) + __ADD(ETH_P_PPP_MP,ppp_mp) + __ADD(ETH_P_LOCALTALK,localtalk) + __ADD(ETH_P_CAN,can) + __ADD(ETH_P_PPPTALK,ppptalk) + __ADD(ETH_P_TR_802_2,tr_802.2) + __ADD(ETH_P_MOBITEX,mobitex) + __ADD(ETH_P_CONTROL,control) + __ADD(ETH_P_IRDA,irda) + __ADD(ETH_P_ECONET,econet) + __ADD(ETH_P_HDLC,hdlc) + __ADD(ETH_P_ARCNET,arcnet) + __ADD(ETH_P_DSA,dsa) + __ADD(ETH_P_TRAILER,trailer) + __ADD(ETH_P_PHONET,phonet) + __ADD(ETH_P_IEEE802154,ieee802154) + __ADD(ETH_P_CAIF,caif) +}; + +char *nl_ether_proto2str(int eproto, char *buf, size_t len) +{ + return __type2str(eproto, buf, len, ether_protos, + ARRAY_SIZE(ether_protos)); +} + +int nl_str2ether_proto(const char *name) +{ + return __str2type(name, ether_protos, ARRAY_SIZE(ether_protos)); +} + +/** @} */ + +/** + * @name IP Protocol Translations + * @{ + */ + +char *nl_ip_proto2str(int proto, char *buf, size_t len) +{ + struct protoent *p = getprotobynumber(proto); + + if (p) { + snprintf(buf, len, "%s", p->p_name); + return buf; + } + + snprintf(buf, len, "0x%x", proto); + return buf; +} + +int nl_str2ip_proto(const char *name) +{ + struct protoent *p = getprotobyname(name); + unsigned long l; + char *end; + + if (p) + return p->p_proto; + + l = strtoul(name, &end, 0); + if (l == ULONG_MAX || *end != '\0') + return -NLE_OBJ_NOTFOUND; + + return (int) l; +} + +/** @} */ + +/** + * @name Dumping Helpers + * @{ + */ + +/** + * Handle a new line while dumping + * @arg params Dumping parameters + * + * This function must be called before dumping any onto a + * new line. It will ensure proper prefixing as specified + * by the dumping parameters. + * + * @note This function will NOT dump any newlines itself + */ +void nl_new_line(struct nl_dump_params *params) +{ + params->dp_line++; + + if (params->dp_prefix) { + int i; + for (i = 0; i < params->dp_prefix; i++) { + if (params->dp_fd) + fprintf(params->dp_fd, " "); + else if (params->dp_buf) + strncat(params->dp_buf, " ", + params->dp_buflen - + strlen(params->dp_buf) - 1); + } + } + + if (params->dp_nl_cb) + params->dp_nl_cb(params, params->dp_line); +} + +static void dump_one(struct nl_dump_params *parms, const char *fmt, + va_list args) +{ + if (parms->dp_fd) + vfprintf(parms->dp_fd, fmt, args); + else if (parms->dp_buf || parms->dp_cb) { + char *buf = NULL; + if (vasprintf(&buf, fmt, args) >= 0) { + if (parms->dp_cb) + parms->dp_cb(parms, buf); + else + strncat(parms->dp_buf, buf, + parms->dp_buflen - + strlen(parms->dp_buf) - 1); + free(buf); + } + } +} + + +/** + * Dump a formatted character string + * @arg params Dumping parameters + * @arg fmt printf style formatting string + * @arg ... Arguments to formatting string + * + * Dumps a printf style formatting string to the output device + * as specified by the dumping parameters. + */ +void nl_dump(struct nl_dump_params *params, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + dump_one(params, fmt, args); + va_end(args); +} + +void nl_dump_line(struct nl_dump_params *parms, const char *fmt, ...) +{ + va_list args; + + nl_new_line(parms); + + va_start(args, fmt); + dump_one(parms, fmt, args); + va_end(args); +} + + +/** @} */ + +/** @cond SKIP */ + +int __trans_list_add(int i, const char *a, struct nl_list_head *head) +{ + struct trans_list *tl; + + tl = calloc(1, sizeof(*tl)); + if (!tl) + return -NLE_NOMEM; + + tl->i = i; + tl->a = strdup(a); + + nl_list_add_tail(&tl->list, head); + + return 0; +} + +void __trans_list_clear(struct nl_list_head *head) +{ + struct trans_list *tl, *next; + + nl_list_for_each_entry_safe(tl, next, head, list) { + free(tl->a); + free(tl); + } + + nl_init_list_head(head); +} + +char *__type2str(int type, char *buf, size_t len, + const struct trans_tbl *tbl, size_t tbl_len) +{ + size_t i; + for (i = 0; i < tbl_len; i++) { + if (tbl[i].i == type) { + snprintf(buf, len, "%s", tbl[i].a); + return buf; + } + } + + snprintf(buf, len, "0x%x", type); + return buf; +} + +char *__list_type2str(int type, char *buf, size_t len, + struct nl_list_head *head) +{ + struct trans_list *tl; + + nl_list_for_each_entry(tl, head, list) { + if (tl->i == type) { + snprintf(buf, len, "%s", tl->a); + return buf; + } + } + + snprintf(buf, len, "0x%x", type); + return buf; +} + +char *__flags2str(int flags, char *buf, size_t len, + const struct trans_tbl *tbl, size_t tbl_len) +{ + size_t i; + int tmp = flags; + + memset(buf, 0, len); + + for (i = 0; i < tbl_len; i++) { + if (tbl[i].i & tmp) { + tmp &= ~tbl[i].i; + strncat(buf, tbl[i].a, len - strlen(buf) - 1); + if ((tmp & flags)) + strncat(buf, ",", len - strlen(buf) - 1); + } + } + + return buf; +} + +int __str2type(const char *buf, const struct trans_tbl *tbl, size_t tbl_len) +{ + unsigned long l; + char *end; + size_t i; + + if (*buf == '\0') + return -NLE_INVAL; + + for (i = 0; i < tbl_len; i++) + if (!strcasecmp(tbl[i].a, buf)) + return tbl[i].i; + + l = strtoul(buf, &end, 0); + if (l == ULONG_MAX || *end != '\0') + return -NLE_OBJ_NOTFOUND; + + return (int) l; +} + +int __list_str2type(const char *buf, struct nl_list_head *head) +{ + struct trans_list *tl; + unsigned long l; + char *end; + + if (*buf == '\0') + return -NLE_INVAL; + + nl_list_for_each_entry(tl, head, list) { + if (!strcasecmp(tl->a, buf)) + return tl->i; + } + + l = strtoul(buf, &end, 0); + if (l == ULONG_MAX || *end != '\0') + return -NLE_OBJ_NOTFOUND; + + return (int) l; +} + +int __str2flags(const char *buf, const struct trans_tbl *tbl, size_t tbl_len) +{ + int flags = 0; + size_t i; + size_t len; /* ptrdiff_t ? */ + char *p = (char *) buf, *t; + + for (;;) { + if (*p == ' ') + p++; + + t = strchr(p, ','); + len = t ? t - p : strlen(p); + for (i = 0; i < tbl_len; i++) + if (len == strlen(tbl[i].a) && + !strncasecmp(tbl[i].a, p, len)) + flags |= tbl[i].i; + + if (!t) + return flags; + + p = ++t; + } + + return 0; +} + +void dump_from_ops(struct nl_object *obj, struct nl_dump_params *params) +{ + int type = params->dp_type; + + if (type < 0 || type > NL_DUMP_MAX) + BUG(); + + params->dp_line = 0; + + if (params->dp_dump_msgtype) { +#if 0 + /* XXX */ + char buf[64]; + + dp_dump_line(params, 0, "%s ", + nl_cache_mngt_type2name(obj->ce_ops, + obj->ce_ops->co_protocol, + obj->ce_msgtype, + buf, sizeof(buf))); +#endif + params->dp_pre_dump = 1; + } + + if (obj->ce_ops->oo_dump[type]) + obj->ce_ops->oo_dump[type](obj, params); +} + +/** @endcond */ + +/** @} */ diff --git a/lib/version.c b/lib/version.c new file mode 100644 index 0000000..0dcafa0 --- /dev/null +++ b/lib/version.c @@ -0,0 +1,36 @@ +/* + * lib/version.c Run-time version information + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2012 Thomas Graf + */ + +/** + * @ingroup core + * @defgroup utils Utilities + * + * Run-time version information + * + * @{ + */ + + +/** + * @name Run-time version information + * @{ + */ + +#include + +const int nl_ver_num = LIBNL_VER_NUM; +const int nl_ver_maj = LIBNL_VER_MAJ; +const int nl_ver_min = LIBNL_VER_MIN; +const int nl_ver_mic = LIBNL_VER_MIC; + +/** @} */ + +/** @} */ diff --git a/libnl-3.0.pc.in b/libnl-3.0.pc.in new file mode 100644 index 0000000..b87e3dc --- /dev/null +++ b/libnl-3.0.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libnl +Description: Convenience library for netlink sockets +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lnl-@MAJ_VERSION@ +Cflags: -I${includedir}/libnl@MAJ_VERSION@ diff --git a/libnl-3.9.0.tar.gz b/libnl-3.9.0.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..d23b05fd1cfc902f10a2c2bcd9101922e9673ab4 GIT binary patch literal 1074117 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≶bH!9 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

J&4x}ut$Mw0nX2YrQz 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

mO{#~+>jMU>OQ3%EW0=a(a? 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 z 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 AK# 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νQWr5K@fFza??C!=;E1fe)jJfg6ss=(rV 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�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 literal 0 HcmV?d00001 diff --git a/libnl-cli-3.0.pc.in b/libnl-cli-3.0.pc.in new file mode 100644 index 0000000..d3638ba --- /dev/null +++ b/libnl-cli-3.0.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libnl-cli +Description: Command Line Interface library for netlink sockets +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lnl-cli-@MAJ_VERSION@ +Cflags: -I${includedir} +Requires: libnl-3.0 libnl-genl-3.0 libnl-nf-3.0 libnl-route-3.0 diff --git a/libnl-genl-3.0.pc.in b/libnl-genl-3.0.pc.in new file mode 100644 index 0000000..d6b69b8 --- /dev/null +++ b/libnl-genl-3.0.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libnl-genl +Description: Generic Netlink Library +Version: @PACKAGE_VERSION@ +Requires: libnl-3.0 +Libs: -L${libdir} -lnl-genl-@MAJ_VERSION@ +Cflags: -I${includedir}/libnl@MAJ_VERSION@ diff --git a/libnl-nf-3.0.pc.in b/libnl-nf-3.0.pc.in new file mode 100644 index 0000000..d82e1a6 --- /dev/null +++ b/libnl-nf-3.0.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libnl-nf +Description: Netfilter Netlink Library +Version: @PACKAGE_VERSION@ +Requires: libnl-route-3.0 +Libs: -L${libdir} -lnl-nf-@MAJ_VERSION@ +Cflags: -I${includedir}/libnl@MAJ_VERSION@ diff --git a/libnl-route-3.0.pc.in b/libnl-route-3.0.pc.in new file mode 100644 index 0000000..372a4f4 --- /dev/null +++ b/libnl-route-3.0.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libnl-route +Description: Netlink Routing Family Library +Version: @PACKAGE_VERSION@ +Requires: libnl-3.0 +Libs: -L${libdir} -lnl-route-@MAJ_VERSION@ +Cflags: -I${includedir}/libnl@MAJ_VERSION@ diff --git a/m4/libtool.m4 b/m4/libtool.m4 new file mode 100644 index 0000000..56666f0 --- /dev/null +++ b/m4/libtool.m4 @@ -0,0 +1,7986 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +]) + +# serial 57 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +m4_defun([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from `configure', and `config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# `config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain="$ac_aux_dir/ltmain.sh" +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the `libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to `config.status' so that its +# declaration there will have the same value as in `configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags="_LT_TAGS"dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the `libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into `config.status', and then the shell code to quote escape them in +# for loops in `config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# `#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test $lt_write_fail = 0 && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +\`$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test $[#] != 0 +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try \`$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try \`$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test "$silent" = yes && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +_LT_COPYING +_LT_LIBTOOL_TAGS + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + _LT_PROG_REPLACE_SHELLFNS + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test $_lt_result -eq 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS="$save_LDFLAGS" + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[[012]]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + m4_if([$1], [CXX], +[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script which will find a shell with a builtin +# printf (which we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case "$ECHO" in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[ --with-sysroot[=DIR] Search for dependent libraries within DIR + (or the compiler's sysroot if not specified).], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([${with_sysroot}]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and in which our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD="${LD-ld}_sol2" + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test x"[$]$2" = xyes; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links="nottested" +if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", + [Define to the sub-directory in which libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || + test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" + + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([], [sys_lib_dlsearch_path_spec], [2], + [Run-time system search path for libraries]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program which can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program which can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi]) +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64 which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global defined + # symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS="$save_LDFLAGS"]) + if test "$lt_cv_irix_exported_symbol" = yes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting ${shlibpath_var} if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report which library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC="$lt_save_CC" +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_caught_CXX_error" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared + # libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + gnu*) + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd2*) + # C++ shared libraries are fairly broken + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + + _LT_TAGVAR(GCC, $1)="$GXX" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test "$_lt_caught_CXX_error" != yes + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case ${prev}${p} in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" || + test $p = "-R"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test "$pre_test_object_deps_done" = no; then + case ${prev} in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)="${prev}${p}" + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)="$p" + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)="$p" + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; + +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC* | sunCC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test "X$F77" = "Xno"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_F77" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$G77" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC="$lt_save_CC" + CFLAGS="$lt_save_CFLAGS" +fi # test "$_lt_disable_F77" != yes + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test "X$FC" = "Xno"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_FC" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test "$_lt_disable_FC" != yes + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)="$LD" +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)="$LD" +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[AC_MSG_CHECKING([whether the shell understands some XSI constructs]) +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +AC_MSG_RESULT([$xsi_shell]) +_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) + +AC_MSG_CHECKING([whether the shell understands "+="]) +lt_shell_append=no +( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +AC_MSG_RESULT([$lt_shell_append]) +_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) +# ------------------------------------------------------ +# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and +# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. +m4_defun([_LT_PROG_FUNCTION_REPLACE], +[dnl { +sed -e '/^$1 ()$/,/^} # $1 /c\ +$1 ()\ +{\ +m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) +} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: +]) + + +# _LT_PROG_REPLACE_SHELLFNS +# ------------------------- +# Replace existing portable implementations of several shell functions with +# equivalent extended shell implementations where those features are available.. +m4_defun([_LT_PROG_REPLACE_SHELLFNS], +[if test x"$xsi_shell" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl + func_split_long_opt_name=${1%%=*} + func_split_long_opt_arg=${1#*=}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) + + _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) + + _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) + + _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) +fi + +if test x"$lt_shell_append" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) + + _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl + func_quote_for_eval "${2}" +dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ + eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) +fi +]) + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine which file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4 new file mode 100644 index 0000000..5d9acd8 --- /dev/null +++ b/m4/ltoptions.m4 @@ -0,0 +1,384 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 7 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option `$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl `shared' nor `disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the `shared' and +# `disable-shared' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the `static' and +# `disable-static' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the `fast-install' +# and `disable-fast-install' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the `pic-only' and `no-pic' +# LT_INIT options. +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for lt_pkg in $withval; do + IFS="$lt_save_ifs" + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [pic_mode=default]) + +test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/m4/ltsugar.m4 b/m4/ltsugar.m4 new file mode 100644 index 0000000..9000a05 --- /dev/null +++ b/m4/ltsugar.m4 @@ -0,0 +1,123 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59 which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/m4/ltversion.m4 b/m4/ltversion.m4 new file mode 100644 index 0000000..07a8602 --- /dev/null +++ b/m4/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 3337 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.2]) +m4_define([LT_PACKAGE_REVISION], [1.3337]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.2' +macro_revision='1.3337' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4 new file mode 100644 index 0000000..c573da9 --- /dev/null +++ b/m4/lt~obsolete.m4 @@ -0,0 +1,98 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/man/Makefile.am b/man/Makefile.am new file mode 100644 index 0000000..af1277b --- /dev/null +++ b/man/Makefile.am @@ -0,0 +1,7 @@ +# -*- Makefile -*- + +dist_man8_MANS = \ + nl-classid-lookup.8 \ + nl-pktloc-lookup.8 \ + nl-qdisc-add.8 nl-qdisc-delete.8 nl-qdisc-list.8 \ + genl-ctrl-list.8 diff --git a/man/Makefile.in b/man/Makefile.in new file mode 100644 index 0000000..69b1803 --- /dev/null +++ b/man/Makefile.in @@ -0,0 +1,502 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# -*- Makefile -*- +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = man +DIST_COMMON = $(dist_man8_MANS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/lib/defs.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man8dir = $(mandir)/man8 +am__installdirs = "$(DESTDIR)$(man8dir)" +NROFF = nroff +MANS = $(dist_man8_MANS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_CFLAGS = @CHECK_CFLAGS@ +CHECK_LIBS = @CHECK_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FLEX = @FLEX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBNL_VERSION = @LIBNL_VERSION@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_CURRENT = @LT_CURRENT@ +LT_REVISION = @LT_REVISION@ +MAJ_VERSION = @MAJ_VERSION@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIC_VERSION = @MIC_VERSION@ +MIN_VERSION = @MIN_VERSION@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgconfigdir = @pkgconfigdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +dist_man8_MANS = \ + nl-classid-lookup.8 \ + nl-pktloc-lookup.8 \ + nl-qdisc-add.8 nl-qdisc-delete.8 nl-qdisc-list.8 \ + genl-ctrl-list.8 + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign man/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign man/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man8: $(dist_man8_MANS) + @$(NORMAL_INSTALL) + @list1='$(dist_man8_MANS)'; \ + list2=''; \ + test -n "$(man8dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.8[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ + done; } + +uninstall-man8: + @$(NORMAL_UNINSTALL) + @list='$(dist_man8_MANS)'; test -n "$(man8dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @list='$(MANS)'; if test -n "$$list"; then \ + list=`for p in $$list; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ + if test -n "$$list" && \ + grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ + echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ + grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ + echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ + echo " typically \`make maintainer-clean' will remove them" >&2; \ + exit 1; \ + else :; fi; \ + else :; fi + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(MANS) +installdirs: + for dir in "$(DESTDIR)$(man8dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man8 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-man + +uninstall-man: uninstall-man8 + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-man8 \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + uninstall uninstall-am uninstall-man uninstall-man8 + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/man/genl-ctrl-list.8 b/man/genl-ctrl-list.8 new file mode 100644 index 0000000..6132475 --- /dev/null +++ b/man/genl-ctrl-list.8 @@ -0,0 +1,104 @@ +.TH genl\-ctrl-list 8 "20 April 2012" "libnl" +.SH NAME +genl\-ctrl\-list \- List available kernel-side Generic Netlink families +.SH SYNOPSIS +.B genl\-ctrl\-list [-d] + +.SH DESCRIPTION +.PP +Queries the Generic Netlink controller in kernel and prints a list of all +registered Generic Netlink families including the version of the interface +that has been registered. + +.SH OPTIONS +.TP +.BR \-\^h " or " \-\-help +Print help text to console and exit. +.TP +.BR \-\^v " or " \-\-version +Print versioning information to console and exit. +.TP +.BR \-\^d " or " \-\-details +Include additional detailed information for each Generic Netlink +family that is printed. + +The information includes: + +.RS +.TP +.B hdrsize N +The size of the user specific header. + +.TP +.B maxattr N +The maximum Netlink attribute identifier expected by the interface. + +.TP +.B op NAME (ID) +A list of available operations including their name, numeric identifier +and the flags indicating the capabilities of the opertion. + +Available flags: +.RS +.TP +.I admin-perm +Requires administrative privileges + +.TP +.I has-doit +Command can handle request + +.TP +.I has-dump +Command can handle a dump request + +.TP +.I has-policy +Command enforces attribute validation policy +.RE + +.TP +.B grp NAME (ID) +A list of registered multicast groups including name (if available) +and identifier. +.RE + +.RS +.B Example: +.RS +0x0010 nlctrl version 2 +.RS 0 + hdrsize 0 maxattr 7 +.RS 0 + op GETFAMILY (0x03) +.RS 0 + grp notify (0x10) +.RE + + +.SH EXAMPLE +.RS 0 +$ genl-ctrl-list +.RS 0 +0x0010 nlctrl version 2 +.RS 0 +0x0011 NLBL_MGMT version 3 +.RS 0 +0x0012 NLBL_CIPSOv4 version 3 +.RS 0 +0x0013 NLBL_UNLBL version 3 +.RS 0 +0x0014 acpi_event version 1 +.RS 0 +0x0015 thermal_event version 1 +.RS 0 +0x0016 VFS_DQUOT version 1 +.RS 0 +0x0017 TASKSTATS version 1 +.RS 0 +0x0018 NET_DM version 2 + +.SH AUTHOR +.PP +Thomas Graf is the original author and current maintainer of libnl and +libnl tools. Many people have contributed to it since. diff --git a/man/nl-classid-lookup.8 b/man/nl-classid-lookup.8 new file mode 100644 index 0000000..3cf13de --- /dev/null +++ b/man/nl-classid-lookup.8 @@ -0,0 +1,51 @@ +.TH nl\-classid\-lookup 8 "19 October 2010" "libnl" +.SH NAME +nl\-classid\-lookup - Lookup classid definitions +.SH SYNOPSIS +.B nl\-classid\-lookup +.RB [ \-hv ] +.RB [ \-r ] +.RB [ \-\-raw ] +.I name + +.SH DESCRIPTION +.PP +nl\-classid\-lookup searches the classid database for a matching entry. It is used +to resolve qdisc/class names to classid values and vice versa. + +.SH OPTIONS +.TP +.BR \-\^h " or " \-\-help +Print help text to console and exit. +.TP +.BR \-\^v " or " \-\-version +Print versioning information to console and exit. +.TP +.BR \-\^r " or " \-\-reverse +Do a reverse lookup. Lookup a classid and print its name. +.TP +.B \-\-raw +Print the raw classid in hexadecimal format, do not pretty print it. + +.SH USAGE +.PP +Resolve the qdisc/class name "interactive": +.PP +.RS +# nl\-classid\-lookup interactive +.RE +.PP +Lookup the name of classid 1:2: +.PP +.RS +# nl\-classid\-lookup -r 1:2 +.RE + +.SH FILES +.PP +/etc/libnl/classid + +.SH AUTHOR +.PP +Thomas Graf is the original author and current maintainer of libnl and +libnl tools. Many people have contributed to it since. diff --git a/man/nl-pktloc-lookup.8 b/man/nl-pktloc-lookup.8 new file mode 100644 index 0000000..7a1daa4 --- /dev/null +++ b/man/nl-pktloc-lookup.8 @@ -0,0 +1,48 @@ +.TH nl\-pktloc-lookup 8 "27 October 2010" "libnl" +.SH NAME +nl\-pktloc\-lookup - Lookup packet location definitions +.SH SYNOPSIS +.B nl\-pktloc\-lookup +.I name +.br +.B nl\-pktloc\-lookup \-\-list + +.SH DESCRIPTION +.PP +nl\-pktloc\-lookup searches the packet location database for a matching +entry. It is used to resolve packet location aliases to their definition, +i.e. alignment, layer, offset, and mask. + +.SH OPTIONS +.TP +.BR \-\^h " or " \-\-help +Print help text to console and exit. +.TP +.BR \-\^v " or " \-\-version +Print versioning information to console and exit. +.TP +.BR \-\^l " or " \-\-list +List all packet location definitions. +.TP +.BR \-\-u32=VALUE +Prints the packet location definition in a special format that is +understood by iproute2's u32 selector parser. It will output a +u32 selector which will compare the provided value with the value +specified by the packet location. + +Please note that due to the limitation of u32, it is not possible +to use packet locations based on the link layer. nl-pktloc-lookup +will print an error message in this case. + +Example: + selector=$(nl-pktloc-lookup --u32 22 tcp.sport) + tc filter add [...] u32 match $(selector) flowid 1:2 + +.SH FILES +.PP +/etc/libnl/pktloc + +.SH AUTHOR +.PP +Thomas Graf is the original author and current maintainer of libnl and +libnl tools. Many people have contributed to it since. diff --git a/man/nl-qdisc-add.8 b/man/nl-qdisc-add.8 new file mode 100644 index 0000000..bc3fb17 --- /dev/null +++ b/man/nl-qdisc-add.8 @@ -0,0 +1,118 @@ +.TH nl\-qdisc 8 "21 October 2010" "libnl" +.SH NAME +nl\-qdisc\-{add|list|delete} - Manage queueing disciplines +.SH SYNOPSIS +.B nl\-qdisc\-add \-\-dev +.I dev +.B \-\-parent +.I id +.B [OPTIONS] +.I qdisc-type +.B [QDISC] +.sp +.B nl\-qdisc\-delete [ \-\-interactive ] [OPTIONS] +.sp +.B nl\-qdisc\-list [OPTIONS] + +.SH DESCRIPTION +.PP +The nl\-qdisc tools allow to manage and configure queueing disciplines +(qdiscs) in the kernel. + +.SH OPTIONS +.TP +.BR \-\^h " or " \-\-help +Print help text to console and exit. +.TP +.BR \-\^v " or " \-\-version +Print versioning information to console and exit. +.TP +.BR \-\^q " or " \-\-quiet +Do not print informal notifications about actions taken to the console. +By default a short description of each qdisc added/update/deleted will +be printed to the console. This option disables this behaviour. +.TP +.BR \-\^d " or " \-\-dev "=DEV" +Network device the qdisc is attached to. +.TP +.BR \-\^p " or " \-\-parent "=ID" +Identifier of the parent qdisc/class this qdisc is attached to. The +identifier can be specified as classid, name or one of the special +values "root" or "ingress". +.TP +.BR \-\^i " or " \-\-id "=ID" +Identifier of qdisc. It can be specified as classid or name. + +.SS nl\-qdisc\-add Options +.TP +.B \-\-update +Update qdisc if it already exists, otherwise attempting to add a qdisc which already +exists will result in an error. This does not include changing the type of the qdisc, +use \-\-replace if you wish to do so. +.TP +.B \-\-replace +Replace or update qdisc if it already exists. Same behaviour as \-\-update but will +completely replace the qdisc if it exists already. +.TP +.B \-\-update\-only +Update an existing qdisc but do not create it if it does not exist. +.TP +.B \-\-replace\-only +Update or replace an existing qdisc but do not create it if it does exist. + +.SS nl\-qdisc\-delete Options +.TP +.B \-\-interactive +The interactive mode requires confirmation by the user for each qdisc deleted. It +will print a prompt for each qdisc matching the provided filter and requires the +user to answer 'y'es or 'n'o. +.TP +.B \-\-yes +Make the default answer for interactive prompts be 'y'es. This option is also +required to delete all qdiscs on all network devices. +.TP +.BR \-\^k " or " \-\-kind "=TYPE" +Only delete qdiscs of this type. + +.SS nl\-qdisc\-list Options +.TP +.B \-\-details +Show detailed information for each qdisc listed. +.TP +.B \-\-stats +Show statistics information for each qdisc listed. This option will also turn +on detailed information automatically. +.TP +.BR \-\^r " or " \-\-recursive +List all TC objects recurisvely attached to all qdiscs matching the filter. +.TP +.BR \-\^k " or " \-\-kind "=TYPE" +Only list qdiscs of this type. + +.SH USAGE +.PP +Add a HTB root qdisc with id "5:": +.PP +.RS +nl\-qdisc\-add \-\-dev eth0 \-\-parent root \-\-id 5: htb +.RE +.PP +List all qdiscs on eth0 and print statistical data: +.PP +.RS +nl\-qdisc\-list \-\-stats \-\-dev eth0 +.RE +.PP +Delete the qdisc "5:": +.RS +nl\-qdisc\-delete \-\-id 5: +.RE + +.SH "SEE ALSO" +.PP +.B nl\-classid\-lookup(8) + +.SH AUTHOR +.PP +Thomas Graf is the original author and current maintainer of libnl and +libnl tools. Many people have contributed to it since. diff --git a/man/nl-qdisc-delete.8 b/man/nl-qdisc-delete.8 new file mode 100644 index 0000000..864a4e0 --- /dev/null +++ b/man/nl-qdisc-delete.8 @@ -0,0 +1 @@ +.so man8/nl-qdisc-add.8 diff --git a/man/nl-qdisc-list.8 b/man/nl-qdisc-list.8 new file mode 100644 index 0000000..864a4e0 --- /dev/null +++ b/man/nl-qdisc-list.8 @@ -0,0 +1 @@ +.so man8/nl-qdisc-add.8 diff --git a/python/Makefile.am b/python/Makefile.am new file mode 100644 index 0000000..bd5ac11 --- /dev/null +++ b/python/Makefile.am @@ -0,0 +1,3 @@ +# -*- Makefile -*- + +SUBDIRS = netlink diff --git a/python/Makefile.in b/python/Makefile.in new file mode 100644 index 0000000..ba2d070 --- /dev/null +++ b/python/Makefile.in @@ -0,0 +1,607 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# -*- Makefile -*- +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = python +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/setup.py.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/lib/defs.h +CONFIG_CLEAN_FILES = setup.py +CONFIG_CLEAN_VPATH_FILES = +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_CFLAGS = @CHECK_CFLAGS@ +CHECK_LIBS = @CHECK_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FLEX = @FLEX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBNL_VERSION = @LIBNL_VERSION@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_CURRENT = @LT_CURRENT@ +LT_REVISION = @LT_REVISION@ +MAJ_VERSION = @MAJ_VERSION@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIC_VERSION = @MIC_VERSION@ +MIN_VERSION = @MIN_VERSION@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgconfigdir = @pkgconfigdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = netlink +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign python/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign python/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +setup.py: $(top_builddir)/config.status $(srcdir)/setup.py.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic clean-libtool \ + ctags ctags-recursive distclean distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ + uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/python/README b/python/README new file mode 100644 index 0000000..4ccc337 --- /dev/null +++ b/python/README @@ -0,0 +1,12 @@ + +*************************************************************************** + +NOTE: The python wrapper is experimental and may or may not work. + +*************************************************************************** + +For the brave: + + (requires an installed libnl) + - $ python ./setup.py build + - $ sudo python ./setup.py install diff --git a/python/netlink/Makefile.am b/python/netlink/Makefile.am new file mode 100644 index 0000000..0f1045b --- /dev/null +++ b/python/netlink/Makefile.am @@ -0,0 +1,10 @@ +# -*- Makefile -*- + +SUBDIRS = route + +EXTRA_DIST = \ + capi.i \ + fixes.h \ + __init__.py \ + core.py \ + util.py diff --git a/python/netlink/Makefile.in b/python/netlink/Makefile.in new file mode 100644 index 0000000..60f6672 --- /dev/null +++ b/python/netlink/Makefile.in @@ -0,0 +1,611 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# -*- Makefile -*- +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = python/netlink +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/lib/defs.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_CFLAGS = @CHECK_CFLAGS@ +CHECK_LIBS = @CHECK_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FLEX = @FLEX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBNL_VERSION = @LIBNL_VERSION@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_CURRENT = @LT_CURRENT@ +LT_REVISION = @LT_REVISION@ +MAJ_VERSION = @MAJ_VERSION@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIC_VERSION = @MIC_VERSION@ +MIN_VERSION = @MIN_VERSION@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgconfigdir = @pkgconfigdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = route +EXTRA_DIST = \ + capi.i \ + fixes.h \ + __init__.py \ + core.py \ + util.py + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign python/netlink/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign python/netlink/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic clean-libtool \ + ctags ctags-recursive distclean distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ + uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/python/netlink/__init__.py b/python/netlink/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/netlink/capi.i b/python/netlink/capi.i new file mode 100644 index 0000000..73c4bf3 --- /dev/null +++ b/python/netlink/capi.i @@ -0,0 +1,454 @@ +%module capi +%{ +#include +#include +#include +#include +#include +#include +%} + +%include +%include + +%inline %{ + struct nl_dump_params *alloc_dump_params(void) + { + struct nl_dump_params *dp; + if (!(dp = calloc(1, sizeof(*dp)))) + return NULL; + dp->dp_fd = stdout; + return dp; + } + + void free_dump_params(struct nl_dump_params *dp) + { + free(dp); + } +%}; + +/* */ + +enum nl_dump_type { + NL_DUMP_LINE, /**< Dump object briefly on one line */ + NL_DUMP_DETAILS, /**< Dump all attributes but no statistics */ + NL_DUMP_STATS, /**< Dump all attributes including statistics */ + __NL_DUMP_MAX, +}; + +struct nl_dump_params +{ + /** + * Specifies the type of dump that is requested. + */ + enum nl_dump_type dp_type; + + /** + * Specifies the number of whitespaces to be put in front + * of every new line (indentation). + */ + int dp_prefix; + + /** + * Causes the cache index to be printed for each element. + */ + int dp_print_index; + + /** + * Causes each element to be prefixed with the message type. + */ + int dp_dump_msgtype; + + /** + * A callback invoked for output + * + * Passed arguments are: + * - dumping parameters + * - string to append to the output + */ + void (*dp_cb)(struct nl_dump_params *, char *); + + /** + * A callback invoked for every new line, can be used to + * customize the indentation. + * + * Passed arguments are: + * - dumping parameters + * - line number starting from 0 + */ + void (*dp_nl_cb)(struct nl_dump_params *, int); + + /** + * User data pointer, can be used to pass data to callbacks. + */ + void *dp_data; + + /** + * File descriptor the dumping output should go to + */ + FILE * dp_fd; + + /** + * Alternatively the output may be redirected into a buffer + */ + char * dp_buf; + + /** + * Length of the buffer dp_buf + */ + size_t dp_buflen; + + /** + * PRIVATE + * Set if a dump was performed prior to the actual dump handler. + */ + int dp_pre_dump; + + /** + * PRIVATE + * Owned by the current caller + */ + int dp_ivar; + + unsigned int dp_line; +}; + +/* */ +extern const char *nl_geterror(int); + +/* */ + +extern double nl_cancel_down_bytes(unsigned long long, char **); +extern double nl_cancel_down_bits(unsigned long long, char **); +%cstring_output_maxsize(char *buf, size_t len) +extern int nl_rate2str(unsigned long long rate, int type, char *buf, size_t len); +extern double nl_cancel_down_us(uint32_t, char **); + +extern long nl_size2int(const char *); +%cstring_output_maxsize(char *buf, const size_t len) +extern char *nl_size2str(const size_t, char *buf, const size_t len); +extern long nl_prob2int(const char *); + +extern int nl_get_user_hz(void); +extern uint32_t nl_us2ticks(uint32_t); +extern uint32_t nl_ticks2us(uint32_t); +extern int nl_str2msec(const char *, uint64_t *); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *nl_msec2str(uint64_t, char *buf, size_t len); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *nl_llproto2str(int, char *buf, size_t len); +extern int nl_str2llproto(const char *); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *nl_ether_proto2str(int, char *buf, size_t len); +extern int nl_str2ether_proto(const char *); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *nl_ip_proto2str(int, char *buf, size_t len); +extern int nl_str2ip_proto(const char *); + +extern void nl_new_line(struct nl_dump_params *); +extern void nl_dump(struct nl_dump_params *, const char *, ...); +extern void nl_dump_line(struct nl_dump_params *, const char *, ...); + +/* */ +extern struct nl_dump_params *alloc_dump_params(void); +extern void free_dump_params(struct nl_dump_params *); + +extern int nl_connect(struct nl_sock *, int); +extern void nl_close(struct nl_sock *); + +/* */ +extern struct nl_sock *nl_socket_alloc(void); +extern struct nl_sock *nl_socket_alloc_cb(struct nl_cb *); +extern void nl_socket_free(struct nl_sock *); + +extern uint32_t nl_socket_get_local_port(const struct nl_sock *); +extern void nl_socket_set_local_port(struct nl_sock *, uint32_t); + +extern uint32_t nl_socket_get_peer_port(const struct nl_sock *); +extern void nl_socket_set_peer_port(struct nl_sock *, uint32_t); + +extern uint32_t nl_socket_get_peer_groups(const struct nl_sock *sk); +extern void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups); + +extern int nl_socket_set_buffer_size(struct nl_sock *, int, int); + +/* */ +extern int nlmsg_size(int); +extern int nlmsg_total_size(int); +extern int nlmsg_padlen(int); + +extern void * nlmsg_data(const struct nlmsghdr *); +extern int nlmsg_datalen(const struct nlmsghdr *); +extern void * nlmsg_tail(const struct nlmsghdr *); + +/* attribute access */ +extern struct nlattr * nlmsg_attrdata(const struct nlmsghdr *, int); +extern int nlmsg_attrlen(const struct nlmsghdr *, int); + +/* message parsing */ +extern int nlmsg_valid_hdr(const struct nlmsghdr *, int); +extern int nlmsg_ok(const struct nlmsghdr *, int); +extern struct nlmsghdr * nlmsg_next(struct nlmsghdr *, int *); +extern int nlmsg_parse(struct nlmsghdr *, int, struct nlattr **, + int, struct nla_policy *); +extern struct nlattr * nlmsg_find_attr(struct nlmsghdr *, int, int); +extern int nlmsg_validate(struct nlmsghdr *, int, int, + struct nla_policy *); + +extern struct nl_msg * nlmsg_alloc(void); +extern struct nl_msg * nlmsg_alloc_size(size_t); +extern struct nl_msg * nlmsg_alloc_simple(int, int); +extern void nlmsg_set_default_size(size_t); +extern struct nl_msg * nlmsg_inherit(struct nlmsghdr *); +extern struct nl_msg * nlmsg_convert(struct nlmsghdr *); +extern void * nlmsg_reserve(struct nl_msg *, size_t, int); +extern int nlmsg_append(struct nl_msg *, void *, size_t, int); +extern int nlmsg_expand(struct nl_msg *, size_t); + +extern struct nlmsghdr * nlmsg_put(struct nl_msg *, uint32_t, uint32_t, + int, int, int); +extern struct nlmsghdr * nlmsg_hdr(struct nl_msg *); +extern void nlmsg_get(struct nl_msg *); +extern void nlmsg_free(struct nl_msg *); + +/* attribute modification */ +extern void nlmsg_set_proto(struct nl_msg *, int); +extern int nlmsg_get_proto(struct nl_msg *); +extern size_t nlmsg_get_max_size(struct nl_msg *); +extern void nlmsg_set_src(struct nl_msg *, struct sockaddr_nl *); +extern struct sockaddr_nl *nlmsg_get_src(struct nl_msg *); +extern void nlmsg_set_dst(struct nl_msg *, struct sockaddr_nl *); +extern struct sockaddr_nl *nlmsg_get_dst(struct nl_msg *); +extern void nlmsg_set_creds(struct nl_msg *, struct ucred *); +extern struct ucred * nlmsg_get_creds(struct nl_msg *); + +extern char * nl_nlmsgtype2str(int, char *, size_t); +extern int nl_str2nlmsgtype(const char *); + +extern char * nl_nlmsg_flags2str(int, char *, size_t); + +extern int nl_msg_parse(struct nl_msg *, + void (*cb)(struct nl_object *, void *), + void *); + +extern void nl_msg_dump(struct nl_msg *, FILE *); + +%inline %{ + struct nl_object *cast_obj(void *obj) + { + return (struct nl_object *) obj; + } + + struct nl_object *object_alloc_name(const char *name) + { + struct nl_object *obj; + + if (nl_object_alloc_name(name, &obj) < 0) + return NULL; + + return obj; + } +%}; + +extern struct nl_object *nl_object_alloc(struct nl_object_ops *); +extern void nl_object_free(struct nl_object *); +extern struct nl_object *nl_object_clone(struct nl_object *); +extern void nl_object_get(struct nl_object *); +extern void nl_object_put(struct nl_object *); +extern int nl_object_shared(struct nl_object *); + +%cstring_output_maxsize(char *buf, size_t len) +extern void nl_object_dump_buf(struct nl_object *, char *buf, size_t len); + +extern void nl_object_dump(struct nl_object *, struct nl_dump_params *); + +extern int nl_object_identical(struct nl_object *, struct nl_object *); +extern uint32_t nl_object_diff(struct nl_object *, struct nl_object *); +extern int nl_object_match_filter(struct nl_object *, struct nl_object *); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *nl_object_attrs2str(struct nl_object *, uint32_t, char *buf, size_t len); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *nl_object_attr_list(struct nl_object *, char *buf, size_t len); + +extern void nl_object_mark(struct nl_object *); +extern void nl_object_unmark(struct nl_object *); +extern int nl_object_is_marked(struct nl_object *); + +extern int nl_object_get_refcnt(struct nl_object *); + +/* */ + +typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int, void *); + +%inline %{ + struct nl_cache *alloc_cache_name(const char *name) + { + struct nl_cache *c; + if (nl_cache_alloc_name(name, &c) < 0) + return NULL; + return c; + } + + struct nl_cache_mngr *alloc_cache_mngr(struct nl_sock *sock, + int protocol, int flags) + { + struct nl_cache_mngr *mngr; + + if (nl_cache_mngr_alloc(sock, protocol, flags, &mngr) < 0) + return NULL; + + return mngr; + } + + struct nl_cache *cache_mngr_add(struct nl_cache_mngr *mngr, + const char *name, change_func_t func, + void *arg) + { + struct nl_cache *cache; + + if (nl_cache_mngr_add(mngr, name, func, arg, &cache) < 0) + return NULL; + + return cache; + } +%} + +/* Access Functions */ +extern int nl_cache_nitems(struct nl_cache *); +extern int nl_cache_nitems_filter(struct nl_cache *, + struct nl_object *); +extern struct nl_cache_ops * nl_cache_get_ops(struct nl_cache *); +extern struct nl_object * nl_cache_get_first(struct nl_cache *); +extern struct nl_object * nl_cache_get_last(struct nl_cache *); +extern struct nl_object * nl_cache_get_next(struct nl_object *); +extern struct nl_object * nl_cache_get_prev(struct nl_object *); + +extern struct nl_cache * nl_cache_alloc(struct nl_cache_ops *); +extern struct nl_cache * nl_cache_subset(struct nl_cache *, + struct nl_object *); +extern void nl_cache_clear(struct nl_cache *); +extern void nl_cache_free(struct nl_cache *); + +/* Cache modification */ +extern int nl_cache_add(struct nl_cache *, + struct nl_object *); +extern int nl_cache_parse_and_add(struct nl_cache *, + struct nl_msg *); +extern void nl_cache_remove(struct nl_object *); +extern int nl_cache_refill(struct nl_sock *, + struct nl_cache *); +extern int nl_cache_pickup(struct nl_sock *, + struct nl_cache *); +extern int nl_cache_resync(struct nl_sock *, + struct nl_cache *, + change_func_t, + void *); +extern int nl_cache_include(struct nl_cache *, + struct nl_object *, + change_func_t, + void *); +extern void nl_cache_set_arg1(struct nl_cache *, int); +extern void nl_cache_set_arg2(struct nl_cache *, int); + +/* General */ +extern int nl_cache_is_empty(struct nl_cache *); +extern struct nl_object * nl_cache_search(struct nl_cache *, + struct nl_object *); +extern void nl_cache_mark_all(struct nl_cache *); + +/* Dumping */ +extern void nl_cache_dump(struct nl_cache *, + struct nl_dump_params *); +extern void nl_cache_dump_filter(struct nl_cache *, + struct nl_dump_params *, + struct nl_object *); + +/* Iterators */ +extern void nl_cache_foreach(struct nl_cache *, + void (*cb)(struct nl_object *, + void *), + void *arg); +extern void nl_cache_foreach_filter(struct nl_cache *, + struct nl_object *, + void (*cb)(struct + nl_object *, + void *), + void *arg); + +/* --- cache management --- */ + +/* Cache type management */ +extern struct nl_cache_ops * nl_cache_ops_lookup(const char *); +extern struct nl_cache_ops * nl_cache_ops_associate(int, int); +extern struct nl_msgtype * nl_msgtype_lookup(struct nl_cache_ops *, int); +extern void nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *); +extern int nl_cache_mngt_register(struct nl_cache_ops *); +extern int nl_cache_mngt_unregister(struct nl_cache_ops *); + +/* Global cache provisioning/requiring */ +extern void nl_cache_mngt_provide(struct nl_cache *); +extern void nl_cache_mngt_unprovide(struct nl_cache *); +extern struct nl_cache * nl_cache_mngt_require(const char *); + +struct nl_cache_mngr; + +#define NL_AUTO_PROVIDE 1 + +extern int nl_cache_mngr_get_fd(struct nl_cache_mngr *); +extern int nl_cache_mngr_poll(struct nl_cache_mngr *, + int); +extern int nl_cache_mngr_data_ready(struct nl_cache_mngr *); +extern void nl_cache_mngr_free(struct nl_cache_mngr *); + +/* */ +%inline %{ + struct nl_addr *addr_parse(const char *addr, int guess) + { + struct nl_addr *result; + + if (nl_addr_parse(addr, guess, &result) < 0) + return NULL; + + return result; + } +%}; + +extern struct nl_addr *nl_addr_alloc(size_t); +extern struct nl_addr *nl_addr_alloc_attr(struct nlattr *, int); +extern struct nl_addr *nl_addr_build(int, void *, size_t); +extern struct nl_addr *nl_addr_clone(struct nl_addr *); + +extern struct nl_addr *nl_addr_get(struct nl_addr *); +extern void nl_addr_put(struct nl_addr *); +extern int nl_addr_shared(struct nl_addr *); + +extern int nl_addr_cmp(struct nl_addr *, struct nl_addr *); +extern int nl_addr_cmp_prefix(struct nl_addr *, struct nl_addr *); +extern int nl_addr_iszero(struct nl_addr *); +extern int nl_addr_valid(char *, int); +extern int nl_addr_guess_family(struct nl_addr *); +extern int nl_addr_fill_sockaddr(struct nl_addr *, struct sockaddr *, socklen_t *); +extern int nl_addr_info(struct nl_addr *, struct addrinfo **); +extern int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen); + +extern void nl_addr_set_family(struct nl_addr *, int); +extern int nl_addr_get_family(struct nl_addr *); +extern int nl_addr_set_binary_addr(struct nl_addr *, void *, size_t); + +extern void *nl_addr_get_binary_addr(struct nl_addr *); +extern unsigned int nl_addr_get_len(struct nl_addr *); +extern void nl_addr_set_prefixlen(struct nl_addr *, int); +extern unsigned int nl_addr_get_prefixlen(struct nl_addr *); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *nl_af2str(int, char *buf, size_t len); +extern int nl_str2af(const char *); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *nl_addr2str(struct nl_addr *, char *buf, size_t len); diff --git a/python/netlink/core.py b/python/netlink/core.py new file mode 100644 index 0000000..3298e2c --- /dev/null +++ b/python/netlink/core.py @@ -0,0 +1,744 @@ +# +# Netlink interface based on libnl +# +# Copyright (c) 2011 Thomas Graf +# + +"""netlink library based on libnl + +This module provides an interface to netlink sockets + +The module contains the following public classes: + - Socket -- The netlink socket + - Object -- Abstract object (based on struct nl_obect in libnl) used as + base class for all object types which can be put into a Cache + - Cache -- A collection of objects which are derived from the base + class Object. Used for netlink protocols which maintain a list + or tree of objects. + - DumpParams -- + +The following exceptions are defined: + - NetlinkError -- Base exception for all general purpose exceptions raised. + - KernelError -- Raised when the kernel returns an error as response to a + request. + +All other classes or functions in this module are considered implementation +details. +""" +from __future__ import absolute_import + + + +from . import capi +import sys +import socket + +__all__ = [ + 'Message', + 'Socket', + 'DumpParams', + 'Object', + 'Cache', + 'KernelError', + 'NetlinkError', +] + +__version__ = '0.1' + +# netlink protocols +NETLINK_ROUTE = 0 +# NETLINK_UNUSED = 1 +NETLINK_USERSOCK = 2 +NETLINK_FIREWALL = 3 +NETLINK_INET_DIAG = 4 +NETLINK_NFLOG = 5 +NETLINK_XFRM = 6 +NETLINK_SELINUX = 7 +NETLINK_ISCSI = 8 +NETLINK_AUDIT = 9 +NETLINK_FIB_LOOKUP = 10 +NETLINK_CONNECTOR = 11 +NETLINK_NETFILTER = 12 +NETLINK_IP6_FW = 13 +NETLINK_DNRTMSG = 14 +NETLINK_KOBJECT_UEVENT = 15 +NETLINK_GENERIC = 16 +NETLINK_SCSITRANSPORT = 18 +NETLINK_ECRYPTFS = 19 + +NL_DONTPAD = 0 +NL_AUTO_PORT = 0 +NL_AUTO_SEQ = 0 + +NL_DUMP_LINE = 0 +NL_DUMP_DETAILS = 1 +NL_DUMP_STATS = 2 + +NLM_F_REQUEST = 1 +NLM_F_MULTI = 2 +NLM_F_ACK = 4 +NLM_F_ECHO = 8 + +NLM_F_ROOT = 0x100 +NLM_F_MATCH = 0x200 +NLM_F_ATOMIC = 0x400 +NLM_F_DUMP = NLM_F_ROOT | NLM_F_MATCH + +NLM_F_REPLACE = 0x100 +NLM_F_EXCL = 0x200 +NLM_F_CREATE = 0x400 +NLM_F_APPEND = 0x800 + +class NetlinkError(Exception): + def __init__(self, error): + self._error = error + self._msg = capi.nl_geterror(error) + + def __str__(self): + return self._msg + +class KernelError(NetlinkError): + def __str__(self): + return 'Kernel returned: {0}'.format(self._msg) + +class ImmutableError(NetlinkError): + def __init__(self, msg): + self._msg = msg + + def __str__(self): + return 'Immutable attribute: {0}'.format(self._msg) + +class Message(object): + """Netlink message""" + + def __init__(self, size=0): + if size == 0: + self._msg = capi.nlmsg_alloc() + else: + self._msg = capi.nlmsg_alloc_size(size) + + if self._msg is None: + raise Exception('Message allocation returned NULL') + + def __del__(self): + capi.nlmsg_free(self._msg) + + def __len__(self): + return capi.nlmsg_len(nlmsg_hdr(self._msg)) + + @property + def protocol(self): + return capi.nlmsg_get_proto(self._msg) + + @protocol.setter + def protocol(self, value): + capi.nlmsg_set_proto(self._msg, value) + + @property + def maxSize(self): + return capi.nlmsg_get_max_size(self._msg) + + @property + def hdr(self): + return capi.nlmsg_hdr(self._msg) + + @property + def data(self): + return capi.nlmsg_data(self._msg) + + @property + def attrs(self): + return capi.nlmsg_attrdata(self._msg) + + def send(self, sock): + sock.send(self) + +class Socket(object): + """Netlink socket""" + + def __init__(self, cb=None): + if cb is None: + self._sock = capi.nl_socket_alloc() + else: + self._sock = capi.nl_socket_alloc_cb(cb) + + if self._sock is None: + raise Exception('NULL pointer returned while allocating socket') + + def __del__(self): + capi.nl_socket_free(self._sock) + + def __str__(self): + return 'nlsock<{0}>'.format(self.localPort) + + @property + def local_port(self): + return capi.nl_socket_get_local_port(self._sock) + + @local_port.setter + def local_port(self, value): + capi.nl_socket_set_local_port(self._sock, int(value)) + + @property + def peer_port(self): + return capi.nl_socket_get_peer_port(self._sock) + + @peer_port.setter + def peer_port(self, value): + capi.nl_socket_set_peer_port(self._sock, int(value)) + + @property + def peer_groups(self): + return capi.nl_socket_get_peer_groups(self._sock) + + @peer_groups.setter + def peer_groups(self, value): + capi.nl_socket_set_peer_groups(self._sock, value) + + def set_bufsize(self, rx, tx): + capi.nl_socket_set_buffer_size(self._sock, rx, tx) + + def connect(self, proto): + capi.nl_connect(self._sock, proto) + return self + + def disconnect(self): + capi.nl_close(self._sock) + + def sendto(self, buf): + ret = capi.nl_sendto(self._sock, buf, len(buf)) + if ret < 0: + raise Exception('Failed to send') + else: + return ret + +_sockets = {} + +def lookup_socket(protocol): + try: + sock = _sockets[protocol] + except KeyError: + sock = Socket() + sock.connect(protocol) + _sockets[protocol] = sock + + return sock + +class DumpParams(object): + """Dumping parameters""" + + def __init__(self, type_=NL_DUMP_LINE): + self._dp = capi.alloc_dump_params() + if not self._dp: + raise Exception('Unable to allocate struct nl_dump_params') + + self._dp.dp_type = type_ + + def __del__(self): + capi.free_dump_params(self._dp) + + @property + def type(self): + return self._dp.dp_type + + @type.setter + def type(self, value): + self._dp.dp_type = value + + @property + def prefix(self): + return self._dp.dp_prefix + + @prefix.setter + def prefix(self, value): + self._dp.dp_prefix = value + +# underscore this to make sure it is deleted first upon module deletion +_defaultDumpParams = DumpParams(NL_DUMP_LINE) + +class Object(object): + """Cacheable object (base class)""" + + def __init__(self, obj_name, name, obj=None): + self._obj_name = obj_name + self._name = name + self._modules = [] + + if not obj: + obj = capi.object_alloc_name(self._obj_name) + + self._nl_object = obj + + # Create a clone which stores the original state to notice + # modifications + clone_obj = capi.nl_object_clone(self._nl_object) + self._orig = self._obj2type(clone_obj) + + def __del__(self): + if not self._nl_object: + raise ValueError() + + capi.nl_object_put(self._nl_object) + + def __str__(self): + if hasattr(self, 'format'): + return self.format() + else: + return capi.nl_object_dump_buf(self._nl_object, 4096).rstrip() + + def _new_instance(self): + raise NotImplementedError() + + def clone(self): + """Clone object""" + return self._new_instance(capi.nl_object_clone(self._nl_object)) + + def _module_lookup(self, path, constructor=None): + """Lookup object specific module and load it + + Object implementations consisting of multiple types may + offload some type specific code to separate modules which + are loadable on demand, e.g. a VLAN link or a specific + queueing discipline implementation. + + Loads the module `path` and calls the constructor if + supplied or `module`.init() + + The constructor/init function typically assigns a new + object covering the type specific implementation aspects + to the new object, e.g. link.vlan = VLANLink() + """ + try: + __import__(path) + except ImportError: + return + + module = sys.modules[path] + + if constructor: + ret = getattr(module, constructor)(self) + else: + ret = module.init(self) + + if ret: + self._modules.append(ret) + + def _module_brief(self): + ret = '' + + for module in self._modules: + if hasattr(module, 'brief'): + ret += module.brief() + + return ret + + def dump(self, params=None): + """Dump object as human readable text""" + if params is None: + params = _defaultDumpParams + + capi.nl_object_dump(self._nl_object, params._dp) + + + @property + def mark(self): + return bool(capi.nl_object_is_marked(self._nl_object)) + + @mark.setter + def mark(self, value): + if value: + capi.nl_object_mark(self._nl_object) + else: + capi.nl_object_unmark(self._nl_object) + + @property + def shared(self): + return capi.nl_object_shared(self._nl_object) != 0 + + @property + def attrs(self): + attr_list = capi.nl_object_attr_list(self._nl_object, 1024) + return attr_list[0].split() + + @property + def refcnt(self): + return capi.nl_object_get_refcnt(self._nl_object) + + # this method resolves multiple levels of sub types to allow + # accessing properties of subclass/subtypes (e.g. link.vlan.id) + def _resolve(self, attr): + obj = self + l = attr.split('.') + while len(l) > 1: + obj = getattr(obj, l.pop(0)) + return (obj, l.pop(0)) + + def _setattr(self, attr, val): + obj, attr = self._resolve(attr) + return setattr(obj, attr, val) + + def _hasattr(self, attr): + obj, attr = self._resolve(attr) + return hasattr(obj, attr) + +class ObjIterator(object): + def __init__(self, cache, obj): + self._cache = cache + self._nl_object = None + + if not obj: + self._end = 1 + else: + capi.nl_object_get(obj) + self._nl_object = obj + self._first = 1 + self._end = 0 + + def __del__(self): + if self._nl_object: + capi.nl_object_put(self._nl_object) + + def __iter__(self): + return self + + def get_next(self): + return capi.nl_cache_get_next(self._nl_object) + + def next(self): + if self._end: + raise StopIteration() + + if self._first: + ret = self._nl_object + self._first = 0 + else: + ret = self.get_next() + if not ret: + self._end = 1 + raise StopIteration() + + # return ref of previous element and acquire ref of current + # element to have object stay around until we fetched the + # next ptr + capi.nl_object_put(self._nl_object) + capi.nl_object_get(ret) + self._nl_object = ret + + # reference used inside object + capi.nl_object_get(ret) + return self._cache._new_object(ret) + + +class ReverseObjIterator(ObjIterator): + def get_next(self): + return capi.nl_cache_get_prev(self._nl_object) + +class Cache(object): + """Collection of netlink objects""" + def __init__(self): + if self.__class__ is Cache: + raise NotImplementedError() + self.arg1 = None + self.arg2 = None + + def __del__(self): + capi.nl_cache_free(self._nl_cache) + + def __len__(self): + return capi.nl_cache_nitems(self._nl_cache) + + def __iter__(self): + obj = capi.nl_cache_get_first(self._nl_cache) + return ObjIterator(self, obj) + + def __reversed__(self): + obj = capi.nl_cache_get_last(self._nl_cache) + return ReverseObjIterator(self, obj) + + def __contains__(self, item): + obj = capi.nl_cache_search(self._nl_cache, item._nl_object) + if obj is None: + return False + else: + capi.nl_object_put(obj) + return True + + # called by sub classes to allocate type specific caches by name + @staticmethod + def _alloc_cache_name(name): + return capi.alloc_cache_name(name) + + # implemented by sub classes, must return new instasnce of cacheable + # object + @staticmethod + def _new_object(obj): + raise NotImplementedError() + + # implemented by sub classes, must return instance of sub class + def _new_cache(self, cache): + raise NotImplementedError() + + def subset(self, filter_): + """Return new cache containing subset of cache + + Cretes a new cache containing all objects which match the + specified filter. + """ + if not filter_: + raise ValueError() + + c = capi.nl_cache_subset(self._nl_cache, filter_._nl_object) + return self._new_cache(cache=c) + + def dump(self, params=None, filter_=None): + """Dump (print) cache as human readable text""" + if not params: + params = _defaultDumpParams + + if filter_: + filter_ = filter_._nl_object + + capi.nl_cache_dump_filter(self._nl_cache, params._dp, filter_) + + def clear(self): + """Remove all cache entries""" + capi.nl_cache_clear(self._nl_cache) + + # Called by sub classes to set first cache argument + def _set_arg1(self, arg): + self.arg1 = arg + capi.nl_cache_set_arg1(self._nl_cache, arg) + + # Called by sub classes to set second cache argument + def _set_arg2(self, arg): + self.arg2 = arg + capi.nl_cache_set_arg2(self._nl_cache, arg) + + def refill(self, socket=None): + """Clear cache and refill it""" + if socket is None: + socket = lookup_socket(self._protocol) + + capi.nl_cache_refill(socket._sock, self._nl_cache) + return self + + def resync(self, socket=None, cb=None): + """Synchronize cache with content in kernel""" + if socket is None: + socket = lookup_socket(self._protocol) + + capi.nl_cache_resync(socket._sock, self._nl_cache, cb) + + def provide(self): + """Provide this cache to others + + Caches which have been "provided" are made available + to other users (of the same application context) which + "require" it. F.e. a link cache is generally provided + to allow others to translate interface indexes to + link names + """ + + capi.nl_cache_mngt_provide(self._nl_cache) + + def unprovide(self): + """Unprovide this cache + + No longer make the cache available to others. If the cache + has been handed out already, that reference will still + be valid. + """ + capi.nl_cache_mngt_unprovide(self._nl_cache) + +# Cache Manager (Work in Progress) +NL_AUTO_PROVIDE = 1 +class CacheManager(object): + def __init__(self, protocol, flags=None): + + self._sock = Socket() + self._sock.connect(protocol) + + if not flags: + flags = NL_AUTO_PROVIDE + + self._mngr = capi.cache_mngr_alloc(self._sock._sock, protocol, flags) + + def __del__(self): + if self._sock: + self._sock.disconnect() + + if self._mngr: + capi.nl_cache_mngr_free(self._mngr) + + def add(self, name): + capi.cache_mngr_add(self._mngr, name, None, None) + +class AddressFamily(object): + """Address family representation + + af = AddressFamily('inet6') + # raises: + # - ValueError if family name is not known + # - TypeError if invalid type is specified for family + + print af # => 'inet6' (string representation) + print int(af) # => 10 (numeric representation) + print repr(af) # => AddressFamily('inet6') + """ + def __init__(self, family=socket.AF_UNSPEC): + if isinstance(family, str): + family = capi.nl_str2af(family) + if family < 0: + raise ValueError('Unknown family name') + elif not isinstance(family, int): + raise TypeError() + + self._family = family + + def __str__(self): + return capi.nl_af2str(self._family, 32)[0] + + def __int__(self): + return self._family + + def __repr__(self): + return 'AddressFamily({0!r})'.format(str(self)) + + +class AbstractAddress(object): + """Abstract address object + + addr = AbstractAddress('127.0.0.1/8') + print addr # => '127.0.0.1/8' + print addr.prefixlen # => '8' + print addr.family # => 'inet' + print len(addr) # => '4' (32bit ipv4 address) + + a = AbstractAddress('10.0.0.1/24') + b = AbstractAddress('10.0.0.2/24') + print a == b # => False + + + """ + def __init__(self, addr): + self._nl_addr = None + + if isinstance(addr, str): + addr = capi.addr_parse(addr, socket.AF_UNSPEC) + if addr is None: + raise ValueError('Invalid address format') + elif addr: + capi.nl_addr_get(addr) + + self._nl_addr = addr + + def __del__(self): + if self._nl_addr: + capi.nl_addr_put(self._nl_addr) + + def __cmp__(self, other): + if isinstance(other, str): + other = AbstractAddress(other) + + diff = self.prefixlen - other.prefixlen + if diff == 0: + diff = capi.nl_addr_cmp(self._nl_addr, other._nl_addr) + + return diff + + def contains(self, item): + diff = int(self.family) - int(item.family) + if diff: + return False + + if item.prefixlen < self.prefixlen: + return False + + diff = capi.nl_addr_cmp_prefix(self._nl_addr, item._nl_addr) + return diff == 0 + + def __nonzero__(self): + if self._nl_addr: + return not capi.nl_addr_iszero(self._nl_addr) + else: + return False + + def __len__(self): + if self._nl_addr: + return capi.nl_addr_get_len(self._nl_addr) + else: + return 0 + + def __str__(self): + if self._nl_addr: + return capi.nl_addr2str(self._nl_addr, 64)[0] + else: + return 'none' + + @property + def shared(self): + """True if address is shared (multiple users)""" + if self._nl_addr: + return capi.nl_addr_shared(self._nl_addr) != 0 + else: + return False + + @property + def prefixlen(self): + """Length of prefix (number of bits)""" + if self._nl_addr: + return capi.nl_addr_get_prefixlen(self._nl_addr) + else: + return 0 + + @prefixlen.setter + def prefixlen(self, value): + if not self._nl_addr: + raise TypeError() + + capi.nl_addr_set_prefixlen(self._nl_addr, int(value)) + + @property + def family(self): + """Address family""" + f = 0 + if self._nl_addr: + f = capi.nl_addr_get_family(self._nl_addr) + + return AddressFamily(f) + + @family.setter + def family(self, value): + if not self._nl_addr: + raise TypeError() + + if not isinstance(value, AddressFamily): + value = AddressFamily(value) + + capi.nl_addr_set_family(self._nl_addr, int(value)) + + +# keyword: +# type = { int | str } +# immutable = { True | False } +# fmt = func (formatting function) +# title = string + +def nlattr(**kwds): + """netlink object attribute decorator + + decorator used to mark mutable and immutable properties + of netlink objects. All properties marked as such are + regarded to be accessable. + + @property + @netlink.nlattr(type=int) + def my_attr(self): + return self._my_attr + + """ + + def wrap_fn(func): + func.formatinfo = kwds + return func + return wrap_fn diff --git a/python/netlink/fixes.h b/python/netlink/fixes.h new file mode 100644 index 0000000..9a6118b --- /dev/null +++ b/python/netlink/fixes.h @@ -0,0 +1 @@ +#include diff --git a/python/netlink/route/Makefile.am b/python/netlink/route/Makefile.am new file mode 100644 index 0000000..ef714f4 --- /dev/null +++ b/python/netlink/route/Makefile.am @@ -0,0 +1,14 @@ +# -*- Makefile -*- + +EXTRA_DIST = \ + capi.i \ + __init__.py \ + address.py \ + link.py \ + tc.py \ + links/__init__.py \ + links/dummy.py \ + links/inet.py \ + links/vlan.py \ + qdisc/__init__.py \ + qdisc/htb.py diff --git a/python/netlink/route/Makefile.in b/python/netlink/route/Makefile.in new file mode 100644 index 0000000..7ea4d10 --- /dev/null +++ b/python/netlink/route/Makefile.in @@ -0,0 +1,417 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# -*- Makefile -*- +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = python/netlink/route +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/lib/defs.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_CFLAGS = @CHECK_CFLAGS@ +CHECK_LIBS = @CHECK_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FLEX = @FLEX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBNL_VERSION = @LIBNL_VERSION@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_CURRENT = @LT_CURRENT@ +LT_REVISION = @LT_REVISION@ +MAJ_VERSION = @MAJ_VERSION@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIC_VERSION = @MIC_VERSION@ +MIN_VERSION = @MIN_VERSION@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgconfigdir = @pkgconfigdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = \ + capi.i \ + __init__.py \ + address.py \ + link.py \ + tc.py \ + links/__init__.py \ + links/dummy.py \ + links/inet.py \ + links/vlan.py \ + qdisc/__init__.py \ + qdisc/htb.py + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign python/netlink/route/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign python/netlink/route/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/python/netlink/route/__init__.py b/python/netlink/route/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/netlink/route/address.py b/python/netlink/route/address.py new file mode 100644 index 0000000..cab2a97 --- /dev/null +++ b/python/netlink/route/address.py @@ -0,0 +1,367 @@ +# +# Copyright (c) 2011 Thomas Graf +# + +"""Module providing access to network addresses +""" + +from __future__ import absolute_import + + +__version__ = '1.0' +__all__ = [ + 'AddressCache', + 'Address'] + +import datetime +from .. import core as netlink +from . import capi as capi +from . import link as Link +from .. import util as util + +class AddressCache(netlink.Cache): + """Cache containing network addresses""" + + def __init__(self, cache=None): + if not cache: + cache = self._alloc_cache_name('route/addr') + + self._protocol = netlink.NETLINK_ROUTE + self._nl_cache = cache + + def __getitem__(self, key): + # Using ifindex=0 here implies that the local address itself + # is unique, otherwise the first occurence is returned. + return self.lookup(0, key) + + def lookup(self, ifindex, local): + if type(local) is str: + local = netlink.AbstractAddress(local) + + addr = capi.rtnl_addr_get(self._nl_cache, ifindex, + local._nl_addr) + if addr is None: + raise KeyError() + + return Address._from_capi(addr) + + @staticmethod + def _new_object(obj): + return Address(obj) + + @staticmethod + def _new_cache(cache): + return AddressCache(cache=cache) + +class Address(netlink.Object): + """Network address""" + + def __init__(self, obj=None): + netlink.Object.__init__(self, 'route/addr', 'address', obj) + self._rtnl_addr = self._obj2type(self._nl_object) + + @classmethod + def _from_capi(cls, obj): + return cls(capi.addr2obj(obj)) + + @staticmethod + def _obj2type(obj): + return capi.obj2addr(obj) + + def __cmp__(self, other): + # sort by: + # 1. network link + # 2. address family + # 3. local address (including prefixlen) + diff = self.ifindex - other.ifindex + + if diff == 0: + diff = self.family - other.family + if diff == 0: + diff = capi.nl_addr_cmp(self.local, other.local) + + return diff + + @staticmethod + def _new_instance(obj): + return Address(obj) + + @property + @netlink.nlattr(type=int, immutable=True, fmt=util.num) + def ifindex(self): + """interface index""" + return capi.rtnl_addr_get_ifindex(self._rtnl_addr) + + @ifindex.setter + def ifindex(self, value): + link = Link.resolve(value) + if not link: + raise ValueError() + + self.link = link + + @property + @netlink.nlattr(type=str, fmt=util.string) + def link(self): + link = capi.rtnl_addr_get_link(self._rtnl_addr) + if not link: + return None + + return Link.Link.from_capi(link) + + @link.setter + def link(self, value): + if type(value) is str: + try: + value = Link.resolve(value) + except KeyError: + raise ValueError() + + capi.rtnl_addr_set_link(self._rtnl_addr, value._rtnl_link) + + # ifindex is immutable but we assume that if _orig does not + # have an ifindex specified, it was meant to be given here + if capi.rtnl_addr_get_ifindex(self._orig) == 0: + capi.rtnl_addr_set_ifindex(self._orig, value.ifindex) + + @property + @netlink.nlattr(type=str, fmt=util.string) + def label(self): + """address label""" + return capi.rtnl_addr_get_label(self._rtnl_addr) + + @label.setter + def label(self, value): + capi.rtnl_addr_set_label(self._rtnl_addr, value) + + @property + @netlink.nlattr(type=str, fmt=util.string) + def flags(self): + """Flags + + Setting this property will *Not* reset flags to value you supply in + + Examples: + addr.flags = '+xxx' # add xxx flag + addr.flags = 'xxx' # exactly the same + addr.flags = '-xxx' # remove xxx flag + addr.flags = [ '+xxx', '-yyy' ] # list operation + """ + flags = capi.rtnl_addr_get_flags(self._rtnl_addr) + return capi.rtnl_addr_flags2str(flags, 256)[0].split(',') + + def _set_flag(self, flag): + if flag.startswith('-'): + i = capi.rtnl_addr_str2flags(flag[1:]) + capi.rtnl_addr_unset_flags(self._rtnl_addr, i) + elif flag.startswith('+'): + i = capi.rtnl_addr_str2flags(flag[1:]) + capi.rtnl_addr_set_flags(self._rtnl_addr, i) + else: + i = capi.rtnl_addr_str2flags(flag) + capi.rtnl_addr_set_flags(self._rtnl_addr, i) + + @flags.setter + def flags(self, value): + if type(value) is list: + for flag in value: + self._set_flag(flag) + else: + self._set_flag(value) + + @property + @netlink.nlattr(type=int, immutable=True, fmt=util.num) + def family(self): + """Address family""" + fam = capi.rtnl_addr_get_family(self._rtnl_addr) + return netlink.AddressFamily(fam) + + @family.setter + def family(self, value): + if not isinstance(value, netlink.AddressFamily): + value = netlink.AddressFamily(value) + + capi.rtnl_addr_set_family(self._rtnl_addr, int(value)) + + @property + @netlink.nlattr(type=int, fmt=util.num) + def scope(self): + """Address scope""" + scope = capi.rtnl_addr_get_scope(self._rtnl_addr) + return capi.rtnl_scope2str(scope, 32)[0] + + @scope.setter + def scope(self, value): + if type(value) is str: + value = capi.rtnl_str2scope(value) + capi.rtnl_addr_set_scope(self._rtnl_addr, value) + + @property + @netlink.nlattr(type=str, immutable=True, fmt=util.addr) + def local(self): + """Local address""" + a = capi.rtnl_addr_get_local(self._rtnl_addr) + return netlink.AbstractAddress(a) + + @local.setter + def local(self, value): + a = netlink.AbstractAddress(value) + capi.rtnl_addr_set_local(self._rtnl_addr, a._nl_addr) + + # local is immutable but we assume that if _orig does not + # have a local address specified, it was meant to be given here + if capi.rtnl_addr_get_local(self._orig) is None: + capi.rtnl_addr_set_local(self._orig, a._nl_addr) + + @property + @netlink.nlattr(type=str, fmt=util.addr) + def peer(self): + """Peer address""" + a = capi.rtnl_addr_get_peer(self._rtnl_addr) + return netlink.AbstractAddress(a) + + @peer.setter + def peer(self, value): + a = netlink.AbstractAddress(value) + capi.rtnl_addr_set_peer(self._rtnl_addr, a._nl_addr) + + @property + @netlink.nlattr(type=str, fmt=util.addr) + def broadcast(self): + """Broadcast address""" + a = capi.rtnl_addr_get_broadcast(self._rtnl_addr) + return netlink.AbstractAddress(a) + + @broadcast.setter + def broadcast(self, value): + a = netlink.AbstractAddress(value) + capi.rtnl_addr_set_broadcast(self._rtnl_addr, a._nl_addr) + + @property + @netlink.nlattr(type=str, fmt=util.addr) + def multicast(self): + """multicast address""" + a = capi.rtnl_addr_get_multicast(self._rtnl_addr) + return netlink.AbstractAddress(a) + + @multicast.setter + def multicast(self, value): + try: + a = netlink.AbstractAddress(value) + except ValueError as err: + raise AttributeError('multicast', err) + + capi.rtnl_addr_set_multicast(self._rtnl_addr, a._nl_addr) + + @property + @netlink.nlattr(type=str, fmt=util.addr) + def anycast(self): + """anycast address""" + a = capi.rtnl_addr_get_anycast(self._rtnl_addr) + return netlink.AbstractAddress(a) + + @anycast.setter + def anycast(self, value): + a = netlink.AbstractAddress(value) + capi.rtnl_addr_set_anycast(self._rtnl_addr, a._nl_addr) + + @property + @netlink.nlattr(type=int, immutable=True, fmt=util.num) + def valid_lifetime(self): + """Valid lifetime""" + msecs = capi.rtnl_addr_get_valid_lifetime(self._rtnl_addr) + if msecs == 0xFFFFFFFF: + return None + else: + return datetime.timedelta(seconds=msecs) + + @valid_lifetime.setter + def valid_lifetime(self, value): + capi.rtnl_addr_set_valid_lifetime(self._rtnl_addr, int(value)) + + @property + @netlink.nlattr(type=int, immutable=True, fmt=util.num) + def preferred_lifetime(self): + """Preferred lifetime""" + msecs = capi.rtnl_addr_get_preferred_lifetime(self._rtnl_addr) + if msecs == 0xFFFFFFFF: + return None + else: + return datetime.timedelta(seconds=msecs) + + @preferred_lifetime.setter + def preferred_lifetime(self, value): + capi.rtnl_addr_set_preferred_lifetime(self._rtnl_addr, int(value)) + + @property + @netlink.nlattr(type=int, immutable=True, fmt=util.num) + def create_time(self): + """Creation time""" + hsec = capi.rtnl_addr_get_create_time(self._rtnl_addr) + return datetime.timedelta(milliseconds=10*hsec) + + @property + @netlink.nlattr(type=int, immutable=True, fmt=util.num) + def last_update(self): + """Last update""" + hsec = capi.rtnl_addr_get_last_update_time(self._rtnl_addr) + return datetime.timedelta(milliseconds=10*hsec) + + def add(self, socket=None, flags=None): + if not socket: + socket = netlink.lookup_socket(netlink.NETLINK_ROUTE) + + if not flags: + flags = netlink.NLM_F_CREATE + + ret = capi.rtnl_addr_add(socket._sock, self._rtnl_addr, flags) + if ret < 0: + raise netlink.KernelError(ret) + + def delete(self, socket, flags=0): + """Attempt to delete this address in the kernel""" + ret = capi.rtnl_addr_delete(socket._sock, self._rtnl_addr, flags) + if ret < 0: + raise netlink.KernelError(ret) + + ################################################################### + # private properties + # + # Used for formatting output. USE AT OWN RISK + @property + def _flags(self): + return ','.join(self.flags) + + def format(self, details=False, stats=False, nodev=False, indent=''): + """Return address as formatted text""" + fmt = util.MyFormatter(self, indent) + + buf = fmt.format('{a|local!b}') + + if not nodev: + buf += fmt.format(' {a|ifindex}') + + buf += fmt.format(' {a|scope}') + + if self.label: + buf += fmt.format(' "{a|label}"') + + buf += fmt.format(' <{a|_flags}>') + + if details: + buf += fmt.nl('\t{t|broadcast} {t|multicast}') \ + + fmt.nl('\t{t|peer} {t|anycast}') + + if self.valid_lifetime: + buf += fmt.nl('\t{s|valid-lifetime!k} '\ + '{a|valid_lifetime}') + + if self.preferred_lifetime: + buf += fmt.nl('\t{s|preferred-lifetime!k} '\ + '{a|preferred_lifetime}') + + if stats and (self.create_time or self.last_update): + buf += self.nl('\t{s|created!k} {a|create_time}'\ + ' {s|last-updated!k} {a|last_update}') + + return buf diff --git a/python/netlink/route/capi.i b/python/netlink/route/capi.i new file mode 100644 index 0000000..8ac114b --- /dev/null +++ b/python/netlink/route/capi.i @@ -0,0 +1,396 @@ +%module capi +%{ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +%} + +%include +%include + +%inline %{ + struct nl_object *link2obj(struct rtnl_link *link) + { + return OBJ_CAST(link); + } + + struct rtnl_link *obj2link(struct nl_object *obj) + { + return (struct rtnl_link *) obj; + } + + struct rtnl_link *get_from_kernel(struct nl_sock *sk, int ifindex, const char *name) + { + struct rtnl_link *link; + if (rtnl_link_get_kernel(sk, ifindex, name, &link) < 0) + return NULL; + return link; + } + + uint32_t inet_get_conf(struct rtnl_link *link, const unsigned int id) + { + uint32_t result; + + if (rtnl_link_inet_get_conf(link, id, &result) < 0) + return 0; + + return result; + } +%}; + +extern struct nl_object *link2obj(struct rtnl_link *); +extern struct rtnl_link *obj2link(struct nl_object *); + +/* */ + +%cstring_output_maxsize(char *buf, size_t len) +extern char * rtnl_scope2str(int, char *buf, size_t len); +extern int rtnl_str2scope(const char *); + +/* */ + +extern struct rtnl_link *rtnl_link_alloc(void); + +extern struct rtnl_link *rtnl_link_get(struct nl_cache *, int); +extern struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *, const char *); + +extern int rtnl_link_build_add_request(struct rtnl_link *, int, struct nl_msg **); +extern int rtnl_link_add(struct nl_sock *, struct rtnl_link *, int); +extern int rtnl_link_build_change_request(struct rtnl_link *, struct rtnl_link *, int, struct nl_msg **); +extern int rtnl_link_change(struct nl_sock *, struct rtnl_link *, struct rtnl_link *, int); + +extern int rtnl_link_build_delete_request(const struct rtnl_link *, struct nl_msg **); +extern int rtnl_link_delete(struct nl_sock *, const struct rtnl_link *); +extern int rtnl_link_build_get_request(int, const char *, struct nl_msg **); + +extern char *rtnl_link_stat2str(int, char *, size_t); +extern int rtnl_link_str2stat(const char *); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *rtnl_link_flags2str(int, char *buf, size_t len); +extern int rtnl_link_str2flags(const char *); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *rtnl_link_operstate2str(uint8_t, char *buf, size_t len); +extern int rtnl_link_str2operstate(const char *); + +%cstring_output_maxsize(char *buf, size_t len) +extern char *rtnl_link_mode2str(uint8_t, char *buf, size_t len); +extern int rtnl_link_str2mode(const char *); + +extern void rtnl_link_set_qdisc(struct rtnl_link *, const char *); +extern char *rtnl_link_get_qdisc(struct rtnl_link *); + +extern void rtnl_link_set_name(struct rtnl_link *, const char *); +extern char *rtnl_link_get_name(struct rtnl_link *); + +extern void rtnl_link_set_flags(struct rtnl_link *, unsigned int); +extern void rtnl_link_unset_flags(struct rtnl_link *, unsigned int); +extern unsigned int rtnl_link_get_flags(struct rtnl_link *); + +extern void rtnl_link_set_mtu(struct rtnl_link *, unsigned int); +extern unsigned int rtnl_link_get_mtu(struct rtnl_link *); + +extern void rtnl_link_set_txqlen(struct rtnl_link *, unsigned int); +extern unsigned int rtnl_link_get_txqlen(struct rtnl_link *); + +extern void rtnl_link_set_ifindex(struct rtnl_link *, int); +extern int rtnl_link_get_ifindex(struct rtnl_link *); + +extern void rtnl_link_set_family(struct rtnl_link *, int); +extern int rtnl_link_get_family(struct rtnl_link *); + +extern void rtnl_link_set_arptype(struct rtnl_link *, unsigned int); +extern unsigned int rtnl_link_get_arptype(struct rtnl_link *); + +extern void rtnl_link_set_addr(struct rtnl_link *, struct nl_addr *); +extern struct nl_addr *rtnl_link_get_addr(struct rtnl_link *); + +extern void rtnl_link_set_broadcast(struct rtnl_link *, struct nl_addr *); +extern struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *); + +extern void rtnl_link_set_link(struct rtnl_link *, int); +extern int rtnl_link_get_link(struct rtnl_link *); + +extern void rtnl_link_set_master(struct rtnl_link *, int); +extern int rtnl_link_get_master(struct rtnl_link *); + +extern void rtnl_link_set_operstate(struct rtnl_link *, uint8_t); +extern uint8_t rtnl_link_get_operstate(struct rtnl_link *); + +extern void rtnl_link_set_linkmode(struct rtnl_link *, uint8_t); +extern uint8_t rtnl_link_get_linkmode(struct rtnl_link *); + +extern const char *rtnl_link_get_ifalias(struct rtnl_link *); +extern void rtnl_link_set_ifalias(struct rtnl_link *, const char *); + +extern int rtnl_link_get_num_vf(struct rtnl_link *, uint32_t *); + +extern uint64_t rtnl_link_get_stat(struct rtnl_link *, int); +extern int rtnl_link_set_stat(struct rtnl_link *, const unsigned int, const uint64_t); + +extern int rtnl_link_set_type(struct rtnl_link *, const char *); +extern char *rtnl_link_get_type(struct rtnl_link *); + +/* */ + +struct vlan_map +{ + uint32_t vm_from; + uint32_t vm_to; +}; + +#define VLAN_PRIO_MAX 7 + +%cstring_output_maxsize(char *buf, size_t len) +extern char *rtnl_link_vlan_flags2str(int, char *buf, size_t len); +extern int rtnl_link_vlan_str2flags(const char *); + +extern int rtnl_link_vlan_set_id(struct rtnl_link *, int); +extern int rtnl_link_vlan_get_id(struct rtnl_link *); + +extern int rtnl_link_vlan_set_flags(struct rtnl_link *, unsigned int); +extern int rtnl_link_vlan_unset_flags(struct rtnl_link *, unsigned int); +extern unsigned int rtnl_link_vlan_get_flags(struct rtnl_link *); + +extern int rtnl_link_vlan_set_ingress_map(struct rtnl_link *, int, uint32_t); +extern uint32_t *rtnl_link_vlan_get_ingress_map(struct rtnl_link *); + +extern int rtnl_link_vlan_set_egress_map(struct rtnl_link *, uint32_t, int); +extern struct vlan_map *rtnl_link_vlan_get_egress_map(struct rtnl_link *, int *); + +/* */ +%cstring_output_maxsize(char *buf, size_t len) +extern const char *rtnl_link_inet_devconf2str(int, char *buf, size_t len); +extern unsigned int rtnl_link_inet_str2devconf(const char *); + +extern int rtnl_link_inet_set_conf(struct rtnl_link *, const unsigned int, uint32_t); + +/* */ + +%inline %{ + uint32_t tc_str2handle(const char *name) + { + uint32_t result; + + if (rtnl_tc_str2handle(name, &result) < 0) + return 0; + + return result; + } +%}; + +extern void rtnl_tc_set_ifindex(struct rtnl_tc *, int); +extern int rtnl_tc_get_ifindex(struct rtnl_tc *); +extern void rtnl_tc_set_link(struct rtnl_tc *, struct rtnl_link *); +extern struct rtnl_link *rtnl_tc_get_link(struct rtnl_tc *); +extern void rtnl_tc_set_mtu(struct rtnl_tc *, uint32_t); +extern uint32_t rtnl_tc_get_mtu(struct rtnl_tc *); +extern void rtnl_tc_set_mpu(struct rtnl_tc *, uint32_t); +extern uint32_t rtnl_tc_get_mpu(struct rtnl_tc *); +extern void rtnl_tc_set_overhead(struct rtnl_tc *, uint32_t); +extern uint32_t rtnl_tc_get_overhead(struct rtnl_tc *); +extern void rtnl_tc_set_linktype(struct rtnl_tc *, uint32_t); +extern uint32_t rtnl_tc_get_linktype(struct rtnl_tc *); +extern void rtnl_tc_set_handle(struct rtnl_tc *, uint32_t); +extern uint32_t rtnl_tc_get_handle(struct rtnl_tc *); +extern void rtnl_tc_set_parent(struct rtnl_tc *, uint32_t); +extern uint32_t rtnl_tc_get_parent(struct rtnl_tc *); +extern int rtnl_tc_set_kind(struct rtnl_tc *, const char *); +extern char * rtnl_tc_get_kind(struct rtnl_tc *); +extern uint64_t rtnl_tc_get_stat(struct rtnl_tc *, enum rtnl_tc_stat); + +extern int rtnl_tc_calc_txtime(int, int); +extern int rtnl_tc_calc_bufsize(int, int); +extern int rtnl_tc_calc_cell_log(int); + +extern int rtnl_tc_read_classid_file(void); +%cstring_output_maxsize(char *buf, size_t len) +extern char * rtnl_tc_handle2str(uint32_t, char *buf, size_t len); +extern int rtnl_classid_generate(const char *, uint32_t *, uint32_t); + +/* */ + +%inline %{ + struct nl_object *qdisc2obj(struct rtnl_qdisc *qdisc) + { + return OBJ_CAST(qdisc); + } + + struct rtnl_qdisc *obj2qdisc(struct nl_object *obj) + { + return (struct rtnl_qdisc *) obj; + } + + struct nl_object *class2obj(struct rtnl_class *cl) + { + return OBJ_CAST(cl); + } + + struct rtnl_class *obj2class(struct nl_object *obj) + { + return (struct rtnl_class *) obj; + } + + struct nl_object *cls2obj(struct rtnl_cls *cls) + { + return OBJ_CAST(cls); + } + + struct rtnl_cls *obj2cls(struct nl_object *obj) + { + return (struct rtnl_cls *) obj; + } + + struct rtnl_tc *obj2tc(struct nl_object *obj) + { + return TC_CAST(obj); + } +%}; +extern struct rtnl_qdisc * + rtnl_qdisc_alloc(void); + +extern struct rtnl_qdisc * + rtnl_qdisc_get(struct nl_cache *, int, uint32_t); + +extern struct rtnl_qdisc * + rtnl_qdisc_get_by_parent(struct nl_cache *, int, uint32_t); + +extern int rtnl_qdisc_build_add_request(struct rtnl_qdisc *, int, + struct nl_msg **); +extern int rtnl_qdisc_add(struct nl_sock *, struct rtnl_qdisc *, int); + +extern int rtnl_qdisc_build_update_request(struct rtnl_qdisc *, + struct rtnl_qdisc *, + int, struct nl_msg **); + +extern int rtnl_qdisc_update(struct nl_sock *, struct rtnl_qdisc *, + struct rtnl_qdisc *, int); + +extern int rtnl_qdisc_build_delete_request(struct rtnl_qdisc *, + struct nl_msg **); +extern int rtnl_qdisc_delete(struct nl_sock *, struct rtnl_qdisc *); + +/* */ + +extern struct rtnl_cls *rtnl_cls_alloc(void); +extern void rtnl_cls_put(struct rtnl_cls *); + +extern int rtnl_cls_add(struct nl_sock *, struct rtnl_cls *, int); + +extern int rtnl_cls_delete(struct nl_sock *, struct rtnl_cls *, + int); + +extern void rtnl_cls_set_prio(struct rtnl_cls *, uint16_t); +extern uint16_t rtnl_cls_get_prio(struct rtnl_cls *); + +extern void rtnl_cls_set_protocol(struct rtnl_cls *, uint16_t); +extern uint16_t rtnl_cls_get_protocol(struct rtnl_cls *); + +/* */ + +extern uint32_t rtnl_htb_get_rate2quantum(struct rtnl_qdisc *); +extern int rtnl_htb_set_rate2quantum(struct rtnl_qdisc *, uint32_t); +extern uint32_t rtnl_htb_get_defcls(struct rtnl_qdisc *); +extern int rtnl_htb_set_defcls(struct rtnl_qdisc *, uint32_t); + +extern uint32_t rtnl_htb_get_prio(struct rtnl_class *); +extern int rtnl_htb_set_prio(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_rate(struct rtnl_class *); +extern int rtnl_htb_set_rate(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_ceil(struct rtnl_class *); +extern int rtnl_htb_set_ceil(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *); +extern int rtnl_htb_set_rbuffer(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_cbuffer(struct rtnl_class *); +extern int rtnl_htb_set_cbuffer(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_quantum(struct rtnl_class *); +extern int rtnl_htb_set_quantum(struct rtnl_class *, uint32_t); +extern int rtnl_htb_get_level(struct rtnl_class *); + +/* */ + +%inline %{ + struct nl_object *addr2obj(struct rtnl_addr *addr) + { + return OBJ_CAST(addr); + } + + struct rtnl_addr *obj2addr(struct nl_object *obj) + { + return (struct rtnl_addr *) obj; + } +%}; + +extern struct rtnl_addr *rtnl_addr_alloc(void); + +extern struct rtnl_addr * + rtnl_addr_get(struct nl_cache *, int, struct nl_addr *); + +extern int rtnl_addr_build_add_request(struct rtnl_addr *, int, + struct nl_msg **); +extern int rtnl_addr_add(struct nl_sock *, struct rtnl_addr *, int); + +extern int rtnl_addr_build_delete_request(struct rtnl_addr *, int, + struct nl_msg **); +extern int rtnl_addr_delete(struct nl_sock *, + struct rtnl_addr *, int); + +%cstring_output_maxsize(char *buf, size_t len) +extern char * rtnl_addr_flags2str(int, char *buf, size_t len); +extern int rtnl_addr_str2flags(const char *); + +extern int rtnl_addr_set_label(struct rtnl_addr *, const char *); +extern char * rtnl_addr_get_label(struct rtnl_addr *); + +extern void rtnl_addr_set_ifindex(struct rtnl_addr *, int); +extern int rtnl_addr_get_ifindex(struct rtnl_addr *); + +extern void rtnl_addr_set_link(struct rtnl_addr *, struct rtnl_link *); +extern struct rtnl_link * + rtnl_addr_get_link(struct rtnl_addr *); +extern void rtnl_addr_set_family(struct rtnl_addr *, int); +extern int rtnl_addr_get_family(struct rtnl_addr *); + +extern void rtnl_addr_set_prefixlen(struct rtnl_addr *, int); +extern int rtnl_addr_get_prefixlen(struct rtnl_addr *); + +extern void rtnl_addr_set_scope(struct rtnl_addr *, int); +extern int rtnl_addr_get_scope(struct rtnl_addr *); + +extern void rtnl_addr_set_flags(struct rtnl_addr *, unsigned int); +extern void rtnl_addr_unset_flags(struct rtnl_addr *, unsigned int); +extern unsigned int rtnl_addr_get_flags(struct rtnl_addr *); + +extern int rtnl_addr_set_local(struct rtnl_addr *, + struct nl_addr *); +extern struct nl_addr *rtnl_addr_get_local(struct rtnl_addr *); + +extern int rtnl_addr_set_peer(struct rtnl_addr *, struct nl_addr *); +extern struct nl_addr *rtnl_addr_get_peer(struct rtnl_addr *); + +extern int rtnl_addr_set_broadcast(struct rtnl_addr *, struct nl_addr *); +extern struct nl_addr *rtnl_addr_get_broadcast(struct rtnl_addr *); + +extern int rtnl_addr_set_multicast(struct rtnl_addr *, struct nl_addr *); +extern struct nl_addr *rtnl_addr_get_multicast(struct rtnl_addr *); + +extern int rtnl_addr_set_anycast(struct rtnl_addr *, struct nl_addr *); +extern struct nl_addr *rtnl_addr_get_anycast(struct rtnl_addr *); + +extern uint32_t rtnl_addr_get_valid_lifetime(struct rtnl_addr *); +extern void rtnl_addr_set_valid_lifetime(struct rtnl_addr *, uint32_t); +extern uint32_t rtnl_addr_get_preferred_lifetime(struct rtnl_addr *); +extern void rtnl_addr_set_preferred_lifetime(struct rtnl_addr *, uint32_t); +extern uint32_t rtnl_addr_get_create_time(struct rtnl_addr *); +extern uint32_t rtnl_addr_get_last_update_time(struct rtnl_addr *); diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py new file mode 100644 index 0000000..36d0e9d --- /dev/null +++ b/python/netlink/route/link.py @@ -0,0 +1,539 @@ +# +# Copyright (c) 2011 Thomas Graf +# + +"""Module providing access to network links + +This module provides an interface to view configured network links, +modify them and to add and delete virtual network links. + +The following is a basic example: + import netlink.core as netlink + import netlink.route.link as link + + sock = netlink.Socket() + sock.connect(netlink.NETLINK_ROUTE) + + cache = link.LinkCache() # create new empty link cache + cache.refill(sock) # fill cache with all configured links + eth0 = cache['eth0'] # lookup link "eth0" + print eth0 # print basic configuration + +The module contains the following public classes: + + - Link -- Represents a network link. Instances can be created directly + via the constructor (empty link objects) or via the refill() + method of a LinkCache. + - LinkCache -- Derived from netlink.Cache, holds any number of + network links (Link instances). Main purpose is to keep + a local list of all network links configured in the + kernel. + +The following public functions exist: + - get_from_kernel(socket, name) + +""" + +from __future__ import absolute_import + +__version__ = '0.1' +__all__ = [ + 'LinkCache', + 'Link', + 'get_from_kernel', +] + +import socket +from .. import core as netlink +from .. import capi as core_capi +from . import capi as capi +from .links import inet as inet +from .. import util as util + +# Link statistics definitions +RX_PACKETS = 0 +TX_PACKETS = 1 +RX_BYTES = 2 +TX_BYTES = 3 +RX_ERRORS = 4 +TX_ERRORS = 5 +RX_DROPPED = 6 +TX_DROPPED = 7 +RX_COMPRESSED = 8 +TX_COMPRESSED = 9 +RX_FIFO_ERR = 10 +TX_FIFO_ERR = 11 +RX_LEN_ERR = 12 +RX_OVER_ERR = 13 +RX_CRC_ERR = 14 +RX_FRAME_ERR = 15 +RX_MISSED_ERR = 16 +TX_ABORT_ERR = 17 +TX_CARRIER_ERR = 18 +TX_HBEAT_ERR = 19 +TX_WIN_ERR = 20 +COLLISIONS = 21 +MULTICAST = 22 +IP6_INPKTS = 23 +IP6_INHDRERRORS = 24 +IP6_INTOOBIGERRORS = 25 +IP6_INNOROUTES = 26 +IP6_INADDRERRORS = 27 +IP6_INUNKNOWNPROTOS = 28 +IP6_INTRUNCATEDPKTS = 29 +IP6_INDISCARDS = 30 +IP6_INDELIVERS = 31 +IP6_OUTFORWDATAGRAMS = 32 +IP6_OUTPKTS = 33 +IP6_OUTDISCARDS = 34 +IP6_OUTNOROUTES = 35 +IP6_REASMTIMEOUT = 36 +IP6_REASMREQDS = 37 +IP6_REASMOKS = 38 +IP6_REASMFAILS = 39 +IP6_FRAGOKS = 40 +IP6_FRAGFAILS = 41 +IP6_FRAGCREATES = 42 +IP6_INMCASTPKTS = 43 +IP6_OUTMCASTPKTS = 44 +IP6_INBCASTPKTS = 45 +IP6_OUTBCASTPKTS = 46 +IP6_INOCTETS = 47 +IP6_OUTOCTETS = 48 +IP6_INMCASTOCTETS = 49 +IP6_OUTMCASTOCTETS = 50 +IP6_INBCASTOCTETS = 51 +IP6_OUTBCASTOCTETS = 52 +ICMP6_INMSGS = 53 +ICMP6_INERRORS = 54 +ICMP6_OUTMSGS = 55 +ICMP6_OUTERRORS = 56 + +class LinkCache(netlink.Cache): + """Cache of network links""" + + def __init__(self, family=socket.AF_UNSPEC, cache=None): + if not cache: + cache = self._alloc_cache_name('route/link') + + self._info_module = None + self._protocol = netlink.NETLINK_ROUTE + self._nl_cache = cache + self._set_arg1(family) + + def __getitem__(self, key): + if type(key) is int: + link = capi.rtnl_link_get(self._nl_cache, key) + else: + link = capi.rtnl_link_get_by_name(self._nl_cache, key) + + if link is None: + raise KeyError() + else: + return Link.from_capi(link) + + @staticmethod + def _new_object(obj): + return Link(obj) + + def _new_cache(self, cache): + return LinkCache(family=self.arg1, cache=cache) + +class Link(netlink.Object): + """Network link""" + + def __init__(self, obj=None): + netlink.Object.__init__(self, 'route/link', 'link', obj) + self._rtnl_link = self._obj2type(self._nl_object) + + if self.type: + self._module_lookup('netlink.route.links.' + self.type) + + self.inet = inet.InetLink(self) + self.af = {'inet' : self.inet } + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, tb): + if exc_type is None: + self.change() + else: + return false + + @classmethod + def from_capi(cls, obj): + return cls(capi.link2obj(obj)) + + @staticmethod + def _obj2type(obj): + return capi.obj2link(obj) + + def __cmp__(self, other): + return self.ifindex - other.ifindex + + @staticmethod + def _new_instance(obj): + if not obj: + raise ValueError() + + return Link(obj) + + @property + @netlink.nlattr(type=int, immutable=True, fmt=util.num) + def ifindex(self): + """interface index""" + return capi.rtnl_link_get_ifindex(self._rtnl_link) + + @ifindex.setter + def ifindex(self, value): + capi.rtnl_link_set_ifindex(self._rtnl_link, int(value)) + + # ifindex is immutable but we assume that if _orig does not + # have an ifindex specified, it was meant to be given here + if capi.rtnl_link_get_ifindex(self._orig) == 0: + capi.rtnl_link_set_ifindex(self._orig, int(value)) + + @property + @netlink.nlattr(type=str, fmt=util.bold) + def name(self): + """Name of link""" + return capi.rtnl_link_get_name(self._rtnl_link) + + @name.setter + def name(self, value): + capi.rtnl_link_set_name(self._rtnl_link, value) + + # name is the secondary identifier, if _orig does not have + # the name specified yet, assume it was meant to be specified + # here. ifindex will always take priority, therefore if ifindex + # is specified as well, this will be ignored automatically. + if capi.rtnl_link_get_name(self._orig) is None: + capi.rtnl_link_set_name(self._orig, value) + + @property + @netlink.nlattr(type=str, fmt=util.string) + def flags(self): + """Flags + Setting this property will *Not* reset flags to value you supply in + Examples: + link.flags = '+xxx' # add xxx flag + link.flags = 'xxx' # exactly the same + link.flags = '-xxx' # remove xxx flag + link.flags = [ '+xxx', '-yyy' ] # list operation + """ + flags = capi.rtnl_link_get_flags(self._rtnl_link) + return capi.rtnl_link_flags2str(flags, 256)[0].split(',') + + def _set_flag(self, flag): + if flag.startswith('-'): + i = capi.rtnl_link_str2flags(flag[1:]) + capi.rtnl_link_unset_flags(self._rtnl_link, i) + elif flag.startswith('+'): + i = capi.rtnl_link_str2flags(flag[1:]) + capi.rtnl_link_set_flags(self._rtnl_link, i) + else: + i = capi.rtnl_link_str2flags(flag) + capi.rtnl_link_set_flags(self._rtnl_link, i) + + @flags.setter + def flags(self, value): + if not (type(value) is str): + for flag in value: + self._set_flag(flag) + else: + self._set_flag(value) + + @property + @netlink.nlattr(type=int, fmt=util.num) + def mtu(self): + """Maximum Transmission Unit""" + return capi.rtnl_link_get_mtu(self._rtnl_link) + + @mtu.setter + def mtu(self, value): + capi.rtnl_link_set_mtu(self._rtnl_link, int(value)) + + @property + @netlink.nlattr(type=int, immutable=True, fmt=util.num) + def family(self): + """Address family""" + return capi.rtnl_link_get_family(self._rtnl_link) + + @family.setter + def family(self, value): + capi.rtnl_link_set_family(self._rtnl_link, value) + + @property + @netlink.nlattr(type=str, fmt=util.addr) + def address(self): + """Hardware address (MAC address)""" + a = capi.rtnl_link_get_addr(self._rtnl_link) + return netlink.AbstractAddress(a) + + @address.setter + def address(self, value): + capi.rtnl_link_set_addr(self._rtnl_link, value._addr) + + @property + @netlink.nlattr(type=str, fmt=util.addr) + def broadcast(self): + """Hardware broadcast address""" + a = capi.rtnl_link_get_broadcast(self._rtnl_link) + return netlink.AbstractAddress(a) + + @broadcast.setter + def broadcast(self, value): + capi.rtnl_link_set_broadcast(self._rtnl_link, value._addr) + + @property + @netlink.nlattr(type=str, immutable=True, fmt=util.string) + def qdisc(self): + """Name of qdisc (cannot be changed)""" + return capi.rtnl_link_get_qdisc(self._rtnl_link) + + @qdisc.setter + def qdisc(self, value): + capi.rtnl_link_set_qdisc(self._rtnl_link, value) + + @property + @netlink.nlattr(type=int, fmt=util.num) + def txqlen(self): + """Length of transmit queue""" + return capi.rtnl_link_get_txqlen(self._rtnl_link) + + @txqlen.setter + def txqlen(self, value): + capi.rtnl_link_set_txqlen(self._rtnl_link, int(value)) + + @property + @netlink.nlattr(type=str, immutable=True, fmt=util.string) + def arptype(self): + """Type of link (cannot be changed)""" + type_ = capi.rtnl_link_get_arptype(self._rtnl_link) + return core_capi.nl_llproto2str(type_, 64)[0] + + @arptype.setter + def arptype(self, value): + i = core_capi.nl_str2llproto(value) + capi.rtnl_link_set_arptype(self._rtnl_link, i) + + @property + @netlink.nlattr(type=str, immutable=True, fmt=util.string, title='state') + def operstate(self): + """Operational status""" + operstate = capi.rtnl_link_get_operstate(self._rtnl_link) + return capi.rtnl_link_operstate2str(operstate, 32)[0] + + @operstate.setter + def operstate(self, value): + i = capi.rtnl_link_str2operstate(value) + capi.rtnl_link_set_operstate(self._rtnl_link, i) + + @property + @netlink.nlattr(type=str, immutable=True, fmt=util.string) + def mode(self): + """Link mode""" + mode = capi.rtnl_link_get_linkmode(self._rtnl_link) + return capi.rtnl_link_mode2str(mode, 32)[0] + + @mode.setter + def mode(self, value): + i = capi.rtnl_link_str2mode(value) + capi.rtnl_link_set_linkmode(self._rtnl_link, i) + + @property + @netlink.nlattr(type=str, fmt=util.string) + def alias(self): + """Interface alias (SNMP)""" + return capi.rtnl_link_get_ifalias(self._rtnl_link) + + @alias.setter + def alias(self, value): + capi.rtnl_link_set_ifalias(self._rtnl_link, value) + + @property + @netlink.nlattr(type=str, fmt=util.string) + def type(self): + """Link type""" + return capi.rtnl_link_get_type(self._rtnl_link) + + @type.setter + def type(self, value): + if capi.rtnl_link_set_type(self._rtnl_link, value) < 0: + raise NameError('unknown info type') + + self._module_lookup('netlink.route.links.' + value) + + def get_stat(self, stat): + """Retrieve statistical information""" + if type(stat) is str: + stat = capi.rtnl_link_str2stat(stat) + if stat < 0: + raise NameError('unknown name of statistic') + + return capi.rtnl_link_get_stat(self._rtnl_link, stat) + + def add(self, sock=None, flags=None): + if not sock: + sock = netlink.lookup_socket(netlink.NETLINK_ROUTE) + + if not flags: + flags = netlink.NLM_F_CREATE + + ret = capi.rtnl_link_add(sock._sock, self._rtnl_link, flags) + if ret < 0: + raise netlink.KernelError(ret) + + def change(self, sock=None, flags=0): + """Commit changes made to the link object""" + if sock is None: + sock = netlink.lookup_socket(netlink.NETLINK_ROUTE) + + if not self._orig: + raise netlink.NetlinkError('Original link not available') + ret = capi.rtnl_link_change(sock._sock, self._orig, self._rtnl_link, flags) + if ret < 0: + raise netlink.KernelError(ret) + + def delete(self, sock=None): + """Attempt to delete this link in the kernel""" + if sock is None: + sock = netlink.lookup_socket(netlink.NETLINK_ROUTE) + + ret = capi.rtnl_link_delete(sock._sock, self._rtnl_link) + if ret < 0: + raise netlink.KernelError(ret) + + ################################################################### + # private properties + # + # Used for formatting output. USE AT OWN RISK + @property + def _state(self): + if 'up' in self.flags: + buf = util.good('up') + if 'lowerup' not in self.flags: + buf += ' ' + util.bad('no-carrier') + else: + buf = util.bad('down') + return buf + + @property + def _brief(self): + return self._module_brief() + self._foreach_af('brief') + + @property + def _flags(self): + ignore = [ + 'up', + 'running', + 'lowerup', + ] + return ','.join([flag for flag in self.flags if flag not in ignore]) + + def _foreach_af(self, name, args=None): + buf = '' + for af in self.af: + try: + func = getattr(self.af[af], name) + s = str(func(args)) + if len(s) > 0: + buf += ' ' + s + except AttributeError: + pass + return buf + + def format(self, details=False, stats=False, indent=''): + """Return link as formatted text""" + fmt = util.MyFormatter(self, indent) + + buf = fmt.format('{a|ifindex} {a|name} {a|arptype} {a|address} '\ + '{a|_state} <{a|_flags}> {a|_brief}') + + if details: + buf += fmt.nl('\t{t|mtu} {t|txqlen} {t|weight} '\ + '{t|qdisc} {t|operstate}') + buf += fmt.nl('\t{t|broadcast} {t|alias}') + + buf += self._foreach_af('details', fmt) + + if stats: + l = [['Packets', RX_PACKETS, TX_PACKETS], + ['Bytes', RX_BYTES, TX_BYTES], + ['Errors', RX_ERRORS, TX_ERRORS], + ['Dropped', RX_DROPPED, TX_DROPPED], + ['Compressed', RX_COMPRESSED, TX_COMPRESSED], + ['FIFO Errors', RX_FIFO_ERR, TX_FIFO_ERR], + ['Length Errors', RX_LEN_ERR, None], + ['Over Errors', RX_OVER_ERR, None], + ['CRC Errors', RX_CRC_ERR, None], + ['Frame Errors', RX_FRAME_ERR, None], + ['Missed Errors', RX_MISSED_ERR, None], + ['Abort Errors', None, TX_ABORT_ERR], + ['Carrier Errors', None, TX_CARRIER_ERR], + ['Heartbeat Errors', None, TX_HBEAT_ERR], + ['Window Errors', None, TX_WIN_ERR], + ['Collisions', None, COLLISIONS], + ['Multicast', None, MULTICAST], + ['', None, None], + ['Ipv6:', None, None], + ['Packets', IP6_INPKTS, IP6_OUTPKTS], + ['Bytes', IP6_INOCTETS, IP6_OUTOCTETS], + ['Discards', IP6_INDISCARDS, IP6_OUTDISCARDS], + ['Multicast Packets', IP6_INMCASTPKTS, IP6_OUTMCASTPKTS], + ['Multicast Bytes', IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS], + ['Broadcast Packets', IP6_INBCASTPKTS, IP6_OUTBCASTPKTS], + ['Broadcast Bytes', IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS], + ['Delivers', IP6_INDELIVERS, None], + ['Forwarded', None, IP6_OUTFORWDATAGRAMS], + ['No Routes', IP6_INNOROUTES, IP6_OUTNOROUTES], + ['Header Errors', IP6_INHDRERRORS, None], + ['Too Big Errors', IP6_INTOOBIGERRORS, None], + ['Address Errors', IP6_INADDRERRORS, None], + ['Unknown Protocol', IP6_INUNKNOWNPROTOS, None], + ['Truncated Packets', IP6_INTRUNCATEDPKTS, None], + ['Reasm Timeouts', IP6_REASMTIMEOUT, None], + ['Reasm Requests', IP6_REASMREQDS, None], + ['Reasm Failures', IP6_REASMFAILS, None], + ['Reasm OK', IP6_REASMOKS, None], + ['Frag Created', None, IP6_FRAGCREATES], + ['Frag Failures', None, IP6_FRAGFAILS], + ['Frag OK', None, IP6_FRAGOKS], + ['', None, None], + ['ICMPv6:', None, None], + ['Messages', ICMP6_INMSGS, ICMP6_OUTMSGS], + ['Errors', ICMP6_INERRORS, ICMP6_OUTERRORS]] + + buf += '\n\t%s%s%s%s\n' % (33 * ' ', util.title('RX'), + 15 * ' ', util.title('TX')) + + for row in l: + row[0] = util.kw(row[0]) + row[1] = self.get_stat(row[1]) if row[1] else '' + row[2] = self.get_stat(row[2]) if row[2] else '' + buf += '\t{0[0]:27} {0[1]:>16} {0[2]:>16}\n'.format(row) + + buf += self._foreach_af('stats') + + return buf + +def get(name, sock=None): + """Lookup Link object directly from kernel""" + if not name: + raise ValueError() + + if not sock: + sock = netlink.lookup_socket(netlink.NETLINK_ROUTE) + + link = capi.get_from_kernel(sock._sock, 0, name) + if not link: + return None + + return Link.from_capi(link) + +_link_cache = LinkCache() + +def resolve(name): + _link_cache.refill() + return _link_cache[name] diff --git a/python/netlink/route/links/__init__.py b/python/netlink/route/links/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/netlink/route/links/dummy.py b/python/netlink/route/links/dummy.py new file mode 100644 index 0000000..e9491cc --- /dev/null +++ b/python/netlink/route/links/dummy.py @@ -0,0 +1,26 @@ +# +# Copyright (c) 2011 Thomas Graf +# + +"""Dummy + +""" +from __future__ import absolute_import + +__version__ = '1.0' +__all__ = [ + 'init', +] + + +class DummyLink(object): + def __init__(self, link): + self._rtnl_link = link + + @staticmethod + def brief(): + return 'dummy' + +def init(link): + link.dummy = DummyLink(link._rtnl_link) + return link.dummy diff --git a/python/netlink/route/links/inet.py b/python/netlink/route/links/inet.py new file mode 100644 index 0000000..f5f45cb --- /dev/null +++ b/python/netlink/route/links/inet.py @@ -0,0 +1,158 @@ +# +# Copyright (c) 2011 Thomas Graf +# + +"""IPv4 + +""" + +from __future__ import absolute_import + +__all__ = [ + '', +] + +from ... import core as netlink +from .. import capi as capi +from ... import util as util +DEVCONF_FORWARDING = 1 +DEVCONF_MC_FORWARDING = 2 +DEVCONF_PROXY_ARP = 3 +DEVCONF_ACCEPT_REDIRECTS = 4 +DEVCONF_SECURE_REDIRECTS = 5 +DEVCONF_SEND_REDIRECTS = 6 +DEVCONF_SHARED_MEDIA = 7 +DEVCONF_RP_FILTER = 8 +DEVCONF_ACCEPT_SOURCE_ROUTE = 9 +DEVCONF_BOOTP_RELAY = 10 +DEVCONF_LOG_MARTIANS = 11 +DEVCONF_TAG = 12 +DEVCONF_ARPFILTER = 13 +DEVCONF_MEDIUM_ID = 14 +DEVCONF_NOXFRM = 15 +DEVCONF_NOPOLICY = 16 +DEVCONF_FORCE_IGMP_VERSION = 17 +DEVCONF_ARP_ANNOUNCE = 18 +DEVCONF_ARP_IGNORE = 19 +DEVCONF_PROMOTE_SECONDARIES = 20 +DEVCONF_ARP_ACCEPT = 21 +DEVCONF_ARP_NOTIFY = 22 +DEVCONF_ACCEPT_LOCAL = 23 +DEVCONF_SRC_VMARK = 24 +DEVCONF_PROXY_ARP_PVLAN = 25 +DEVCONF_MAX = DEVCONF_PROXY_ARP_PVLAN + +def _resolve(id): + if type(id) is str: + id = capi.rtnl_link_inet_str2devconf(id)[0] + if id < 0: + raise NameError('unknown configuration id') + return id + +class InetLink(object): + def __init__(self, link): + self._link = link + + def details(self, fmt): + buf = fmt.nl('\n\t{0}\n\t'.format(util.title('Configuration:'))) + + for i in range(DEVCONF_FORWARDING, DEVCONF_MAX+1): + if i & 1 and i > 1: + buf += fmt.nl('\t') + txt = util.kw(capi.rtnl_link_inet_devconf2str(i, 32)[0]) + buf += fmt.format('{0:28s} {1:12} ', txt, + self.get_conf(i)) + + + return buf + + def get_conf(self, id): + return capi.inet_get_conf(self._link._rtnl_link, _resolve(id)) + + def set_conf(self, id, value): + return capi.rtnl_link_inet_set_conf(self._link._rtnl_link, + _resolve(id), int(value)) + + @property + @netlink.nlattr(type=bool, fmt=util.boolean) + def forwarding(self): + return bool(self.get_conf(DEVCONF_FORWARDING)) + + @forwarding.setter + def forwarding(self, value): + self.set_conf(DEVCONF_FORWARDING, int(value)) + + + @property + @netlink.nlattr(type=bool, fmt=util.boolean) + def mc_forwarding(self): + return bool(self.get_conf(DEVCONF_MC_FORWARDING)) + + @mc_forwarding.setter + def mc_forwarding(self, value): + self.set_conf(DEVCONF_MC_FORWARDING, int(value)) + + + @property + @netlink.nlattr(type=bool, fmt=util.boolean) + def proxy_arp(self): + return bool(self.get_conf(DEVCONF_PROXY_ARP)) + + @proxy_arp.setter + def proxy_arp(self, value): + self.set_conf(DEVCONF_PROXY_ARP, int(value)) + + @property + @netlink.nlattr(type=bool, fmt=util.boolean) + def accept_redirects(self): + return bool(self.get_conf(DEVCONF_ACCEPT_REDIRECTS)) + + @accept_redirects.setter + def accept_redirects(self, value): + self.set_conf(DEVCONF_ACCEPT_REDIRECTS, int(value)) + + @property + @netlink.nlattr(type=bool, fmt=util.boolean) + def secure_redirects(self): + return bool(self.get_conf(DEVCONF_SECURE_REDIRECTS)) + + @secure_redirects.setter + def secure_redirects(self, value): + self.set_conf(DEVCONF_SECURE_REDIRECTS, int(value)) + + @property + @netlink.nlattr(type=bool, fmt=util.boolean) + def send_redirects(self): + return bool(self.get_conf(DEVCONF_SEND_REDIRECTS)) + + @send_redirects.setter + def send_redirects(self, value): + self.set_conf(DEVCONF_SEND_REDIRECTS, int(value)) + + @property + @netlink.nlattr(type=bool, fmt=util.boolean) + def shared_media(self): + return bool(self.get_conf(DEVCONF_SHARED_MEDIA)) + + @shared_media.setter + def shared_media(self, value): + self.set_conf(DEVCONF_SHARED_MEDIA, int(value)) + +# IPV4_DEVCONF_RP_FILTER, +# IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE, +# IPV4_DEVCONF_BOOTP_RELAY, +# IPV4_DEVCONF_LOG_MARTIANS, +# IPV4_DEVCONF_TAG, +# IPV4_DEVCONF_ARPFILTER, +# IPV4_DEVCONF_MEDIUM_ID, +# IPV4_DEVCONF_NOXFRM, +# IPV4_DEVCONF_NOPOLICY, +# IPV4_DEVCONF_FORCE_IGMP_VERSION, +# IPV4_DEVCONF_ARP_ANNOUNCE, +# IPV4_DEVCONF_ARP_IGNORE, +# IPV4_DEVCONF_PROMOTE_SECONDARIES, +# IPV4_DEVCONF_ARP_ACCEPT, +# IPV4_DEVCONF_ARP_NOTIFY, +# IPV4_DEVCONF_ACCEPT_LOCAL, +# IPV4_DEVCONF_SRC_VMARK, +# IPV4_DEVCONF_PROXY_ARP_PVLAN, diff --git a/python/netlink/route/links/vlan.py b/python/netlink/route/links/vlan.py new file mode 100644 index 0000000..70045d5 --- /dev/null +++ b/python/netlink/route/links/vlan.py @@ -0,0 +1,71 @@ +# +# Copyright (c) 2011 Thomas Graf +# + +"""VLAN network link + +""" + +from __future__ import absolute_import + + +from ... import core as netlink +from .. import capi as capi +class VLANLink(object): + def __init__(self, link): + self._link = link + + @property + @netlink.nlattr(type=int) + def id(self): + """vlan identifier""" + return capi.rtnl_link_vlan_get_id(self._link) + + @id.setter + def id(self, value): + capi.rtnl_link_vlan_set_id(self._link, int(value)) + + @property + @netlink.nlattr(type=str) + def flags(self): + """ VLAN flags + Setting this property will *Not* reset flags to value you supply in + Examples: + link.flags = '+xxx' # add xxx flag + link.flags = 'xxx' # exactly the same + link.flags = '-xxx' # remove xxx flag + link.flags = [ '+xxx', '-yyy' ] # list operation + """ + flags = capi.rtnl_link_vlan_get_flags(self._link) + return capi.rtnl_link_vlan_flags2str(flags, 256)[0].split(',') + + def _set_flag(self, flag): + if flag.startswith('-'): + i = capi.rtnl_link_vlan_str2flags(flag[1:]) + capi.rtnl_link_vlan_unset_flags(self._link, i) + elif flag.startswith('+'): + i = capi.rtnl_link_vlan_str2flags(flag[1:]) + capi.rtnl_link_vlan_set_flags(self._link, i) + else: + i = capi.rtnl_link_vlan_str2flags(flag) + capi.rtnl_link_vlan_set_flags(self._link, i) + + @flags.setter + def flags(self, value): + if type(value) is list: + for flag in value: + self._set_flag(flag) + else: + self._set_flag(value) + + ################################################################### + # TODO: + # - ingress map + # - egress map + + def brief(self): + return 'vlan-id {0}'.format(self.id) + +def init(link): + link.vlan = VLANLink(link._link) + return link.vlan diff --git a/python/netlink/route/qdisc/__init__.py b/python/netlink/route/qdisc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/netlink/route/qdisc/htb.py b/python/netlink/route/qdisc/htb.py new file mode 100644 index 0000000..d051c8d --- /dev/null +++ b/python/netlink/route/qdisc/htb.py @@ -0,0 +1,145 @@ +# +# Copyright (c) 2011 Thomas Graf +# + +"""HTB qdisc + +""" + +from __future__ import absolute_import + +from ... import core as netlink +from ... import util as util +from .. import capi as capi +from .. import tc as tc + +class HTBQdisc(object): + def __init__(self, qdisc): + self._qdisc = qdisc + + @property + @netlink.nlattr(type=int) + def default_class(self): + return tc.Handle(capi.rtnl_htb_get_defcls(self._qdisc._rtnl_qdisc)) + + @default_class.setter + def default_class(self, value): + capi.rtnl_htb_set_defcls(self._qdisc._rtnl_qdisc, int(value)) + + @property + @netlink.nlattr('r2q', type=int) + def r2q(self): + return capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc) + + @r2q.setter + def r2q(self, value): + capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc, + int(value)) + + def brief(self): + fmt = util.MyFormatter(self) + + ret = ' {s|default-class!k} {a|default_class}' + + if self.r2q: + ret += ' {s|r2q!k} {a|r2q}' + + return fmt.format(ret) + +class HTBClass(object): + def __init__(self, cl): + self._class = cl + + @property + @netlink.nlattr(type=str) + def rate(self): + rate = capi.rtnl_htb_get_rate(self._class._rtnl_class) + return util.Rate(rate) + + @rate.setter + def rate(self, value): + capi.rtnl_htb_set_rate(self._class._rtnl_class, int(value)) + + @property + @netlink.nlattr(type=str) + def ceil(self): + ceil = capi.rtnl_htb_get_ceil(self._class._rtnl_class) + return util.Rate(ceil) + + @ceil.setter + def ceil(self, value): + capi.rtnl_htb_set_ceil(self._class._rtnl_class, int(value)) + + @property + @netlink.nlattr(type=str) + def burst(self): + burst = capi.rtnl_htb_get_rbuffer(self._class._rtnl_class) + return util.Size(burst) + + @burst.setter + def burst(self, value): + capi.rtnl_htb_set_rbuffer(self._class._rtnl_class, int(value)) + + @property + @netlink.nlattr(type=str) + def ceil_burst(self): + burst = capi.rtnl_htb_get_cbuffer(self._class._rtnl_class) + return util.Size(burst) + + @ceil_burst.setter + def ceil_burst(self, value): + capi.rtnl_htb_set_cbuffer(self._class._rtnl_class, int(value)) + + @property + @netlink.nlattr(type=int) + def prio(self): + return capi.rtnl_htb_get_prio(self._class._rtnl_class) + + @prio.setter + def prio(self, value): + capi.rtnl_htb_set_prio(self._class._rtnl_class, int(value)) + + @property + @netlink.nlattr(type=int) + def quantum(self): + return capi.rtnl_htb_get_quantum(self._class._rtnl_class) + + @quantum.setter + def quantum(self, value): + capi.rtnl_htb_set_quantum(self._class._rtnl_class, int(value)) + + @property + @netlink.nlattr(type=int) + def level(self): + return capi.rtnl_htb_get_level(self._class._rtnl_class) + + @level.setter + def level(self, value): + capi.rtnl_htb_set_level(self._class._rtnl_class, int(value)) + + def brief(self): + fmt = util.MyFormatter(self) + + ret = ' {t|prio} {t|rate}' + + if self.rate != self.ceil: + ret += ' {s|borrow-up-to!k} {a|ceil}' + + ret += ' {t|burst}' + + return fmt.format(ret) + + def details(self): + fmt = util.MyFormatter(self) + + return fmt.nl('\t{t|level} {t|quantum}') + +def init_qdisc(qdisc): + qdisc.htb = HTBQdisc(qdisc) + return qdisc.htb + +def init_class(cl): + cl.htb = HTBClass(cl) + return cl.htb + +#extern void rtnl_htb_set_quantum(struct rtnl_class *, uint32_t quantum); diff --git a/python/netlink/route/tc.py b/python/netlink/route/tc.py new file mode 100644 index 0000000..0689b71 --- /dev/null +++ b/python/netlink/route/tc.py @@ -0,0 +1,595 @@ +# +# Copyright (c) 2011 Thomas Graf +# +from __future__ import absolute_import + +__all__ = [ + 'TcCache', + 'Tc', + 'QdiscCache', + 'Qdisc', + 'TcClassCache', + 'TcClass', +] + +from .. import core as netlink +from . import capi as capi +from .. import util as util +from . import link as Link + +TC_PACKETS = 0 +TC_BYTES = 1 +TC_RATE_BPS = 2 +TC_RATE_PPS = 3 +TC_QLEN = 4 +TC_BACKLOG = 5 +TC_DROPS = 6 +TC_REQUEUES = 7 +TC_OVERLIMITS = 9 + +TC_H_ROOT = 0xFFFFFFFF +TC_H_INGRESS = 0xFFFFFFF1 + +STAT_PACKETS = 0 +STAT_BYTES = 1 +STAT_RATE_BPS = 2 +STAT_RATE_PPS = 3 +STAT_QLEN = 4 +STAT_BACKLOG = 5 +STAT_DROPS = 6 +STAT_REQUEUES = 7 +STAT_OVERLIMITS = 8 +STAT_MAX = STAT_OVERLIMITS + + +class Handle(object): + """ Traffic control handle + + Representation of a traffic control handle which uniquely identifies + each traffic control object in its link namespace. + + handle = tc.Handle('10:20') + handle = tc.handle('root') + print int(handle) + print str(handle) + """ + def __init__(self, val=None): + if type(val) is str: + val = capi.tc_str2handle(val) + elif not val: + val = 0 + + self._val = int(val) + + def __cmp__(self, other): + if other is None: + other = 0 + + if isinstance(other, Handle): + return int(self) - int(other) + elif isinstance(other, int): + return int(self) - other + else: + raise TypeError() + + def __int__(self): + return self._val + + def __str__(self): + return capi.rtnl_tc_handle2str(self._val, 64)[0] + + def isroot(self): + return self._val == TC_H_ROOT or self._val == TC_H_INGRESS + +class TcCache(netlink.Cache): + """Cache of traffic control object""" + + def __getitem__(self, key): + raise NotImplementedError() + +class Tc(netlink.Object): + def __cmp__(self, other): + diff = self.ifindex - other.ifindex + if diff == 0: + diff = int(self.handle) - int(other.handle) + return diff + + def _tc_module_lookup(self): + self._module_lookup(self._module_path + self.kind, + 'init_' + self._name) + + @property + def root(self): + """True if tc object is a root object""" + return self.parent.isroot() + + @property + def ifindex(self): + """interface index""" + return capi.rtnl_tc_get_ifindex(self._rtnl_tc) + + @ifindex.setter + def ifindex(self, value): + capi.rtnl_tc_set_ifindex(self._rtnl_tc, int(value)) + + @property + def link(self): + link = capi.rtnl_tc_get_link(self._rtnl_tc) + if not link: + return None + + return Link.Link.from_capi(link) + + @link.setter + def link(self, value): + capi.rtnl_tc_set_link(self._rtnl_tc, value._link) + + @property + def mtu(self): + return capi.rtnl_tc_get_mtu(self._rtnl_tc) + + @mtu.setter + def mtu(self, value): + capi.rtnl_tc_set_mtu(self._rtnl_tc, int(value)) + + @property + def mpu(self): + return capi.rtnl_tc_get_mpu(self._rtnl_tc) + + @mpu.setter + def mpu(self, value): + capi.rtnl_tc_set_mpu(self._rtnl_tc, int(value)) + + @property + def overhead(self): + return capi.rtnl_tc_get_overhead(self._rtnl_tc) + + @overhead.setter + def overhead(self, value): + capi.rtnl_tc_set_overhead(self._rtnl_tc, int(value)) + + @property + def linktype(self): + return capi.rtnl_tc_get_linktype(self._rtnl_tc) + + @linktype.setter + def linktype(self, value): + capi.rtnl_tc_set_linktype(self._rtnl_tc, int(value)) + + @property + @netlink.nlattr(fmt=util.handle) + def handle(self): + return Handle(capi.rtnl_tc_get_handle(self._rtnl_tc)) + + @handle.setter + def handle(self, value): + capi.rtnl_tc_set_handle(self._rtnl_tc, int(value)) + + @property + @netlink.nlattr(fmt=util.handle) + def parent(self): + return Handle(capi.rtnl_tc_get_parent(self._rtnl_tc)) + + @parent.setter + def parent(self, value): + capi.rtnl_tc_set_parent(self._rtnl_tc, int(value)) + + @property + @netlink.nlattr(fmt=util.bold) + def kind(self): + return capi.rtnl_tc_get_kind(self._rtnl_tc) + + @kind.setter + def kind(self, value): + capi.rtnl_tc_set_kind(self._rtnl_tc, value) + self._tc_module_lookup() + + def get_stat(self, id): + return capi.rtnl_tc_get_stat(self._rtnl_tc, id) + + @property + def _dev(self): + buf = util.kw('dev') + ' ' + + if self.link: + return buf + util.string(self.link.name) + else: + return buf + util.num(self.ifindex) + + def brief(self, title, nodev=False, noparent=False): + ret = title + ' {a|kind} {a|handle}' + + if not nodev: + ret += ' {a|_dev}' + + if not noparent: + ret += ' {t|parent}' + + return ret + self._module_brief() + + @staticmethod + def details(): + return '{t|mtu} {t|mpu} {t|overhead} {t|linktype}' + + @property + def packets(self): + return self.get_stat(STAT_PACKETS) + + @property + def bytes(self): + return self.get_stat(STAT_BYTES) + + @property + def qlen(self): + return self.get_stat(STAT_QLEN) + + @staticmethod + def stats(fmt): + return fmt.nl('{t|packets} {t|bytes} {t|qlen}') + +class QdiscCache(netlink.Cache): + """Cache of qdiscs""" + + def __init__(self, cache=None): + if not cache: + cache = self._alloc_cache_name('route/qdisc') + + self._protocol = netlink.NETLINK_ROUTE + self._nl_cache = cache + +# def __getitem__(self, key): +# if type(key) is int: +# link = capi.rtnl_link_get(self._this, key) +# elif type(key) is str: +# link = capi.rtnl_link_get_by_name(self._this, key) +# +# if qdisc is None: +# raise KeyError() +# else: +# return Qdisc._from_capi(capi.qdisc2obj(qdisc)) + + @staticmethod + def _new_object(obj): + return Qdisc(obj) + + @staticmethod + def _new_cache(cache): + return QdiscCache(cache=cache) + +class Qdisc(Tc): + """Queueing discipline""" + + def __init__(self, obj=None): + netlink.Object.__init__(self, 'route/qdisc', 'qdisc', obj) + self._module_path = 'netlink.route.qdisc.' + self._rtnl_qdisc = self._obj2type(self._nl_object) + self._rtnl_tc = capi.obj2tc(self._nl_object) + + if self.kind: + self._tc_module_lookup() + + @classmethod + def from_capi(cls, obj): + return cls(capi.qdisc2obj(obj)) + + @staticmethod + def _obj2type(obj): + return capi.obj2qdisc(obj) + + @staticmethod + def _new_instance(obj): + if not obj: + raise ValueError() + + return Qdisc(obj) + + @property + def childs(self): + ret = [] + + if int(self.handle): + ret += get_cls(self.ifindex, parent=self.handle) + + if self.root: + ret += get_class(self.ifindex, parent=TC_H_ROOT) + + ret += get_class(self.ifindex, parent=self.handle) + + return ret + +# def add(self, socket, flags=None): +# if not flags: +# flags = netlink.NLM_F_CREATE +# +# ret = capi.rtnl_link_add(socket._sock, self._link, flags) +# if ret < 0: +# raise netlink.KernelError(ret) +# +# def change(self, socket, flags=0): +# """Commit changes made to the link object""" +# if not self._orig: +# raise NetlinkError('Original link not available') +# ret = capi.rtnl_link_change(socket._sock, self._orig, self._link, flags) +# if ret < 0: +# raise netlink.KernelError(ret) +# +# def delete(self, socket): +# """Attempt to delete this link in the kernel""" +# ret = capi.rtnl_link_delete(socket._sock, self._link) +# if ret < 0: +# raise netlink.KernelError(ret) + + def format(self, details=False, stats=False, nodev=False, + noparent=False, indent=''): + """Return qdisc as formatted text""" + fmt = util.MyFormatter(self, indent) + + buf = fmt.format(self.brief('qdisc', nodev, noparent)) + + if details: + buf += fmt.nl('\t' + self.details()) + + if stats: + buf += self.stats(fmt) + +# if stats: +# l = [['Packets', RX_PACKETS, TX_PACKETS], +# ['Bytes', RX_BYTES, TX_BYTES], +# ['Errors', RX_ERRORS, TX_ERRORS], +# ['Dropped', RX_DROPPED, TX_DROPPED], +# ['Compressed', RX_COMPRESSED, TX_COMPRESSED], +# ['FIFO Errors', RX_FIFO_ERR, TX_FIFO_ERR], +# ['Length Errors', RX_LEN_ERR, None], +# ['Over Errors', RX_OVER_ERR, None], +# ['CRC Errors', RX_CRC_ERR, None], +# ['Frame Errors', RX_FRAME_ERR, None], +# ['Missed Errors', RX_MISSED_ERR, None], +# ['Abort Errors', None, TX_ABORT_ERR], +# ['Carrier Errors', None, TX_CARRIER_ERR], +# ['Heartbeat Errors', None, TX_HBEAT_ERR], +# ['Window Errors', None, TX_WIN_ERR], +# ['Collisions', None, COLLISIONS], +# ['Multicast', None, MULTICAST], +# ['', None, None], +# ['Ipv6:', None, None], +# ['Packets', IP6_INPKTS, IP6_OUTPKTS], +# ['Bytes', IP6_INOCTETS, IP6_OUTOCTETS], +# ['Discards', IP6_INDISCARDS, IP6_OUTDISCARDS], +# ['Multicast Packets', IP6_INMCASTPKTS, IP6_OUTMCASTPKTS], +# ['Multicast Bytes', IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS], +# ['Broadcast Packets', IP6_INBCASTPKTS, IP6_OUTBCASTPKTS], +# ['Broadcast Bytes', IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS], +# ['Delivers', IP6_INDELIVERS, None], +# ['Forwarded', None, IP6_OUTFORWDATAGRAMS], +# ['No Routes', IP6_INNOROUTES, IP6_OUTNOROUTES], +# ['Header Errors', IP6_INHDRERRORS, None], +# ['Too Big Errors', IP6_INTOOBIGERRORS, None], +# ['Address Errors', IP6_INADDRERRORS, None], +# ['Unknown Protocol', IP6_INUNKNOWNPROTOS, None], +# ['Truncated Packets', IP6_INTRUNCATEDPKTS, None], +# ['Reasm Timeouts', IP6_REASMTIMEOUT, None], +# ['Reasm Requests', IP6_REASMREQDS, None], +# ['Reasm Failures', IP6_REASMFAILS, None], +# ['Reasm OK', IP6_REASMOKS, None], +# ['Frag Created', None, IP6_FRAGCREATES], +# ['Frag Failures', None, IP6_FRAGFAILS], +# ['Frag OK', None, IP6_FRAGOKS], +# ['', None, None], +# ['ICMPv6:', None, None], +# ['Messages', ICMP6_INMSGS, ICMP6_OUTMSGS], +# ['Errors', ICMP6_INERRORS, ICMP6_OUTERRORS]] +# +# buf += '\n\t%s%s%s%s\n' % (33 * ' ', util.title('RX'), +# 15 * ' ', util.title('TX')) +# +# for row in l: +# row[0] = util.kw(row[0]) +# row[1] = self.get_stat(row[1]) if row[1] else '' +# row[2] = self.get_stat(row[2]) if row[2] else '' +# buf += '\t{0:27} {1:>16} {2:>16}\n'.format(*row) + + return buf + +class TcClassCache(netlink.Cache): + """Cache of traffic classes""" + + def __init__(self, ifindex, cache=None): + if not cache: + cache = self._alloc_cache_name('route/class') + + self._protocol = netlink.NETLINK_ROUTE + self._nl_cache = cache + self._set_arg1(ifindex) + + @staticmethod + def _new_object(obj): + return TcClass(obj) + + def _new_cache(self, cache): + return TcClassCache(self.arg1, cache=cache) + +class TcClass(Tc): + """Traffic Class""" + + def __init__(self, obj=None): + netlink.Object.__init__(self, 'route/class', 'class', obj) + self._module_path = 'netlink.route.qdisc.' + self._rtnl_class = self._obj2type(self._nl_object) + self._rtnl_tc = capi.obj2tc(self._nl_object) + + if self.kind: + self._tc_module_lookup() + + @classmethod + def from_capi(cls, obj): + return cls(capi.class2obj(obj)) + + @staticmethod + def _obj2type(obj): + return capi.obj2class(obj) + + @staticmethod + def _new_instance(obj): + if not obj: + raise ValueError() + + return TcClass(obj) + + @property + def childs(self): + ret = [] + + # classes can have classifiers, child classes and leaf + # qdiscs + ret += get_cls(self.ifindex, parent=self.handle) + ret += get_class(self.ifindex, parent=self.handle) + ret += get_qdisc(self.ifindex, parent=self.handle) + + return ret + + def format(self, details=False, _stats=False, nodev=False, + noparent=False, indent=''): + """Return class as formatted text""" + fmt = util.MyFormatter(self, indent) + + buf = fmt.format(self.brief('class', nodev, noparent)) + + if details: + buf += fmt.nl('\t' + self.details()) + + return buf + +class ClassifierCache(netlink.Cache): + """Cache of traffic classifiers objects""" + + def __init__(self, ifindex, parent, cache=None): + if not cache: + cache = self._alloc_cache_name('route/cls') + + self._protocol = netlink.NETLINK_ROUTE + self._nl_cache = cache + self._set_arg1(ifindex) + self._set_arg2(int(parent)) + + @staticmethod + def _new_object(obj): + return Classifier(obj) + + def _new_cache(self, cache): + return ClassifierCache(self.arg1, self.arg2, cache=cache) + +class Classifier(Tc): + """Classifier""" + + def __init__(self, obj=None): + netlink.Object.__init__(self, 'route/cls', 'cls', obj) + self._module_path = 'netlink.route.cls.' + self._rtnl_cls = self._obj2type(self._nl_object) + self._rtnl_tc = capi.obj2tc(self._nl_object) + + @classmethod + def from_capi(cls, obj): + return cls(capi.cls2obj(obj)) + + @staticmethod + def _obj2type(obj): + return capi.obj2cls(obj) + + @staticmethod + def _new_instance(obj): + if not obj: + raise ValueError() + + return Classifier(obj) + + @property + def priority(self): + return capi.rtnl_cls_get_prio(self._rtnl_cls) + + @priority.setter + def priority(self, value): + capi.rtnl_cls_set_prio(self._rtnl_cls, int(value)) + + @property + def protocol(self): + return capi.rtnl_cls_get_protocol(self._rtnl_cls) + + @protocol.setter + def protocol(self, value): + capi.rtnl_cls_set_protocol(self._rtnl_cls, int(value)) + + @property + def childs(self): + return [] + + def format(self, details=False, _stats=False, nodev=False, + noparent=False, indent=''): + """Return class as formatted text""" + fmt = util.MyFormatter(self, indent) + + buf = fmt.format(self.brief('classifier', nodev, noparent)) + buf += fmt.format(' {t|priority} {t|protocol}') + + if details: + buf += fmt.nl('\t' + self.details()) + + return buf + +_qdisc_cache = QdiscCache() + +def get_qdisc(ifindex, handle=None, parent=None): + l = [] + + _qdisc_cache.refill() + + for qdisc in _qdisc_cache: + if qdisc.ifindex != ifindex: + continue + if (handle is not None) and (qdisc.handle != handle): + continue + if (parent is not None) and (qdisc.parent != parent): + continue + l.append(qdisc) + + return l + +_class_cache = {} + +def get_class(ifindex, parent, handle=None): + l = [] + + try: + cache = _class_cache[ifindex] + except KeyError: + cache = TcClassCache(ifindex) + _class_cache[ifindex] = cache + + cache.refill() + + for cl in cache: + if (parent is not None) and (cl.parent != parent): + continue + if (handle is not None) and (cl.handle != handle): + continue + l.append(cl) + + return l + +_cls_cache = {} + +def get_cls(ifindex, parent, handle=None): + + chain = _cls_cache.get(ifindex, dict()) + + try: + cache = chain[parent] + except KeyError: + cache = ClassifierCache(ifindex, parent) + chain[parent] = cache + + cache.refill() + + if handle is None: + return [ cls for cls in cache ] + + return [ cls for cls in cache if cls.handle == handle ] diff --git a/python/netlink/util.py b/python/netlink/util.py new file mode 100644 index 0000000..2394033 --- /dev/null +++ b/python/netlink/util.py @@ -0,0 +1,174 @@ +# +# Utilities +# +# Copyright (c) 2011 Thomas Graf +# + +"""utility module for netlink + +""" + +from __future__ import absolute_import + +from . import core as netlink +from . import capi as capi +from string import Formatter +import types + +__version__ = '1.0' + +def _color(t, c): + return b'{esc}[{color}m{text}{esc}[0m'.format(esc=b'\x1b', color=c, text=t) + +def black(t): + return _color(t, 30) + +def red(t): + return _color(t, 31) + +def green(t): + return _color(t, 32) + +def yellow(t): + return _color(t, 33) + +def blue(t): + return _color(t, 34) + +def magenta(t): + return _color(t, 35) + +def cyan(t): + return _color(t, 36) + +def white(t): + return _color(t, 37) + +def bold(t): + return _color(t, 1) + +def kw(t): + return yellow(t) + +def num(t): + return str(t) + +def string(t): + return t + +def addr(t): + return str(t) + +def bad(t): + return red(t) + +def good(t): + return green(t) + +def title(t): + return t + +def boolean(t): + return str(t) + +def handle(t): + return str(t) + +class MyFormatter(Formatter): + def __init__(self, obj, indent=''): + self._obj = obj + self._indent = indent + + def _nlattr(self, key): + value = getattr(self._obj.__class__, key) + if not isinstance(value, property): + raise ValueError('Invalid formatting string {0}'.format(key)) + + d = getattr(value.fget, 'formatinfo', dict()) + + # value = value.fget() is exactly the same + value = getattr(self._obj, key) + + if 'fmt' in d: + value = d['fmt'](value) + + title_ = d.get('title', None) + + return title_, str(value) + + def get_value(self, key, args, kwds): + # Let default get_value() handle ints + if not isinstance(key, str): + return Formatter.get_value(self, key, args, kwds) + + # HACK, we allow defining strings via fields to allow + # conversions + if key[:2] == 's|': + return key[2:] + + if key[:2] == 't|': + # title mode ("TITLE ATTR") + include_title = True + elif key[:2] == 'a|': + # plain attribute mode ("ATTR") + include_title = False + else: + # No special field, have default get_value() get it + return Formatter.get_value(self, key, args, kwds) + + key = key[2:] + (title_, value) = self._nlattr(key) + + if include_title: + if not title_: + title_ = key # fall back to key as title + value = '{0} {1}'.format(kw(title_), value) + + return value + + def convert_field(self, value, conversion): + if conversion == 'r': + return repr(value) + elif conversion == 's': + return str(value) + elif conversion == 'k': + return kw(value) + elif conversion == 'b': + return bold(value) + elif conversion is None: + return value + + raise ValueError('Unknown converion specifier {0!s}'.format(conversion)) + + def nl(self, format_string=''): + return '\n' + self._indent + self.format(format_string) + +NL_BYTE_RATE = 0 +NL_BIT_RATE = 1 + +class Rate(object): + def __init__(self, rate, mode=NL_BYTE_RATE): + self._rate = rate + self._mode = mode + + def __str__(self): + return capi.nl_rate2str(self._rate, self._mode, 32)[1] + + def __int__(self): + return self._rate + + def __cmp__(self, other): + return int(self) - int(other) + +class Size(object): + def __init__(self, size): + self._size = size + + def __str__(self): + return capi.nl_size2str(self._size, 32)[0] + + def __int__(self): + return self._size + + def __cmp__(self, other): + return int(self) - int(other) diff --git a/python/setup.py.in b/python/setup.py.in new file mode 100644 index 0000000..7ba90d7 --- /dev/null +++ b/python/setup.py.in @@ -0,0 +1,30 @@ +#!/usr/bin/env python + +from distutils.core import setup, Extension + +opts = ['-O', '-nodefaultctor'] +include = ['@top_builddir@/include'] + +netlink_capi = Extension('netlink/_capi', + sources = ['netlink/capi.i'], + include_dirs = include, + swig_opts = opts, + libraries = ['nl-3'], + ) + +route_capi = Extension('netlink/route/_capi', + sources = ['netlink/route/capi.i'], + include_dirs = include, + swig_opts = opts, + libraries = ['nl-3', 'nl-route-3'], + ) + +setup(name = 'netlink', + version = '1.0', + description = 'Python wrapper for netlink protocols', + author = 'Thomas Graf', + author_email = 'tgraf@suug.ch', + ext_modules = [netlink_capi, route_capi], + packages = ['netlink', 'netlink.route', 'netlink.route.links', + 'netlink.route.qdisc'], + ) diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..c318dcc --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,100 @@ +# -*- Makefile -*- + +SUBDIRS = lib + +AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" + +LDADD = \ + ${top_builddir}/src/lib/libnl-cli-3.la \ + ${top_builddir}/lib/libnl-3.la \ + ${top_builddir}/lib/libnl-nf-3.la \ + ${top_builddir}/lib/libnl-genl-3.la \ + ${top_builddir}/lib/libnl-route-3.la + +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 = \ + nf-ct-list 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-set nl-link-stats \ + nl-link-ifindex2name nl-link-name2ifindex \ + nl-neigh-add nl-neigh-delete nl-neigh-list \ + nl-rule-list \ + nl-neightbl-list \ + nl-monitor \ + nl-tctree-list \ + nl-route-add nl-route-delete nl-route-get nl-route-list \ + nl-fib-lookup \ + nl-list-caches nl-list-sockets \ + nl-util-addr \ + nl-link-enslave \ + nl-link-release + +genl_ctrl_list_SOURCES = genl-ctrl-list.c + +nf_ct_list_SOURCES = nf-ct-list.c +nf_log_SOURCES = nf-log.c +nf_queue_SOURCES = nf-queue.c +nf_monitor_SOURCES = nf-monitor.c + +nf_exp_list_SOURCES = nf-exp-list.c +nf_exp_add_SOURCES = nf-exp-add.c +nf_exp_delete_SOURCES = nf-exp-delete.c + +nl_addr_add_SOURCES = nl-addr-add.c +nl_addr_delete_SOURCES = nl-addr-delete.c +nl_addr_list_SOURCES = nl-addr-list.c + +nl_link_list_SOURCES = nl-link-list.c +nl_link_set_SOURCES = nl-link-set.c +nl_link_stats_SOURCES = nl-link-stats.c +nl_link_ifindex2name_SOURCES = nl-link-ifindex2name.c +nl_link_name2ifindex_SOURCES = nl-link-name2ifindex.c + +nl_monitor_SOURCES = nl-monitor.c + +nl_neigh_add_SOURCES = nl-neigh-add.c +nl_neigh_delete_SOURCES = nl-neigh-delete.c +nl_neigh_list_SOURCES = nl-neigh-list.c + +nl_neightbl_list_SOURCES = nl-neightbl-list.c + +nl_qdisc_add_SOURCES = nl-qdisc-add.c +nl_qdisc_delete_SOURCES = nl-qdisc-delete.c +nl_qdisc_list_SOURCES = nl-qdisc-list.c + +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_delete_SOURCES = nl-route-delete.c +nl_route_get_SOURCES = nl-route-get.c +nl_route_list_SOURCES = nl-route-list.c + +nl_rule_list_SOURCES = nl-rule-list.c + +nl_tctree_list_SOURCES = nl-tctree-list.c + +nl_fib_lookup_SOURCES = nl-fib-lookup.c + +nl_list_caches_SOURCES = nl-list-caches.c +nl_list_sockets_SOURCES = nl-list-sockets.c + +nl_util_addr_SOURCES = nl-util-addr.c + +nl_pktloc_lookup_SOURCES = nl-pktloc-lookup.c + +nl_classid_lookup_SOURCES = nl-classid-lookup.c diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..78abc10 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,1374 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# -*- Makefile -*- + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +sbin_PROGRAMS = genl-ctrl-list$(EXEEXT) nl-qdisc-add$(EXEEXT) \ + nl-qdisc-list$(EXEEXT) nl-qdisc-delete$(EXEEXT) \ + nl-class-add$(EXEEXT) nl-class-list$(EXEEXT) \ + nl-class-delete$(EXEEXT) nl-cls-add$(EXEEXT) \ + nl-cls-list$(EXEEXT) nl-cls-delete$(EXEEXT) \ + nl-classid-lookup$(EXEEXT) nl-pktloc-lookup$(EXEEXT) \ + nl-link-list$(EXEEXT) +noinst_PROGRAMS = nf-ct-list$(EXEEXT) nf-log$(EXEEXT) \ + nf-queue$(EXEEXT) nf-monitor$(EXEEXT) nf-exp-list$(EXEEXT) \ + nf-exp-add$(EXEEXT) nf-exp-delete$(EXEEXT) \ + nl-addr-add$(EXEEXT) nl-addr-delete$(EXEEXT) \ + nl-addr-list$(EXEEXT) nl-link-set$(EXEEXT) \ + nl-link-stats$(EXEEXT) nl-link-ifindex2name$(EXEEXT) \ + nl-link-name2ifindex$(EXEEXT) nl-neigh-add$(EXEEXT) \ + nl-neigh-delete$(EXEEXT) nl-neigh-list$(EXEEXT) \ + nl-rule-list$(EXEEXT) nl-neightbl-list$(EXEEXT) \ + nl-monitor$(EXEEXT) nl-tctree-list$(EXEEXT) \ + nl-route-add$(EXEEXT) nl-route-delete$(EXEEXT) \ + nl-route-get$(EXEEXT) nl-route-list$(EXEEXT) \ + nl-fib-lookup$(EXEEXT) nl-list-caches$(EXEEXT) \ + nl-list-sockets$(EXEEXT) nl-util-addr$(EXEEXT) \ + nl-link-enslave$(EXEEXT) nl-link-release$(EXEEXT) +subdir = src +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/lib/defs.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" +PROGRAMS = $(noinst_PROGRAMS) $(sbin_PROGRAMS) +am_genl_ctrl_list_OBJECTS = genl-ctrl-list.$(OBJEXT) +genl_ctrl_list_OBJECTS = $(am_genl_ctrl_list_OBJECTS) +genl_ctrl_list_LDADD = $(LDADD) +genl_ctrl_list_DEPENDENCIES = ${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 +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am_nf_ct_list_OBJECTS = nf-ct-list.$(OBJEXT) +nf_ct_list_OBJECTS = $(am_nf_ct_list_OBJECTS) +nf_ct_list_LDADD = $(LDADD) +nf_ct_list_DEPENDENCIES = ${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 +am_nf_exp_add_OBJECTS = nf-exp-add.$(OBJEXT) +nf_exp_add_OBJECTS = $(am_nf_exp_add_OBJECTS) +nf_exp_add_LDADD = $(LDADD) +nf_exp_add_DEPENDENCIES = ${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 +am_nf_exp_delete_OBJECTS = nf-exp-delete.$(OBJEXT) +nf_exp_delete_OBJECTS = $(am_nf_exp_delete_OBJECTS) +nf_exp_delete_LDADD = $(LDADD) +nf_exp_delete_DEPENDENCIES = ${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 +am_nf_exp_list_OBJECTS = nf-exp-list.$(OBJEXT) +nf_exp_list_OBJECTS = $(am_nf_exp_list_OBJECTS) +nf_exp_list_LDADD = $(LDADD) +nf_exp_list_DEPENDENCIES = ${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 +am_nf_log_OBJECTS = nf-log.$(OBJEXT) +nf_log_OBJECTS = $(am_nf_log_OBJECTS) +nf_log_LDADD = $(LDADD) +nf_log_DEPENDENCIES = ${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 +am_nf_monitor_OBJECTS = nf-monitor.$(OBJEXT) +nf_monitor_OBJECTS = $(am_nf_monitor_OBJECTS) +nf_monitor_LDADD = $(LDADD) +nf_monitor_DEPENDENCIES = ${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 +am_nf_queue_OBJECTS = nf-queue.$(OBJEXT) +nf_queue_OBJECTS = $(am_nf_queue_OBJECTS) +nf_queue_LDADD = $(LDADD) +nf_queue_DEPENDENCIES = ${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 +am_nl_addr_add_OBJECTS = nl-addr-add.$(OBJEXT) +nl_addr_add_OBJECTS = $(am_nl_addr_add_OBJECTS) +nl_addr_add_LDADD = $(LDADD) +nl_addr_add_DEPENDENCIES = ${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 +am_nl_addr_delete_OBJECTS = nl-addr-delete.$(OBJEXT) +nl_addr_delete_OBJECTS = $(am_nl_addr_delete_OBJECTS) +nl_addr_delete_LDADD = $(LDADD) +nl_addr_delete_DEPENDENCIES = ${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 +am_nl_addr_list_OBJECTS = nl-addr-list.$(OBJEXT) +nl_addr_list_OBJECTS = $(am_nl_addr_list_OBJECTS) +nl_addr_list_LDADD = $(LDADD) +nl_addr_list_DEPENDENCIES = ${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 +am_nl_class_add_OBJECTS = nl-class-add.$(OBJEXT) +nl_class_add_OBJECTS = $(am_nl_class_add_OBJECTS) +nl_class_add_LDADD = $(LDADD) +nl_class_add_DEPENDENCIES = ${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 +am_nl_class_delete_OBJECTS = nl-class-delete.$(OBJEXT) +nl_class_delete_OBJECTS = $(am_nl_class_delete_OBJECTS) +nl_class_delete_LDADD = $(LDADD) +nl_class_delete_DEPENDENCIES = ${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 +am_nl_class_list_OBJECTS = nl-class-list.$(OBJEXT) +nl_class_list_OBJECTS = $(am_nl_class_list_OBJECTS) +nl_class_list_LDADD = $(LDADD) +nl_class_list_DEPENDENCIES = ${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 +am_nl_classid_lookup_OBJECTS = nl-classid-lookup.$(OBJEXT) +nl_classid_lookup_OBJECTS = $(am_nl_classid_lookup_OBJECTS) +nl_classid_lookup_LDADD = $(LDADD) +nl_classid_lookup_DEPENDENCIES = \ + ${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 +am_nl_cls_add_OBJECTS = nl-cls-add.$(OBJEXT) +nl_cls_add_OBJECTS = $(am_nl_cls_add_OBJECTS) +nl_cls_add_LDADD = $(LDADD) +nl_cls_add_DEPENDENCIES = ${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 +am_nl_cls_delete_OBJECTS = nl-cls-delete.$(OBJEXT) +nl_cls_delete_OBJECTS = $(am_nl_cls_delete_OBJECTS) +nl_cls_delete_LDADD = $(LDADD) +nl_cls_delete_DEPENDENCIES = ${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 +am_nl_cls_list_OBJECTS = nl-cls-list.$(OBJEXT) +nl_cls_list_OBJECTS = $(am_nl_cls_list_OBJECTS) +nl_cls_list_LDADD = $(LDADD) +nl_cls_list_DEPENDENCIES = ${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 +am_nl_fib_lookup_OBJECTS = nl-fib-lookup.$(OBJEXT) +nl_fib_lookup_OBJECTS = $(am_nl_fib_lookup_OBJECTS) +nl_fib_lookup_LDADD = $(LDADD) +nl_fib_lookup_DEPENDENCIES = ${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 +nl_link_enslave_SOURCES = nl-link-enslave.c +nl_link_enslave_OBJECTS = nl-link-enslave.$(OBJEXT) +nl_link_enslave_LDADD = $(LDADD) +nl_link_enslave_DEPENDENCIES = ${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 +am_nl_link_ifindex2name_OBJECTS = nl-link-ifindex2name.$(OBJEXT) +nl_link_ifindex2name_OBJECTS = $(am_nl_link_ifindex2name_OBJECTS) +nl_link_ifindex2name_LDADD = $(LDADD) +nl_link_ifindex2name_DEPENDENCIES = \ + ${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 +am_nl_link_list_OBJECTS = nl-link-list.$(OBJEXT) +nl_link_list_OBJECTS = $(am_nl_link_list_OBJECTS) +nl_link_list_LDADD = $(LDADD) +nl_link_list_DEPENDENCIES = ${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 +am_nl_link_name2ifindex_OBJECTS = nl-link-name2ifindex.$(OBJEXT) +nl_link_name2ifindex_OBJECTS = $(am_nl_link_name2ifindex_OBJECTS) +nl_link_name2ifindex_LDADD = $(LDADD) +nl_link_name2ifindex_DEPENDENCIES = \ + ${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 +nl_link_release_SOURCES = nl-link-release.c +nl_link_release_OBJECTS = nl-link-release.$(OBJEXT) +nl_link_release_LDADD = $(LDADD) +nl_link_release_DEPENDENCIES = ${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 +am_nl_link_set_OBJECTS = nl-link-set.$(OBJEXT) +nl_link_set_OBJECTS = $(am_nl_link_set_OBJECTS) +nl_link_set_LDADD = $(LDADD) +nl_link_set_DEPENDENCIES = ${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 +am_nl_link_stats_OBJECTS = nl-link-stats.$(OBJEXT) +nl_link_stats_OBJECTS = $(am_nl_link_stats_OBJECTS) +nl_link_stats_LDADD = $(LDADD) +nl_link_stats_DEPENDENCIES = ${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 +am_nl_list_caches_OBJECTS = nl-list-caches.$(OBJEXT) +nl_list_caches_OBJECTS = $(am_nl_list_caches_OBJECTS) +nl_list_caches_LDADD = $(LDADD) +nl_list_caches_DEPENDENCIES = ${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 +am_nl_list_sockets_OBJECTS = nl-list-sockets.$(OBJEXT) +nl_list_sockets_OBJECTS = $(am_nl_list_sockets_OBJECTS) +nl_list_sockets_LDADD = $(LDADD) +nl_list_sockets_DEPENDENCIES = ${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 +am_nl_monitor_OBJECTS = nl-monitor.$(OBJEXT) +nl_monitor_OBJECTS = $(am_nl_monitor_OBJECTS) +nl_monitor_LDADD = $(LDADD) +nl_monitor_DEPENDENCIES = ${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 +am_nl_neigh_add_OBJECTS = nl-neigh-add.$(OBJEXT) +nl_neigh_add_OBJECTS = $(am_nl_neigh_add_OBJECTS) +nl_neigh_add_LDADD = $(LDADD) +nl_neigh_add_DEPENDENCIES = ${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 +am_nl_neigh_delete_OBJECTS = nl-neigh-delete.$(OBJEXT) +nl_neigh_delete_OBJECTS = $(am_nl_neigh_delete_OBJECTS) +nl_neigh_delete_LDADD = $(LDADD) +nl_neigh_delete_DEPENDENCIES = ${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 +am_nl_neigh_list_OBJECTS = nl-neigh-list.$(OBJEXT) +nl_neigh_list_OBJECTS = $(am_nl_neigh_list_OBJECTS) +nl_neigh_list_LDADD = $(LDADD) +nl_neigh_list_DEPENDENCIES = ${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 +am_nl_neightbl_list_OBJECTS = nl-neightbl-list.$(OBJEXT) +nl_neightbl_list_OBJECTS = $(am_nl_neightbl_list_OBJECTS) +nl_neightbl_list_LDADD = $(LDADD) +nl_neightbl_list_DEPENDENCIES = \ + ${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 +am_nl_pktloc_lookup_OBJECTS = nl-pktloc-lookup.$(OBJEXT) +nl_pktloc_lookup_OBJECTS = $(am_nl_pktloc_lookup_OBJECTS) +nl_pktloc_lookup_LDADD = $(LDADD) +nl_pktloc_lookup_DEPENDENCIES = \ + ${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 +am_nl_qdisc_add_OBJECTS = nl-qdisc-add.$(OBJEXT) +nl_qdisc_add_OBJECTS = $(am_nl_qdisc_add_OBJECTS) +nl_qdisc_add_LDADD = $(LDADD) +nl_qdisc_add_DEPENDENCIES = ${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 +am_nl_qdisc_delete_OBJECTS = nl-qdisc-delete.$(OBJEXT) +nl_qdisc_delete_OBJECTS = $(am_nl_qdisc_delete_OBJECTS) +nl_qdisc_delete_LDADD = $(LDADD) +nl_qdisc_delete_DEPENDENCIES = ${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 +am_nl_qdisc_list_OBJECTS = nl-qdisc-list.$(OBJEXT) +nl_qdisc_list_OBJECTS = $(am_nl_qdisc_list_OBJECTS) +nl_qdisc_list_LDADD = $(LDADD) +nl_qdisc_list_DEPENDENCIES = ${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 +am_nl_route_add_OBJECTS = nl-route-add.$(OBJEXT) +nl_route_add_OBJECTS = $(am_nl_route_add_OBJECTS) +nl_route_add_LDADD = $(LDADD) +nl_route_add_DEPENDENCIES = ${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 +am_nl_route_delete_OBJECTS = nl-route-delete.$(OBJEXT) +nl_route_delete_OBJECTS = $(am_nl_route_delete_OBJECTS) +nl_route_delete_LDADD = $(LDADD) +nl_route_delete_DEPENDENCIES = ${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 +am_nl_route_get_OBJECTS = nl-route-get.$(OBJEXT) +nl_route_get_OBJECTS = $(am_nl_route_get_OBJECTS) +nl_route_get_LDADD = $(LDADD) +nl_route_get_DEPENDENCIES = ${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 +am_nl_route_list_OBJECTS = nl-route-list.$(OBJEXT) +nl_route_list_OBJECTS = $(am_nl_route_list_OBJECTS) +nl_route_list_LDADD = $(LDADD) +nl_route_list_DEPENDENCIES = ${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 +am_nl_rule_list_OBJECTS = nl-rule-list.$(OBJEXT) +nl_rule_list_OBJECTS = $(am_nl_rule_list_OBJECTS) +nl_rule_list_LDADD = $(LDADD) +nl_rule_list_DEPENDENCIES = ${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 +am_nl_tctree_list_OBJECTS = nl-tctree-list.$(OBJEXT) +nl_tctree_list_OBJECTS = $(am_nl_tctree_list_OBJECTS) +nl_tctree_list_LDADD = $(LDADD) +nl_tctree_list_DEPENDENCIES = ${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 +am_nl_util_addr_OBJECTS = nl-util-addr.$(OBJEXT) +nl_util_addr_OBJECTS = $(am_nl_util_addr_OBJECTS) +nl_util_addr_LDADD = $(LDADD) +nl_util_addr_DEPENDENCIES = ${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 +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/lib +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(genl_ctrl_list_SOURCES) $(nf_ct_list_SOURCES) \ + $(nf_exp_add_SOURCES) $(nf_exp_delete_SOURCES) \ + $(nf_exp_list_SOURCES) $(nf_log_SOURCES) $(nf_monitor_SOURCES) \ + $(nf_queue_SOURCES) $(nl_addr_add_SOURCES) \ + $(nl_addr_delete_SOURCES) $(nl_addr_list_SOURCES) \ + $(nl_class_add_SOURCES) $(nl_class_delete_SOURCES) \ + $(nl_class_list_SOURCES) $(nl_classid_lookup_SOURCES) \ + $(nl_cls_add_SOURCES) $(nl_cls_delete_SOURCES) \ + $(nl_cls_list_SOURCES) $(nl_fib_lookup_SOURCES) \ + nl-link-enslave.c $(nl_link_ifindex2name_SOURCES) \ + $(nl_link_list_SOURCES) $(nl_link_name2ifindex_SOURCES) \ + nl-link-release.c $(nl_link_set_SOURCES) \ + $(nl_link_stats_SOURCES) $(nl_list_caches_SOURCES) \ + $(nl_list_sockets_SOURCES) $(nl_monitor_SOURCES) \ + $(nl_neigh_add_SOURCES) $(nl_neigh_delete_SOURCES) \ + $(nl_neigh_list_SOURCES) $(nl_neightbl_list_SOURCES) \ + $(nl_pktloc_lookup_SOURCES) $(nl_qdisc_add_SOURCES) \ + $(nl_qdisc_delete_SOURCES) $(nl_qdisc_list_SOURCES) \ + $(nl_route_add_SOURCES) $(nl_route_delete_SOURCES) \ + $(nl_route_get_SOURCES) $(nl_route_list_SOURCES) \ + $(nl_rule_list_SOURCES) $(nl_tctree_list_SOURCES) \ + $(nl_util_addr_SOURCES) +DIST_SOURCES = $(genl_ctrl_list_SOURCES) $(nf_ct_list_SOURCES) \ + $(nf_exp_add_SOURCES) $(nf_exp_delete_SOURCES) \ + $(nf_exp_list_SOURCES) $(nf_log_SOURCES) $(nf_monitor_SOURCES) \ + $(nf_queue_SOURCES) $(nl_addr_add_SOURCES) \ + $(nl_addr_delete_SOURCES) $(nl_addr_list_SOURCES) \ + $(nl_class_add_SOURCES) $(nl_class_delete_SOURCES) \ + $(nl_class_list_SOURCES) $(nl_classid_lookup_SOURCES) \ + $(nl_cls_add_SOURCES) $(nl_cls_delete_SOURCES) \ + $(nl_cls_list_SOURCES) $(nl_fib_lookup_SOURCES) \ + nl-link-enslave.c $(nl_link_ifindex2name_SOURCES) \ + $(nl_link_list_SOURCES) $(nl_link_name2ifindex_SOURCES) \ + nl-link-release.c $(nl_link_set_SOURCES) \ + $(nl_link_stats_SOURCES) $(nl_list_caches_SOURCES) \ + $(nl_list_sockets_SOURCES) $(nl_monitor_SOURCES) \ + $(nl_neigh_add_SOURCES) $(nl_neigh_delete_SOURCES) \ + $(nl_neigh_list_SOURCES) $(nl_neightbl_list_SOURCES) \ + $(nl_pktloc_lookup_SOURCES) $(nl_qdisc_add_SOURCES) \ + $(nl_qdisc_delete_SOURCES) $(nl_qdisc_list_SOURCES) \ + $(nl_route_add_SOURCES) $(nl_route_delete_SOURCES) \ + $(nl_route_get_SOURCES) $(nl_route_list_SOURCES) \ + $(nl_rule_list_SOURCES) $(nl_tctree_list_SOURCES) \ + $(nl_util_addr_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_CFLAGS = @CHECK_CFLAGS@ +CHECK_LIBS = @CHECK_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FLEX = @FLEX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBNL_VERSION = @LIBNL_VERSION@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_CURRENT = @LT_CURRENT@ +LT_REVISION = @LT_REVISION@ +MAJ_VERSION = @MAJ_VERSION@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIC_VERSION = @MIC_VERSION@ +MIN_VERSION = @MIN_VERSION@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgconfigdir = @pkgconfigdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = lib +AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" +LDADD = \ + ${top_builddir}/src/lib/libnl-cli-3.la \ + ${top_builddir}/lib/libnl-3.la \ + ${top_builddir}/lib/libnl-nf-3.la \ + ${top_builddir}/lib/libnl-genl-3.la \ + ${top_builddir}/lib/libnl-route-3.la + +genl_ctrl_list_SOURCES = genl-ctrl-list.c +nf_ct_list_SOURCES = nf-ct-list.c +nf_log_SOURCES = nf-log.c +nf_queue_SOURCES = nf-queue.c +nf_monitor_SOURCES = nf-monitor.c +nf_exp_list_SOURCES = nf-exp-list.c +nf_exp_add_SOURCES = nf-exp-add.c +nf_exp_delete_SOURCES = nf-exp-delete.c +nl_addr_add_SOURCES = nl-addr-add.c +nl_addr_delete_SOURCES = nl-addr-delete.c +nl_addr_list_SOURCES = nl-addr-list.c +nl_link_list_SOURCES = nl-link-list.c +nl_link_set_SOURCES = nl-link-set.c +nl_link_stats_SOURCES = nl-link-stats.c +nl_link_ifindex2name_SOURCES = nl-link-ifindex2name.c +nl_link_name2ifindex_SOURCES = nl-link-name2ifindex.c +nl_monitor_SOURCES = nl-monitor.c +nl_neigh_add_SOURCES = nl-neigh-add.c +nl_neigh_delete_SOURCES = nl-neigh-delete.c +nl_neigh_list_SOURCES = nl-neigh-list.c +nl_neightbl_list_SOURCES = nl-neightbl-list.c +nl_qdisc_add_SOURCES = nl-qdisc-add.c +nl_qdisc_delete_SOURCES = nl-qdisc-delete.c +nl_qdisc_list_SOURCES = nl-qdisc-list.c +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_delete_SOURCES = nl-route-delete.c +nl_route_get_SOURCES = nl-route-get.c +nl_route_list_SOURCES = nl-route-list.c +nl_rule_list_SOURCES = nl-rule-list.c +nl_tctree_list_SOURCES = nl-tctree-list.c +nl_fib_lookup_SOURCES = nl-fib-lookup.c +nl_list_caches_SOURCES = nl-list-caches.c +nl_list_sockets_SOURCES = nl-list-sockets.c +nl_util_addr_SOURCES = nl-util-addr.c +nl_pktloc_lookup_SOURCES = nl-pktloc-lookup.c +nl_classid_lookup_SOURCES = nl-classid-lookup.c +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sbindir)" && rm -f $$files + +clean-sbinPROGRAMS: + @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +genl-ctrl-list$(EXEEXT): $(genl_ctrl_list_OBJECTS) $(genl_ctrl_list_DEPENDENCIES) $(EXTRA_genl_ctrl_list_DEPENDENCIES) + @rm -f genl-ctrl-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(genl_ctrl_list_OBJECTS) $(genl_ctrl_list_LDADD) $(LIBS) +nf-ct-list$(EXEEXT): $(nf_ct_list_OBJECTS) $(nf_ct_list_DEPENDENCIES) $(EXTRA_nf_ct_list_DEPENDENCIES) + @rm -f nf-ct-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nf_ct_list_OBJECTS) $(nf_ct_list_LDADD) $(LIBS) +nf-exp-add$(EXEEXT): $(nf_exp_add_OBJECTS) $(nf_exp_add_DEPENDENCIES) $(EXTRA_nf_exp_add_DEPENDENCIES) + @rm -f nf-exp-add$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nf_exp_add_OBJECTS) $(nf_exp_add_LDADD) $(LIBS) +nf-exp-delete$(EXEEXT): $(nf_exp_delete_OBJECTS) $(nf_exp_delete_DEPENDENCIES) $(EXTRA_nf_exp_delete_DEPENDENCIES) + @rm -f nf-exp-delete$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nf_exp_delete_OBJECTS) $(nf_exp_delete_LDADD) $(LIBS) +nf-exp-list$(EXEEXT): $(nf_exp_list_OBJECTS) $(nf_exp_list_DEPENDENCIES) $(EXTRA_nf_exp_list_DEPENDENCIES) + @rm -f nf-exp-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nf_exp_list_OBJECTS) $(nf_exp_list_LDADD) $(LIBS) +nf-log$(EXEEXT): $(nf_log_OBJECTS) $(nf_log_DEPENDENCIES) $(EXTRA_nf_log_DEPENDENCIES) + @rm -f nf-log$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nf_log_OBJECTS) $(nf_log_LDADD) $(LIBS) +nf-monitor$(EXEEXT): $(nf_monitor_OBJECTS) $(nf_monitor_DEPENDENCIES) $(EXTRA_nf_monitor_DEPENDENCIES) + @rm -f nf-monitor$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nf_monitor_OBJECTS) $(nf_monitor_LDADD) $(LIBS) +nf-queue$(EXEEXT): $(nf_queue_OBJECTS) $(nf_queue_DEPENDENCIES) $(EXTRA_nf_queue_DEPENDENCIES) + @rm -f nf-queue$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nf_queue_OBJECTS) $(nf_queue_LDADD) $(LIBS) +nl-addr-add$(EXEEXT): $(nl_addr_add_OBJECTS) $(nl_addr_add_DEPENDENCIES) $(EXTRA_nl_addr_add_DEPENDENCIES) + @rm -f nl-addr-add$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_addr_add_OBJECTS) $(nl_addr_add_LDADD) $(LIBS) +nl-addr-delete$(EXEEXT): $(nl_addr_delete_OBJECTS) $(nl_addr_delete_DEPENDENCIES) $(EXTRA_nl_addr_delete_DEPENDENCIES) + @rm -f nl-addr-delete$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_addr_delete_OBJECTS) $(nl_addr_delete_LDADD) $(LIBS) +nl-addr-list$(EXEEXT): $(nl_addr_list_OBJECTS) $(nl_addr_list_DEPENDENCIES) $(EXTRA_nl_addr_list_DEPENDENCIES) + @rm -f nl-addr-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_addr_list_OBJECTS) $(nl_addr_list_LDADD) $(LIBS) +nl-class-add$(EXEEXT): $(nl_class_add_OBJECTS) $(nl_class_add_DEPENDENCIES) $(EXTRA_nl_class_add_DEPENDENCIES) + @rm -f nl-class-add$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_class_add_OBJECTS) $(nl_class_add_LDADD) $(LIBS) +nl-class-delete$(EXEEXT): $(nl_class_delete_OBJECTS) $(nl_class_delete_DEPENDENCIES) $(EXTRA_nl_class_delete_DEPENDENCIES) + @rm -f nl-class-delete$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_class_delete_OBJECTS) $(nl_class_delete_LDADD) $(LIBS) +nl-class-list$(EXEEXT): $(nl_class_list_OBJECTS) $(nl_class_list_DEPENDENCIES) $(EXTRA_nl_class_list_DEPENDENCIES) + @rm -f nl-class-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_class_list_OBJECTS) $(nl_class_list_LDADD) $(LIBS) +nl-classid-lookup$(EXEEXT): $(nl_classid_lookup_OBJECTS) $(nl_classid_lookup_DEPENDENCIES) $(EXTRA_nl_classid_lookup_DEPENDENCIES) + @rm -f nl-classid-lookup$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_classid_lookup_OBJECTS) $(nl_classid_lookup_LDADD) $(LIBS) +nl-cls-add$(EXEEXT): $(nl_cls_add_OBJECTS) $(nl_cls_add_DEPENDENCIES) $(EXTRA_nl_cls_add_DEPENDENCIES) + @rm -f nl-cls-add$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_cls_add_OBJECTS) $(nl_cls_add_LDADD) $(LIBS) +nl-cls-delete$(EXEEXT): $(nl_cls_delete_OBJECTS) $(nl_cls_delete_DEPENDENCIES) $(EXTRA_nl_cls_delete_DEPENDENCIES) + @rm -f nl-cls-delete$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_cls_delete_OBJECTS) $(nl_cls_delete_LDADD) $(LIBS) +nl-cls-list$(EXEEXT): $(nl_cls_list_OBJECTS) $(nl_cls_list_DEPENDENCIES) $(EXTRA_nl_cls_list_DEPENDENCIES) + @rm -f nl-cls-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_cls_list_OBJECTS) $(nl_cls_list_LDADD) $(LIBS) +nl-fib-lookup$(EXEEXT): $(nl_fib_lookup_OBJECTS) $(nl_fib_lookup_DEPENDENCIES) $(EXTRA_nl_fib_lookup_DEPENDENCIES) + @rm -f nl-fib-lookup$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_fib_lookup_OBJECTS) $(nl_fib_lookup_LDADD) $(LIBS) +nl-link-enslave$(EXEEXT): $(nl_link_enslave_OBJECTS) $(nl_link_enslave_DEPENDENCIES) $(EXTRA_nl_link_enslave_DEPENDENCIES) + @rm -f nl-link-enslave$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_link_enslave_OBJECTS) $(nl_link_enslave_LDADD) $(LIBS) +nl-link-ifindex2name$(EXEEXT): $(nl_link_ifindex2name_OBJECTS) $(nl_link_ifindex2name_DEPENDENCIES) $(EXTRA_nl_link_ifindex2name_DEPENDENCIES) + @rm -f nl-link-ifindex2name$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_link_ifindex2name_OBJECTS) $(nl_link_ifindex2name_LDADD) $(LIBS) +nl-link-list$(EXEEXT): $(nl_link_list_OBJECTS) $(nl_link_list_DEPENDENCIES) $(EXTRA_nl_link_list_DEPENDENCIES) + @rm -f nl-link-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_link_list_OBJECTS) $(nl_link_list_LDADD) $(LIBS) +nl-link-name2ifindex$(EXEEXT): $(nl_link_name2ifindex_OBJECTS) $(nl_link_name2ifindex_DEPENDENCIES) $(EXTRA_nl_link_name2ifindex_DEPENDENCIES) + @rm -f nl-link-name2ifindex$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_link_name2ifindex_OBJECTS) $(nl_link_name2ifindex_LDADD) $(LIBS) +nl-link-release$(EXEEXT): $(nl_link_release_OBJECTS) $(nl_link_release_DEPENDENCIES) $(EXTRA_nl_link_release_DEPENDENCIES) + @rm -f nl-link-release$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_link_release_OBJECTS) $(nl_link_release_LDADD) $(LIBS) +nl-link-set$(EXEEXT): $(nl_link_set_OBJECTS) $(nl_link_set_DEPENDENCIES) $(EXTRA_nl_link_set_DEPENDENCIES) + @rm -f nl-link-set$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_link_set_OBJECTS) $(nl_link_set_LDADD) $(LIBS) +nl-link-stats$(EXEEXT): $(nl_link_stats_OBJECTS) $(nl_link_stats_DEPENDENCIES) $(EXTRA_nl_link_stats_DEPENDENCIES) + @rm -f nl-link-stats$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_link_stats_OBJECTS) $(nl_link_stats_LDADD) $(LIBS) +nl-list-caches$(EXEEXT): $(nl_list_caches_OBJECTS) $(nl_list_caches_DEPENDENCIES) $(EXTRA_nl_list_caches_DEPENDENCIES) + @rm -f nl-list-caches$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_list_caches_OBJECTS) $(nl_list_caches_LDADD) $(LIBS) +nl-list-sockets$(EXEEXT): $(nl_list_sockets_OBJECTS) $(nl_list_sockets_DEPENDENCIES) $(EXTRA_nl_list_sockets_DEPENDENCIES) + @rm -f nl-list-sockets$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_list_sockets_OBJECTS) $(nl_list_sockets_LDADD) $(LIBS) +nl-monitor$(EXEEXT): $(nl_monitor_OBJECTS) $(nl_monitor_DEPENDENCIES) $(EXTRA_nl_monitor_DEPENDENCIES) + @rm -f nl-monitor$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_monitor_OBJECTS) $(nl_monitor_LDADD) $(LIBS) +nl-neigh-add$(EXEEXT): $(nl_neigh_add_OBJECTS) $(nl_neigh_add_DEPENDENCIES) $(EXTRA_nl_neigh_add_DEPENDENCIES) + @rm -f nl-neigh-add$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_neigh_add_OBJECTS) $(nl_neigh_add_LDADD) $(LIBS) +nl-neigh-delete$(EXEEXT): $(nl_neigh_delete_OBJECTS) $(nl_neigh_delete_DEPENDENCIES) $(EXTRA_nl_neigh_delete_DEPENDENCIES) + @rm -f nl-neigh-delete$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_neigh_delete_OBJECTS) $(nl_neigh_delete_LDADD) $(LIBS) +nl-neigh-list$(EXEEXT): $(nl_neigh_list_OBJECTS) $(nl_neigh_list_DEPENDENCIES) $(EXTRA_nl_neigh_list_DEPENDENCIES) + @rm -f nl-neigh-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_neigh_list_OBJECTS) $(nl_neigh_list_LDADD) $(LIBS) +nl-neightbl-list$(EXEEXT): $(nl_neightbl_list_OBJECTS) $(nl_neightbl_list_DEPENDENCIES) $(EXTRA_nl_neightbl_list_DEPENDENCIES) + @rm -f nl-neightbl-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_neightbl_list_OBJECTS) $(nl_neightbl_list_LDADD) $(LIBS) +nl-pktloc-lookup$(EXEEXT): $(nl_pktloc_lookup_OBJECTS) $(nl_pktloc_lookup_DEPENDENCIES) $(EXTRA_nl_pktloc_lookup_DEPENDENCIES) + @rm -f nl-pktloc-lookup$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_pktloc_lookup_OBJECTS) $(nl_pktloc_lookup_LDADD) $(LIBS) +nl-qdisc-add$(EXEEXT): $(nl_qdisc_add_OBJECTS) $(nl_qdisc_add_DEPENDENCIES) $(EXTRA_nl_qdisc_add_DEPENDENCIES) + @rm -f nl-qdisc-add$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_qdisc_add_OBJECTS) $(nl_qdisc_add_LDADD) $(LIBS) +nl-qdisc-delete$(EXEEXT): $(nl_qdisc_delete_OBJECTS) $(nl_qdisc_delete_DEPENDENCIES) $(EXTRA_nl_qdisc_delete_DEPENDENCIES) + @rm -f nl-qdisc-delete$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_qdisc_delete_OBJECTS) $(nl_qdisc_delete_LDADD) $(LIBS) +nl-qdisc-list$(EXEEXT): $(nl_qdisc_list_OBJECTS) $(nl_qdisc_list_DEPENDENCIES) $(EXTRA_nl_qdisc_list_DEPENDENCIES) + @rm -f nl-qdisc-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_qdisc_list_OBJECTS) $(nl_qdisc_list_LDADD) $(LIBS) +nl-route-add$(EXEEXT): $(nl_route_add_OBJECTS) $(nl_route_add_DEPENDENCIES) $(EXTRA_nl_route_add_DEPENDENCIES) + @rm -f nl-route-add$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_route_add_OBJECTS) $(nl_route_add_LDADD) $(LIBS) +nl-route-delete$(EXEEXT): $(nl_route_delete_OBJECTS) $(nl_route_delete_DEPENDENCIES) $(EXTRA_nl_route_delete_DEPENDENCIES) + @rm -f nl-route-delete$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_route_delete_OBJECTS) $(nl_route_delete_LDADD) $(LIBS) +nl-route-get$(EXEEXT): $(nl_route_get_OBJECTS) $(nl_route_get_DEPENDENCIES) $(EXTRA_nl_route_get_DEPENDENCIES) + @rm -f nl-route-get$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_route_get_OBJECTS) $(nl_route_get_LDADD) $(LIBS) +nl-route-list$(EXEEXT): $(nl_route_list_OBJECTS) $(nl_route_list_DEPENDENCIES) $(EXTRA_nl_route_list_DEPENDENCIES) + @rm -f nl-route-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_route_list_OBJECTS) $(nl_route_list_LDADD) $(LIBS) +nl-rule-list$(EXEEXT): $(nl_rule_list_OBJECTS) $(nl_rule_list_DEPENDENCIES) $(EXTRA_nl_rule_list_DEPENDENCIES) + @rm -f nl-rule-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_rule_list_OBJECTS) $(nl_rule_list_LDADD) $(LIBS) +nl-tctree-list$(EXEEXT): $(nl_tctree_list_OBJECTS) $(nl_tctree_list_DEPENDENCIES) $(EXTRA_nl_tctree_list_DEPENDENCIES) + @rm -f nl-tctree-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_tctree_list_OBJECTS) $(nl_tctree_list_LDADD) $(LIBS) +nl-util-addr$(EXEEXT): $(nl_util_addr_OBJECTS) $(nl_util_addr_DEPENDENCIES) $(EXTRA_nl_util_addr_DEPENDENCIES) + @rm -f nl-util-addr$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nl_util_addr_OBJECTS) $(nl_util_addr_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/genl-ctrl-list.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nf-ct-list.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nf-exp-add.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nf-exp-delete.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nf-exp-list.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nf-log.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nf-monitor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nf-queue.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-addr-add.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-addr-delete.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-addr-list.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-class-add.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-class-delete.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-class-list.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-classid-lookup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-cls-add.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-cls-delete.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-cls-list.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-fib-lookup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-link-enslave.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-link-ifindex2name.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-link-list.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-link-name2ifindex.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-link-release.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-link-set.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-link-stats.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-list-caches.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-list-sockets.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-monitor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-neigh-add.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-neigh-delete.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-neigh-list.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-neightbl-list.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-pktloc-lookup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-qdisc-add.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-qdisc-delete.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-qdisc-list.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-route-add.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-route-delete.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-route-get.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-route-list.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-rule-list.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-tctree-list.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-util-addr.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(PROGRAMS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(sbindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + clean-sbinPROGRAMS mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-sbinPROGRAMS + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-sbinPROGRAMS + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic clean-libtool \ + clean-noinstPROGRAMS clean-sbinPROGRAMS ctags ctags-recursive \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-sbinPROGRAMS install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-sbinPROGRAMS + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/genl-ctrl-list.c b/src/genl-ctrl-list.c new file mode 100644 index 0000000..0895bcc --- /dev/null +++ b/src/genl-ctrl-list.c @@ -0,0 +1,71 @@ +/* + * 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-2012 Thomas Graf + */ + +#include + +static struct nl_cache *alloc_genl_family_cache(struct nl_sock *sk) +{ + return nl_cli_alloc_cache(sk, "generic netlink family", + genl_ctrl_alloc_cache); +} + +static void print_usage(void) +{ + printf( + "Usage: genl-ctrl-list [--details]\n" + "\n" + "Options\n" + " -d, --details Include detailed information in the list\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 *family_cache; + struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_GENERIC); + family_cache = alloc_genl_family_cache(sock); + + 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, "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; + } + } + + nl_cache_dump(family_cache, ¶ms); + + return 0; +} diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am new file mode 100644 index 0000000..6688e7c --- /dev/null +++ b/src/lib/Makefile.am @@ -0,0 +1,43 @@ +# -*- Makefile -*- + +AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DPKGLIBDIR=\"$(pkglibdir)\" -DSYSCONFDIR=\"$(sysconfdir)\" -rdynamic +AM_LDFLAGS = \ + -L${top_builddir}/lib \ + -ldl \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) + +#nobase_pkglib_LTLIBRARIES = cls/basic.la cls/ematch/cmp.la +#cls_basic_la_LDFLAGS = -module -version-info 2:0:0 +#cls_ematch_cmp_la_LDFLAGS = -module -version-info 2:0:0 + +#cls/ematch_grammar.c: cls/ematch_grammar.l +# $(LEX) --header-file=cls/ematch_grammar.h $(LFLAGS) -o $@ $^ + +#cls/ematch_syntax.c: cls/ematch_syntax.y +# $(YACC) -d $(YFLAGS) -o $@ $^ + +#cls/pktloc_grammar.c: cls/pktloc_grammar.l +# $(LEX) --header-file=cls/pktloc_grammar.h $(LFLAGS) -o $@ $^ + +#cls/pktloc_syntax.c: cls/pktloc_syntax.y +# $(YACC) -d $(YFLAGS) -o $@ $^ + +#CLEANFILES = \ +# cls/ematch_grammar.c cls/ematch_grammar.h \ +# cls/ematch_syntax.c cls/ematch_syntax.h \ +# cls/pktloc_grammar.c cls/pktloc_grammar.h \ +# cls/pktloc_syntax.c cls/pktloc_syntax.h + +lib_LTLIBRARIES = \ + libnl-cli-3.la + +libnl_cli_3_la_LIBADD = ${top_builddir}/lib/libnl-3.la \ + ${top_builddir}/lib/libnl-route-3.la \ + ${top_builddir}/lib/libnl-nf-3.la \ + ${top_builddir}/lib/libnl-genl-3.la + +libnl_cli_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/Makefile.in b/src/lib/Makefile.in new file mode 100644 index 0000000..025484a --- /dev/null +++ b/src/lib/Makefile.in @@ -0,0 +1,643 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# -*- Makefile -*- + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/lib/defs.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +libnl_cli_3_la_DEPENDENCIES = ${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 +am_libnl_cli_3_la_OBJECTS = utils.lo addr.lo ct.lo link.lo neigh.lo \ + rule.lo route.lo tc.lo qdisc.lo class.lo cls.lo exp.lo +libnl_cli_3_la_OBJECTS = $(am_libnl_cli_3_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/lib +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libnl_cli_3_la_SOURCES) +DIST_SOURCES = $(libnl_cli_3_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_CFLAGS = @CHECK_CFLAGS@ +CHECK_LIBS = @CHECK_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FLEX = @FLEX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBNL_VERSION = @LIBNL_VERSION@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_CURRENT = @LT_CURRENT@ +LT_REVISION = @LT_REVISION@ +MAJ_VERSION = @MAJ_VERSION@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIC_VERSION = @MIC_VERSION@ +MIN_VERSION = @MIN_VERSION@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgconfigdir = @pkgconfigdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DPKGLIBDIR=\"$(pkglibdir)\" -DSYSCONFDIR=\"$(sysconfdir)\" -rdynamic +AM_LDFLAGS = \ + -L${top_builddir}/lib \ + -ldl \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) + + +#nobase_pkglib_LTLIBRARIES = cls/basic.la cls/ematch/cmp.la +#cls_basic_la_LDFLAGS = -module -version-info 2:0:0 +#cls_ematch_cmp_la_LDFLAGS = -module -version-info 2:0:0 + +#cls/ematch_grammar.c: cls/ematch_grammar.l +# $(LEX) --header-file=cls/ematch_grammar.h $(LFLAGS) -o $@ $^ + +#cls/ematch_syntax.c: cls/ematch_syntax.y +# $(YACC) -d $(YFLAGS) -o $@ $^ + +#cls/pktloc_grammar.c: cls/pktloc_grammar.l +# $(LEX) --header-file=cls/pktloc_grammar.h $(LFLAGS) -o $@ $^ + +#cls/pktloc_syntax.c: cls/pktloc_syntax.y +# $(YACC) -d $(YFLAGS) -o $@ $^ + +#CLEANFILES = \ +# cls/ematch_grammar.c cls/ematch_grammar.h \ +# cls/ematch_syntax.c cls/ematch_syntax.h \ +# cls/pktloc_grammar.c cls/pktloc_grammar.h \ +# cls/pktloc_syntax.c cls/pktloc_syntax.h +lib_LTLIBRARIES = \ + libnl-cli-3.la + +libnl_cli_3_la_LIBADD = ${top_builddir}/lib/libnl-3.la \ + ${top_builddir}/lib/libnl-route-3.la \ + ${top_builddir}/lib/libnl-nf-3.la \ + ${top_builddir}/lib/libnl-genl-3.la + +libnl_cli_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 + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libnl-cli-3.la: $(libnl_cli_3_la_OBJECTS) $(libnl_cli_3_la_DEPENDENCIES) $(EXTRA_libnl_cli_3_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) -rpath $(libdir) $(libnl_cli_3_la_OBJECTS) $(libnl_cli_3_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/class.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cls.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ct.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/link.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/neigh.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qdisc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/route.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rule.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-libLTLIBRARIES + +# cls/ematch_syntax.c cls/ematch_grammar.c cls/ematch.c +# cls/pktloc_syntax.c cls/pktloc_grammar.c cls/utils.c + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/lib/addr.c b/src/lib/addr.c new file mode 100644 index 0000000..a9c137b --- /dev/null +++ b/src/lib/addr.c @@ -0,0 +1,135 @@ +/* + * src/lib/addr.c Address 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 + */ + +/** + * @ingroup cli + * @defgroup cli_addr Addresses + * + * @{ + */ + +#include +#include + +struct rtnl_addr *nl_cli_addr_alloc(void) +{ + struct rtnl_addr *addr; + + addr = rtnl_addr_alloc(); + if (!addr) + nl_cli_fatal(ENOMEM, "Unable to allocate address object"); + + return addr; +} + +void nl_cli_addr_parse_family(struct rtnl_addr *addr, char *arg) +{ + int family; + + if ((family = nl_str2af(arg)) != AF_UNSPEC) + rtnl_addr_set_family(addr, family); +} + +void nl_cli_addr_parse_local(struct rtnl_addr *addr, char *arg) +{ + struct nl_addr *a; + int err; + + a = nl_cli_addr_parse(arg, rtnl_addr_get_family(addr)); + if ((err = rtnl_addr_set_local(addr, a)) < 0) + nl_cli_fatal(err, "Unable to set local address: %s", + nl_geterror(err)); + + nl_addr_put(a); +} + +void nl_cli_addr_parse_dev(struct rtnl_addr *addr, 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_addr_set_ifindex(addr, ival); +} + +void nl_cli_addr_parse_label(struct rtnl_addr *addr, char *arg) +{ + int err; + + if ((err = rtnl_addr_set_label(addr, arg)) < 0) + nl_cli_fatal(err, "Unable to set address label: %s", + nl_geterror(err)); +} + +void nl_cli_addr_parse_peer(struct rtnl_addr *addr, char *arg) +{ + struct nl_addr *a; + int err; + + a = nl_cli_addr_parse(arg, rtnl_addr_get_family(addr)); + if ((err = rtnl_addr_set_peer(addr, a)) < 0) + nl_cli_fatal(err, "Unable to set peer address: %s", + nl_geterror(err)); + + nl_addr_put(a); +} + +void nl_cli_addr_parse_scope(struct rtnl_addr *addr, char *arg) +{ + int ival; + + if ((ival = rtnl_str2scope(arg)) < 0) + nl_cli_fatal(EINVAL, "Unknown address scope \"%s\"", arg); + + rtnl_addr_set_scope(addr, ival); +} + +void nl_cli_addr_parse_broadcast(struct rtnl_addr *addr, char *arg) +{ + struct nl_addr *a; + int err; + + a = nl_cli_addr_parse(arg, rtnl_addr_get_family(addr)); + if ((err = rtnl_addr_set_broadcast(addr, a)) < 0) + nl_cli_fatal(err, "Unable to set broadcast address: %s", + nl_geterror(err)); + + nl_addr_put(a); +} + +static uint32_t parse_lifetime(const char *arg) +{ + uint64_t msecs; + int err; + + if (!strcasecmp(arg, "forever")) + return 0xFFFFFFFFU; + + if ((err = nl_str2msec(arg, &msecs)) < 0) + nl_cli_fatal(err, "Unable to parse time string \"%s\": %s", + arg, nl_geterror(err)); + + return (msecs / 1000); +} + +void nl_cli_addr_parse_preferred(struct rtnl_addr *addr, char *arg) +{ + rtnl_addr_set_preferred_lifetime(addr, parse_lifetime(arg)); +} + +void nl_cli_addr_parse_valid(struct rtnl_addr *addr, char *arg) +{ + rtnl_addr_set_valid_lifetime(addr, parse_lifetime(arg)); +} + +/** @} */ diff --git a/src/lib/class.c b/src/lib/class.c new file mode 100644 index 0000000..96f60cd --- /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 + */ + +/** + * @ingroup cli + * @defgroup cli_class Traffic Classes + * @{ + */ + +#include +#include + +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 0000000..86d775d --- /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 + */ + +/** + * @ingroup cli + * @defgroup cli_cls Classifiers + * @{ + */ + +#include +#include +#include + +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 new file mode 100644 index 0000000..5bab08f --- /dev/null +++ b/src/lib/ct.c @@ -0,0 +1,162 @@ +/* + * src/lib/ct.c CLI Conntrack 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 + */ + +/** + * @ingroup cli + * @defgroup cli_ct Connection Tracking + * + * @{ + */ + +#include +#include + +struct nfnl_ct *nl_cli_ct_alloc(void) +{ + struct nfnl_ct *ct; + + ct = nfnl_ct_alloc(); + if (!ct) + nl_cli_fatal(ENOMEM, "Unable to allocate conntrack object"); + + return ct; +} + +struct nl_cache *nl_cli_ct_alloc_cache(struct nl_sock *sk) +{ + return nl_cli_alloc_cache(sk, "conntrack", nfnl_ct_alloc_cache); +} + +void nl_cli_ct_parse_family(struct nfnl_ct *ct, char *arg) +{ + int family; + + if ((family = nl_str2af(arg)) == AF_UNSPEC) + nl_cli_fatal(EINVAL, + "Unable to nl_cli_ct_parse family \"%s\": %s", + arg, nl_geterror(NLE_INVAL)); + + nfnl_ct_set_family(ct, family); +} + +void nl_cli_ct_parse_protocol(struct nfnl_ct *ct, char *arg) +{ + int proto; + + if ((proto = nl_str2ip_proto(arg)) < 0) + nl_cli_fatal(proto, + "Unable to nl_cli_ct_parse protocol \"%s\": %s", + arg, nl_geterror(proto)); + + nfnl_ct_set_proto(ct, proto); +} + +void nl_cli_ct_parse_mark(struct nfnl_ct *ct, char *arg) +{ + uint32_t mark = nl_cli_parse_u32(arg); + nfnl_ct_set_mark(ct, mark); +} + +void nl_cli_ct_parse_timeout(struct nfnl_ct *ct, char *arg) +{ + uint32_t timeout = nl_cli_parse_u32(arg); + nfnl_ct_set_timeout(ct, timeout); +} + +void nl_cli_ct_parse_id(struct nfnl_ct *ct, char *arg) +{ + uint32_t id = nl_cli_parse_u32(arg); + nfnl_ct_set_id(ct, id); +} + +void nl_cli_ct_parse_use(struct nfnl_ct *ct, char *arg) +{ + uint32_t use = nl_cli_parse_u32(arg); + nfnl_ct_set_use(ct, use); +} + +void nl_cli_ct_parse_src(struct nfnl_ct *ct, int reply, char *arg) +{ + int err; + struct nl_addr *a = nl_cli_addr_parse(arg, nfnl_ct_get_family(ct)); + if ((err = nfnl_ct_set_src(ct, reply, a)) < 0) + nl_cli_fatal(err, "Unable to set source address: %s", + nl_geterror(err)); +} + +void nl_cli_ct_parse_dst(struct nfnl_ct *ct, int reply, char *arg) +{ + int err; + struct nl_addr *a = nl_cli_addr_parse(arg, nfnl_ct_get_family(ct)); + if ((err = nfnl_ct_set_dst(ct, reply, a)) < 0) + nl_cli_fatal(err, "Unable to set destination address: %s", + nl_geterror(err)); +} + +void nl_cli_ct_parse_src_port(struct nfnl_ct *ct, int reply, char *arg) +{ + uint32_t port = nl_cli_parse_u32(arg); + nfnl_ct_set_src_port(ct, reply, port); +} + +void nl_cli_ct_parse_dst_port(struct nfnl_ct *ct, int reply, char *arg) +{ + uint32_t port = nl_cli_parse_u32(arg); + nfnl_ct_set_dst_port(ct, reply, port); +} + +void nl_cli_ct_parse_tcp_state(struct nfnl_ct *ct, char *arg) +{ + int state; + + if ((state = nfnl_ct_str2tcp_state(arg)) < 0) + nl_cli_fatal(state, + "Unable to nl_cli_ct_parse tcp state \"%s\": %s", + arg, nl_geterror(state)); + + nfnl_ct_set_tcp_state(ct, state); +} + +void nl_cli_ct_parse_status(struct nfnl_ct *ct, char *arg) +{ + int status; + + if ((status = nfnl_ct_str2status(arg)) < 0) + nl_cli_fatal(status, + "Unable to nl_cli_ct_parse flags \"%s\": %s", + arg, nl_geterror(status)); + + nfnl_ct_set_status(ct, status); +} + +#if 0 + } else if (arg_match("origicmpid")) { + if (argc > ++idx) + nfnl_ct_set_icmp_id(ct, 0, strtoul(argv[idx++], NULL, 0)); + } else if (arg_match("origicmptype")) { + if (argc > ++idx) + nfnl_ct_set_icmp_type(ct, 0, strtoul(argv[idx++], NULL, 0)); + } else if (arg_match("origicmpcode")) { + if (argc > ++idx) + nfnl_ct_set_icmp_code(ct, 0, strtoul(argv[idx++], NULL, 0)); + } else if (arg_match("replyicmpid")) { + if (argc > ++idx) + nfnl_ct_set_icmp_id(ct, 1, strtoul(argv[idx++], NULL, 0)); + } else if (arg_match("replyicmptype")) { + if (argc > ++idx) + nfnl_ct_set_icmp_type(ct, 1, strtoul(argv[idx++], NULL, 0)); + } else if (arg_match("replyicmpcode")) { + if (argc > ++idx) + nfnl_ct_set_icmp_code(ct, 1, strtoul(argv[idx++], NULL, 0)); + } +#endif + +/** @} */ diff --git a/src/lib/exp.c b/src/lib/exp.c new file mode 100644 index 0000000..a7a74f5 --- /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 + * Copyright (c) 2012 Rich Fought + */ + +/** + * @ingroup cli + * @defgroup cli_exp Expectation Tracking + * + * @{ + */ + +#include +#include + +struct nfnl_exp *nl_cli_exp_alloc(void) +{ + struct nfnl_exp *exp; + + exp = nfnl_exp_alloc(); + if (!exp) + nl_cli_fatal(ENOMEM, "Unable to allocate expectation object"); + + return exp; +} + +struct nl_cache *nl_cli_exp_alloc_cache(struct nl_sock *sk) +{ + return nl_cli_alloc_cache(sk, "expectation", nfnl_exp_alloc_cache); +} + +void nl_cli_exp_parse_family(struct nfnl_exp *exp, char *arg) +{ + int family; + + if ((family = nl_str2af(arg)) == AF_UNSPEC) + nl_cli_fatal(EINVAL, + "Unable to nl_cli_exp_parse family \"%s\": %s", + arg, nl_geterror(NLE_INVAL)); + + nfnl_exp_set_family(exp, family); +} + +void nl_cli_exp_parse_timeout(struct nfnl_exp *exp, char *arg) +{ + uint32_t timeout = nl_cli_parse_u32(arg); + nfnl_exp_set_timeout(exp, timeout); +} + +void nl_cli_exp_parse_id(struct nfnl_exp *exp, char *arg) +{ + uint32_t id = nl_cli_parse_u32(arg); + nfnl_exp_set_id(exp, id); +} + +void nl_cli_exp_parse_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 new file mode 100644 index 0000000..5bce824 --- /dev/null +++ b/src/lib/link.c @@ -0,0 +1,101 @@ +/* + * src/lib/link.c CLI Link 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-2010 Thomas Graf + */ + +/** + * @ingroup cli + * @defgroup cli_link Links + * + * @{ + */ + +#include +#include +#include + +struct rtnl_link *nl_cli_link_alloc(void) +{ + struct rtnl_link *link; + + link = rtnl_link_alloc(); + if (!link) + nl_cli_fatal(ENOMEM, "Unable to allocate link object"); + + 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)) < 0) + nl_cli_fatal(EINVAL, + "Unable to translate address family \"%s\"", arg); + + rtnl_link_set_family(link, family); +} + +void nl_cli_link_parse_name(struct rtnl_link *link, char *arg) +{ + rtnl_link_set_name(link, arg); +} + +void nl_cli_link_parse_mtu(struct rtnl_link *link, char *arg) +{ + uint32_t mtu = nl_cli_parse_u32(arg); + rtnl_link_set_mtu(link, mtu); +} + +void nl_cli_link_parse_ifindex(struct rtnl_link *link, char *arg) +{ + uint32_t index = nl_cli_parse_u32(arg); + rtnl_link_set_ifindex(link, index); +} + +void nl_cli_link_parse_txqlen(struct rtnl_link *link, char *arg) +{ + uint32_t qlen = nl_cli_parse_u32(arg); + rtnl_link_set_txqlen(link, qlen); +} + +void nl_cli_link_parse_weight(struct rtnl_link *link, char *arg) +{ +} + +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 new file mode 100644 index 0000000..a814bd8 --- /dev/null +++ b/src/lib/neigh.c @@ -0,0 +1,88 @@ +/* + * src/lib/neigh.c CLI Neighbour 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 + */ + +/** + * @ingroup cli + * @defgroup cli_neigh Neighbour + * + * @{ + */ + +#include +#include + +struct rtnl_neigh *nl_cli_neigh_alloc(void) +{ + struct rtnl_neigh *neigh; + + neigh = rtnl_neigh_alloc(); + if (!neigh) + nl_cli_fatal(ENOMEM, "Unable to allocate neighbout object"); + + return neigh; +} + +void nl_cli_neigh_parse_dst(struct rtnl_neigh *neigh, char *arg) +{ + struct nl_addr *a; + int err; + + a = nl_cli_addr_parse(arg, rtnl_neigh_get_family(neigh)); + if ((err = rtnl_neigh_set_dst(neigh, a)) < 0) + nl_cli_fatal(err, "Unable to set local address: %s", + nl_geterror(err)); + + nl_addr_put(a); +} + +void nl_cli_neigh_parse_lladdr(struct rtnl_neigh *neigh, char *arg) +{ + struct nl_addr *a; + + a = nl_cli_addr_parse(arg, AF_UNSPEC); + rtnl_neigh_set_lladdr(neigh, a); + nl_addr_put(a); +} + +void nl_cli_neigh_parse_dev(struct rtnl_neigh *neigh, + 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_neigh_set_ifindex(neigh, ival); +} + +void nl_cli_neigh_parse_family(struct rtnl_neigh *neigh, char *arg) +{ + int family; + + if ((family = nl_str2af(arg)) == AF_UNSPEC) + nl_cli_fatal(EINVAL, + "Unable to translate address family \"%s\"", arg); + + rtnl_neigh_set_family(neigh, family); +} + +void nl_cli_neigh_parse_state(struct rtnl_neigh *neigh, char *arg) +{ + int state; + + if ((state = rtnl_neigh_str2state(arg)) < 0) + nl_cli_fatal(state, "Unable to translate state \"%s\": %s", + arg, state); + + rtnl_neigh_set_state(neigh, state); +} + +/** @} */ diff --git a/src/lib/qdisc.c b/src/lib/qdisc.c new file mode 100644 index 0000000..ccf7d26 --- /dev/null +++ b/src/lib/qdisc.c @@ -0,0 +1,32 @@ +/* + * src/lib/qdisc.c CLI QDisc 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-2011 Thomas Graf + */ + +/** + * @ingroup cli + * @defgroup cli_qdisc Queueing Disciplines + * @{ + */ + +#include +#include +#include + +struct rtnl_qdisc *nl_cli_qdisc_alloc(void) +{ + struct rtnl_qdisc *qdisc; + + if (!(qdisc = rtnl_qdisc_alloc())) + nl_cli_fatal(ENOMEM, "Unable to allocate qdisc object"); + + return qdisc; +} + +/** @} */ diff --git a/src/lib/route.c b/src/lib/route.c new file mode 100644 index 0000000..cd3e897 --- /dev/null +++ b/src/lib/route.c @@ -0,0 +1,278 @@ +/* + * src/lib/route.c CLI Route 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 + */ + +/** + * @ingroup cli + * @defgroup cli_route Routing + * + * @{ + */ + +#include +#include + +struct rtnl_route *nl_cli_route_alloc(void) +{ + struct rtnl_route *route; + + route = rtnl_route_alloc(); + if (!route) + nl_cli_fatal(ENOMEM, "Unable to allocate route object"); + + return route; +} + +struct nl_cache *nl_cli_route_alloc_cache(struct nl_sock *sk, int flags) +{ + struct nl_cache *cache; + int err; + + if ((err = rtnl_route_alloc_cache(sk, AF_UNSPEC, flags, &cache)) < 0) + nl_cli_fatal(err, "Unable to allocate route cache: %s\n", + nl_geterror(err)); + + nl_cache_mngt_provide(cache); + + return cache; +} + +void nl_cli_route_parse_family(struct rtnl_route *route, char *arg) +{ + int family; + + if ((family = nl_str2af(arg)) != AF_UNSPEC) + rtnl_route_set_family(route, family); +} + +void nl_cli_route_parse_dst(struct rtnl_route *route, char *arg) +{ + struct nl_addr *addr; + int err; + + addr = nl_cli_addr_parse(arg, rtnl_route_get_family(route)); + if ((err = rtnl_route_set_dst(route, addr)) < 0) + nl_cli_fatal(err, "Unable to set destination address: %s", + nl_geterror(err)); + + nl_addr_put(addr); +} + +void nl_cli_route_parse_src(struct rtnl_route *route, char *arg) +{ + struct nl_addr *addr; + int err; + + addr = nl_cli_addr_parse(arg, rtnl_route_get_family(route)); + if ((err = rtnl_route_set_src(route, addr)) < 0) + nl_cli_fatal(err, "Unable to set source address: %s", + nl_geterror(err)); + + nl_addr_put(addr); +} + +void nl_cli_route_parse_pref_src(struct rtnl_route *route, char *arg) +{ + struct nl_addr *addr; + int err; + + addr = nl_cli_addr_parse(arg, rtnl_route_get_family(route)); + if ((err = rtnl_route_set_pref_src(route, addr)) < 0) + nl_cli_fatal(err, "Unable to set preferred source address: %s", + nl_geterror(err)); + + nl_addr_put(addr); +} + +void nl_cli_route_parse_metric(struct rtnl_route *route, char *subopts) +{ + /* strict equal order to RTAX_* */ + static char *const tokens[] = { + "unspec", + "lock", + "mtu", + "window", + "rtt", + "rttvar", + "sstresh", + "cwnd", + "advmss", + "reordering", + "hoplimit", + "initcwnd", + "features", + NULL, + }; + unsigned long lval; + char *arg, *endptr; + + while (*subopts != '\0') { + int ret = getsubopt(&subopts, tokens, &arg); + if (ret == -1) + nl_cli_fatal(EINVAL, "Unknown metric token \"%s\"", arg); + + if (ret == 0) + nl_cli_fatal(EINVAL, "Invalid metric \"%s\"", tokens[ret]); + + if (arg == NULL) + nl_cli_fatal(EINVAL, "Metric \"%s\", no value given", tokens[ret]); + + lval = strtoul(arg, &endptr, 0); + if (endptr == arg) + nl_cli_fatal(EINVAL, "Metric \"%s\", value not numeric", tokens[ret]); + + if ((ret = rtnl_route_set_metric(route, ret, lval)) < 0) + nl_cli_fatal(ret, "Unable to set metric: %s", + nl_geterror(ret)); + } +} + +void nl_cli_route_parse_nexthop(struct rtnl_route *route, char *subopts, + struct nl_cache *link_cache) +{ + enum { + NH_DEV, + NH_VIA, + NH_WEIGHT, + }; + static char *const tokens[] = { + "dev", + "via", + "weight", + NULL, + }; + struct rtnl_nexthop *nh; + unsigned long lval; + struct nl_addr *addr; + int ival; + char *arg, *endptr; + + if (!(nh = rtnl_route_nh_alloc())) + nl_cli_fatal(ENOMEM, "Out of memory"); + + while (*subopts != '\0') { + int ret = getsubopt(&subopts, tokens, &arg); + if (ret == -1) + nl_cli_fatal(EINVAL, "Unknown nexthop token \"%s\"", arg); + + if (arg == NULL) + nl_cli_fatal(EINVAL, "Missing argument to option \"%s\"\n", + tokens[ret]); + + switch (ret) { + case NH_DEV: + if (!(ival = rtnl_link_name2i(link_cache, arg))) + nl_cli_fatal(ENOENT,"Link \"%s\" does not exist", arg); + + rtnl_route_nh_set_ifindex(nh, ival); + break; + + case NH_VIA: + addr = nl_cli_addr_parse(arg,rtnl_route_get_family(route)); + rtnl_route_nh_set_gateway(nh, addr); + nl_addr_put(addr); + break; + + case NH_WEIGHT: + lval = strtoul(arg, &endptr, 0); + if (endptr == arg) + nl_cli_fatal(EINVAL, + "Invalid weight \"%s\", not numeric", + arg); + rtnl_route_nh_set_weight(nh, lval); + break; + } + } + + rtnl_route_add_nexthop(route, nh); +} + +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 ((table = rtnl_route_str2table(arg)) < 0) + nl_cli_fatal(EINVAL, "Unknown table name \"%s\"", arg); + } + else { + table = lval; + } + + rtnl_route_set_table(route, table); +} + +void nl_cli_route_parse_prio(struct rtnl_route *route, char *arg) +{ + unsigned long lval; + char *endptr; + + lval = strtoul(arg, &endptr, 0); + if (endptr == arg) + nl_cli_fatal(EINVAL, "Invalid priority value, not numeric"); + rtnl_route_set_priority(route, lval); +} + +void nl_cli_route_parse_scope(struct rtnl_route *route, char *arg) +{ + int ival; + + if ((ival = rtnl_str2scope(arg)) < 0) + nl_cli_fatal(EINVAL, "Unknown routing scope \"%s\"", arg); + + rtnl_route_set_scope(route, ival); +} + +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 ((proto = rtnl_route_str2proto(arg)) < 0) + nl_cli_fatal(EINVAL, + "Unknown routing protocol name \"%s\"", + arg); + } + else { + proto = lval; + } + + rtnl_route_set_protocol(route, proto); +} + +void nl_cli_route_parse_type(struct rtnl_route *route, char *arg) +{ + int ival; + + if ((ival = nl_str2rtntype(arg)) < 0) + nl_cli_fatal(EINVAL, "Unknown routing type \"%s\"", arg); + + if ((ival = rtnl_route_set_type(route, ival)) < 0) + nl_cli_fatal(ival, "Unable to set routing type: %s", + nl_geterror(ival)); +} + +void nl_cli_route_parse_iif(struct rtnl_route *route, char *arg, struct nl_cache *link_cache) +{ + int ival; + + if (!(ival = rtnl_link_name2i(link_cache, arg))) + nl_cli_fatal(ENOENT, "Link \"%s\" does not exist", arg); + + rtnl_route_set_iif(route, ival); +} + +/** @} */ diff --git a/src/lib/rule.c b/src/lib/rule.c new file mode 100644 index 0000000..96f1d4c --- /dev/null +++ b/src/lib/rule.c @@ -0,0 +1,55 @@ +/* + * src/lib/rule.c CLI Routing Rule 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 + */ + +/** + * @ingroup cli + * @defgroup cli_rule Routing Rules + * + * @{ + */ + +#include +#include + +struct rtnl_rule *nl_cli_rule_alloc(void) +{ + struct rtnl_rule *rule; + + rule = rtnl_rule_alloc(); + if (!rule) + nl_cli_fatal(ENOMEM, "Unable to allocate rule object"); + + return rule; +} + +struct nl_cache *nl_cli_rule_alloc_cache(struct nl_sock *sk) +{ + struct nl_cache *cache; + int err; + + if ((err = rtnl_rule_alloc_cache(sk, AF_UNSPEC, &cache)) < 0) + nl_cli_fatal(err, "Unable to allocate routing rule cache: %s\n", + nl_geterror(err)); + + nl_cache_mngt_provide(cache); + + return cache; +} + +void nl_cli_rule_parse_family(struct rtnl_rule *rule, char *arg) +{ + int family; + + if ((family = nl_str2af(arg)) != AF_UNSPEC) + rtnl_rule_set_family(rule, family); +} + +/** @} */ diff --git a/src/lib/tc.c b/src/lib/tc.c new file mode 100644 index 0000000..dde729f --- /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 + */ + +#include +#include +#include + +/** + * @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 new file mode 100644 index 0000000..e5eacde --- /dev/null +++ b/src/lib/utils.c @@ -0,0 +1,196 @@ +/* + * src/utils.c Utilities + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2009 Thomas Graf + */ + +/** + * @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 + +/** + * 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; + char *endptr; + + lval = strtoul(arg, &endptr, 0); + if (endptr == arg || lval == ULONG_MAX) + nl_cli_fatal(EINVAL, "Unable to parse \"%s\", not a number.", + arg); + + return (uint32_t) lval; +} + +void nl_cli_print_version(void) +{ + printf("libnl tools version %s\n", LIBNL_VERSION); + printf( + "Copyright (C) 2003-2010 Thomas Graf \n" + "\n" + "This program comes with ABSOLUTELY NO WARRANTY. This is free \n" + "software, and you are welcome to redistribute it under certain\n" + "conditions. See the GNU General Public License for details.\n" + ); + + 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: "); + + if (fmt) { + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + } else + fprintf(stderr, "%s\n", strerror_r(err, buf, sizeof(buf))); + + exit(abs(err)); +} + +int nl_cli_connect(struct nl_sock *sk, int protocol) +{ + int err; + + if ((err = nl_connect(sk, protocol)) < 0) + nl_cli_fatal(err, "Unable to connect netlink socket: %s", + nl_geterror(err)); + + return err; +} + +struct nl_sock *nl_cli_alloc_socket(void) +{ + struct nl_sock *sock; + + if (!(sock = nl_socket_alloc())) + nl_cli_fatal(ENOBUFS, "Unable to allocate netlink socket"); + + return sock; +} + +struct nl_addr *nl_cli_addr_parse(const char *str, int family) +{ + struct nl_addr *addr; + int err; + + if ((err = nl_addr_parse(str, family, &addr)) < 0) + nl_cli_fatal(err, "Unable to parse address \"%s\": %s", + str, nl_geterror(err)); + + return addr; +} + +int nl_cli_parse_dumptype(const char *str) +{ + if (!strcasecmp(str, "brief")) + return NL_DUMP_LINE; + else if (!strcasecmp(str, "details") || !strcasecmp(str, "detailed")) + return NL_DUMP_DETAILS; + else if (!strcasecmp(str, "stats")) + return NL_DUMP_STATS; + else + nl_cli_fatal(EINVAL, "Invalid dump type \"%s\".\n", str); + + return 0; +} + +int nl_cli_confirm(struct nl_object *obj, struct nl_dump_params *params, + int default_yes) +{ + nl_object_dump(obj, params); + + 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'; + case 'y': + case 'n': + return answer == 'y'; + } + + fprintf(stderr, "Invalid input, try again.\n"); + } + + return 0; + +} + +struct nl_cache *nl_cli_alloc_cache(struct nl_sock *sock, const char *name, + int (*ac)(struct nl_sock *, struct nl_cache **)) +{ + struct nl_cache *cache; + int err; + + if ((err = ac(sock, &cache)) < 0) + nl_cli_fatal(err, "Unable to allocate %s cache: %s", + name, nl_geterror(err)); + + nl_cache_mngt_provide(cache); + + 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-list.c b/src/nf-ct-list.c new file mode 100644 index 0000000..5f72998 --- /dev/null +++ b/src/nf-ct-list.c @@ -0,0 +1,136 @@ +/* + * 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 + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + */ + +#include +#include + +static void print_usage(void) +{ + printf( + "Usage: nf-ct-list [OPTION]... [CONNTRACK ENTRY]\n" + "\n" + "Options\n" + " -f, --format=TYPE Output format { brief | details | stats }\n" + " -h, --help Show this help\n" + " -v, --version Show versioning information\n" + "\n" + "Conntrack Selection\n" + " -i, --id=NUM Identifier\n" + " -p, --proto=PROTOCOL Protocol\n" + " --tcp-state=STATE TCP connection state\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" + " --refcnt=NUM Use counter value\n" + " --flags Flags\n" + ); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_cache *ct_cache; + struct nfnl_ct *ct; + struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + + ct = nl_cli_ct_alloc(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_MARK = 257, + ARG_TCP_STATE = 258, + ARG_ORIG_SRC, + ARG_ORIG_SPORT, + ARG_ORIG_DST, + ARG_ORIG_DPORT, + ARG_REPLY_SRC, + ARG_REPLY_SPORT, + ARG_REPLY_DST, + ARG_REPLY_DPORT, + ARG_TIMEOUT, + ARG_REFCNT, + ARG_FLAGS, + }; + static struct option long_opts[] = { + { "format", 1, 0, 'f' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "id", 1, 0, 'i' }, + { "proto", 1, 0, 'p' }, + { "tcp-state", 1, 0, ARG_TCP_STATE }, + { "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 }, + { "refcnt", 1, 0, ARG_REFCNT }, + { 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_ct_set_family(ct, AF_INET); break; + case '6': nfnl_ct_set_family(ct, 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_ct_parse_id(ct, optarg); break; + case 'p': nl_cli_ct_parse_protocol(ct, optarg); break; + case ARG_TCP_STATE: nl_cli_ct_parse_tcp_state(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_REFCNT: nl_cli_ct_parse_use(ct, optarg); break; + case ARG_FLAGS: nl_cli_ct_parse_status(ct, optarg); break; + } + } + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_NETFILTER); + ct_cache = nl_cli_ct_alloc_cache(sock); + + nl_cache_dump_filter(ct_cache, ¶ms, OBJ_CAST(ct)); + + return 0; +} diff --git a/src/nf-exp-add.c b/src/nf-exp-add.c new file mode 100644 index 0000000..4b7f9d9 --- /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 + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c) 2012 Rich Fought + * + */ + +#include +#include + +static int quiet = 0; + +static void print_usage(void) +{ + printf( + "Usage: nf-exp-list [OPTION]... [CONNTRACK ENTRY]\n" + "\n" + "Options\n" + " --replace Replace the address if it exists.\n" + " -q, --quiet Do not print informal notifications.\n" + " -h, --help Show this help\n" + " -v, --version Show versioning information\n" + "\n" + "Expectation Selection\n" + " -i, --id=NUM Identifier\n" + " --expect-proto=PROTOCOL Expectation protocol\n" + " --expect-src=ADDR Expectation source address\n" + " --expect-sport=PORT Expectation source port\n" + " --expect-dst=ADDR Expectation destination address\n" + " --expect-dport=PORT Expectation destination port\n" + " --master-proto=PROTOCOL Master conntrack protocol\n" + " --master-src=ADDR Master conntrack source address\n" + " --master-sport=PORT Master conntrack source port\n" + " --master-dst=ADDR Master conntrack destination address\n" + " --master-dport=PORT Master conntrack destination port\n" + " --mask-proto=PROTOCOL Mask protocol\n" + " --mask-src=ADDR Mask source address\n" + " --mask-sport=PORT Mask source port\n" + " --mask-dst=ADDR Mask destination address\n" + " --mask-dport=PORT Mask destination port\n" + " -F, --family=FAMILY Address family\n" + " --timeout=NUM Timeout value\n" + " --helper=STRING Helper Name\n" + " --flags Flags (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 0000000..2ec45ae --- /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 + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c) 2012 Rich Fought + */ + +#include +#include + +static int quiet = 0; + +static void print_usage(void) +{ + printf( + "Usage: nf-exp-list [OPTION]... [CONNTRACK ENTRY]\n" + "\n" + "Options\n" + " --replace Replace the address if it exists.\n" + " -q, --quiet Do not print informal notifications.\n" + " -h, --help Show this help\n" + " -v, --version Show versioning information\n" + "\n" + "Expectation Selection\n" + " -i, --id=NUM Identifier\n" + " --expect-proto=PROTOCOL Expectation protocol\n" + " --expect-src=ADDR Expectation source address\n" + " --expect-sport=PORT Expectation source port\n" + " --expect-dst=ADDR Expectation destination address\n" + " --expect-dport=PORT Expectation destination port\n" + " --master-proto=PROTOCOL Master conntrack protocol\n" + " --master-src=ADDR Master conntrack source address\n" + " --master-sport=PORT Master conntrack source port\n" + " --master-dst=ADDR Master conntrack destination address\n" + " --master-dport=PORT Master conntrack destination port\n" + " --mask-proto=PROTOCOL Mask protocol\n" + " --mask-src=ADDR Mask source address\n" + " --mask-sport=PORT Mask source port\n" + " --mask-dst=ADDR Mask destination address\n" + " --mask-dport=PORT Mask destination port\n" + " -F, --family=FAMILY Address family\n" + " --timeout=NUM Timeout value\n" + " --helper=STRING Helper Name\n" + " --flags Flags\n" + ); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nfnl_exp *exp; + struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + int err, nlflags = 0; + + exp = nl_cli_exp_alloc(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_MARK = 270, + ARG_TCP_STATE = 271, + ARG_EXPECT_PROTO, + ARG_EXPECT_SRC, + ARG_EXPECT_SPORT, + ARG_EXPECT_DST, + ARG_EXPECT_DPORT, + ARG_MASTER_PROTO, + ARG_MASTER_SRC, + ARG_MASTER_SPORT, + ARG_MASTER_DST, + ARG_MASTER_DPORT, + ARG_MASK_PROTO, + ARG_MASK_SRC, + ARG_MASK_SPORT, + ARG_MASK_DST, + ARG_MASK_DPORT, + ARG_TIMEOUT, + ARG_HELPER_NAME, + ARG_FLAGS, + }; + static struct option long_opts[] = { + { "quiet", 0, 0, 'q' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "id", 1, 0, 'i' }, + { "expect-proto", 1, 0, ARG_EXPECT_PROTO }, + { "expect-src", 1, 0, ARG_EXPECT_SRC }, + { "expect-sport", 1, 0, ARG_EXPECT_SPORT }, + { "expect-dst", 1, 0, ARG_EXPECT_DST }, + { "expect-dport", 1, 0, ARG_EXPECT_DPORT }, + { "master-proto", 1, 0, ARG_MASTER_PROTO }, + { "master-src", 1, 0, ARG_MASTER_SRC }, + { "master-sport", 1, 0, ARG_MASTER_SPORT }, + { "master-dst", 1, 0, ARG_MASTER_DST }, + { "master-dport", 1, 0, ARG_MASTER_DPORT }, + { "mask-proto", 1, 0, ARG_MASK_PROTO }, + { "mask-src", 1, 0, ARG_MASK_SRC }, + { "mask-sport", 1, 0, ARG_MASK_SPORT }, + { "mask-dst", 1, 0, ARG_MASK_DST }, + { "mask-dport", 1, 0, ARG_MASK_DPORT }, + { "family", 1, 0, 'F' }, + { "timeout", 1, 0, ARG_TIMEOUT }, + { "helper", 1, 0, ARG_HELPER_NAME }, + { "flags", 1, 0, ARG_FLAGS}, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "46f:hvi:p:F:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case '?': exit(NLE_INVAL); + case 'q': quiet = 1; break; + case '4': nfnl_exp_set_family(exp, AF_INET); break; + case '6': nfnl_exp_set_family(exp, AF_INET6); break; + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + case 'i': nl_cli_exp_parse_id(exp, optarg); break; + case ARG_EXPECT_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_EXPECT_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_EXPECT_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_EXPECT_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_EXPECT_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_EXPECT, optarg); break; + case ARG_MASTER_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASTER_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASTER, optarg); break; + case ARG_MASK_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case 'F': nl_cli_exp_parse_family(exp, optarg); break; + case ARG_TIMEOUT: nl_cli_exp_parse_timeout(exp, optarg); break; + case ARG_HELPER_NAME: nl_cli_exp_parse_helper_name(exp, optarg); break; + case ARG_FLAGS: nl_cli_exp_parse_flags(exp, optarg); break; + } + } + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_NETFILTER); + + if ((err = nfnl_exp_del(sock, exp, nlflags)) < 0) + nl_cli_fatal(err, "Unable to delete expectation: %s", nl_geterror(err)); + + if (!quiet) { + printf("Deleted "); + nl_object_dump(OBJ_CAST(exp), ¶ms); + } + + return 0; +} diff --git a/src/nf-exp-list.c b/src/nf-exp-list.c new file mode 100644 index 0000000..1c6ec69 --- /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 + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + * Copyright (c) 2012 Rich Fought + */ + +#include +#include + +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 new file mode 100644 index 0000000..913ba16 --- /dev/null +++ b/src/nf-log.c @@ -0,0 +1,147 @@ +/* + * src/nf-log.c Monitor netfilter log events + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + */ + +#include +#include +#include +#include +#include + +static struct nfnl_log *alloc_log(void) +{ + struct nfnl_log *log; + + log = nfnl_log_alloc(); + if (!log) + nl_cli_fatal(ENOMEM, "Unable to allocate log object"); + + return log; +} + +static void obj_input(struct nl_object *obj, void *arg) +{ + struct nl_dump_params dp = { + .dp_type = NL_DUMP_STATS, + .dp_fd = stdout, + .dp_dump_msgtype = 1, + }; + + nl_object_dump(obj, &dp); +} + +static int event_input(struct nl_msg *msg, void *arg) +{ + if (nl_msg_parse(msg, &obj_input, NULL) < 0) + fprintf(stderr, "<> Unknown message type\n"); + + /* Exit nl_recvmsgs_def() and return to the main select() */ + return NL_STOP; +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *nf_sock; + struct nl_sock *rt_sock; + struct nl_cache *link_cache; + struct nfnl_log *log; + enum nfnl_log_copy_mode copy_mode; + uint32_t copy_range; + int err; + int family; + + nf_sock = nl_cli_alloc_socket(); + nl_socket_disable_seq_check(nf_sock); + nl_socket_modify_cb(nf_sock, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL); + + if ((argc > 1 && !strcasecmp(argv[1], "-h")) || argc < 3) { + printf("Usage: nf-log family group [ copy_mode ] " + "[copy_range] \n"); + return 2; + } + + nl_cli_connect(nf_sock, NETLINK_NETFILTER); + + family = nl_str2af(argv[1]); + if (family == AF_UNSPEC) + nl_cli_fatal(NLE_INVAL, "Unknown family \"%s\": %s", + argv[1], nl_geterror(family)); + + nfnl_log_pf_unbind(nf_sock, family); + if ((err = nfnl_log_pf_bind(nf_sock, family)) < 0) + nl_cli_fatal(err, "Unable to bind logger: %s", + nl_geterror(err)); + + log = alloc_log(); + nfnl_log_set_group(log, atoi(argv[2])); + + copy_mode = NFNL_LOG_COPY_META; + if (argc > 3) { + copy_mode = nfnl_log_str2copy_mode(argv[3]); + if (copy_mode < 0) + nl_cli_fatal(copy_mode, + "Unable to parse copy mode \"%s\": %s", + argv[3], nl_geterror(copy_mode)); + } + nfnl_log_set_copy_mode(log, copy_mode); + + copy_range = 0xFFFF; + if (argc > 4) + copy_range = atoi(argv[4]); + nfnl_log_set_copy_range(log, copy_range); + + if ((err = nfnl_log_create(nf_sock, log)) < 0) + nl_cli_fatal(err, "Unable to bind instance: %s", + nl_geterror(err)); + + { + struct nl_dump_params dp = { + .dp_type = NL_DUMP_STATS, + .dp_fd = stdout, + .dp_dump_msgtype = 1, + }; + + printf("log params: "); + nl_object_dump((struct nl_object *) log, &dp); + } + + rt_sock = nl_cli_alloc_socket(); + nl_cli_connect(rt_sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(rt_sock); + + while (1) { + fd_set rfds; + int nffd, rtfd, maxfd, retval; + + FD_ZERO(&rfds); + + maxfd = nffd = nl_socket_get_fd(nf_sock); + FD_SET(nffd, &rfds); + + rtfd = nl_socket_get_fd(rt_sock); + FD_SET(rtfd, &rfds); + if (maxfd < rtfd) + maxfd = rtfd; + + /* wait for an incoming message on the netlink nf_socket */ + retval = select(maxfd+1, &rfds, NULL, NULL, NULL); + + if (retval) { + if (FD_ISSET(nffd, &rfds)) + nl_recvmsgs_default(nf_sock); + if (FD_ISSET(rtfd, &rfds)) + nl_recvmsgs_default(rt_sock); + } + } + + return 0; +} diff --git a/src/nf-monitor.c b/src/nf-monitor.c new file mode 100644 index 0000000..fe99af4 --- /dev/null +++ b/src/nf-monitor.c @@ -0,0 +1,105 @@ +/* + * src/nf-monitor.c Monitor netfilter events + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + */ + +#include +#include + +static void obj_input(struct nl_object *obj, void *arg) +{ + struct nl_dump_params dp = { + .dp_type = NL_DUMP_STATS, + .dp_fd = stdout, + .dp_dump_msgtype = 1, + }; + + nl_object_dump(obj, &dp); +} + +static int event_input(struct nl_msg *msg, void *arg) +{ + if (nl_msg_parse(msg, &obj_input, NULL) < 0) + fprintf(stderr, "<> Unknown message type\n"); + + /* Exit nl_recvmsgs_def() and return to the main select() */ + return NL_STOP; +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + int err; + int i, idx; + + static const struct { + enum nfnetlink_groups gr_id; + const char* gr_name; + } groups[] = { + { NFNLGRP_CONNTRACK_NEW, "ct-new" }, + { NFNLGRP_CONNTRACK_UPDATE, "ct-update" }, + { NFNLGRP_CONNTRACK_DESTROY, "ct-destroy" }, + { NFNLGRP_NONE, NULL } + }; + + sock = nl_cli_alloc_socket(); + nl_socket_disable_seq_check(sock); + nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL); + + if (argc > 1 && !strcasecmp(argv[1], "-h")) { + printf("Usage: nf-monitor []\n"); + + printf("Known groups:"); + for (i = 0; groups[i].gr_id != NFNLGRP_NONE; i++) + printf(" %s", groups[i].gr_name); + printf("\n"); + return 2; + } + + nl_cli_connect(sock, NETLINK_NETFILTER); + + for (idx = 1; argc > idx; idx++) { + for (i = 0; groups[i].gr_id != NFNLGRP_NONE; i++) { + if (strcmp(argv[idx], groups[i].gr_name)) + continue; + + err = nl_socket_add_membership(sock, groups[i].gr_id); + if (err < 0) + nl_cli_fatal(err, + "Unable to add membership: %s", + nl_geterror(err)); + break; + } + + if (groups[i].gr_id == NFNLGRP_NONE) + nl_cli_fatal(NLE_OBJ_NOTFOUND, "Unknown group: \"%s\"", + argv[idx]); + } + + while (1) { + fd_set rfds; + int fd, retval; + + fd = nl_socket_get_fd(sock); + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + /* wait for an incoming message on the netlink socket */ + retval = select(fd+1, &rfds, NULL, NULL, NULL); + + if (retval) { + /* FD_ISSET(fd, &rfds) will be true */ + nl_recvmsgs_default(sock); + } + } + + return 0; +} diff --git a/src/nf-queue.c b/src/nf-queue.c new file mode 100644 index 0000000..922d9c8 --- /dev/null +++ b/src/nf-queue.c @@ -0,0 +1,149 @@ +/* + * src/nf-queue.c Monitor netfilter queue events + * + * 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) 2007, 2008 Patrick McHardy + * Copyright (c) 2010 Karl Hiramoto + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct nl_sock *nf_sock; + +static struct nfnl_queue *alloc_queue(void) +{ + struct nfnl_queue *queue; + + queue = nfnl_queue_alloc(); + if (!queue) + nl_cli_fatal(ENOMEM, "Unable to allocate queue object"); + + return queue; +} + + +static void obj_input(struct nl_object *obj, void *arg) +{ + struct nfnl_queue_msg *msg = (struct nfnl_queue_msg *) obj; + struct nl_dump_params dp = { + .dp_type = NL_DUMP_STATS, + .dp_fd = stdout, + .dp_dump_msgtype = 1, + }; + + nfnl_queue_msg_set_verdict(msg, NF_ACCEPT); + nl_object_dump(obj, &dp); + nfnl_queue_msg_send_verdict(nf_sock, msg); +} + +static int event_input(struct nl_msg *msg, void *arg) +{ + if (nl_msg_parse(msg, &obj_input, NULL) < 0) + fprintf(stderr, "<> Unknown message type\n"); + + /* Exit nl_recvmsgs_def() and return to the main select() */ + return NL_STOP; +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *rt_sock; + struct nl_cache *link_cache; + struct nfnl_queue *queue; + enum nfnl_queue_copy_mode copy_mode; + uint32_t copy_range; + int err = 1; + int family; + + nf_sock = nfnl_queue_socket_alloc(); + if (nf_sock == NULL) + nl_cli_fatal(ENOBUFS, "Unable to allocate netlink socket"); + + nl_socket_disable_seq_check(nf_sock); + nl_socket_modify_cb(nf_sock, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL); + + if ((argc > 1 && !strcasecmp(argv[1], "-h")) || argc < 3) { + printf("Usage: nf-queue family group [ copy_mode ] " + "[ copy_range ]\n"); + printf("family: [ inet | inet6 | ... ] \n"); + printf("group: the --queue-num arg that you gave to iptables\n"); + printf("copy_mode: [ none | meta | packet ] \n"); + return 2; + } + + nl_cli_connect(nf_sock, NETLINK_NETFILTER); + + if ((family = nl_str2af(argv[1])) == AF_UNSPEC) + nl_cli_fatal(NLE_INVAL, "Unknown family \"%s\"", argv[1]); + + nfnl_queue_pf_unbind(nf_sock, family); + if ((err = nfnl_queue_pf_bind(nf_sock, family)) < 0) + nl_cli_fatal(err, "Unable to bind logger: %s", + nl_geterror(err)); + + queue = alloc_queue(); + nfnl_queue_set_group(queue, atoi(argv[2])); + + copy_mode = NFNL_QUEUE_COPY_PACKET; + if (argc > 3) { + copy_mode = nfnl_queue_str2copy_mode(argv[3]); + if (copy_mode < 0) + nl_cli_fatal(copy_mode, + "Unable to parse copy mode \"%s\": %s", + argv[3], nl_geterror(copy_mode)); + } + nfnl_queue_set_copy_mode(queue, copy_mode); + + copy_range = 0xFFFF; + if (argc > 4) + copy_range = atoi(argv[4]); + nfnl_queue_set_copy_range(queue, copy_range); + + if ((err = nfnl_queue_create(nf_sock, queue)) < 0) + nl_cli_fatal(err, "Unable to bind queue: %s", nl_geterror(err)); + + rt_sock = nl_cli_alloc_socket(); + nl_cli_connect(rt_sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(rt_sock); + + nl_socket_set_buffer_size(nf_sock, 1024*127, 1024*127); + + while (1) { + fd_set rfds; + int nffd, rtfd, maxfd, retval; + + FD_ZERO(&rfds); + + maxfd = nffd = nl_socket_get_fd(nf_sock); + FD_SET(nffd, &rfds); + + rtfd = nl_socket_get_fd(rt_sock); + FD_SET(rtfd, &rfds); + if (maxfd < rtfd) + maxfd = rtfd; + + /* wait for an incoming message on the netlink socket */ + retval = select(maxfd+1, &rfds, NULL, NULL, NULL); + + if (retval) { + if (FD_ISSET(nffd, &rfds)) + nl_recvmsgs_default(nf_sock); + if (FD_ISSET(rtfd, &rfds)) + nl_recvmsgs_default(rt_sock); + } + } + + return 0; +} diff --git a/src/nl-addr-add.c b/src/nl-addr-add.c new file mode 100644 index 0000000..52995ec --- /dev/null +++ b/src/nl-addr-add.c @@ -0,0 +1,120 @@ +/* + * src/nl-addr-add.c Add addresses + * + * 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) 2003-2009 Thomas Graf + */ + +#include +#include +#include + +static int quiet = 0; + +static void print_usage(void) +{ + printf( +"Usage: nl-addr-add [OPTION]... [ADDRESS]\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" +"Address Options\n" +" -a, --local=ADDR Address to be considered local.\n" +" -d, --dev=DEV Device the address should be assigned to.\n" +" --family=FAMILY Address family (normally autodetected).\n" +" --broadcast=ADDR Broadcast address of network (IPv4).\n" +" --peer=ADDR Peer address (IPv4).\n" +" --label=STRING Additional address label (IPv4).\n" +" --scope=SCOPE Scope of local address (IPv4).\n" +" --preferred=TIME Preferred lifetime (IPv6).\n" +" --valid=TIME Valid lifetime (IPv6).\n" + ); + + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct rtnl_addr *addr; + struct nl_cache *link_cache; + struct nl_dump_params dp = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + int err, nlflags = NLM_F_CREATE; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + addr = nl_cli_addr_alloc(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_FAMILY = 257, + ARG_LABEL = 258, + ARG_PEER, + ARG_SCOPE, + ARG_BROADCAST, + ARG_REPLACE, + ARG_PREFERRED, + ARG_VALID, + }; + static struct option long_opts[] = { + { "replace", 0, 0, ARG_REPLACE }, + { "quiet", 0, 0, 'q' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "local", 1, 0, 'a' }, + { "dev", 1, 0, 'd' }, + { "family", 1, 0, ARG_FAMILY }, + { "label", 1, 0, ARG_LABEL }, + { "peer", 1, 0, ARG_PEER }, + { "scope", 1, 0, ARG_SCOPE }, + { "broadcast", 1, 0, ARG_BROADCAST }, + { "preferred", 1, 0, ARG_PREFERRED }, + { "valid", 1, 0, ARG_VALID }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "qhva:d:", 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 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + case 'a': nl_cli_addr_parse_local(addr, optarg); break; + case 'd': nl_cli_addr_parse_dev(addr, link_cache, optarg); break; + case ARG_FAMILY: nl_cli_addr_parse_family(addr, optarg); break; + case ARG_LABEL: nl_cli_addr_parse_label(addr, optarg); break; + case ARG_PEER: nl_cli_addr_parse_peer(addr, optarg); break; + case ARG_SCOPE: nl_cli_addr_parse_scope(addr, optarg); break; + case ARG_BROADCAST: nl_cli_addr_parse_broadcast(addr, optarg); break; + case ARG_PREFERRED: nl_cli_addr_parse_preferred(addr, optarg); break; + case ARG_VALID: nl_cli_addr_parse_valid(addr, optarg); break; + } + } + + if ((err = rtnl_addr_add(sock, addr, nlflags)) < 0) + nl_cli_fatal(err, "Unable to add address: %s", + nl_geterror(err)); + + if (!quiet) { + printf("Added "); + nl_object_dump(OBJ_CAST(addr), &dp); + } + + return 0; +} diff --git a/src/nl-addr-delete.c b/src/nl-addr-delete.c new file mode 100644 index 0000000..2849c01 --- /dev/null +++ b/src/nl-addr-delete.c @@ -0,0 +1,140 @@ +/* + * src/nl-addr-delete.c Delete addresses + * + * 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) 2003-2009 Thomas Graf + */ + +#include +#include +#include + +static struct nl_sock *sock; +static int interactive = 0, default_yes = 0, quiet = 0; +static int deleted = 0; + +static void print_usage(void) +{ + printf( +"Usage: nl-addr-delete [OPTION]... [ADDRESS]\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" +"Address Options\n" +" -a, --local=ADDR Local address.\n" +" -d, --dev=DEV Associated network device.\n" +" --family=FAMILY Family of local address.\n" +" --label=STRING Address label (IPv4).\n" +" --peer=ADDR Peer address (IPv4).\n" +" --scope=SCOPE Address scope (IPv4).\n" +" --broadcast=ADDR Broadcast address of network (IPv4).\n" +" --valid-lifetime=TS Valid lifetime before route expires (IPv6).\n" +" --preferred=TIME Preferred lifetime (IPv6).\n" +" --valid=TIME Valid lifetime (IPv6).\n" + ); + + exit(0); +} + +static void delete_cb(struct nl_object *obj, void *arg) +{ + struct rtnl_addr *addr = 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_addr_delete(sock, addr, 0)) < 0) + nl_cli_fatal(err, "Unable to delete address: %s\n", + nl_geterror(err)); + + if (!quiet) { + printf("Deleted "); + nl_object_dump(obj, ¶ms); + } + + deleted++; +} + +int main(int argc, char *argv[]) +{ + struct rtnl_addr *addr; + struct nl_cache *link_cache, *addr_cache; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + addr_cache = nl_cli_addr_alloc_cache(sock); + addr = nl_cli_addr_alloc(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_FAMILY = 257, + ARG_LABEL = 258, + ARG_YES, + ARG_PEER, + ARG_SCOPE, + ARG_BROADCAST, + ARG_PREFERRED, + ARG_VALID, + }; + static struct option long_opts[] = { + { "interactive", 0, 0, 'i' }, + { "yes", 0, 0, ARG_YES }, + { "quiet", 0, 0, 'q' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "local", 1, 0, 'a' }, + { "dev", 1, 0, 'd' }, + { "family", 1, 0, ARG_FAMILY }, + { "label", 1, 0, ARG_LABEL }, + { "peer", 1, 0, ARG_PEER }, + { "scope", 1, 0, ARG_SCOPE }, + { "broadcast", 1, 0, ARG_BROADCAST }, + { "preferred", 1, 0, ARG_PREFERRED }, + { "valid", 1, 0, ARG_VALID }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "iqhva:d:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'i': 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 'a': nl_cli_addr_parse_local(addr, optarg); break; + case 'd': nl_cli_addr_parse_dev(addr, link_cache, optarg); break; + case ARG_FAMILY: nl_cli_addr_parse_family(addr, optarg); break; + case ARG_LABEL: nl_cli_addr_parse_label(addr, optarg); break; + case ARG_PEER: nl_cli_addr_parse_peer(addr, optarg); break; + case ARG_SCOPE: nl_cli_addr_parse_scope(addr, optarg); break; + case ARG_BROADCAST: nl_cli_addr_parse_broadcast(addr, optarg); break; + case ARG_PREFERRED: nl_cli_addr_parse_preferred(addr, optarg); break; + case ARG_VALID: nl_cli_addr_parse_valid(addr, optarg); break; + } + } + + nl_cache_foreach_filter(addr_cache, OBJ_CAST(addr), delete_cb, NULL); + + if (!quiet) + printf("Deleted %d addresses\n", deleted); + + return 0; +} diff --git a/src/nl-addr-list.c b/src/nl-addr-list.c new file mode 100644 index 0000000..20995a8 --- /dev/null +++ b/src/nl-addr-list.c @@ -0,0 +1,196 @@ +/* + * src/nl-addr-list.c List addresses + * + * 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) 2003-2009 Thomas Graf + */ + +#include +#include +#include + +static void print_usage(void) +{ + printf( +"Usage: nl-addr-list [OPTION]... [ADDRESS]\n" +"\n" +"Options\n" +" --details Show details on multiple lines.\n" +" --env Print address details in sh env variable syntax.\n" +" --prefix=STRING Prefix each printed line.\n" +" -h, --help Show this help.\n" +" -v, --version Show versioning information.\n" +"\n" +"Address Selection\n" +" -a, --local=ADDR Local address.\n" +" -d, --dev=DEV Associated network device.\n" +" --family=FAMILY Family of local address.\n" +" --label=STRING Address label (IPv4).\n" +" --peer=ADDR Peer address (IPv4).\n" +" --scope=SCOPE Address scope (IPv4).\n" +" --broadcast=ADDR Broadcast address of network (IPv4).\n" +" --valid-lifetime=TS Valid lifetime before route expires (IPv6).\n" +" --preferred=TIME Preferred lifetime (IPv6).\n" +" --valid=TIME Valid lifetime (IPv6).\n" + ); + exit(0); +} + +static char *prefix; + +static void print_prefix(struct nl_dump_params *p, int line) +{ + if (prefix) + nl_dump(p, "%s", prefix); +} + +static void env_dump(struct nl_object *obj, void *arg) +{ + struct nl_dump_params *p = arg; + struct rtnl_addr *addr = (struct rtnl_addr *) obj; + struct nl_cache *link_cache; + struct nl_addr *a; + static int index = 0; + char buf[128], pfx[32], *s; + + snprintf(pfx, sizeof(pfx), "ADDR%d", index++); + + nl_dump_line(p, "%s_FAMILY=%s\n", pfx, + nl_af2str(rtnl_addr_get_family(addr), buf, sizeof(buf))); + + nl_dump_line(p, "%s_LOCAL=%s\n", pfx, + 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_safe("route/link"); + if (link_cache) + nl_dump_line(p, "%s_IFNAME=%s\n", pfx, + rtnl_link_i2name(link_cache, + rtnl_addr_get_ifindex(addr), + buf, sizeof(buf))); + + if ((a = rtnl_addr_get_peer(addr))) + nl_dump_line(p, "%s_PEER=%s\n", pfx, + nl_addr2str(a, buf, sizeof(buf))); + + if ((a = rtnl_addr_get_broadcast(addr))) + nl_dump_line(p, "%s_BROADCAST=%s\n", pfx, + nl_addr2str(a, buf, sizeof(buf))); + + nl_dump_line(p, "%s_SCOPE=%s\n", pfx, + rtnl_scope2str(rtnl_addr_get_scope(addr), + buf, sizeof(buf))); + + if ((s = rtnl_addr_get_label(addr))) + nl_dump_line(p, "%s_LABEL=%s\n", pfx, s); + + rtnl_addr_flags2str(rtnl_addr_get_flags(addr), buf, sizeof(buf)); + if (buf[0]) + nl_dump_line(p, "%s_FLAGS=%s\n", pfx, buf); + + 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; + + nl_dump_line(p, "ADDR_CACHEINFO_PREFERRED=%u\n", + ci->aci_prefered); + + nl_dump_line(p, "ADDR_CACHEINFO_CREATED=%u\n", ci->aci_cstamp); + nl_dump_line(p, "ADDR_CACHEINFO_LASTUPDATE=%u\n", + ci->aci_tstamp); + } +#endif +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct rtnl_addr *addr; + struct nl_cache *link_cache, *addr_cache; + struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, + .dp_nl_cb = print_prefix, + .dp_fd = stdout, + }; + int dump_env = 0; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + addr_cache = nl_cli_addr_alloc_cache(sock); + addr = nl_cli_addr_alloc(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_FAMILY = 257, + ARG_LABEL = 258, + ARG_PEER, + ARG_SCOPE, + ARG_BROADCAST, + ARG_DETAILS, + ARG_ENV, + ARG_PREFIX, + ARG_PREFERRED, + ARG_VALID, + }; + static struct option long_opts[] = { + { "details", 0, 0, ARG_DETAILS }, + { "env", 0, 0, ARG_ENV }, + { "prefix", 1, 0, ARG_PREFIX }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "local", 1, 0, 'a' }, + { "dev", 1, 0, 'd' }, + { "family", 1, 0, ARG_FAMILY }, + { "label", 1, 0, ARG_LABEL }, + { "peer", 1, 0, ARG_PEER }, + { "scope", 1, 0, ARG_SCOPE }, + { "broadcast", 1, 0, ARG_BROADCAST }, + { "preferred", 1, 0, ARG_PREFERRED }, + { "valid", 1, 0, ARG_VALID }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "46hva:d:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case '?': exit(NLE_INVAL); + case '4': rtnl_addr_set_family(addr, AF_INET); break; + case '6': rtnl_addr_set_family(addr, AF_INET6); break; + case ARG_DETAILS: params.dp_type = NL_DUMP_DETAILS; break; + case ARG_ENV: dump_env = 1; break; + case ARG_PREFIX: prefix = strdup(optarg); break; + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + case 'a': nl_cli_addr_parse_local(addr, optarg); break; + case 'd': nl_cli_addr_parse_dev(addr, link_cache, optarg); break; + case ARG_FAMILY: nl_cli_addr_parse_family(addr, optarg); break; + case ARG_LABEL: nl_cli_addr_parse_label(addr, optarg); break; + case ARG_PEER: nl_cli_addr_parse_peer(addr, optarg); break; + case ARG_SCOPE: nl_cli_addr_parse_scope(addr, optarg); break; + case ARG_BROADCAST: nl_cli_addr_parse_broadcast(addr, optarg); break; + case ARG_PREFERRED: nl_cli_addr_parse_preferred(addr, optarg); break; + case ARG_VALID: nl_cli_addr_parse_valid(addr, optarg); break; + } + } + + if (dump_env) + nl_cache_foreach_filter(addr_cache, OBJ_CAST(addr), env_dump, + ¶ms); + else + nl_cache_dump_filter(addr_cache, ¶ms, OBJ_CAST(addr)); + + return 0; +} diff --git a/src/nl-class-add.c b/src/nl-class-add.c new file mode 100644 index 0000000..b9a17dc --- /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 + */ + +#include +#include +#include +#include +#include + +#include + +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 0000000..37657a4 --- /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 + */ + +#include +#include +#include + +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 0000000..c2423fb --- /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 + */ + +#include +#include +#include +#include + +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 0000000..1d45d0b --- /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 + */ + +#include + +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 new file mode 100644 index 0000000..6acb320 --- /dev/null +++ b/src/nl-cls-add.c @@ -0,0 +1,163 @@ +/* + * src/nl-cls-add.c Add 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) 2003-2011 Thomas Graf + */ + +#include +#include +#include +#include + +#include + +static int quiet = 0; + +static void print_usage(void) +{ + printf( +"Usage: nl-cls-add [OPTIONS]... classifier [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 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" + ); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct rtnl_cls *cls; + 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); + + cls = nl_cli_cls_alloc(); + tc = (struct rtnl_tc *) cls; + + for (;;) { + int c, optidx = 0; + enum { + 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' }, + { "help", 0, 0, 'h' }, + { "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 }, + { "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; + 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) + 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 classifier \"%s\".", kind); + + if (!(tm = nl_cli_tc_lookup(ops))) + nl_cli_fatal(ENOTSUP, "Classifier type \"%s\" not supported.", kind); + + tm->tm_parse_argv(tc, argc, argv); + + if (!quiet) { + 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 new file mode 100644 index 0000000..2b3db1f --- /dev/null +++ b/src/nl-cls-delete.c @@ -0,0 +1,155 @@ +/* + * src/nl-cls-delete.c Delete Classifier + * + * 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-2010 Thomas Graf + */ + +#include +#include +#include + +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-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 = 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_cls_delete(sock, cls, 0)) < 0) + nl_cli_fatal(err, "Unable to delete classifier: %s\n", + nl_geterror(err)); + + if (!quiet) { + printf("Deleted "); + nl_object_dump(obj, ¶ms); + } + + deleted++; +} + +static void __delete_link(int ifindex, struct rtnl_cls *filter) +{ + 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); + + __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_YES = 257, + ARG_INTERACTIVE = 258, + ARG_PROTO, + ARG_PRIO, + }; + 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' }, + { "proto", 1, 0, ARG_PROTO }, + { "prio", 1, 0, ARG_PRIO }, + { 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; + 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 ((ifindex = rtnl_tc_get_ifindex(tc))) + __delete_link(ifindex, cls); + else + nl_cache_foreach(link_cache, delete_link, cls); + + if (!quiet) + printf("Deleted %d classs\n", deleted); + + return 0; +} diff --git a/src/nl-cls-list.c b/src/nl-cls-list.c new file mode 100644 index 0000000..5072585 --- /dev/null +++ b/src/nl-cls-list.c @@ -0,0 +1,129 @@ +/* + * src/nl-cls-list.c List classifiers + * + * 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-2010 Thomas Graf + */ + +#include +#include +#include +#include + +static struct nl_sock *sock; + +static struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, +}; + +static void print_usage(void) +{ + printf( +"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 __dump_link(int ifindex, struct rtnl_cls *filter) +{ + 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_dump_filter(cache, ¶ms, OBJ_CAST(filter)); + nl_cache_free(cache); +} + +static void dump_link(struct nl_object *obj, void *arg) +{ + struct rtnl_link *link = nl_object_priv(obj); + + __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 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; + + for (;;) { + int c, optidx = 0; + enum { + ARG_DETAILS = 257, + ARG_STATS = 258, + ARG_PROTO, + ARG_PRIO, + }; + 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' }, + { "proto", 1, 0, ARG_PROTO }, + { "prio", 1, 0, ARG_PRIO }, + { 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; + 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 ((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-fib-lookup.c b/src/nl-fib-lookup.c new file mode 100644 index 0000000..705cf32 --- /dev/null +++ b/src/nl-fib-lookup.c @@ -0,0 +1,109 @@ +/* + * src/nl-fib-lookup.c FIB Route Lookup + * + * 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 + */ + +#include + +static void print_usage(void) +{ + printf( + "Usage: nl-fib-lookup [options] \n" + "Options:\n" + " -t, --table Table id\n" + " -f, --fwmark Firewall mark\n" + " -s, --scope Routing scope\n" + " -T, --tos Type of Service\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *nlh; + struct nl_cache *result; + struct flnl_request *request; + struct nl_addr *addr; + struct nl_dump_params params = { + .dp_fd = stdout, + .dp_type = NL_DUMP_DETAILS, + }; + int table = RT_TABLE_UNSPEC, scope = RT_SCOPE_UNIVERSE; + int tos = 0, err = 1; + uint64_t fwmark = 0; + + while (1) { + static struct option long_opts[] = { + {"table", 1, 0, 't'}, + {"fwmark", 1, 0, 'f'}, + {"scope", 1, 0, 's'}, + {"tos", 1, 0, 'T'}, + {"help", 0, 0, 'h'}, + {0, 0, 0, 0}, + }; + int c, idx = 0; + + c = getopt_long(argc, argv, "t:f:s:T:h", long_opts, &idx); + if (c == -1) + break; + + switch (c) { + case 't': + table = strtoul(optarg, NULL, 0); + break; + case 'f': + fwmark = strtoul(optarg, NULL, 0); + break; + case 's': + scope = strtoul(optarg, NULL, 0); + break; + case 'T': + tos = strtoul(optarg, NULL, 0); + break; + default: + print_usage(); + } + } + + if (optind >= argc) + print_usage(); + + nlh = nl_cli_alloc_socket(); + + if ((err = nl_addr_parse(argv[optind], AF_INET, &addr)) < 0) + nl_cli_fatal(err, "Unable to parse address \"%s\": %s\n", + argv[optind], nl_geterror(err)); + + result = flnl_result_alloc_cache(); + if (!result) + nl_cli_fatal(ENOMEM, "Unable to allocate cache"); + + request = flnl_request_alloc(); + if (!request) + nl_cli_fatal(ENOMEM, "Unable to allocate request"); + + flnl_request_set_table(request, table); + flnl_request_set_fwmark(request, fwmark); + flnl_request_set_scope(request, scope); + flnl_request_set_tos(request, tos); + + err = flnl_request_set_addr(request, addr); + nl_addr_put(addr); + if (err < 0) + nl_cli_fatal(err, "Unable to send request: %s", nl_geterror(err)); + + nl_cli_connect(nlh, NETLINK_FIB_LOOKUP); + + err = flnl_lookup(nlh, request, result); + if (err < 0) + nl_cli_fatal(err, "Unable to lookup: %s\n", nl_geterror(err)); + + nl_cache_dump(result, ¶ms); + + return 0; +} diff --git a/src/nl-link-enslave.c b/src/nl-link-enslave.c new file mode 100644 index 0000000..2b5d47d --- /dev/null +++ b/src/nl-link-enslave.c @@ -0,0 +1,50 @@ +/* + * src/nl-link-enslave.c Enslave a link + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2011 Thomas Graf + */ + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_cache *link_cache; + struct rtnl_link *master, *slave; + int err; + + if (argc < 3) { + fprintf(stderr, "Usage: nl-link-enslave master slave\n"); + return 1; + } + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + + if (!(master = rtnl_link_get_by_name(link_cache, argv[1]))) { + fprintf(stderr, "Unknown link: %s\n", argv[1]); + return 1; + } + + if (!(slave = rtnl_link_get_by_name(link_cache, argv[2]))) { + fprintf(stderr, "Unknown link: %s\n", argv[2]); + return 1; + } + + if ((err = rtnl_link_bond_enslave(sock, master, slave)) < 0) { + fprintf(stderr, "Unable to enslave %s to %s: %s\n", + argv[2], argv[1], nl_geterror(err)); + return 1; + } + + return 0; +} + diff --git a/src/nl-link-ifindex2name.c b/src/nl-link-ifindex2name.c new file mode 100644 index 0000000..68e5158 --- /dev/null +++ b/src/nl-link-ifindex2name.c @@ -0,0 +1,44 @@ +/* + * src/nl-link-ifindex2name.c Transform a interface index to its name + * + * 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 + */ + +#include +#include + +static void print_usage(void) +{ + printf("Usage: nl-link-ifindex2name \n"); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_cache *link_cache; + char name[IFNAMSIZ]; + uint32_t ifindex; + + if (argc < 2) + print_usage(); + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + + ifindex = nl_cli_parse_u32(argv[1]); + + if (!rtnl_link_i2name(link_cache, ifindex, name, sizeof(name))) + nl_cli_fatal(ENOENT, "Interface index %d does not exist", + ifindex); + + printf("%s\n", name); + + return 0; +} diff --git a/src/nl-link-list.c b/src/nl-link-list.c new file mode 100644 index 0000000..b5c98b4 --- /dev/null +++ b/src/nl-link-list.c @@ -0,0 +1,98 @@ +/* + * src/nl-link-dump.c Dump link 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-2010 Thomas Graf + */ + +#include +#include + +static void print_usage(void) +{ + printf( +"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); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_cache *link_cache; + struct rtnl_link *link; + struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link = nl_cli_link_alloc(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_FAMILY = 257, + ARG_MTU = 258, + ARG_TXQLEN, + ARG_WEIGHT, + ARG_DETAILS, + ARG_STATS, + }; + static struct option long_opts[] = { + { "details", 0, 0, ARG_DETAILS }, + { "stats", 0, 0, ARG_STATS }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "name", 1, 0, 'n' }, + { "index", 1, 0, 'i' }, + { "family", 1, 0, ARG_FAMILY }, + { "mtu", 1, 0, ARG_MTU }, + { "txqlen", 1, 0, ARG_TXQLEN }, + { "weight", 1, 0, ARG_WEIGHT }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "hvn:i:", 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 'n': nl_cli_link_parse_name(link, optarg); break; + case 'i': nl_cli_link_parse_ifindex(link, optarg); break; + case ARG_FAMILY: nl_cli_link_parse_family(link, 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; + } + } + + 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 new file mode 100644 index 0000000..b8ae4bc --- /dev/null +++ b/src/nl-link-name2ifindex.c @@ -0,0 +1,41 @@ +/* + * src/nl-link-name2ifindex.c Transform a interface name to its index + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2008 Thomas Graf + */ + +#include +#include + +static void print_usage(void) +{ + printf("Usage: nl-link-name2ifindex \n"); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_cache *link_cache; + uint32_t ifindex; + + if (argc < 2) + print_usage(); + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + + if (!(ifindex = rtnl_link_name2i(link_cache, argv[1]))) + nl_cli_fatal(ENOENT, "Interface \"%s\" does not exist", + argv[1]); + + printf("%u\n", ifindex); + + return 0; +} diff --git a/src/nl-link-release.c b/src/nl-link-release.c new file mode 100644 index 0000000..4c9f15a --- /dev/null +++ b/src/nl-link-release.c @@ -0,0 +1,45 @@ +/* + * src/nl-link-release.c release a link + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2011 Thomas Graf + */ + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_cache *link_cache; + struct rtnl_link *slave; + int err; + + if (argc < 2) { + fprintf(stderr, "Usage: nl-link-release slave\n"); + return 1; + } + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + + if (!(slave = rtnl_link_get_by_name(link_cache, argv[1]))) { + fprintf(stderr, "Unknown link: %s\n", argv[1]); + return 1; + } + + if ((err = rtnl_link_bond_release(sock, slave)) < 0) { + fprintf(stderr, "Unable to release slave %s: %s\n", + argv[1], nl_geterror(err)); + return 1; + } + + return 0; +} + diff --git a/src/nl-link-set.c b/src/nl-link-set.c new file mode 100644 index 0000000..3178a98 --- /dev/null +++ b/src/nl-link-set.c @@ -0,0 +1,128 @@ +/* + * src/nl-link-set.c Set link 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-2010 Thomas Graf + */ + +#include +#include + +static struct nl_sock *sock; +static int quiet = 0; + +#if 0 + " changes := [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"); +#endif + +static void print_usage(void) +{ + printf( + "Usage: nl-link-set [OPTION]... [LINK]\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" + "Selecting the Link\n" + " -n, --name=NAME link name\n" + " -i, --index interface index\n" + "Change Options\n" + " --rename=NAME rename interface\n" + " --mtu=NUM MTU value\n" + " --txqlen=NUM TX queue length\n" + " --weight=NUM weight\n" + " --ifalias=NAME alias name (SNMP IfAlias)\n" + ); + exit(0); +} + +static void set_cb(struct nl_object *obj, void *arg) +{ + struct rtnl_link *link = nl_object_priv(obj); + struct rtnl_link *change = arg; + struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + int err; + + if ((err = rtnl_link_change(sock, link, change, 0) < 0)) + nl_cli_fatal(err, "Unable to change link: %s", + nl_geterror(err)); + + if (!quiet) { + printf("Changed "); + nl_object_dump(OBJ_CAST(link), ¶ms); + } +} + +int main(int argc, char *argv[]) +{ + struct nl_cache *link_cache; + struct rtnl_link *link, *change; + int ok = 0; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + link = nl_cli_link_alloc(); + change = nl_cli_link_alloc(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_RENAME = 257, + ARG_MTU = 258, + ARG_TXQLEN, + ARG_WEIGHT, + ARG_IFALIAS, + }; + static struct option long_opts[] = { + { "quiet", 0, 0, 'q' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "name", 1, 0, 'n' }, + { "index", 1, 0, 'i' }, + { "rename", 1, 0, ARG_RENAME }, + { "mtu", 1, 0, ARG_MTU }, + { "txqlen", 1, 0, ARG_TXQLEN }, + { "weight", 1, 0, ARG_WEIGHT }, + { "ifalias", 1, 0, ARG_IFALIAS }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "qhvn: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 '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(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; + } + } + + if (!ok) + print_usage(); + + nl_cache_foreach_filter(link_cache, OBJ_CAST(link), set_cb, change); + + return 0; +} diff --git a/src/nl-link-stats.c b/src/nl-link-stats.c new file mode 100644 index 0000000..4dfca86 --- /dev/null +++ b/src/nl-link-stats.c @@ -0,0 +1,119 @@ +/* + * src/nl-link-stats.c Retrieve link statistics + * + * 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 + */ + +#include +#include + +static void print_usage(void) +{ + printf( + "Usage: nl-link-stats [OPTION]... [LINK] [ListOfStats]\n" + "\n" + "Options\n" + " -l, --list List available statistic names\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=NUM interface index\n" + ); + exit(0); +} + +static void list_stat_names(void) +{ + char buf[64]; + int i; + + for (i = 0; i < RTNL_LINK_STATS_MAX; i++) + printf("%s\n", rtnl_link_stat2str(i, buf, sizeof(buf))); + + exit(0); +} + +static int gargc; + +static void dump_stat(struct rtnl_link *link, int id) +{ + uint64_t st = rtnl_link_get_stat(link, id); + char buf[64]; + + printf("%s.%s %" PRIu64 "\n", rtnl_link_get_name(link), + rtnl_link_stat2str(id, buf, sizeof(buf)), st); +} + +static void dump_stats(struct nl_object *obj, void *arg) +{ + struct rtnl_link *link = (struct rtnl_link *) obj; + char **argv = arg; + + if (optind >= gargc) { + int i; + + for (i = 0; i < RTNL_LINK_STATS_MAX; i++) + dump_stat(link, i); + } else { + while (optind < gargc) { + int id = rtnl_link_str2stat(argv[optind]); + + if (id < 0) + fprintf(stderr, "Warning: Unknown statistic " + "\"%s\"\n", argv[optind]); + else + dump_stat(link, id); + + optind++; + } + } +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_cache *link_cache; + struct rtnl_link *link; + + 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 (;;) { + int c, optidx = 0; + static struct option long_opts[] = { + { "list", 0, 0, 'l' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "name", 1, 0, 'n' }, + { "index", 1, 0, 'i' }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "lhvn:i:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'l': list_stat_names(); break; + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + case 'n': nl_cli_link_parse_name(link, optarg); break; + case 'i': nl_cli_link_parse_ifindex(link, optarg); break; + } + } + + gargc = argc; + nl_cache_foreach_filter(link_cache, OBJ_CAST(link), dump_stats, argv); + + return 0; +} + diff --git a/src/nl-list-caches.c b/src/nl-list-caches.c new file mode 100644 index 0000000..853d8a4 --- /dev/null +++ b/src/nl-list-caches.c @@ -0,0 +1,117 @@ +/* + * nl-list-caches.c List registered cache types + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2009 Thomas Graf + */ + +#include +#include + +static void print_usage(void) +{ + fprintf(stderr, "Usage: nl-list-caches\n"); + exit(1); +} + +static char *id_attr_list(struct nl_object_ops *ops, char *buf, size_t len) +{ + if (ops->oo_attrs2str != NULL) + return ops->oo_attrs2str(ops->oo_id_attrs, buf, len); + else { + memset(buf, 0, len); + return buf; + } +} + +static void print(struct nl_cache_ops *ops, void *arg) +{ + char buf[64]; + + printf("%s:\n" \ + " hdrsize: %d bytes\n" \ + " protocol: %s\n" \ + " request-update: %s\n" \ + " msg-parser: %s\n", + ops->co_name, ops->co_hdrsize, + nl_nlfamily2str(ops->co_protocol, buf, sizeof(buf)), + ops->co_request_update ? "yes" : "no", + ops->co_msg_parser ? "yes" : "no"); + + if (ops->co_obj_ops) { + struct nl_object_ops *obj_ops = ops->co_obj_ops; + const char *dump_names[NL_DUMP_MAX+1] = { + "brief", + "detailed", + "stats", + }; + int i; + + printf(" cacheable object:\n" \ + " name: %s:\n" \ + " size: %zu bytes\n" \ + " constructor: %s\n" \ + " free-data: %s\n" \ + " clone: %s\n" \ + " compare: %s\n" \ + " id attributes: %s\n" \ + " dump: ", + obj_ops->oo_name, obj_ops->oo_size, + obj_ops->oo_constructor ? "yes" : "no", + obj_ops->oo_free_data ? "yes" : "no", + obj_ops->oo_clone ? "yes" : "no", + obj_ops->oo_compare ? "yes" : "no", + id_attr_list(obj_ops, buf, sizeof(buf))); + + for (i = 0; i <= NL_DUMP_MAX; i++) + if (obj_ops->oo_dump[i]) + printf("%s%s", + i == 0 ? "" : ", ", + dump_names[i]); + + printf("\n"); + } + + if (ops->co_genl) { + struct genl_ops *genl_ops = ops->co_genl; + + printf(" genl:\n" \ + " name: %s\n" \ + " user-hdr: %d\n" \ + " id: %d\n", + genl_ops->o_name, genl_ops->o_hdrsize, genl_ops->o_id); + + if (genl_ops->o_ncmds) { + int i; + + printf(" cmds:\n"); + + for (i = 0; i < genl_ops->o_ncmds; i++) { + struct genl_cmd *cmd = &genl_ops->o_cmds[i]; + + printf(" %s:\n" + " id: %d\n" \ + " maxattr: %d\n" \ + " msg-parser: %s\n" \ + " attr-policy: %s\n", + cmd->c_name, cmd->c_id, cmd->c_maxattr, + cmd->c_msg_parser ? "yes" : "no", + cmd->c_attr_policy ? "yes" : "no"); + } + } + } +} + +int main(int argc, char *argv[]) +{ + if (argc > 1 && !strcasecmp(argv[1], "-h")) + print_usage(); + + nl_cache_ops_foreach(print, NULL); + + return 0; +} diff --git a/src/nl-list-sockets.c b/src/nl-list-sockets.c new file mode 100644 index 0000000..c2fa1cd --- /dev/null +++ b/src/nl-list-sockets.c @@ -0,0 +1,49 @@ +/* + * nl-list-sockets.c Pretty-print /proc/net/netlink + * + * 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 + */ + +#include + +#define PROC_NETLINK "/proc/net/netlink" + +int main(int argc, char *argv[]) +{ + FILE *fd; + char buf[2048], p[64]; + + fd = fopen(PROC_NETLINK, "r"); + if (fd == NULL) { + perror("fopen"); + return -1; + } + + printf("Address Family PID Groups rmem " + "wmem CB refcnt\n"); + + while (fgets(buf, sizeof(buf), fd)) { + unsigned long sk, cb; + int ret, proto, pid, rmem, wmem, refcnt; + unsigned int groups; + + ret = sscanf(buf, "%lx %d %d %08x %d %d %lx %d\n", + &sk, &proto, &pid, &groups, &rmem, &wmem, + &cb, &refcnt); + if (ret != 8) + continue; + + printf("0x%016lx %-16s %-6d %08x %-6d %-6d 0x%08lx %d\n", + sk, nl_nlfamily2str(proto, p, sizeof(p)), pid, + groups, rmem, wmem, cb, refcnt); + } + + fclose(fd); + + return 0; +} diff --git a/src/nl-monitor.c b/src/nl-monitor.c new file mode 100644 index 0000000..fdf6497 --- /dev/null +++ b/src/nl-monitor.c @@ -0,0 +1,115 @@ +/* + * src/nl-monitor.c Monitor events + * + * 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 + */ + +#include +#include + +static void obj_input(struct nl_object *obj, void *arg) +{ + struct nl_dump_params dp = { + .dp_type = NL_DUMP_STATS, + .dp_fd = stdout, + .dp_dump_msgtype = 1, + }; + + nl_object_dump(obj, &dp); +} + +static int event_input(struct nl_msg *msg, void *arg) +{ + if (nl_msg_parse(msg, &obj_input, NULL) < 0) + fprintf(stderr, "<> Unknown message type\n"); + + /* Exit nl_recvmsgs_def() and return to the main select() */ + return NL_STOP; +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_cache *link_cache; + int err = 1; + int i, idx; + + static const struct { + enum rtnetlink_groups gr_id; + const char* gr_name; + } known_groups[] = { + { RTNLGRP_LINK, "link" }, + { RTNLGRP_NOTIFY, "notify" }, + { RTNLGRP_NEIGH, "neigh" }, + { RTNLGRP_TC, "tc" }, + { RTNLGRP_IPV4_IFADDR, "ipv4-ifaddr" }, + { RTNLGRP_IPV4_MROUTE, "ipv4-mroute" }, + { RTNLGRP_IPV4_ROUTE, "ipv4-route" }, + { RTNLGRP_IPV6_IFADDR, "ipv6-ifaddr" }, + { RTNLGRP_IPV6_MROUTE, "ipv6-mroute" }, + { RTNLGRP_IPV6_ROUTE, "ipv6-route" }, + { RTNLGRP_IPV6_IFINFO, "ipv6-ifinfo" }, + { RTNLGRP_DECnet_IFADDR, "decnet-ifaddr" }, + { RTNLGRP_DECnet_ROUTE, "decnet-route" }, + { RTNLGRP_IPV6_PREFIX, "ipv6-prefix" }, + { RTNLGRP_NONE, NULL } + }; + + sock = nl_cli_alloc_socket(); + nl_socket_disable_seq_check(sock); + nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL); + + if (argc > 1 && !strcasecmp(argv[1], "-h")) { + printf("Usage: nl-monitor []\n"); + + printf("Known groups:"); + for (i = 0; known_groups[i].gr_id != RTNLGRP_NONE; i++) + printf(" %s", known_groups[i].gr_name); + printf("\n"); + return 2; + } + + nl_cli_connect(sock, NETLINK_ROUTE); + + for (idx = 1; argc > idx; idx++) { + for (i = 0; known_groups[i].gr_id != RTNLGRP_NONE; i++) { + if (!strcmp(argv[idx], known_groups[i].gr_name)) { + + if ((err = nl_socket_add_membership(sock, known_groups[i].gr_id)) < 0) { + nl_cli_fatal(err, "%s: %s\n", argv[idx], + nl_geterror(err)); + } + + break; + } + } + if (known_groups[i].gr_id == RTNLGRP_NONE) + fprintf(stderr, "Warning: Unknown group: %s\n", argv[idx]); + } + + link_cache = nl_cli_link_alloc_cache(sock); + + while (1) { + fd_set rfds; + int fd, retval; + + fd = nl_socket_get_fd(sock); + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + /* wait for an incoming message on the netlink socket */ + retval = select(fd+1, &rfds, NULL, NULL, NULL); + + if (retval) { + /* FD_ISSET(fd, &rfds) will be true */ + nl_recvmsgs_default(sock); + } + } + + return 0; +} diff --git a/src/nl-neigh-add.c b/src/nl-neigh-add.c new file mode 100644 index 0000000..4cddabe --- /dev/null +++ b/src/nl-neigh-add.c @@ -0,0 +1,110 @@ +/* + * src/ nl-neigh-add.c Add a neighbour + * + * 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 + */ + +#include +#include +#include + +static int quiet = 0; + +static void print_usage(void) +{ + printf( + "Usage: nl-neigh-add [OPTION]... NEIGHBOUR\n" + "\n" + "Options\n" + " --update-only Do not create neighbour, updates exclusively\n" + " --create-only Do not update neighbour if it exists already.\n" + " -q, --quiet Do not print informal notifications\n" + " -h, --help Show this help\n" + " -v, --version Show versioning information\n" + "\n" + "Neighbour Options\n" + " -a, --addr=ADDR Destination address of neighbour\n" + " -l, --lladdr=ADDR Link layer address of neighbour\n" + " -d, --dev=DEV Device the neighbour is connected to\n" + " --state=STATE Neighbour state, (default = permanent)\n" + "\n" + "Example\n" + " nl-neigh-add --create-only --addr=10.0.0.1 --dev=eth0 \\\n" + " --lladdr=AA:BB:CC:DD:EE:FF\n" + ); + + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct rtnl_neigh *neigh; + struct nl_cache *link_cache; + struct nl_dump_params dp = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + int err, ok = 0, nlflags = NLM_F_REPLACE | NLM_F_CREATE; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + neigh = nl_cli_neigh_alloc(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_UPDATE_ONLY = 257, + ARG_CREATE_ONLY = 258, + ARG_STATE, + }; + static struct option long_opts[] = { + { "update-only", 0, 0, ARG_UPDATE_ONLY }, + { "create-only", 0, 0, ARG_CREATE_ONLY }, + { "quiet", 0, 0, 'q' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "addr", 1, 0, 'a' }, + { "lladdr", 1, 0, 'l' }, + { "dev", 1, 0, 'd' }, + { "state", 1, 0, ARG_STATE }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "qhva:l:d:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case ARG_UPDATE_ONLY: nlflags &= ~NLM_F_CREATE; break; + case ARG_CREATE_ONLY: nlflags |= NLM_F_EXCL; break; + case 'q': quiet = 1; break; + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + case 'a': ok++; nl_cli_neigh_parse_dst(neigh, optarg); break; + case 'l': nl_cli_neigh_parse_lladdr(neigh, optarg); break; + case 'd': nl_cli_neigh_parse_dev(neigh, link_cache, optarg); break; + case ARG_STATE: nl_cli_neigh_parse_state(neigh, optarg); break; + } + } + + if (!ok) + print_usage(); + + if ((err = rtnl_neigh_add(sock, neigh, nlflags)) < 0) + nl_cli_fatal(err, "Unable to add neighbour: %s", + nl_geterror(err)); + + if (!quiet) { + printf("Added "); + nl_object_dump(OBJ_CAST(neigh), &dp); + } + + return 0; +} diff --git a/src/nl-neigh-delete.c b/src/nl-neigh-delete.c new file mode 100644 index 0000000..c418608 --- /dev/null +++ b/src/nl-neigh-delete.c @@ -0,0 +1,122 @@ +/* + * src/nl-neigh-delete.c Delete a neighbour + * + * 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 + */ + +#include +#include +#include + +static int quiet = 0, default_yes = 0, deleted = 0, interactive = 0; +static struct nl_sock *sock; + +static void print_usage(void) +{ + printf( + "Usage: nl-neigh-delete [OPTION]... [NEIGHBOUR]\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" + "Neighbour Options\n" + " -a, --addr=ADDR Destination address of neighbour\n" + " -l, --lladdr=ADDR Link layer address of neighbour\n" + " -d, --dev=DEV Device the neighbour is connected to\n" + " --family=FAMILY Destination address family\n" + " --state=STATE Neighbour state, (default = permanent)\n" + ); + + exit(0); +} + +static void delete_cb(struct nl_object *obj, void *arg) +{ + struct rtnl_neigh *neigh = 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_neigh_delete(sock, neigh, 0)) < 0) + nl_cli_fatal(err, "Unable to delete neighbour: %s\n", + nl_geterror(err)); + + if (!quiet) { + printf("Deleted "); + nl_object_dump(obj, ¶ms); + } + + deleted++; +} + +int main(int argc, char *argv[]) +{ + struct rtnl_neigh *neigh; + struct nl_cache *link_cache, *neigh_cache; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + neigh_cache = nl_cli_neigh_alloc_cache(sock); + neigh = nl_cli_neigh_alloc(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_FAMILY = 257, + ARG_STATE = 258, + ARG_YES, + }; + static struct option long_opts[] = { + { "interactive", 0, 0, 'i' }, + { "yes", 0, 0, ARG_YES }, + { "quiet", 0, 0, 'q' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "addr", 1, 0, 'a' }, + { "lladdr", 1, 0, 'l' }, + { "dev", 1, 0, 'd' }, + { "family", 1, 0, ARG_FAMILY }, + { "state", 1, 0, ARG_STATE }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "qhva:l:d:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'i': 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 'a': nl_cli_neigh_parse_dst(neigh, optarg); break; + case 'l': nl_cli_neigh_parse_lladdr(neigh, optarg); break; + case 'd': nl_cli_neigh_parse_dev(neigh, link_cache, optarg); break; + case ARG_FAMILY: nl_cli_neigh_parse_family(neigh, optarg); break; + case ARG_STATE: nl_cli_neigh_parse_state(neigh, optarg); break; + } + } + + nl_cache_foreach_filter(neigh_cache, OBJ_CAST(neigh), delete_cb, NULL); + + if (!quiet) + printf("Deleted %d neighbours\n", deleted); + + return 0; +} diff --git a/src/nl-neigh-list.c b/src/nl-neigh-list.c new file mode 100644 index 0000000..ebf5486 --- /dev/null +++ b/src/nl-neigh-list.c @@ -0,0 +1,89 @@ +/* + * src/nl-neigh-list.c List Neighbours + * + * 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 + */ + +#include +#include +#include + +static void print_usage(void) +{ + printf( + "Usage: nl-neigh-list [OPTION]... [NEIGHBOUR]\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" + "Neighbour Options\n" + " -a, --addr=ADDR Destination address of neighbour\n" + " -l, --lladdr=ADDR Link layer address of neighbour\n" + " -d, --dev=DEV Device the neighbour is connected to\n" + " --family=FAMILY Destination address family\n" + " --state=STATE Neighbour state, (default = permanent)\n" + ); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct rtnl_neigh *neigh; + struct nl_cache *link_cache, *neigh_cache; + struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + neigh_cache = nl_cli_neigh_alloc_cache(sock); + neigh = nl_cli_neigh_alloc(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_FAMILY = 257, + ARG_STATE = 258, + }; + static struct option long_opts[] = { + { "format", 1, 0, 'f' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "addr", 1, 0, 'a' }, + { "lladdr", 1, 0, 'l' }, + { "dev", 1, 0, 'd' }, + { "family", 1, 0, ARG_FAMILY }, + { "state", 1, 0, ARG_STATE }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "f:hva:l:d:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'f': params.dp_type = nl_cli_parse_dumptype(optarg); break; + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + case 'a': nl_cli_neigh_parse_dst(neigh, optarg); break; + case 'l': nl_cli_neigh_parse_lladdr(neigh, optarg); break; + case 'd': nl_cli_neigh_parse_dev(neigh, link_cache, optarg); break; + case ARG_FAMILY: nl_cli_neigh_parse_family(neigh, optarg); break; + case ARG_STATE: nl_cli_neigh_parse_state(neigh, optarg); break; + } + } + + nl_cache_dump_filter(neigh_cache, ¶ms, OBJ_CAST(neigh)); + + return 0; +} diff --git a/src/nl-neightbl-list.c b/src/nl-neightbl-list.c new file mode 100644 index 0000000..5010b92 --- /dev/null +++ b/src/nl-neightbl-list.c @@ -0,0 +1,66 @@ +/* + * src/nl-neightbl-list.c Dump neighbour tables + * + * 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 + */ + +#include +#include + +static void print_usage(void) +{ + printf( + "Usage: nl-neightbl-list [OPTION]...\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" + ); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_cache *link_cache, *neightbl_cache; + struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + neightbl_cache = nl_cli_alloc_cache(sock, "neighbour table", + rtnl_neightbl_alloc_cache); + + for (;;) { + int c, optidx = 0; + static struct option long_opts[] = { + { "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); + if (c == -1) + break; + + switch (c) { + case 'f': params.dp_type = nl_cli_parse_dumptype(optarg); break; + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + } + } + + nl_cache_dump(neightbl_cache, ¶ms); + + return 0; +} diff --git a/src/nl-pktloc-lookup.c b/src/nl-pktloc-lookup.c new file mode 100644 index 0000000..17c867b --- /dev/null +++ b/src/nl-pktloc-lookup.c @@ -0,0 +1,154 @@ +/* + * src/nl-pktloc-lookup.c Lookup packet location alias + * + * 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 + */ + +#include +#include + +static void print_usage(void) +{ +printf( +"Usage: nl-pktloc-lookup [OPTIONS] \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, 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 (optind >= argc) + print_usage(); + + if ((err = rtnl_pktloc_lookup(argv[optind++], &loc)) < 0) + nl_cli_fatal(err, "Unable to lookup packet location: %s", + nl_geterror(err)); + + 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 0000000..c2a7c9f --- /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 + */ + +#include +#include +#include +#include + +#include + +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 new file mode 100644 index 0000000..2f945bb --- /dev/null +++ b/src/nl-qdisc-delete.c @@ -0,0 +1,144 @@ +/* + * src/nl-qdisc-delete.c Delete Queuing 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-2010 Thomas Graf + */ + +#include +#include +#include +#include + +static int quiet = 0, default_yes = 0, deleted = 0, interactive = 0; +static struct nl_sock *sock; + +static void print_usage(void) +{ + printf( + "Usage: nl-qdisc-delete [OPTION]... [QDISC]\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 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" + ); + + exit(0); +} + +static void delete_cb(struct nl_object *obj, void *arg) +{ + struct rtnl_qdisc *qdisc = nl_object_priv(obj); + struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + 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; + + if ((err = rtnl_qdisc_delete(sock, qdisc)) < 0) + nl_cli_fatal(err, "Unable to delete qdisc: %s\n", nl_geterror(err)); + + if (!quiet) { + printf("Deleted "); + nl_object_dump(obj, ¶ms); + } + + deleted++; +} + +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, 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': + 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) + printf("Deleted %d qdiscs\n", deleted); + + return 0; +} diff --git a/src/nl-qdisc-list.c b/src/nl-qdisc-list.c new file mode 100644 index 0000000..5b0a3f0 --- /dev/null +++ b/src/nl-qdisc-list.c @@ -0,0 +1,183 @@ +/* + * 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-2010 Thomas Graf + */ + +#include +#include +#include +#include +#include +#include + +#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" + " --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" + " -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 rtnl_qdisc *qdisc; + struct rtnl_tc *tc; + struct nl_cache *link_cache, *qdisc_cache; + + 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_DETAILS = 257, + ARG_STATS = 258, + }; + static struct option long_opts[] = { + { "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' }, + { "id", 1, 0, 'i' }, + { "kind", 1, 0, 'k' }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "rhvd: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 'r': recursive = 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 (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 new file mode 100644 index 0000000..d4aa767 --- /dev/null +++ b/src/nl-route-add.c @@ -0,0 +1,132 @@ +/* + * src/nl-route-add.c Route addition utility + * + * 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 + */ + +#include +#include +#include + +static int quiet = 0; +static struct nl_cache *link_cache, *route_cache; + +static void print_usage(void) +{ + printf( + "Usage: nl-route-add [OPTION]... [ROUTE]\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" + "Route Options\n" + " -d, --dst=ADDR destination prefix, e.g. 10.10.0.0/16\n" + " -n, --nexthop=NH nexthop configuration:\n" + " dev=DEV route via device\n" + " weight=WEIGHT weight of nexthop\n" + " flags=FLAGS\n" + " via=GATEWAY route via other node\n" + " realms=REALMS\n" + " e.g. dev=eth0,via=192.168.1.12\n" + " -t, --table=TABLE Routing table\n" + " --family=FAMILY Address family\n" + " --src=ADDR Source prefix\n" + " --iif=DEV Incomming interface\n" + " --pref-src=ADDR Preferred source address\n" + " --metrics=OPTS Metrics configurations\n" + " --priority=NUM Priotity\n" + " --scope=SCOPE Scope\n" + " --protocol=PROTO Protocol\n" + " --type=TYPE { unicast | local | broadcast | multicast }\n" + ); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct rtnl_route *route; + struct nl_dump_params dp = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + int err = 1; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + route_cache = nl_cli_route_alloc_cache(sock, 0); + route = nl_cli_route_alloc(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_FAMILY = 257, + ARG_SRC = 258, + ARG_IIF, + ARG_PREF_SRC, + ARG_METRICS, + ARG_PRIORITY, + ARG_SCOPE, + ARG_PROTOCOL, + ARG_TYPE, + }; + static struct option long_opts[] = { + { "quiet", 0, 0, 'q' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "dst", 1, 0, 'd' }, + { "nexthop", 1, 0, 'n' }, + { "table", 1, 0, 't' }, + { "family", 1, 0, ARG_FAMILY }, + { "src", 1, 0, ARG_SRC }, + { "iif", 1, 0, ARG_IIF }, + { "pref-src", 1, 0, ARG_PREF_SRC }, + { "metrics", 1, 0, ARG_METRICS }, + { "priority", 1, 0, ARG_PRIORITY }, + { "scope", 1, 0, ARG_SCOPE }, + { "protocol", 1, 0, ARG_PROTOCOL }, + { "type", 1, 0, ARG_TYPE }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "qhvd:n:t:", 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_route_parse_dst(route, optarg); break; + case 'n': nl_cli_route_parse_nexthop(route, optarg, link_cache); break; + case 't': nl_cli_route_parse_table(route, optarg); break; + case ARG_FAMILY: nl_cli_route_parse_family(route, optarg); break; + case ARG_SRC: nl_cli_route_parse_src(route, optarg); break; + case ARG_IIF: nl_cli_route_parse_iif(route, optarg, link_cache); break; + case ARG_PREF_SRC: nl_cli_route_parse_pref_src(route, optarg); break; + case ARG_METRICS: nl_cli_route_parse_metric(route, optarg); break; + case ARG_PRIORITY: nl_cli_route_parse_prio(route, optarg); break; + case ARG_SCOPE: nl_cli_route_parse_scope(route, optarg); break; + case ARG_PROTOCOL: nl_cli_route_parse_protocol(route, optarg); break; + case ARG_TYPE: nl_cli_route_parse_type(route, optarg); break; + } + } + + 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) { + printf("Added "); + nl_object_dump(OBJ_CAST(route), &dp); + } + + return 0; +} diff --git a/src/nl-route-delete.c b/src/nl-route-delete.c new file mode 100644 index 0000000..884fd7f --- /dev/null +++ b/src/nl-route-delete.c @@ -0,0 +1,168 @@ +/* + * src/nl-route-delete.c Delete Routes + * + * 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 + */ + +#include +#include +#include + +static int interactive = 0, default_yes = 0, quiet = 0; +static int deleted = 0; +static struct nl_sock *sock; + +static void print_version(void) +{ + fprintf(stderr, "%s\n", LIBNL_STRING); + exit(0); +} + +static void print_usage(void) +{ + printf( + "Usage: nl-route-delete [OPTION]... [ROUTE]\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" + "Route Options\n" + " -d, --dst=ADDR destination prefix, e.g. 10.10.0.0/16\n" + " -n, --nexthop=NH nexthop configuration:\n" + " dev=DEV route via device\n" + " weight=WEIGHT weight of nexthop\n" + " flags=FLAGS\n" + " via=GATEWAY route via other node\n" + " realms=REALMS\n" + " e.g. dev=eth0,via=192.168.1.12\n" + " -t, --table=TABLE Routing table\n" + " --family=FAMILY Address family\n" + " --src=ADDR Source prefix\n" + " --iif=DEV Incomming interface\n" + " --pref-src=ADDR Preferred source address\n" + " --metrics=OPTS Metrics configurations\n" + " --priority=NUM Priotity\n" + " --scope=SCOPE Scope\n" + " --protocol=PROTO Protocol\n" + " --type=TYPE { unicast | local | broadcast | multicast }\n" + ); + exit(0); +} + +static void delete_cb(struct nl_object *obj, void *arg) +{ + struct rtnl_route *route = (struct rtnl_route *) 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_route_delete(sock, route, 0)) < 0) + nl_cli_fatal(err, "Unable to delete route: %s", nl_geterror(err)); + + if (!quiet) { + printf("Deleted "); + nl_object_dump(obj, ¶ms); + } + + deleted++; +} + +int main(int argc, char *argv[]) +{ + struct nl_cache *link_cache, *route_cache; + struct rtnl_route *route; + int nf = 0; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + route_cache = nl_cli_route_alloc_cache(sock, 0); + route = nl_cli_route_alloc(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_FAMILY = 257, + ARG_SRC = 258, + ARG_IIF, + ARG_PREF_SRC, + ARG_METRICS, + ARG_PRIORITY, + ARG_SCOPE, + ARG_PROTOCOL, + ARG_TYPE, + ARG_YES, + }; + static struct option long_opts[] = { + { "interactive", 0, 0, 'i' }, + { "yes", 0, 0, ARG_YES }, + { "quiet", 0, 0, 'q' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "dst", 1, 0, 'd' }, + { "nexthop", 1, 0, 'n' }, + { "table", 1, 0, 't' }, + { "family", 1, 0, ARG_FAMILY }, + { "src", 1, 0, ARG_SRC }, + { "iif", 1, 0, ARG_IIF }, + { "pref-src", 1, 0, ARG_PREF_SRC }, + { "metrics", 1, 0, ARG_METRICS }, + { "priority", 1, 0, ARG_PRIORITY }, + { "scope", 1, 0, ARG_SCOPE }, + { "protocol", 1, 0, ARG_PROTOCOL }, + { "type", 1, 0, ARG_TYPE }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "iqhvd:n:t:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'i': interactive = 1; break; + case ARG_YES: default_yes = 1; break; + case 'q': quiet = 1; break; + case 'h': print_usage(); break; + case 'v': print_version(); break; + case 'd': nf++; nl_cli_route_parse_dst(route, optarg); break; + case 'n': nf++; nl_cli_route_parse_nexthop(route, optarg, link_cache); break; + case 't': nf++; nl_cli_route_parse_table(route, optarg); break; + case ARG_FAMILY: nf++; nl_cli_route_parse_family(route, optarg); break; + case ARG_SRC: nf++; nl_cli_route_parse_src(route, optarg); break; + case ARG_IIF: nf++; nl_cli_route_parse_iif(route, optarg, link_cache); break; + case ARG_PREF_SRC: nf++; nl_cli_route_parse_pref_src(route, optarg); break; + case ARG_METRICS: nf++; nl_cli_route_parse_metric(route, optarg); break; + case ARG_PRIORITY: nf++; nl_cli_route_parse_prio(route, optarg); break; + case ARG_SCOPE: nf++; nl_cli_route_parse_scope(route, optarg); break; + case ARG_PROTOCOL: nf++; nl_cli_route_parse_protocol(route, optarg); break; + case ARG_TYPE: nf++; nl_cli_route_parse_type(route, optarg); break; + } + } + + if (nf == 0 && !interactive && !default_yes) { + fprintf(stderr, "You attempted to delete all routes in " + "non-interactive mode, aborting.\n"); + exit(0); + } + + nl_cache_foreach_filter(route_cache, OBJ_CAST(route), delete_cb, NULL); + + if (!quiet) + printf("Deleted %d routes\n", deleted); + + return 0; +} diff --git a/src/nl-route-get.c b/src/nl-route-get.c new file mode 100644 index 0000000..c2f07d4 --- /dev/null +++ b/src/nl-route-get.c @@ -0,0 +1,85 @@ +/* + * src/nl-route-get.c Get Route 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-2009 Thomas Graf + */ + +#include +#include +#include + +static void print_usage(void) +{ + printf("Usage: nl-route-get \n"); + exit(1); +} + +static void parse_cb(struct nl_object *obj, void *arg) +{ + //struct rtnl_route *route = (struct rtnl_route *) obj; + struct nl_dump_params params = { + .dp_fd = stdout, + .dp_type = NL_DUMP_DETAILS, + }; + + nl_object_dump(obj, ¶ms); +} + +static int cb(struct nl_msg *msg, void *arg) +{ + int err; + + if ((err = nl_msg_parse(msg, &parse_cb, NULL)) < 0) + nl_cli_fatal(err, "Unable to parse object: %s", nl_geterror(err)); + + return 0; +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_cache *link_cache, *route_cache; + struct nl_addr *dst; + int err = 1; + + if (argc < 2 || !strcmp(argv[1], "-h")) + print_usage(); + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + route_cache = nl_cli_route_alloc_cache(sock, 0); + + dst = nl_cli_addr_parse(argv[1], AF_INET); + + { + struct nl_msg *m; + struct rtmsg rmsg = { + .rtm_family = nl_addr_get_family(dst), + .rtm_dst_len = nl_addr_get_prefixlen(dst), + }; + + m = nlmsg_alloc_simple(RTM_GETROUTE, 0); + nlmsg_append(m, &rmsg, sizeof(rmsg), NLMSG_ALIGNTO); + nla_put_addr(m, RTA_DST, dst); + + err = nl_send_auto_complete(sock, m); + nlmsg_free(m); + if (err < 0) + nl_cli_fatal(err, "%s", nl_geterror(err)); + + nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL); + + if (nl_recvmsgs_default(sock) < 0) + nl_cli_fatal(err, "%s", nl_geterror(err)); + } + + //nl_cache_dump(route_cache, ¶ms); + + return 0; +} diff --git a/src/nl-route-list.c b/src/nl-route-list.c new file mode 100644 index 0000000..e0e57be --- /dev/null +++ b/src/nl-route-list.c @@ -0,0 +1,129 @@ +/* + * src/nl-route-list.c List route 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-2009 Thomas Graf + */ + +#include +#include +#include + +static void print_usage(void) +{ + printf( + "Usage: nl-route-list [OPTION]... [ROUTE]\n" + "\n" + "Options\n" + " -c, --cache List the contents of the route cache\n" + " -f, --format=TYPE Output format { brief | details | stats }\n" + " -h, --help Show this help\n" + " -v, --version Show versioning information\n" + "\n" + "Route Options\n" + " -d, --dst=ADDR destination prefix, e.g. 10.10.0.0/16\n" + " -n, --nexthop=NH nexthop configuration:\n" + " dev=DEV route via device\n" + " weight=WEIGHT weight of nexthop\n" + " flags=FLAGS\n" + " via=GATEWAY route via other node\n" + " realms=REALMS\n" + " e.g. dev=eth0,via=192.168.1.12\n" + " -t, --table=TABLE Routing table\n" + " --family=FAMILY Address family\n" + " --src=ADDR Source prefix\n" + " --iif=DEV Incomming interface\n" + " --pref-src=ADDR Preferred source address\n" + " --metrics=OPTS Metrics configurations\n" + " --priority=NUM Priotity\n" + " --scope=SCOPE Scope\n" + " --protocol=PROTO Protocol\n" + " --type=TYPE { unicast | local | broadcast | multicast }\n" + ); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_cache *link_cache, *route_cache; + struct rtnl_route *route; + struct nl_dump_params params = { + .dp_fd = stdout, + .dp_type = NL_DUMP_LINE, + }; + int print_cache = 0; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + route = nl_cli_route_alloc(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_FAMILY = 257, + ARG_SRC = 258, + ARG_IIF, + ARG_PREF_SRC, + ARG_METRICS, + ARG_PRIORITY, + ARG_SCOPE, + ARG_PROTOCOL, + ARG_TYPE, + }; + static struct option long_opts[] = { + { "cache", 0, 0, 'c' }, + { "format", 1, 0, 'f' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "dst", 1, 0, 'd' }, + { "nexthop", 1, 0, 'n' }, + { "table", 1, 0, 't' }, + { "family", 1, 0, ARG_FAMILY }, + { "src", 1, 0, ARG_SRC }, + { "iif", 1, 0, ARG_IIF }, + { "pref-src", 1, 0, ARG_PREF_SRC }, + { "metrics", 1, 0, ARG_METRICS }, + { "priority", 1, 0, ARG_PRIORITY }, + { "scope", 1, 0, ARG_SCOPE }, + { "protocol", 1, 0, ARG_PROTOCOL }, + { "type", 1, 0, ARG_TYPE }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "cf:hvd:n:t:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'c': print_cache = 1; 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 'd': nl_cli_route_parse_dst(route, optarg); break; + case 'n': nl_cli_route_parse_nexthop(route, optarg, link_cache); break; + case 't': nl_cli_route_parse_table(route, optarg); break; + case ARG_FAMILY: nl_cli_route_parse_family(route, optarg); break; + case ARG_SRC: nl_cli_route_parse_src(route, optarg); break; + case ARG_IIF: nl_cli_route_parse_iif(route, optarg, link_cache); break; + case ARG_PREF_SRC: nl_cli_route_parse_pref_src(route, optarg); break; + case ARG_METRICS: nl_cli_route_parse_metric(route, optarg); break; + case ARG_PRIORITY: nl_cli_route_parse_prio(route, optarg); break; + case ARG_SCOPE: nl_cli_route_parse_scope(route, optarg); break; + case ARG_PROTOCOL: nl_cli_route_parse_protocol(route, optarg); break; + case ARG_TYPE: nl_cli_route_parse_type(route, optarg); break; + } + } + + route_cache = nl_cli_route_alloc_cache(sock, + print_cache ? ROUTE_CACHE_CONTENT : 0); + + nl_cache_dump_filter(route_cache, ¶ms, OBJ_CAST(route)); + + return 0; +} diff --git a/src/nl-rule-list.c b/src/nl-rule-list.c new file mode 100644 index 0000000..8b474fa --- /dev/null +++ b/src/nl-rule-list.c @@ -0,0 +1,77 @@ +/* + * src/nl-rule-dump.c Dump rule 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-2009 Thomas Graf + */ + +#include +#include +#include + +static void print_usage(void) +{ + printf( + "Usage: nl-rule-list [OPTION]... [ROUTE]\n" + "\n" + "Options\n" + " -c, --cache List the contents of the route cache\n" + " -f, --format=TYPE Output format { brief | details | stats }\n" + " -h, --help Show this help\n" + " -v, --version Show versioning information\n" + "\n" + "Rule Options\n" + " --family Address family\n" + ); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct rtnl_rule *rule; + struct nl_cache *link_cache, *rule_cache; + struct nl_dump_params params = { + .dp_fd = stdout, + .dp_type = NL_DUMP_LINE, + }; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + link_cache = nl_cli_link_alloc_cache(sock); + rule_cache = nl_cli_rule_alloc_cache(sock); + rule = nl_cli_rule_alloc(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_FAMILY = 257, + }; + static struct option long_opts[] = { + { "format", 1, 0, 'f' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "family", 1, 0, ARG_FAMILY }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "f:hv", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'f': params.dp_type = nl_cli_parse_dumptype(optarg); break; + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + case ARG_FAMILY: nl_cli_rule_parse_family(rule, optarg); break; + } + } + + nl_cache_dump_filter(rule_cache, ¶ms, OBJ_CAST(rule)); + + return 0; +} diff --git a/src/nl-tctree-list.c b/src/nl-tctree-list.c new file mode 100644 index 0000000..d90cb28 --- /dev/null +++ b/src/nl-tctree-list.c @@ -0,0 +1,165 @@ +/* + * src/nl-tctree-list.c List Traffic Control Tree + * + * 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 + */ + +#include +#include +#include +#include +#include + +static struct nl_sock *sock; +static struct nl_cache *qdisc_cache, *class_cache; +static struct nl_dump_params params = { + .dp_type = NL_DUMP_DETAILS, +}; + +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) +{ + printf( + "Usage: nl-tctree-list [OPTION]...\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" + ); + exit(0); +} + +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_tc_get_handle((struct rtnl_tc *) class); + + params.dp_prefix = (int)(long) arg; + nl_object_dump(obj, ¶ms); + + leaf = rtnl_class_leaf_qdisc(class, qdisc_cache); + if (leaf) + print_qdisc((struct nl_object *) leaf, arg + 2); + + print_tc_childs(TC_CAST(class), arg + 2); + + if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0) + return; + + params.dp_prefix = (int)(long) arg + 2; + nl_cache_dump(cls_cache, ¶ms); + 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_tc_get_handle((struct rtnl_tc *) qdisc); + + params.dp_prefix = (int)(long) arg; + nl_object_dump(obj, ¶ms); + + print_tc_childs(TC_CAST(qdisc), arg + 2); + + if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0) + return; + + params.dp_prefix = (int)(long) arg + 2; + nl_cache_dump(cls_cache, ¶ms); + nl_cache_free(cls_cache); +} + +static void print_link(struct nl_object *obj, void *arg) +{ + struct rtnl_link *link = (struct rtnl_link *) obj; + struct rtnl_qdisc *qdisc; + + ifindex = rtnl_link_get_ifindex(link); + params.dp_prefix = 0; + nl_object_dump(obj, ¶ms); + + if (rtnl_class_alloc_cache(sock, ifindex, &class_cache) < 0) + return; + + qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_ROOT); + if (qdisc) { + print_qdisc((struct nl_object *) qdisc, (void *) 2); + rtnl_qdisc_put(qdisc); + } + + qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, 0); + if (qdisc) { + print_qdisc((struct nl_object *) qdisc, (void *) 2); + rtnl_qdisc_put(qdisc); + } + + qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_INGRESS); + if (qdisc) { + print_qdisc((struct nl_object *) qdisc, (void *) 2); + rtnl_qdisc_put(qdisc); + } + + nl_cache_free(class_cache); +} + +int main(int argc, char *argv[]) +{ + struct nl_cache *link_cache; + + 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); + + params.dp_fd = stdout; + + for (;;) { + int c, optidx = 0; + static struct option long_opts[] = { + { "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); + if (c == -1) + break; + + switch (c) { + case 'f': params.dp_type = nl_cli_parse_dumptype(optarg); break; + case 'h': print_usage(); break; + case 'v': nl_cli_print_version(); break; + } + } + + nl_cache_foreach(link_cache, &print_link, NULL); + + return 0; +} diff --git a/src/nl-util-addr.c b/src/nl-util-addr.c new file mode 100644 index 0000000..5f0738d --- /dev/null +++ b/src/nl-util-addr.c @@ -0,0 +1,34 @@ +/* + * src/nl-util-addr.c Address Helper + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2009 Thomas Graf + */ + +#include + +int main(int argc, char *argv[]) +{ + int err; + char host[256]; + struct nl_addr *a; + + if (argc < 2) { + fprintf(stderr, "Usage: nl-util-addr
    \n"); + return -1; + } + + a = nl_cli_addr_parse(argv[1], AF_UNSPEC); + err = nl_addr_resolve(a, host, sizeof(host)); + if (err != 0) + nl_cli_fatal(err, "Unable to resolve address \"%s\": %s", + argv[1], nl_geterror(err)); + + printf("%s\n", host); + + return 0; +} diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..7953176 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,54 @@ +# -*- Makefile -*- + +EXTRA_DIST = \ + util.h + +if ENABLE_UNIT_TESTS + +AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" + +LDADD = \ + ${top_builddir}/lib/libnl-3.la \ + ${top_builddir}/lib/libnl-nf-3.la \ + ${top_builddir}/lib/libnl-genl-3.la \ + ${top_builddir}/lib/libnl-route-3.la \ + @CHECK_LIBS@ + +CFLAGS += @CHECK_CFLAGS@ + +UNIT_TESTS = check-all + +check_PROGRAMS = \ + test-create-bond \ + test-create-vlan \ + test-delete-link \ + test-socket-creation \ + test-complex-HTB-with-hash-filters \ + ${UNIT_TESTS} + +TESTS = \ + ${UNIT_TESTS} + +if ENABLE_CLI +LDADD += ${top_builddir}/src/lib/libnl-cli-3.la +check_PROGRAMS += \ + test-cache-mngr \ + test-genl \ + test-nf-cache-mngr +endif + +test_cache_mngr_SOURCES = test-cache-mngr.c +test_create_bond_SOURCES = test-create-bond.c +test_create_vlan_SOURCES = test-create-vlan.c +test_delete_link_SOURCES = test-delete-link.c +test_genl_SOURCES = test-genl.c +test_nf_cache_mngr_SOURCES = test-nf-cache-mngr.c +test_socket_creation_SOURCES = test-socket-creation.c +test_complex_HTB_with_hash_filters_SOURCES = test-complex-HTB-with-hash-filters.c + +# Unit tests +check_all_SOURCES = \ + check-all.c \ + check-addr.c \ + check-attr.c +endif diff --git a/tests/Makefile.in b/tests/Makefile.in new file mode 100644 index 0000000..85d4fd8 --- /dev/null +++ b/tests/Makefile.in @@ -0,0 +1,814 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# -*- Makefile -*- +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@ENABLE_UNIT_TESTS_TRUE@am__append_1 = @CHECK_CFLAGS@ +@ENABLE_UNIT_TESTS_TRUE@check_PROGRAMS = test-create-bond$(EXEEXT) \ +@ENABLE_UNIT_TESTS_TRUE@ test-create-vlan$(EXEEXT) \ +@ENABLE_UNIT_TESTS_TRUE@ test-delete-link$(EXEEXT) \ +@ENABLE_UNIT_TESTS_TRUE@ test-socket-creation$(EXEEXT) \ +@ENABLE_UNIT_TESTS_TRUE@ test-complex-HTB-with-hash-filters$(EXEEXT) \ +@ENABLE_UNIT_TESTS_TRUE@ $(am__EXEEXT_1) $(am__EXEEXT_2) +@ENABLE_UNIT_TESTS_TRUE@TESTS = $(am__EXEEXT_1) +@ENABLE_CLI_TRUE@@ENABLE_UNIT_TESTS_TRUE@am__append_2 = ${top_builddir}/src/lib/libnl-cli-3.la +@ENABLE_CLI_TRUE@@ENABLE_UNIT_TESTS_TRUE@am__append_3 = \ +@ENABLE_CLI_TRUE@@ENABLE_UNIT_TESTS_TRUE@ test-cache-mngr \ +@ENABLE_CLI_TRUE@@ENABLE_UNIT_TESTS_TRUE@ test-genl \ +@ENABLE_CLI_TRUE@@ENABLE_UNIT_TESTS_TRUE@ test-nf-cache-mngr + +subdir = tests +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/lib/defs.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@ENABLE_UNIT_TESTS_TRUE@am__EXEEXT_1 = check-all$(EXEEXT) +@ENABLE_CLI_TRUE@@ENABLE_UNIT_TESTS_TRUE@am__EXEEXT_2 = test-cache-mngr$(EXEEXT) \ +@ENABLE_CLI_TRUE@@ENABLE_UNIT_TESTS_TRUE@ test-genl$(EXEEXT) \ +@ENABLE_CLI_TRUE@@ENABLE_UNIT_TESTS_TRUE@ test-nf-cache-mngr$(EXEEXT) +am__check_all_SOURCES_DIST = check-all.c check-addr.c check-attr.c +@ENABLE_UNIT_TESTS_TRUE@am_check_all_OBJECTS = check-all.$(OBJEXT) \ +@ENABLE_UNIT_TESTS_TRUE@ check-addr.$(OBJEXT) \ +@ENABLE_UNIT_TESTS_TRUE@ check-attr.$(OBJEXT) +check_all_OBJECTS = $(am_check_all_OBJECTS) +check_all_LDADD = $(LDADD) +@ENABLE_UNIT_TESTS_TRUE@check_all_DEPENDENCIES = \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ $(am__append_2) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__test_cache_mngr_SOURCES_DIST = test-cache-mngr.c +@ENABLE_UNIT_TESTS_TRUE@am_test_cache_mngr_OBJECTS = \ +@ENABLE_UNIT_TESTS_TRUE@ test-cache-mngr.$(OBJEXT) +test_cache_mngr_OBJECTS = $(am_test_cache_mngr_OBJECTS) +test_cache_mngr_LDADD = $(LDADD) +@ENABLE_UNIT_TESTS_TRUE@test_cache_mngr_DEPENDENCIES = \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ $(am__append_2) +am__test_complex_HTB_with_hash_filters_SOURCES_DIST = \ + test-complex-HTB-with-hash-filters.c +@ENABLE_UNIT_TESTS_TRUE@am_test_complex_HTB_with_hash_filters_OBJECTS = test-complex-HTB-with-hash-filters.$(OBJEXT) +test_complex_HTB_with_hash_filters_OBJECTS = \ + $(am_test_complex_HTB_with_hash_filters_OBJECTS) +test_complex_HTB_with_hash_filters_LDADD = $(LDADD) +@ENABLE_UNIT_TESTS_TRUE@test_complex_HTB_with_hash_filters_DEPENDENCIES = \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ $(am__append_2) +am__test_create_bond_SOURCES_DIST = test-create-bond.c +@ENABLE_UNIT_TESTS_TRUE@am_test_create_bond_OBJECTS = \ +@ENABLE_UNIT_TESTS_TRUE@ test-create-bond.$(OBJEXT) +test_create_bond_OBJECTS = $(am_test_create_bond_OBJECTS) +test_create_bond_LDADD = $(LDADD) +@ENABLE_UNIT_TESTS_TRUE@test_create_bond_DEPENDENCIES = \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ $(am__append_2) +am__test_create_vlan_SOURCES_DIST = test-create-vlan.c +@ENABLE_UNIT_TESTS_TRUE@am_test_create_vlan_OBJECTS = \ +@ENABLE_UNIT_TESTS_TRUE@ test-create-vlan.$(OBJEXT) +test_create_vlan_OBJECTS = $(am_test_create_vlan_OBJECTS) +test_create_vlan_LDADD = $(LDADD) +@ENABLE_UNIT_TESTS_TRUE@test_create_vlan_DEPENDENCIES = \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ $(am__append_2) +am__test_delete_link_SOURCES_DIST = test-delete-link.c +@ENABLE_UNIT_TESTS_TRUE@am_test_delete_link_OBJECTS = \ +@ENABLE_UNIT_TESTS_TRUE@ test-delete-link.$(OBJEXT) +test_delete_link_OBJECTS = $(am_test_delete_link_OBJECTS) +test_delete_link_LDADD = $(LDADD) +@ENABLE_UNIT_TESTS_TRUE@test_delete_link_DEPENDENCIES = \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ $(am__append_2) +am__test_genl_SOURCES_DIST = test-genl.c +@ENABLE_UNIT_TESTS_TRUE@am_test_genl_OBJECTS = test-genl.$(OBJEXT) +test_genl_OBJECTS = $(am_test_genl_OBJECTS) +test_genl_LDADD = $(LDADD) +@ENABLE_UNIT_TESTS_TRUE@test_genl_DEPENDENCIES = \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ $(am__append_2) +am__test_nf_cache_mngr_SOURCES_DIST = test-nf-cache-mngr.c +@ENABLE_UNIT_TESTS_TRUE@am_test_nf_cache_mngr_OBJECTS = \ +@ENABLE_UNIT_TESTS_TRUE@ test-nf-cache-mngr.$(OBJEXT) +test_nf_cache_mngr_OBJECTS = $(am_test_nf_cache_mngr_OBJECTS) +test_nf_cache_mngr_LDADD = $(LDADD) +@ENABLE_UNIT_TESTS_TRUE@test_nf_cache_mngr_DEPENDENCIES = \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ $(am__append_2) +am__test_socket_creation_SOURCES_DIST = test-socket-creation.c +@ENABLE_UNIT_TESTS_TRUE@am_test_socket_creation_OBJECTS = \ +@ENABLE_UNIT_TESTS_TRUE@ test-socket-creation.$(OBJEXT) +test_socket_creation_OBJECTS = $(am_test_socket_creation_OBJECTS) +test_socket_creation_LDADD = $(LDADD) +@ENABLE_UNIT_TESTS_TRUE@test_socket_creation_DEPENDENCIES = \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ $(am__append_2) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/lib +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(check_all_SOURCES) $(test_cache_mngr_SOURCES) \ + $(test_complex_HTB_with_hash_filters_SOURCES) \ + $(test_create_bond_SOURCES) $(test_create_vlan_SOURCES) \ + $(test_delete_link_SOURCES) $(test_genl_SOURCES) \ + $(test_nf_cache_mngr_SOURCES) $(test_socket_creation_SOURCES) +DIST_SOURCES = $(am__check_all_SOURCES_DIST) \ + $(am__test_cache_mngr_SOURCES_DIST) \ + $(am__test_complex_HTB_with_hash_filters_SOURCES_DIST) \ + $(am__test_create_bond_SOURCES_DIST) \ + $(am__test_create_vlan_SOURCES_DIST) \ + $(am__test_delete_link_SOURCES_DIST) \ + $(am__test_genl_SOURCES_DIST) \ + $(am__test_nf_cache_mngr_SOURCES_DIST) \ + $(am__test_socket_creation_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +am__tty_colors = \ +red=; grn=; lgn=; blu=; std= +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ $(am__append_1) +CHECK_CFLAGS = @CHECK_CFLAGS@ +CHECK_LIBS = @CHECK_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FLEX = @FLEX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBNL_VERSION = @LIBNL_VERSION@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_CURRENT = @LT_CURRENT@ +LT_REVISION = @LT_REVISION@ +MAJ_VERSION = @MAJ_VERSION@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIC_VERSION = @MIC_VERSION@ +MIN_VERSION = @MIN_VERSION@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgconfigdir = @pkgconfigdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = \ + util.h + +@ENABLE_UNIT_TESTS_TRUE@AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" +@ENABLE_UNIT_TESTS_TRUE@LDADD = ${top_builddir}/lib/libnl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ +@ENABLE_UNIT_TESTS_TRUE@ @CHECK_LIBS@ $(am__append_2) +@ENABLE_UNIT_TESTS_TRUE@UNIT_TESTS = check-all +@ENABLE_UNIT_TESTS_TRUE@test_cache_mngr_SOURCES = test-cache-mngr.c +@ENABLE_UNIT_TESTS_TRUE@test_create_bond_SOURCES = test-create-bond.c +@ENABLE_UNIT_TESTS_TRUE@test_create_vlan_SOURCES = test-create-vlan.c +@ENABLE_UNIT_TESTS_TRUE@test_delete_link_SOURCES = test-delete-link.c +@ENABLE_UNIT_TESTS_TRUE@test_genl_SOURCES = test-genl.c +@ENABLE_UNIT_TESTS_TRUE@test_nf_cache_mngr_SOURCES = test-nf-cache-mngr.c +@ENABLE_UNIT_TESTS_TRUE@test_socket_creation_SOURCES = test-socket-creation.c +@ENABLE_UNIT_TESTS_TRUE@test_complex_HTB_with_hash_filters_SOURCES = test-complex-HTB-with-hash-filters.c + +# Unit tests +@ENABLE_UNIT_TESTS_TRUE@check_all_SOURCES = \ +@ENABLE_UNIT_TESTS_TRUE@ check-all.c \ +@ENABLE_UNIT_TESTS_TRUE@ check-addr.c \ +@ENABLE_UNIT_TESTS_TRUE@ check-attr.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +check-all$(EXEEXT): $(check_all_OBJECTS) $(check_all_DEPENDENCIES) $(EXTRA_check_all_DEPENDENCIES) + @rm -f check-all$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(check_all_OBJECTS) $(check_all_LDADD) $(LIBS) +test-cache-mngr$(EXEEXT): $(test_cache_mngr_OBJECTS) $(test_cache_mngr_DEPENDENCIES) $(EXTRA_test_cache_mngr_DEPENDENCIES) + @rm -f test-cache-mngr$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_cache_mngr_OBJECTS) $(test_cache_mngr_LDADD) $(LIBS) +test-complex-HTB-with-hash-filters$(EXEEXT): $(test_complex_HTB_with_hash_filters_OBJECTS) $(test_complex_HTB_with_hash_filters_DEPENDENCIES) $(EXTRA_test_complex_HTB_with_hash_filters_DEPENDENCIES) + @rm -f test-complex-HTB-with-hash-filters$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_complex_HTB_with_hash_filters_OBJECTS) $(test_complex_HTB_with_hash_filters_LDADD) $(LIBS) +test-create-bond$(EXEEXT): $(test_create_bond_OBJECTS) $(test_create_bond_DEPENDENCIES) $(EXTRA_test_create_bond_DEPENDENCIES) + @rm -f test-create-bond$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_create_bond_OBJECTS) $(test_create_bond_LDADD) $(LIBS) +test-create-vlan$(EXEEXT): $(test_create_vlan_OBJECTS) $(test_create_vlan_DEPENDENCIES) $(EXTRA_test_create_vlan_DEPENDENCIES) + @rm -f test-create-vlan$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_create_vlan_OBJECTS) $(test_create_vlan_LDADD) $(LIBS) +test-delete-link$(EXEEXT): $(test_delete_link_OBJECTS) $(test_delete_link_DEPENDENCIES) $(EXTRA_test_delete_link_DEPENDENCIES) + @rm -f test-delete-link$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_delete_link_OBJECTS) $(test_delete_link_LDADD) $(LIBS) +test-genl$(EXEEXT): $(test_genl_OBJECTS) $(test_genl_DEPENDENCIES) $(EXTRA_test_genl_DEPENDENCIES) + @rm -f test-genl$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_genl_OBJECTS) $(test_genl_LDADD) $(LIBS) +test-nf-cache-mngr$(EXEEXT): $(test_nf_cache_mngr_OBJECTS) $(test_nf_cache_mngr_DEPENDENCIES) $(EXTRA_test_nf_cache_mngr_DEPENDENCIES) + @rm -f test-nf-cache-mngr$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_nf_cache_mngr_OBJECTS) $(test_nf_cache_mngr_LDADD) $(LIBS) +test-socket-creation$(EXEEXT): $(test_socket_creation_OBJECTS) $(test_socket_creation_DEPENDENCIES) $(EXTRA_test_socket_creation_DEPENDENCIES) + @rm -f test-socket-creation$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_socket_creation_OBJECTS) $(test_socket_creation_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check-addr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check-all.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check-attr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-cache-mngr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-complex-HTB-with-hash-filters.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-create-bond.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-create-vlan.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-delete-link.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-genl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-nf-cache-mngr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-socket-creation.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + fi; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \ + clean-checkPROGRAMS clean-generic clean-libtool ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/check-addr.c b/tests/check-addr.c new file mode 100644 index 0000000..39f3ede --- /dev/null +++ b/tests/check-addr.c @@ -0,0 +1,212 @@ +/* + * tests/check-addr.c nl_addr unit tests + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2013 Thomas Graf + */ + +#include +#include + +START_TEST(addr_alloc) +{ + struct nl_addr *addr; + + addr = nl_addr_alloc(16); + fail_if(addr == NULL, + "Allocation should not return NULL"); + + fail_if(nl_addr_iszero(addr) == 0, + "New empty address should be all zeros"); + + fail_if(nl_addr_get_family(addr) != AF_UNSPEC, + "New empty address should have family AF_UNSPEC"); + + fail_if(nl_addr_get_prefixlen(addr) != 0, + "New empty address should have prefix length 0"); + + fail_if(nl_addr_shared(addr), + "New empty address should not be shared"); + + fail_if(nl_addr_get(addr) != addr, + "nl_addr_get() should return pointer to address"); + + fail_if(nl_addr_shared(addr) == 0, + "Address should be shared after call to nl_addr_get()"); + + nl_addr_put(addr); + + fail_if(nl_addr_shared(addr), + "Address should not be shared after call to nl_addr_put()"); + + fail_if(nl_addr_fill_sockaddr(addr, NULL, 0) == 0, + "Socket address filling should fail for empty address"); + + nl_addr_put(addr); +} +END_TEST + +START_TEST(addr_binary_addr) +{ + struct nl_addr *addr, *addr2; + char baddr[4] = { 0x1, 0x2, 0x3, 0x4 }; + char baddr2[6] = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6 }; + + addr = nl_addr_alloc(4); + fail_if(addr == NULL, + "Allocation should not return NULL"); + + fail_if(nl_addr_set_binary_addr(addr, baddr, 4) < 0, + "Valid binary address should be settable"); + + fail_if(nl_addr_get_prefixlen(addr) != 0, + "Prefix length should be unchanged after nl_addr_set_binary_addr()"); + + fail_if(nl_addr_get_len(addr) != 4, + "Address length should be 4"); + + fail_if(nl_addr_set_binary_addr(addr, baddr2, 6) == 0, + "Should not be able to set binary address exceeding maximum length"); + + fail_if(nl_addr_get_len(addr) != 4, + "Address length should still be 4"); + + fail_if(nl_addr_guess_family(addr) != AF_INET, + "Binary address of length 4 should be guessed as AF_INET"); + + fail_if(memcmp(baddr, nl_addr_get_binary_addr(addr), 4) != 0, + "Binary address mismatches"); + + addr2 = nl_addr_build(AF_UNSPEC, baddr, 4); + fail_if(addr2 == NULL, + "Building of address should not fail"); + + nl_addr_set_prefixlen(addr, 32); + fail_if(nl_addr_get_prefixlen(addr) != 32, + "Prefix length should be successful changed after nl_addr_set_prefixlen()"); + + fail_if(nl_addr_cmp(addr, addr2), + "Addresses built from same binary address should match"); + + nl_addr_put(addr); + nl_addr_put(addr2); +} +END_TEST + +START_TEST(addr_parse4) +{ + struct nl_addr *addr4, *clone; + struct sockaddr_in sin; + socklen_t len = sizeof(sin); + char *addr_str = "10.0.0.1/16"; + char buf[128]; + + fail_if(nl_addr_parse(addr_str, AF_INET6, &addr4) == 0, + "Should not be able to parse IPv4 address in IPv6 mode"); + + fail_if(nl_addr_parse(addr_str, AF_UNSPEC, &addr4) != 0, + "Should be able to parse \"%s\"", addr_str); + + fail_if(nl_addr_get_family(addr4) != AF_INET, + "Address family should be AF_INET"); + + fail_if(nl_addr_get_prefixlen(addr4) != 16, + "Prefix length should be 16"); + + fail_if(nl_addr_iszero(addr4), + "Address should not be all zeroes"); + + clone = nl_addr_clone(addr4); + fail_if(clone == NULL, + "Cloned address should not be NULL"); + + fail_if(nl_addr_cmp(addr4, clone) != 0, + "Cloned address should not mismatch original"); + + fail_if(nl_addr_fill_sockaddr(addr4, (struct sockaddr *) &sin, &len) != 0, + "Should be able to fill socketaddr"); + + fail_if(strcmp(nl_addr2str(addr4, buf, sizeof(buf)), addr_str), + "Address translated back to string does not match original"); + + nl_addr_put(addr4); + nl_addr_put(clone); +} +END_TEST + +START_TEST(addr_parse6) +{ + struct nl_addr *addr6, *clone; + struct sockaddr_in6 sin; + socklen_t len = sizeof(sin); + char *addr_str = "2001:1:2::3/64"; + char buf[128]; + + fail_if(nl_addr_parse(addr_str, AF_INET, &addr6) == 0, + "Should not be able to parse IPv6 address in IPv4 mode"); + + fail_if(nl_addr_parse(addr_str, AF_UNSPEC, &addr6) != 0, + "Should be able to parse \"%s\"", addr_str); + + fail_if(nl_addr_get_family(addr6) != AF_INET6, + "Address family should be AF_INET6"); + + fail_if(nl_addr_get_prefixlen(addr6) != 64, + "Prefix length should be 64"); + + fail_if(nl_addr_iszero(addr6), + "Address should not be all zeroes"); + + clone = nl_addr_clone(addr6); + fail_if(clone == NULL, + "Cloned address should not be NULL"); + + fail_if(nl_addr_cmp(addr6, clone) != 0, + "Cloned address should not mismatch original"); + + fail_if(nl_addr_fill_sockaddr(addr6, (struct sockaddr *) &sin, &len) != 0, + "Should be able to fill socketaddr"); + + fail_if(strcmp(nl_addr2str(addr6, buf, sizeof(buf)), addr_str), + "Address translated back to string does not match original"); + + nl_addr_put(addr6); + nl_addr_put(clone); +} +END_TEST + +START_TEST(addr_info) +{ + struct nl_addr *addr; + char *addr_str = "127.0.0.1"; + struct addrinfo *result; + + fail_if(nl_addr_parse(addr_str, AF_UNSPEC, &addr) != 0, + "Parsing of valid address should not fail"); + + fail_if(nl_addr_info(addr, &result) != 0, + "getaddrinfo() on loopback address should work"); + + freeaddrinfo(result); + nl_addr_put(addr); +} +END_TEST + +Suite *make_nl_addr_suite(void) +{ + Suite *suite = suite_create("Abstract addresses"); + + TCase *tc_addr = tcase_create("Core"); + tcase_add_test(tc_addr, addr_alloc); + tcase_add_test(tc_addr, addr_binary_addr); + tcase_add_test(tc_addr, addr_parse4); + tcase_add_test(tc_addr, addr_parse6); + tcase_add_test(tc_addr, addr_info); + suite_add_tcase(suite, tc_addr); + + return suite; +} diff --git a/tests/check-all.c b/tests/check-all.c new file mode 100644 index 0000000..e431802 --- /dev/null +++ b/tests/check-all.c @@ -0,0 +1,44 @@ +/* + * tests/check-all.c overall unit test program + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2013 Thomas Graf + */ + +#include + +extern Suite *make_nl_addr_suite(void); +extern Suite *make_nl_attr_suite(void); + +static Suite *main_suite(void) +{ + Suite *suite = suite_create("main"); + + return suite; +} + +int main(int argc, char *argv[]) +{ + SRunner *runner; + int nfailed; + + runner = srunner_create(main_suite()); + + /* Add testsuites below */ + + srunner_add_suite(runner, make_nl_addr_suite()); + srunner_add_suite(runner, make_nl_attr_suite()); + + /* Do not add testsuites below this line */ + + srunner_run_all(runner, CK_ENV); + + nfailed = srunner_ntests_failed(runner); + srunner_free(runner); + + return nfailed != 0; +} diff --git a/tests/check-attr.c b/tests/check-attr.c new file mode 100644 index 0000000..d862230 --- /dev/null +++ b/tests/check-attr.c @@ -0,0 +1,88 @@ +/* + * tests/check-attr.c nla_attr unit tests + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2013 Thomas Graf + */ + +#include "util.h" +#include +#include + +START_TEST(attr_size) +{ + fail_if(nla_attr_size(0) != NLA_HDRLEN, + "Length of empty attribute should match header size"); + fail_if(nla_attr_size(1) != NLA_HDRLEN + 1, + "Length of 1 bytes payload should be NLA_HDRLEN + 1"); + fail_if(nla_attr_size(2) != NLA_HDRLEN + 2, + "Length of 2 bytes payload should be NLA_HDRLEN + 2"); + fail_if(nla_attr_size(3) != NLA_HDRLEN + 3, + "Length of 3 bytes payload should be NLA_HDRLEN + 3"); + fail_if(nla_attr_size(4) != NLA_HDRLEN + 4, + "Length of 4 bytes payload should be NLA_HDRLEN + 4"); + + fail_if(nla_total_size(1) != NLA_HDRLEN + 4, + "Total size of 1 bytes payload should result in 8 bytes"); + fail_if(nla_total_size(2) != NLA_HDRLEN + 4, + "Total size of 2 bytes payload should result in 8 bytes"); + fail_if(nla_total_size(3) != NLA_HDRLEN + 4, + "Total size of 3 bytes payload should result in 8 bytes"); + fail_if(nla_total_size(4) != NLA_HDRLEN + 4, + "Total size of 4 bytes payload should result in 8 bytes"); + + fail_if(nla_padlen(1) != 3, + "2 bytes of payload should result in 3 padding bytes"); + fail_if(nla_padlen(2) != 2, + "2 bytes of payload should result in 2 padding bytes"); + fail_if(nla_padlen(3) != 1, + "3 bytes of payload should result in 1 padding bytes"); + fail_if(nla_padlen(4) != 0, + "4 bytes of payload should result in 0 padding bytes"); + fail_if(nla_padlen(5) != 3, + "5 bytes of payload should result in 3 padding bytes"); +} +END_TEST + +START_TEST(msg_construct) +{ + struct nl_msg *msg; + struct nlmsghdr *nlh; + struct nlattr *a; + int i, rem; + + msg = nlmsg_alloc(); + fail_if(!msg, "Unable to allocate netlink message"); + + for (i = 1; i < 256; i++) { + fail_if(nla_put_u32(msg, i, i+1) != 0, + "Unable to add attribute %d", i); + } + + nlh = nlmsg_hdr(msg); + i = 1; + nlmsg_for_each_attr(a, nlh, 0, rem) { + fail_if(nla_type(a) != i, "Expected attribute %d", i); + i++; + fail_if(nla_get_u32(a) != i, "Expected attribute value %d", i); + } + + nlmsg_free(msg); +} +END_TEST + +Suite *make_nl_attr_suite(void) +{ + Suite *suite = suite_create("Netlink attributes"); + + TCase *nl_attr = tcase_create("Core"); + tcase_add_test(nl_attr, attr_size); + tcase_add_test(nl_attr, msg_construct); + suite_add_tcase(suite, nl_attr); + + return suite; +} diff --git a/tests/test-cache-mngr.c b/tests/test-cache-mngr.c new file mode 100644 index 0000000..8999e58 --- /dev/null +++ b/tests/test-cache-mngr.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include + +#include + +static int quit = 0; + +static struct nl_dump_params dp = { + .dp_type = NL_DUMP_LINE, +}; + + +static void change_cb(struct nl_cache *cache, struct nl_object *obj, + int action, void *data) +{ + if (action == NL_ACT_NEW) + printf("NEW "); + else if (action == NL_ACT_DEL) + printf("DEL "); + else if (action == NL_ACT_CHANGE) + printf("CHANGE "); + + nl_object_dump(obj, &dp); +} + +static void sigint(int arg) +{ + quit = 1; +} + +int main(int argc, char *argv[]) +{ + struct nl_cache_mngr *mngr; + struct nl_cache *cache; + int err, i; + + dp.dp_fd = stdout; + + signal(SIGINT, sigint); + + err = nl_cache_mngr_alloc(NULL, NETLINK_ROUTE, NL_AUTO_PROVIDE, &mngr); + if (err < 0) + nl_cli_fatal(err, "Unable to allocate cache manager: %s", + nl_geterror(err)); + + for (i = 1; i < argc; i++) { + err = nl_cache_mngr_add(mngr, argv[i], &change_cb, NULL, &cache); + if (err < 0) + nl_cli_fatal(err, "Unable to add cache %s: %s", + argv[i], nl_geterror(err)); + } + + while (!quit) { + int err = nl_cache_mngr_poll(mngr, 1000); + if (err < 0 && err != -NLE_INTR) + nl_cli_fatal(err, "Polling failed: %s", nl_geterror(err)); + + nl_cache_mngr_info(mngr, &dp); + } + + nl_cache_mngr_free(mngr); + + return 0; +} diff --git a/tests/test-complex-HTB-with-hash-filters.c b/tests/test-complex-HTB-with-hash-filters.c new file mode 100644 index 0000000..48cf5e3 --- /dev/null +++ b/tests/test-complex-HTB-with-hash-filters.c @@ -0,0 +1,761 @@ +/* + * test/test-complex-HTB-with-hash-filters.c Add HTB qdisc, HTB classes and creates some hash filters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2011 Adrian Ban + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +//#include "include/rtnl_u32.h" + +#include +#include +//#include "include/rtnl_u32_addon.h" + +#define TC_HANDLE(maj, min) (TC_H_MAJ((maj) << 16) | TC_H_MIN(min)) + +/* some functions are copied from iproute-tc tool */ +int get_u32(__u32 *val, const char *arg, int base) +{ + unsigned long res; + char *ptr; + + if (!arg || !*arg) + return -1; + res = strtoul(arg, &ptr, base); + if (!ptr || ptr == arg || *ptr || res > 0xFFFFFFFFUL) + return -1; + *val = res; + return 0; +} + +int get_u32_handle(__u32 *handle, const char *str) +{ + __u32 htid=0, hash=0, nodeid=0; + char *tmp = strchr(str, ':'); + + if (tmp == NULL) { + if (memcmp("0x", str, 2) == 0) + return get_u32(handle, str, 16); + return -1; + } + htid = strtoul(str, &tmp, 16); + if (tmp == str && *str != ':' && *str != 0) + return -1; + if (htid>=0x1000) + return -1; + if (*tmp) { + str = tmp+1; + hash = strtoul(str, &tmp, 16); + if (tmp == str && *str != ':' && *str != 0) + return -1; + if (hash>=0x100) + return -1; + if (*tmp) { + str = tmp+1; + nodeid = strtoul(str, &tmp, 16); + if (tmp == str && *str != 0) + return -1; + if (nodeid>=0x1000) + return -1; + } + } + *handle = (htid<<20)|(hash<<12)|nodeid; + return 0; +} + +uint32_t get_u32_parse_handle(const char *cHandle) +{ + uint32_t handle=0; + + if(get_u32_handle(&handle, cHandle)) { + printf ("Illegal \"ht\"\n"); + return -1; + } + + if (handle && TC_U32_NODE(handle)) { + printf("\"link\" must be a hash table.\n"); + return -1; + } + return handle; +} + +int get_tc_classid(__u32 *h, const char *str) +{ + __u32 maj, min; + char *p; + + maj = TC_H_ROOT; + if (strcmp(str, "root") == 0) + goto ok; + maj = TC_H_UNSPEC; + if (strcmp(str, "none") == 0) + goto ok; + maj = strtoul(str, &p, 16); + if (p == str) { + maj = 0; + if (*p != ':') + return -1; + } + if (*p == ':') { + if (maj >= (1<<16)) + return -1; + maj <<= 16; + str = p+1; + min = strtoul(str, &p, 16); + if (*p != 0) + return -1; + if (min >= (1<<16)) + return -1; + maj |= min; + } else if (*p != 0) + return -1; + +ok: + *h = maj; + return 0; +} + +/* + * Function that adds a new filter and attach it to a hash table + * + */ +int u32_add_filter_on_ht(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio, + uint32_t keyval, uint32_t keymask, int keyoff, int keyoffmask, + uint32_t htid, uint32_t classid +) +{ + struct rtnl_cls *cls; + int err; + + //printf("Key Val : 0x%x\n", keyval); + //printf("Key Mask : 0x%x\n", keymask); + + cls=rtnl_cls_alloc(); + if (!(cls)) { + printf("Can not allocate classifier\n"); + nl_socket_free(sock); + exit(1); + } + + rtnl_tc_set_link(TC_CAST(cls), rtnlLink); + + if ((err = rtnl_tc_set_kind(TC_CAST(cls), "u32"))) { + printf("Can not set classifier as u32\n"); + return 1; + } + + rtnl_cls_set_prio(cls, prio); + rtnl_cls_set_protocol(cls, ETH_P_IP); + + rtnl_tc_set_parent(TC_CAST(cls), TC_HANDLE(1, 0)); + + rtnl_u32_set_hashtable(cls, htid); + + rtnl_u32_add_key_uint32(cls, keyval, keymask, keyoff, keyoffmask); /* 10.0.0.0/8 */ + + rtnl_u32_set_classid(cls, classid); + + rtnl_u32_set_cls_terminal(cls); + + if ((err = rtnl_cls_add(sock, cls, NLM_F_CREATE))) { + printf("Can not add classifier: %s\n", nl_geterror(err)); + return -1; + } + rtnl_cls_put(cls); + return 0; + +} + +/* + * Function that adds a new filter and attach it to a hash table + * and set next hash table link with hash mask + * + */ +int u32_add_filter_on_ht_with_hashmask(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio, + uint32_t keyval, uint32_t keymask, int keyoff, int keyoffmask, + uint32_t htid, uint32_t htlink, uint32_t hmask, uint32_t hoffset +) +{ + struct rtnl_cls *cls; + int err; + + //printf("Key Val : 0x%x\n", keyval); + //printf("Key Mask : 0x%x\n", keymask); + + cls=rtnl_cls_alloc(); + if (!(cls)) { + printf("Can not allocate classifier\n"); + nl_socket_free(sock); + exit(1); + } + + rtnl_tc_set_link(TC_CAST(cls), rtnlLink); + + if ((err = rtnl_tc_set_kind(TC_CAST(cls), "u32"))) { + printf("Can not set classifier as u32\n"); + return 1; + } + + rtnl_cls_set_prio(cls, prio); + rtnl_cls_set_protocol(cls, ETH_P_IP); + + rtnl_tc_set_parent(TC_CAST(cls), TC_HANDLE(1, 0)); + + if (htid) + rtnl_u32_set_hashtable(cls, htid); + + rtnl_u32_add_key_uint32(cls, keyval, keymask, keyoff, keyoffmask); + + rtnl_u32_set_hashmask(cls, hmask, hoffset); + + rtnl_u32_set_link(cls, htlink); + + + if ((err = rtnl_cls_add(sock, cls, NLM_F_CREATE))) { + printf("Can not add classifier: %s\n", nl_geterror(err)); + return -1; + } + rtnl_cls_put(cls); + return 0; +} + +/* + * function that creates a new hash table + */ +int u32_add_ht(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio, uint32_t htid, uint32_t divisor) +{ + + int err; + struct rtnl_cls *cls; + + cls=rtnl_cls_alloc(); + if (!(cls)) { + printf("Can not allocate classifier\n"); + nl_socket_free(sock); + exit(1); + } + + rtnl_tc_set_link(TC_CAST(cls), rtnlLink); + + if ((err = rtnl_tc_set_kind(TC_CAST(cls), "u32"))) { + printf("Can not set classifier as u32\n"); + return 1; + } + + rtnl_cls_set_prio(cls, prio); + rtnl_cls_set_protocol(cls, ETH_P_IP); + rtnl_tc_set_parent(TC_CAST(cls), TC_HANDLE(1, 0)); + + rtnl_u32_set_handle(cls, htid, 0x0, 0x0); + //printf("htid: 0x%X\n", htid); + rtnl_u32_set_divisor(cls, divisor); + + if ((err = rtnl_cls_add(sock, cls, NLM_F_CREATE))) { + printf("Can not add classifier: %s\n", nl_geterror(err)); + return -1; + } + rtnl_cls_put(cls); + return 0; +} + +/* + * function that adds a new HTB qdisc and set the default class for unclassified traffic + */ +int qdisc_add_HTB(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t defaultClass) +{ + + struct rtnl_qdisc *qdisc; + int err; + + /* Allocation of a qdisc object */ + if (!(qdisc = rtnl_qdisc_alloc())) { + printf("Can not allocate Qdisc\n"); + return -1; + } + + //rtnl_tc_set_ifindex(TC_CAST(qdisc), master_index); + rtnl_tc_set_link(TC_CAST(qdisc), rtnlLink); + rtnl_tc_set_parent(TC_CAST(qdisc), TC_H_ROOT); + + //delete the qdisc + //printf("Delete current qdisc\n"); + rtnl_qdisc_delete(sock, qdisc); + //rtnl_qdisc_put(qdisc); + + //add a HTB qdisc + //printf("Add a new HTB qdisc\n"); + rtnl_tc_set_handle(TC_CAST(qdisc), TC_HANDLE(1,0)); + + if ((err = rtnl_tc_set_kind(TC_CAST(qdisc), "htb"))) { + printf("Can not allocate HTB\n"); + return -1; + } + + /* Set default class for unclassified traffic */ + //printf("Set default class for unclassified traffic\n"); + rtnl_htb_set_defcls(qdisc, TC_HANDLE(1, defaultClass)); + rtnl_htb_set_rate2quantum(qdisc, 1); + + /* Submit request to kernel and wait for response */ + if ((err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE))) { + printf("Can not allocate HTB Qdisc\n"); + return -1; + } + + /* Return the qdisc object to free memory resources */ + rtnl_qdisc_put(qdisc); + + return 0; +} + +/* + * function that adds a new HTB class and set its parameters + */ +int class_add_HTB(struct nl_sock *sock, struct rtnl_link *rtnlLink, + uint32_t parentMaj, uint32_t parentMin, + uint32_t childMaj, uint32_t childMin, + uint64_t rate, uint64_t ceil, + uint32_t burst, uint32_t cburst, + uint32_t prio +) +{ + int err; + struct rtnl_class *class; + //struct rtnl_class *class = (struct rtnl_class *) tc; + + //create a HTB class + //class = (struct rtnl_class *)rtnl_class_alloc(); + if (!(class = rtnl_class_alloc())) { + printf("Can not allocate class object\n"); + return 1; + } + // + rtnl_tc_set_link(TC_CAST(class), rtnlLink); + //add a HTB qdisc + //printf("Add a new HTB class with 0x%X:0x%X on parent 0x%X:0x%X\n", childMaj, childMin, parentMaj, parentMin); + rtnl_tc_set_parent(TC_CAST(class), TC_HANDLE(parentMaj, parentMin)); + rtnl_tc_set_handle(TC_CAST(class), TC_HANDLE(childMaj, childMin)); + + if ((err = rtnl_tc_set_kind(TC_CAST(class), "htb"))) { + printf("Can not set HTB to class\n"); + return 1; + } + + //printf("set HTB class prio to %u\n", prio); + rtnl_htb_set_prio((struct rtnl_class *)class, prio); + + if (rate) { + //rate=rate/8; + rtnl_htb_set_rate(class, rate); + } + if (ceil) { + //ceil=ceil/8; + rtnl_htb_set_ceil(class, ceil); + } + + if (burst) { + //printf ("Class HTB: set rate burst: %u\n", burst); + rtnl_htb_set_rbuffer(class, burst); + } + if (cburst) { + //printf ("Class HTB: set rate cburst: %u\n", cburst); + rtnl_htb_set_cbuffer(class, cburst); + } + /* Submit request to kernel and wait for response */ + if ((err = rtnl_class_add(sock, class, NLM_F_CREATE))) { + printf("Can not allocate HTB Qdisc\n"); + return 1; + } + rtnl_class_put(class); + return 0; +} + +/* + * function that adds a HTB root class and set its parameters + */ +int class_add_HTB_root(struct nl_sock *sock, struct rtnl_link *rtnlLink, + uint64_t rate, uint64_t ceil, + uint32_t burst, uint32_t cburst +) +{ + int err; + struct rtnl_class *class; + + //create a HTB class + class = (struct rtnl_class *)rtnl_class_alloc(); + //class = rtnl_class_alloc(); + if (!class) { + printf("Can not allocate class object\n"); + return 1; + } + // + rtnl_tc_set_link(TC_CAST(class), rtnlLink); + rtnl_tc_set_parent(TC_CAST(class), TC_H_ROOT); + //add a HTB class + //printf("Add a new HTB ROOT class\n"); + rtnl_tc_set_handle(TC_CAST(class), 1); + + if ((err = rtnl_tc_set_kind(TC_CAST(class), "htb"))) { + printf("Can not set HTB to class\n"); + return 1; + } + + if (rate) { + //rate=rate/8; + rtnl_htb_set_rate(class, rate); + } + if (ceil) { + //ceil=ceil/8; + rtnl_htb_set_ceil(class, ceil); + } + + if (burst) { + rtnl_htb_set_rbuffer(class, burst); + } + if (cburst) { + rtnl_htb_set_cbuffer(class, cburst); + } + + /* Submit request to kernel and wait for response */ + if ((err = rtnl_class_add(sock, class, NLM_F_CREATE))) { + printf("Can not allocate HTB Qdisc\n"); + return 1; + } + rtnl_class_put(class); + return 0; +} + +/* + * function that adds a new SFQ qdisc as a leaf for a HTB class + */ +int qdisc_add_SFQ_leaf(struct nl_sock *sock, struct rtnl_link *rtnlLink, + uint32_t parentMaj, uint32_t parentMin, + int quantum, int limit, int perturb +) +{ + int err; + struct rtnl_qdisc *qdisc; + + if (!(qdisc = rtnl_qdisc_alloc())) { + printf("Can not allocate qdisc object\n"); + return 1; + } + rtnl_tc_set_link(TC_CAST(qdisc), rtnlLink); + rtnl_tc_set_parent(TC_CAST(qdisc), TC_HANDLE(parentMaj, parentMin)); + + rtnl_tc_set_handle(TC_CAST(qdisc), TC_HANDLE(parentMin,0)); + + if ((err = rtnl_tc_set_kind(TC_CAST(qdisc), "sfq"))) { + printf("Can not set SQF class\n"); + return 1; + } + + if(quantum) { + rtnl_sfq_set_quantum(qdisc, quantum); + } else { + rtnl_sfq_set_quantum(qdisc, 16000); // tc default value + } + if(limit) { + rtnl_sfq_set_limit(qdisc, limit); // default is 127 + } + if(perturb) { + rtnl_sfq_set_perturb(qdisc, perturb); // default never perturb the hash + } + + /* Submit request to kernel and wait for response */ + if ((err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE))) { + printf("Can not allocate SFQ qdisc\n"); + return -1; + } + + /* Return the qdisc object to free memory resources */ + rtnl_qdisc_put(qdisc); + return 0; +} + + + + +int main() { + + struct nl_sock *sock; + struct rtnl_link *link; + + //struct rtnl_qdisc *qdisc; + //struct rtnl_class *class; + //struct rtnl_cls *cls; + + uint32_t ht, htlink, htid, direction, classid; + //uint32_t hash, hashmask, nodeid, divisor, handle; + //struct rtnl_u32 *f_u32; + char chashlink[16]=""; + + //uint64_t drops, qlen; + + //int master_index; + int err; + + //uint64_t rate=0, ceil=0; + + struct nl_cache *link_cache; + + if (!(sock = nl_socket_alloc())) { + printf("Unable to allocate netlink socket\n"); + exit(1); + } + + if ((err = nl_connect(sock, NETLINK_ROUTE)) < 0 ) { + printf("Nu s-a putut conecta la NETLINK!\n"); + nl_socket_free(sock); + exit(1); + } + + + if ((err = rtnl_link_alloc_cache(sock, AF_UNSPEC, &link_cache)) < 0) { + printf("Unable to allocate link cache: %s\n", + nl_geterror(err)); + nl_socket_free(sock); + exit(1); + } + + /* lookup interface index of eth0 */ + if (!(link = rtnl_link_get_by_name(link_cache, "imq0"))) { + /* error */ + printf("Interface not found\n"); + nl_socket_free(sock); + exit(1); + } + + err=qdisc_add_HTB(sock, link, 0xffff); + //drops = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_DROPS); + + //printf("Add ROOT HTB class\n"); + err=class_add_HTB_root(sock, link, 12500000, 12500000, 25000, 25000); + err=class_add_HTB(sock, link, 1, 0, 1, 0xffff, 1250000, 12500000, 25000, 25000, 5); + err=qdisc_add_SFQ_leaf(sock, link, 1, 0xffff, 16000, 0, 10); + err=class_add_HTB(sock, link, 1, 1, 1, 0x5, 2000000, 2000000, 25000, 25000, 5); + err=qdisc_add_SFQ_leaf(sock, link, 1, 0x5, 16000, 0, 10); + err=class_add_HTB(sock, link, 1, 1, 1, 0x6, 1000000, 1000000, 25000, 25000, 5); + err=qdisc_add_SFQ_leaf(sock, link, 1, 0x6, 16000, 0, 10); + //err=class_add_HTB(sock, link, 1, 0, 1, 0x7, 1024000, 100000000, 5); + //err=class_add_HTB(sock, link, 1, 0, 1, 0x8, 2048000, 100000000, 5); + //err=class_add_HTB(sock, link, 1, 0, 1, 0x9, 4096000, 100000000, 5); + //err=class_add_HTB(sock, link, 1, 0, 1, 0xa, 8192000, 100000000, 5); + + //printf("Add main hash table\n"); + + /* create u32 first hash filter table + * + */ + /* formula calcul handle: + * uint32_t handle = (htid << 20) | (hash << 12) | nodeid; + */ + + /* + * Upper limit of number of hash tables: 4096 (0xFFF) + * Number of hashes in a table: 256 values (0xFF) + * + */ + + /* using 256 values for hash table + * each entry in hash table match a byte from IP address specified later by a hash key + */ + + uint32_t i; + for (i = 1; i <= 0xf; i++) + u32_add_ht(sock, link, 1, i, 256); + + /* + * attach a u32 filter to the first hash + * that redirects all traffic and make a hash key + * from the fist byte of the IP address + * + */ + + //divisor=0x0; // unused here + //handle = 0x0; // unused here + //hash = 0x0; // unused here + //htid = 0x0; // unused here + //nodeid = 0x0; // unused here + + // direction = 12 -> source IP + // direction = 16 -> destination IP + direction = 16; + + /* + * which hash table will use + * in our case is hash table no 1 defined previous + * + * There are 2 posibilities to set the the hash table: + * 1. Using function get_u32_handle and sent a string in + * format 10: where 10 is number of the hash table + * 2. Create your own value in format: 0xa00000 + * + */ + strcpy(chashlink, "1:"); + //printf("Hash Link: %s\n", chashlink); + //chashlink=malloc(sizeof(char) * + htlink = 0x0; // is used by get_u32_handle to return the correct value of hash table (link) + + if(get_u32_handle(&htlink, chashlink)) { + printf ("Illegal \"link\""); + nl_socket_free(sock); + exit(1); + } + //printf ("hash link : 0x%X\n", htlink); + //printf ("hash link test : %u\n", (htlink && TC_U32_NODE(htlink))); + + if (htlink && TC_U32_NODE(htlink)) { + printf("\"link\" must be a hash table.\n"); + nl_socket_free(sock); + exit(1); + } + /* the hash mask will hit the hash table (link) no 1: in our case + */ + + /* set the hash key mask */ + //hashmask = 0xFF000000UL; // the mask that is used to match the hash in specific table, in our case for example 1:a with mean the first byte which is 10 in hash table 1 + + /* Here we add a hash filter which match the first byte (see the hashmask value) + * of the source IP (offset 12 in the packet header) + * You can use also offset 16 to match the destination IP + */ + + /* + * Also we need a filter to match our rule + * This mean that we will put a 0.0.0.0/0 filter in our first rule + * that match the offset 12 (source IP) + * Also you can put offset 16 to match the destination IP + */ + + u32_add_filter_on_ht_with_hashmask(sock, link, 1, + 0x0, 0x0, direction, 0, + 0, htlink, 0xff000000, direction); + + /* + * For each first byte that we need to match we will create a new hash table + * For example: you have those clases: 10.0.0.0/24 and 172.16.0.0/23 + * For byte 10 and byte 172 will create a separate hash table that will match the second + * byte from each class. + * + */ + + + // Create a new hash table with prio 1, id 2 and 256 entries +// u32_CreateNewHashTable(sock, link, 1, 2, 256); + // Create a new hash table with prio 1, id 3 and 256 entries +// u32_CreateNewHashTable(sock, link, 1, 3, 256); +// u32_CreateNewHashTable(sock, link, 1, 4, 256); +// u32_CreateNewHashTable(sock, link, 1, 5, 256); + + /* + * Now we will create other filter under (ATENTION) our first hash table (link) 1: + * Previous rule redirects the trafic according the hash mask to hash table (link) no 1: + * Here we will match the hash tables from 1:0 to 1:ff. Under each hash table we will attach + * other rules that matches next byte from IP source/destination IP and we will repeat the + * previous steps. + * + */ + + + // /8 check + + // 10.0.0.0/8 + ht=get_u32_parse_handle("1:a:"); + htid = (ht&0xFFFFF000); + htlink=get_u32_parse_handle("2:"); + + u32_add_filter_on_ht_with_hashmask(sock, link, 1, + 0x0a000000, 0xff000000, direction, 0, + htid, htlink, 0x00ff0000, direction); + + // 172.0.0.0/8 + ht=get_u32_parse_handle("1:ac:"); + htid = (ht&0xFFFFF000); + htlink=get_u32_parse_handle("3:"); + + u32_add_filter_on_ht_with_hashmask(sock, link, 1, + 0xac000000, 0xff000000, direction, 0, + htid, htlink, 0x00ff0000, direction); + + + // /16 check + // 10.0.0.0/16 + ht=get_u32_parse_handle("2:0:"); + htid = (ht&0xFFFFF000); + htlink=get_u32_parse_handle("4:"); + + u32_add_filter_on_ht_with_hashmask(sock, link, 1, + 0x0a000000, 0xffff0000, direction, 0, + htid, htlink, 0x0000ff00, direction); + + // 172.17.0.0/16 + ht=get_u32_parse_handle("3:11:"); + htid = (ht&0xFFFFF000); + htlink=get_u32_parse_handle("5:"); + + u32_add_filter_on_ht_with_hashmask(sock, link, 1, + 0xac110000, 0xffff0000, direction, 0, + htid, htlink, 0x0000ff00, direction); + + // /24 check + // 10.0.9.0/24 + ht=get_u32_parse_handle("4:9:"); + htid = (ht&0xFFFFF000); + htlink=get_u32_parse_handle("6:"); + + u32_add_filter_on_ht_with_hashmask(sock, link, 1, + 0x0a000900, 0xffffff00, direction, 0, + htid, htlink, 0x000000ff, direction); + + // 172.17.2.0/16 + ht=get_u32_parse_handle("5:2:"); + htid = (ht&0xFFFFF000); + htlink=get_u32_parse_handle("7:"); + + u32_add_filter_on_ht_with_hashmask(sock, link, 1, + 0xac110200, 0xffffff00, direction, 0, + htid, htlink, 0x000000ff, direction); + + + // final filters + // 10.0.9.20 + ht=get_u32_parse_handle("6:14:"); + htid = (ht&0xFFFFF000); + + err = get_tc_classid(&classid, "1:5"); + + u32_add_filter_on_ht(sock, link, 1, + 0x0a000914, 0xffffffff, direction, 0, + htid, classid); + + // 172.17.2.120 + ht=get_u32_parse_handle("7:78:"); + htid = (ht&0xFFFFF000); + + err = get_tc_classid(&classid, "1:6"); + + u32_add_filter_on_ht(sock, link, 1, + 0xac110278, 0xffffffff, direction, 0, + htid, classid); + + + + nl_socket_free(sock); + return 0; +} diff --git a/tests/test-create-bond.c b/tests/test-create-bond.c new file mode 100644 index 0000000..11bc5b0 --- /dev/null +++ b/tests/test-create-bond.c @@ -0,0 +1,29 @@ +#include +#include +#include + +int main(int argc, char *argv[]) +{ + struct rtnl_link *link; + struct nl_sock *sk; + int err; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + link = rtnl_link_bond_alloc(); + rtnl_link_set_name(link, "my_bond"); + + if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-create-vlan.c b/tests/test-create-vlan.c new file mode 100644 index 0000000..64e478f --- /dev/null +++ b/tests/test-create-vlan.c @@ -0,0 +1,43 @@ +#include +#include +#include + +int main(int argc, char *argv[]) +{ + struct rtnl_link *link; + struct nl_cache *link_cache; + struct nl_sock *sk; + int err, master_index; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + if ((err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache)) < 0) { + nl_perror(err, "Unable to allocate cache"); + return err; + } + + if (!(master_index = rtnl_link_name2i(link_cache, "eth0"))) { + fprintf(stderr, "Unable to lookup eth0"); + return -1; + } + + link = rtnl_link_vlan_alloc(); + + rtnl_link_set_link(link, master_index); + + rtnl_link_vlan_set_id(link, 10); + + if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-delete-link.c b/tests/test-delete-link.c new file mode 100644 index 0000000..9cf1034 --- /dev/null +++ b/tests/test-delete-link.c @@ -0,0 +1,28 @@ +#include +#include + +int main(int argc, char *argv[]) +{ + struct rtnl_link *link; + struct nl_sock *sk; + int err; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + link = rtnl_link_alloc(); + rtnl_link_set_name(link, "my_bond"); + + if ((err = rtnl_link_delete(sk, link)) < 0) { + nl_perror(err, "Unable to delete link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-genl.c b/tests/test-genl.c new file mode 100644 index 0000000..74aea10 --- /dev/null +++ b/tests/test-genl.c @@ -0,0 +1,118 @@ +#include +#include + +static struct nla_policy attr_policy[TASKSTATS_TYPE_MAX+1] = { + [TASKSTATS_TYPE_PID] = { .type = NLA_U32 }, + [TASKSTATS_TYPE_TGID] = { .type = NLA_U32 }, + [TASKSTATS_TYPE_STATS] = { .minlen = sizeof(struct taskstats) }, + [TASKSTATS_TYPE_AGGR_PID] = { .type = NLA_NESTED }, + [TASKSTATS_TYPE_AGGR_TGID] = { .type = NLA_NESTED }, +}; + + +static int parse_cmd_new(struct nl_cache_ops *unused, struct genl_cmd *cmd, + struct genl_info *info, void *arg) +{ + struct nlattr *attrs[TASKSTATS_TYPE_MAX+1]; + struct nlattr *nested; + int err; + + if (info->attrs[TASKSTATS_TYPE_AGGR_PID]) + nested = info->attrs[TASKSTATS_TYPE_AGGR_PID]; + else if (info->attrs[TASKSTATS_TYPE_AGGR_TGID]) + nested = info->attrs[TASKSTATS_TYPE_AGGR_TGID]; + else { + fprintf(stderr, "Invalid taskstats message: Unable to find " + "nested attribute/\n"); + return NL_SKIP; + } + + err = nla_parse_nested(attrs, TASKSTATS_TYPE_MAX, nested, attr_policy); + if (err < 0) { + nl_perror(err, "Error while parsing generic netlink message"); + return err; + } + + + if (attrs[TASKSTATS_TYPE_STATS]) { + struct taskstats *stats = nla_data(attrs[TASKSTATS_TYPE_STATS]); + + printf("%s pid %u uid %u gid %u parent %u\n", + stats->ac_comm, stats->ac_pid, stats->ac_uid, + stats->ac_gid, stats->ac_ppid); + } + + return 0; +} + +static int parse_cb(struct nl_msg *msg, void *arg) +{ + return genl_handle_msg(msg, NULL); +} + +static struct genl_cmd cmds[] = { + { + .c_id = TASKSTATS_CMD_NEW, + .c_name = "taskstats_new()", + .c_maxattr = TASKSTATS_TYPE_MAX, + .c_attr_policy = attr_policy, + .c_msg_parser = &parse_cmd_new, + }, +}; + +#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0])) + +static struct genl_ops ops = { + .o_name = TASKSTATS_GENL_NAME, + .o_cmds = cmds, + .o_ncmds = ARRAY_SIZE(cmds), +}; + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_msg *msg; + void *hdr; + int err; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_GENERIC); + + if ((err = genl_register_family(&ops)) < 0) + nl_cli_fatal(err, "Unable to register Generic Netlink family"); + + if ((err = genl_ops_resolve(sock, &ops)) < 0) + nl_cli_fatal(err, "Unable to resolve family name"); + + if (genl_ctrl_resolve(sock, "nlctrl") != GENL_ID_CTRL) + nl_cli_fatal(NLE_INVAL, "Resolving of \"nlctrl\" failed"); + + msg = nlmsg_alloc(); + if (msg == NULL) + nl_cli_fatal(NLE_NOMEM, "Unable to allocate netlink message"); + + hdr = genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, ops.o_id, + 0, 0, TASKSTATS_CMD_GET, TASKSTATS_GENL_VERSION); + if (hdr == NULL) + nl_cli_fatal(ENOMEM, "Unable to write genl header"); + + if ((err = nla_put_u32(msg, TASKSTATS_CMD_ATTR_PID, 1)) < 0) + nl_cli_fatal(err, "Unable to add attribute: %s", nl_geterror(err)); + + if ((err = nl_send_auto_complete(sock, msg)) < 0) + nl_cli_fatal(err, "Unable to send message: %s", nl_geterror(err)); + + nlmsg_free(msg); + + if ((err = nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, + parse_cb, NULL)) < 0) + nl_cli_fatal(err, "Unable to modify valid message callback"); + + if ((err = nl_recvmsgs_default(sock)) < 0) + nl_cli_fatal(err, "Unable to receive message: %s", nl_geterror(err)); + + nl_close(sock); + nl_socket_free(sock); + + return 0; +} diff --git a/tests/test-nf-cache-mngr.c b/tests/test-nf-cache-mngr.c new file mode 100644 index 0000000..b4f3022 --- /dev/null +++ b/tests/test-nf-cache-mngr.c @@ -0,0 +1,57 @@ +#include + +static void change_cb(struct nl_cache *cache, struct nl_object *obj, + int action, void *data) +{ + struct nfnl_ct *ct = (struct nfnl_ct *) obj; + static struct nl_addr *hack = NULL; + + if (!hack) + nl_addr_parse("194.88.212.233", AF_INET, &hack); + + if (!nl_addr_cmp(hack, nfnl_ct_get_src(ct, 1)) || + !nl_addr_cmp(hack, nfnl_ct_get_dst(ct, 1))) { + struct nl_dump_params dp = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + + printf("UPDATE "); + nl_object_dump(obj, &dp); + } +} + +int main(int argc, char *argv[]) +{ + struct nl_cache_mngr *mngr; + struct nl_sock *sock; + struct nl_cache *ct; + int err; + + sock = nl_cli_alloc_socket(); + + err = nl_cache_mngr_alloc(sock, NETLINK_NETFILTER, NL_AUTO_PROVIDE, &mngr); + if (err < 0) { + nl_perror(err, "nl_cache_mngr_alloc"); + return -1; + } + + err = nl_cache_mngr_add(mngr, "netfilter/ct", &change_cb, NULL, &ct); + if (err < 0) { + nl_perror(err, "nl_cache_mngr_add(netfilter/ct)"); + return -1; + } + + for (;;) { + int err = nl_cache_mngr_poll(mngr, 5000); + if (err < 0) { + nl_perror(err, "nl_cache_mngr_poll()"); + return -1; + } + + } + + nl_cache_mngr_free(mngr); + + return 0; +} diff --git a/tests/test-socket-creation.c b/tests/test-socket-creation.c new file mode 100644 index 0000000..83f3ad4 --- /dev/null +++ b/tests/test-socket-creation.c @@ -0,0 +1,28 @@ +#include +#include + +int main(int argc, char *argv[]) +{ + struct nl_sock *h[1025]; + int i; + + h[0] = nl_socket_alloc(); + printf("Created handle with port 0x%x\n", + nl_socket_get_local_port(h[0])); + nl_socket_free(h[0]); + h[0] = nl_socket_alloc(); + printf("Created handle with port 0x%x\n", + nl_socket_get_local_port(h[0])); + nl_socket_free(h[0]); + + for (i = 0; i < 1025; i++) { + h[i] = nl_socket_alloc(); + if (h[i] == NULL) + nl_perror(ENOMEM, "Unable to allocate socket"); + else + printf("Created handle with port 0x%x\n", + nl_socket_get_local_port(h[i])); + } + + return 0; +} diff --git a/tests/util.h b/tests/util.h new file mode 100644 index 0000000..c675383 --- /dev/null +++ b/tests/util.h @@ -0,0 +1,5 @@ +#include + +#define nl_fail_if(condition, error, message) \ + fail_if((condition), "nlerr=%d (%s): %s", \ + (error), nl_geterror(error), (message)) -- 2.7.4 From 4f8964f0e77a8398ba679654d49728a1762c2cec Mon Sep 17 00:00:00 2001 From: "hyunuk.tak" Date: Mon, 26 Aug 2024 12:12:11 +0900 Subject: [PATCH 2/2] Imported Upstream version 3.9.0 Change-Id: I9bd396bbc5bef02070a5442ff199c0d3bbc29d24 Signed-off-by: hyunuk.tak --- ChangeLog | 14 +- Makefile.am | 1187 ++- Makefile.in | 7808 ++++++++++++++++- aclocal.m4 | 1194 ++- build-aux/ar-lib | 19 +- build-aux/compile | 23 +- build-aux/config.guess | 1744 ++-- build-aux/config.sub | 2662 +++--- build-aux/depcomp | 461 +- build-aux/install-sh | 430 +- build-aux/ltmain.sh | 5874 ++++++++----- build-aux/missing | 420 +- build-aux/test-driver | 153 + configure | 9254 ++++++++++++-------- configure.ac | 114 +- etc/pktloc | 2 +- include/Makefile.am | 135 - include/Makefile.in | 640 -- include/base/nl-base-utils.h | 842 ++ lib/defs.h.in => include/config.h.in | 32 +- include/linux-private/linux/atm.h | 242 + include/linux-private/linux/atmapi.h | 30 + include/linux-private/linux/atmioc.h | 42 + include/linux-private/linux/atmsap.h | 163 + .../linux-private/linux/byteorder/little_endian.h | 107 + include/{ => linux-private}/linux/can/netlink.h | 81 +- include/linux-private/linux/const.h | 36 + include/linux-private/linux/errno.h | 1 + include/linux-private/linux/ethtool.h | 2206 +++++ include/linux-private/linux/falloc.h | 80 + include/{ => linux-private}/linux/fib_rules.h | 29 +- include/{ => linux-private}/linux/gen_stats.h | 19 +- include/{ => linux-private}/linux/genetlink.h | 24 +- include/linux-private/linux/hdlc/ioctl.h | 94 + include/linux-private/linux/if.h | 296 + include/{ => linux-private}/linux/if_addr.h | 22 + include/{ => linux-private}/linux/if_arp.h | 29 +- include/linux-private/linux/if_bridge.h | 839 ++ include/{ => linux-private}/linux/if_ether.h | 64 +- include/linux-private/linux/if_link.h | 1397 +++ include/linux-private/linux/if_macsec.h | 194 + include/linux-private/linux/if_packet.h | 319 + include/linux-private/linux/if_tunnel.h | 185 + include/{ => linux-private}/linux/if_vlan.h | 14 +- include/linux-private/linux/in.h | 333 + include/linux-private/linux/in6.h | 302 + include/linux-private/linux/in_route.h | 33 + include/linux-private/linux/inet_diag.h | 239 + include/linux-private/linux/ioctl.h | 8 + include/linux-private/linux/ip.h | 181 + include/{ => linux-private}/linux/ipv6.h | 65 +- include/linux-private/linux/libc-compat.h | 267 + include/linux-private/linux/limits.h | 21 + include/linux-private/linux/lwtunnel.h | 124 + include/linux-private/linux/mpls.h | 77 + include/linux-private/linux/mpls_iptunnel.h | 31 + include/{ => linux-private}/linux/neighbour.h | 81 +- include/linux-private/linux/netconf.h | 30 + include/linux-private/linux/netdevice.h | 66 + include/linux-private/linux/netfilter.h | 76 + .../linux/netfilter/nf_conntrack_common.h | 49 +- .../linux/netfilter/nf_conntrack_tcp.h | 58 + .../linux/netfilter/nfnetlink.h | 34 +- .../linux/netfilter/nfnetlink_compat.h | 3 +- .../linux/netfilter/nfnetlink_conntrack.h | 57 +- .../linux/netfilter/nfnetlink_log.h | 19 +- .../linux/netfilter/nfnetlink_queue.h | 37 +- include/linux-private/linux/netlink.h | 374 + include/linux-private/linux/nexthop.h | 104 + include/linux-private/linux/pkt_cls.h | 804 ++ include/linux-private/linux/pkt_sched.h | 1298 +++ include/linux-private/linux/posix_types.h | 38 + include/{ => linux-private}/linux/rtnetlink.h | 271 +- include/linux-private/linux/seg6.h | 55 + include/linux-private/linux/seg6_hmac.h | 23 + include/linux-private/linux/seg6_iptunnel.h | 42 + include/linux-private/linux/seg6_local.h | 137 + include/{ => linux-private}/linux/snmp.h | 118 +- include/linux-private/linux/sock_diag.h | 65 + include/linux-private/linux/socket.h | 38 + include/linux-private/linux/stddef.h | 47 + include/linux-private/linux/swab.h | 305 + include/linux-private/linux/taskstats.h | 252 + include/linux-private/linux/tc_act/tc_gact.h | 33 + include/linux-private/linux/tc_act/tc_mirred.h | 28 + include/linux-private/linux/tc_act/tc_nat.h | 27 + include/linux-private/linux/tc_act/tc_skbedit.h | 41 + include/linux-private/linux/tc_act/tc_vlan.h | 36 + include/linux-private/linux/tc_ematch/tc_em_cmp.h | 26 + .../linux/tc_ematch/tc_em_meta.h | 6 +- .../linux-private/linux/tc_ematch/tc_em_nbyte.h | 14 + include/linux-private/linux/tc_ematch/tc_em_text.h | 20 + include/linux-private/linux/types.h | 53 + include/linux-private/linux/version.h | 5 + include/linux-private/linux/veth.h | 13 + include/linux-private/linux/xfrm.h | 568 ++ include/linux/if.h | 146 - include/linux/if_bridge.h | 185 - include/linux/if_link.h | 446 - include/linux/inetdevice.h | 36 - include/linux/ip_mp_alg.h | 22 - include/linux/netfilter.h | 57 - include/linux/netlink.h | 149 - include/linux/pkt_cls.h | 467 - include/linux/pkt_sched.h | 627 -- include/netlink-private/genl.h | 22 - include/netlink-private/netlink.h | 262 - include/netlink-private/route/tc-api.h | 134 - include/netlink-private/tc.h | 55 - include/netlink-private/types.h | 912 -- include/netlink/addr.h | 49 +- include/netlink/attr.h | 104 +- include/netlink/cache-api.h | 8 +- include/netlink/cache.h | 27 +- include/netlink/cli/addr.h | 16 +- include/netlink/cli/class.h | 16 +- include/netlink/cli/cls.h | 16 +- include/netlink/cli/ct.h | 17 +- include/netlink/cli/exp.h | 15 +- include/netlink/cli/link.h | 20 +- include/netlink/cli/mdb.h | 11 + include/netlink/cli/neigh.h | 19 +- include/netlink/cli/nh.h | 30 + include/netlink/cli/qdisc.h | 16 +- include/netlink/cli/route.h | 16 +- include/netlink/cli/rule.h | 16 +- include/netlink/cli/tc.h | 16 +- include/netlink/cli/utils.h | 20 +- include/netlink/data.h | 25 +- include/netlink/errno.h | 11 +- include/netlink/fib_lookup/lookup.h | 15 +- include/netlink/fib_lookup/request.h | 8 +- include/netlink/genl/ctrl.h | 8 +- include/netlink/genl/family.h | 8 +- include/netlink/genl/genl.h | 12 +- include/netlink/genl/mngt.h | 8 +- include/netlink/handlers.h | 21 +- include/netlink/hash.h | 9 + include/netlink/hashtable.h | 11 +- include/netlink/idiag/idiagnl.h | 145 + include/netlink/idiag/meminfo.h | 35 + include/netlink/idiag/msg.h | 79 + include/netlink/idiag/req.h | 48 + include/netlink/idiag/vegasinfo.h | 37 + include/netlink/list.h | 32 +- include/netlink/msg.h | 14 +- include/netlink/netfilter/ct.h | 24 +- include/netlink/netfilter/exp.h | 11 +- include/netlink/netfilter/log.h | 11 +- include/netlink/netfilter/log_msg.h | 39 +- include/netlink/netfilter/netfilter.h | 8 +- include/netlink/netfilter/nfnl.h | 8 +- include/netlink/netfilter/queue.h | 10 +- include/netlink/netfilter/queue_msg.h | 12 +- include/netlink/netlink-compat.h | 20 +- include/netlink/netlink.h | 17 +- include/netlink/object-api.h | 8 +- include/netlink/object.h | 10 +- include/netlink/route/act/gact.h | 25 + include/netlink/route/act/mirred.h | 29 + include/netlink/route/act/nat.h | 35 + include/netlink/route/act/skbedit.h | 31 + include/netlink/route/act/vlan.h | 32 + include/netlink/route/action.h | 42 + include/netlink/route/addr.h | 12 +- include/netlink/route/class.h | 11 +- include/netlink/route/classifier.h | 15 +- include/netlink/route/cls/basic.h | 12 +- include/netlink/route/cls/cgroup.h | 8 +- include/netlink/route/cls/ematch.h | 10 +- include/netlink/route/cls/ematch/cmp.h | 10 +- include/netlink/route/cls/ematch/meta.h | 8 +- include/netlink/route/cls/ematch/nbyte.h | 8 +- include/netlink/route/cls/ematch/text.h | 8 +- include/netlink/route/cls/flower.h | 59 + include/netlink/route/cls/fw.h | 8 +- include/netlink/route/cls/matchall.h | 30 + include/netlink/route/cls/police.h | 8 +- include/netlink/route/cls/u32.h | 22 +- include/netlink/route/link.h | 321 +- include/netlink/route/link/api.h | 8 +- include/netlink/route/link/bonding.h | 14 +- include/netlink/route/link/bridge.h | 46 +- include/netlink/route/link/bridge_info.h | 35 + include/netlink/route/link/can.h | 30 +- include/netlink/route/link/geneve.h | 54 + include/netlink/route/link/inet.h | 9 +- include/netlink/route/link/inet6.h | 52 + include/netlink/route/link/info-api.h | 8 +- include/netlink/route/link/ip6gre.h | 58 + include/netlink/route/link/ip6tnl.h | 55 + include/netlink/route/link/ip6vti.h | 40 + include/netlink/route/link/ipgre.h | 61 + include/netlink/route/link/ipip.h | 45 + include/netlink/route/link/ipvlan.h | 31 + include/netlink/route/link/ipvti.h | 42 + include/netlink/route/link/macsec.h | 72 + include/netlink/route/link/macvlan.h | 58 + include/netlink/route/link/macvtap.h | 40 + include/netlink/route/link/ppp.h | 24 + include/netlink/route/link/sit.h | 64 + include/netlink/route/link/sriov.h | 139 + include/netlink/route/link/team.h | 26 + include/netlink/route/link/veth.h | 30 + include/netlink/route/link/vlan.h | 11 +- include/netlink/route/link/vrf.h | 26 + include/netlink/route/link/vxlan.h | 118 + include/netlink/route/link/xfrmi.h | 31 + include/netlink/route/mdb.h | 42 + include/netlink/route/neighbour.h | 22 +- include/netlink/route/neightbl.h | 9 +- include/netlink/route/netconf.h | 40 + include/netlink/route/nexthop.h | 22 +- include/netlink/route/nh.h | 52 + include/netlink/route/pktloc.h | 8 +- include/netlink/route/qdisc.h | 10 +- include/netlink/route/qdisc/cbq.h | 8 +- include/netlink/route/qdisc/dsmark.h | 8 +- include/netlink/route/qdisc/fifo.h | 8 +- include/netlink/route/qdisc/fq_codel.h | 38 + include/netlink/route/qdisc/hfsc.h | 33 + include/netlink/route/qdisc/htb.h | 24 +- include/netlink/route/qdisc/mqprio.h | 42 + include/netlink/route/qdisc/netem.h | 9 +- include/netlink/route/qdisc/plug.h | 8 +- include/netlink/route/qdisc/prio.h | 8 +- include/netlink/route/qdisc/red.h | 20 +- include/netlink/route/qdisc/sfq.h | 8 +- include/netlink/route/qdisc/tbf.h | 8 +- include/netlink/route/route.h | 14 +- include/netlink/route/rtnl.h | 8 +- include/netlink/route/rule.h | 26 +- include/netlink/route/tc-api.h | 8 +- include/netlink/route/tc.h | 13 +- include/netlink/socket.h | 9 +- include/netlink/types.h | 16 +- include/netlink/utils.h | 282 +- include/netlink/version.h | 28 +- include/netlink/version.h.in | 16 +- include/netlink/xfrm/ae.h | 111 + include/netlink/xfrm/lifetime.h | 87 + include/netlink/xfrm/sa.h | 183 + include/netlink/xfrm/selector.h | 100 + include/netlink/xfrm/sp.h | 142 + include/netlink/xfrm/template.h | 101 + include/nl-aux-core/nl-core.h | 59 + include/nl-aux-route/nl-route.h | 90 + include/nl-aux-xfrm/nl-xfrm.h | 33 + include/nl-default.h | 10 + .../cache-api.h | 38 +- include/nl-priv-dynamic-core/nl-core.h | 90 + .../object-api.h | 32 +- .../nl-priv-dynamic-route/nl-priv-dynamic-route.h | 96 + .../nl-priv-static-route/nl-priv-static-route.h | 8 + lib/Makefile.am | 118 - lib/Makefile.in | 1370 --- lib/addr.c | 243 +- lib/attr.c | 293 +- lib/cache.c | 178 +- lib/cache_mngr.c | 176 +- lib/cache_mngt.c | 21 +- lib/cli/cls/basic.c | 20 +- lib/cli/cls/cgroup.c | 18 +- lib/cli/qdisc/bfifo.c | 18 +- lib/cli/qdisc/blackhole.c | 18 +- lib/cli/qdisc/fq_codel.c | 108 + lib/cli/qdisc/hfsc.c | 249 + lib/cli/qdisc/htb.c | 22 +- lib/cli/qdisc/ingress.c | 60 + lib/cli/qdisc/pfifo.c | 19 +- lib/cli/qdisc/plug.c | 21 +- lib/data.c | 49 +- lib/error.c | 12 +- lib/fib_lookup/lookup.c | 50 +- lib/fib_lookup/request.c | 54 +- lib/genl/ctrl.c | 25 +- lib/genl/family.c | 72 +- lib/genl/genl.c | 27 +- lib/genl/mngt.c | 64 +- lib/genl/nl-genl.h | 48 + lib/handlers.c | 49 +- lib/hash.c | 49 +- lib/hashtable.c | 71 +- lib/idiag/idiag.c | 276 + lib/idiag/idiag_meminfo_obj.c | 101 + lib/idiag/idiag_msg_obj.c | 1003 +++ lib/idiag/idiag_req_obj.c | 272 + lib/idiag/idiag_vegasinfo_obj.c | 104 + lib/idiag/nl-idiag.h | 30 + lib/mpls.c | 112 + lib/mpls.h | 7 + lib/msg.c | 60 +- lib/netfilter/ct.c | 183 +- lib/netfilter/ct_obj.c | 261 +- lib/netfilter/exp.c | 49 +- lib/netfilter/exp_obj.c | 231 +- lib/netfilter/log.c | 24 +- lib/netfilter/log_msg.c | 99 +- lib/netfilter/log_msg_obj.c | 267 +- lib/netfilter/log_obj.c | 80 +- lib/netfilter/netfilter.c | 38 +- lib/netfilter/nfnl.c | 20 +- lib/netfilter/nl-netfilter.h | 156 + lib/netfilter/queue.c | 19 +- lib/netfilter/queue_msg.c | 77 +- lib/netfilter/queue_msg_obj.c | 77 +- lib/netfilter/queue_obj.c | 65 +- lib/nl-core.h | 60 + lib/nl.c | 226 +- lib/object.c | 117 +- lib/route/act.c | 631 ++ lib/route/act/gact.c | 162 + lib/route/act/mirred.c | 222 + lib/route/act/nat.c | 289 + lib/route/act/skbedit.c | 284 + lib/route/act/vlan.c | 423 + lib/route/addr.c | 279 +- lib/route/class.c | 57 +- lib/route/classid.c | 33 +- lib/route/cls.c | 128 +- lib/route/cls/basic.c | 100 +- lib/route/cls/cgroup.c | 38 +- lib/route/cls/ematch.c | 89 +- lib/route/cls/ematch/cmp.c | 18 +- lib/route/cls/ematch/container.c | 16 +- lib/route/cls/ematch/meta.c | 119 +- lib/route/cls/ematch/nbyte.c | 18 +- lib/route/cls/ematch/text.c | 22 +- lib/route/cls/ematch_grammar.l | 18 +- lib/route/cls/ematch_syntax.y | 37 +- lib/route/cls/flower.c | 921 ++ lib/route/cls/fw.c | 33 +- lib/route/cls/mall.c | 307 + lib/route/cls/police.c | 25 +- lib/route/cls/u32.c | 416 +- lib/route/link-sriov.h | 20 + lib/route/link.c | 1373 ++- lib/route/link/api.c | 70 +- lib/route/link/bonding.c | 200 +- lib/route/link/bridge.c | 563 +- lib/route/link/bridge_info.c | 306 + lib/route/link/can.c | 245 +- lib/route/link/dummy.c | 18 +- lib/route/link/geneve.c | 803 ++ lib/route/link/ifb.c | 36 + lib/route/link/inet.c | 96 +- lib/route/link/inet6.c | 525 +- lib/route/link/ip6gre.c | 890 ++ lib/route/link/ip6tnl.c | 746 ++ lib/route/link/ip6vti.c | 558 ++ lib/route/link/ipgre.c | 896 ++ lib/route/link/ipip.c | 593 ++ lib/route/link/ipvlan.c | 273 + lib/route/link/ipvti.c | 542 ++ .../route/link/api.h => lib/route/link/link-api.h | 64 +- lib/route/link/macsec.c | 894 ++ lib/route/link/macvlan.c | 875 ++ lib/route/link/ppp.c | 219 + lib/route/link/sit.c | 873 ++ lib/route/link/sriov.c | 1479 ++++ lib/route/link/team.c | 104 + lib/route/link/veth.c | 305 + lib/route/link/vlan.c | 169 +- lib/route/link/vrf.c | 260 + lib/route/link/vxlan.c | 1787 ++++ lib/route/link/xfrmi.c | 316 + lib/route/mdb.c | 491 ++ lib/route/neigh.c | 375 +- lib/route/neightbl.c | 417 +- lib/route/netconf.c | 573 ++ lib/route/nexthop-encap.h | 35 + lib/route/nexthop.c | 168 +- lib/route/nexthop_encap.c | 109 + lib/route/nh.c | 590 ++ lib/route/nh_encap_mpls.c | 161 + lib/route/nl-route.h | 191 + lib/route/pktloc.c | 33 +- lib/route/pktloc_grammar.l | 8 +- lib/route/pktloc_syntax.y | 5 +- lib/route/qdisc.c | 54 +- lib/route/qdisc/blackhole.c | 18 +- lib/route/qdisc/cbq.c | 38 +- lib/route/qdisc/dsmark.c | 32 +- lib/route/qdisc/fifo.c | 24 +- lib/route/qdisc/fq_codel.c | 382 + lib/route/qdisc/hfsc.c | 358 + lib/route/qdisc/htb.c | 256 +- lib/route/qdisc/ingress.c | 59 + lib/route/qdisc/mqprio.c | 618 ++ lib/route/qdisc/netem.c | 365 +- lib/route/qdisc/plug.c | 24 +- lib/route/qdisc/prio.c | 37 +- lib/route/qdisc/red.c | 30 +- lib/route/qdisc/sfq.c | 28 +- lib/route/qdisc/tbf.c | 78 +- lib/route/route.c | 47 +- lib/route/route_obj.c | 522 +- lib/route/route_utils.c | 53 +- lib/route/rtnl.c | 56 +- lib/route/rule.c | 396 +- lib/route/tc-api.h | 104 + lib/route/tc.c | 312 +- lib/socket.c | 392 +- lib/utils.c | 632 +- lib/version.c | 10 +- lib/xfrm/ae.c | 1027 +++ lib/xfrm/lifetime.c | 278 + lib/xfrm/nl-xfrm.h | 81 + lib/xfrm/sa.c | 2385 +++++ lib/xfrm/selector.c | 371 + lib/xfrm/sp.c | 1462 ++++ lib/xfrm/template.c | 345 + libnl-3.0.pc.in | 1 + libnl-3.9.0.tar.gz | Bin 1074117 -> 0 bytes libnl-3.sym | 374 + libnl-cli-3.sym | 129 + libnl-genl-3.sym | 57 + libnl-idiag-3.0.pc.in | 12 + libnl-idiag-3.sym | 115 + libnl-nf-3.sym | 351 + libnl-route-3.sym | 1316 +++ libnl-xfrm-3.0.pc.in | 11 + libnl-xfrm-3.sym | 257 + m4/libtool.m4 | 2725 +++--- m4/ltoptions.m4 | 127 +- m4/ltsugar.m4 | 7 +- m4/ltversion.m4 | 13 +- m4/lt~obsolete.m4 | 7 +- man/Makefile.am | 7 - man/Makefile.in | 502 -- python/Makefile.am | 3 - python/Makefile.in | 607 -- python/doc/conf.py | 224 + python/doc/core.rst | 215 + python/doc/index.rst | 24 + python/doc/route.rst | 3 + python/doc/route_addr.rst | 47 + python/examples/iface.py | 112 + python/examples/nl80211.py | 1575 ++++ python/examples/wiphy.py | 161 + python/netlink/Makefile.am | 10 - python/netlink/Makefile.in | 611 -- python/netlink/capi.i | 528 ++ python/netlink/core.py | 135 +- python/netlink/fixes.h | 1 - python/netlink/genl/__init__.py | 0 python/netlink/genl/capi.i | 116 + python/netlink/route/Makefile.am | 14 - python/netlink/route/Makefile.in | 417 - python/netlink/route/address.py | 59 +- python/netlink/route/capi.i | 111 + python/netlink/route/link.py | 207 +- python/netlink/route/links/dummy.py | 7 +- python/netlink/route/links/inet.py | 65 +- python/netlink/route/links/vlan.py | 17 +- python/netlink/route/qdisc/htb.py | 28 +- python/netlink/route/tc.py | 285 +- python/netlink/util.py | 66 +- python/netlink/utils.h | 41 + python/setup.py.in | 71 +- python/tests/test-create-bridge.py | 29 + src/Makefile.am | 100 - src/Makefile.in | 1374 --- src/genl-ctrl-list.c | 22 +- src/idiag-socket-details.c | 88 + src/lib/Makefile.am | 43 - src/lib/Makefile.in | 643 -- src/lib/addr.c | 10 +- src/lib/class.c | 10 +- src/lib/cls.c | 10 +- src/lib/ct.c | 16 +- src/lib/exp.c | 10 +- src/lib/link.c | 30 +- src/lib/neigh.c | 12 +- src/lib/nh.c | 64 + src/lib/qdisc.c | 10 +- src/lib/route.c | 28 +- src/lib/rule.c | 10 +- src/lib/tc.c | 13 +- src/lib/utils.c | 78 +- src/nf-ct-add.c | 140 + src/nf-ct-events.c | 111 + src/nf-ct-list.c | 22 +- src/nf-exp-add.c | 57 +- src/nf-exp-delete.c | 40 +- src/nf-exp-list.c | 24 +- src/nf-log.c | 19 +- src/nf-monitor.c | 13 +- src/nf-queue.c | 21 +- src/nl-addr-add.c | 23 +- src/nl-addr-delete.c | 15 +- src/nl-addr-list.c | 11 +- src/nl-class-add.c | 26 +- src/nl-class-delete.c | 22 +- src/nl-class-list.c | 24 +- src/nl-classid-lookup.c | 16 +- src/nl-cls-add.c | 29 +- src/nl-cls-delete.c | 26 +- src/nl-cls-list.c | 26 +- src/nl-fib-lookup.c | 12 +- src/nl-link-enslave.c | 12 +- src/nl-link-ifindex2name.c | 12 +- src/nl-link-list.c | 12 +- src/nl-link-name2ifindex.c | 12 +- src/nl-link-release.c | 12 +- src/nl-link-set.c | 24 +- src/nl-link-stats.c | 16 +- src/nl-list-caches.c | 14 +- src/nl-list-sockets.c | 12 +- src/nl-monitor.c | 136 +- src/nl-neigh-add.c | 24 +- src/nl-neigh-delete.c | 22 +- src/nl-neigh-list.c | 29 +- src/nl-neightbl-list.c | 24 +- src/nl-nh-list.c | 76 + src/nl-pktloc-lookup.c | 71 +- src/nl-qdisc-add.c | 26 +- src/nl-qdisc-delete.c | 22 +- src/nl-qdisc-list.c | 23 +- src/nl-route-add.c | 12 +- src/nl-route-delete.c | 12 +- src/nl-route-get.c | 27 +- src/nl-route-list.c | 12 +- src/nl-rule-list.c | 16 +- src/nl-tctree-list.c | 20 +- src/nl-util-addr.c | 10 +- tests/Makefile.am | 54 - tests/Makefile.in | 814 -- tests/check-addr.c | 212 - tests/check-all.c | 21 +- tests/check-attr.c | 88 - tests/check-direct.c | 80 + tests/cksuite-all-addr.c | 229 + tests/cksuite-all-attr.c | 159 + tests/cksuite-all-ematch-tree-clone.c | 142 + tests/cksuite-all-netns.c | 318 + tests/cksuite-all.h | 13 + tests/nl-test-util.c | 655 ++ tests/nl-test-util.h | 397 + tests/test-cache-mngr.c | 155 +- tests/test-complex-HTB-with-hash-filters.c | 48 +- tests/test-create-bond.c | 6 + tests/test-create-bridge.c | 92 + tests/test-create-geneve.c | 91 + tests/test-create-ifb.c | 35 + tests/test-create-ip6tnl.c | 58 + tests/test-create-ipgre.c | 59 + tests/test-create-ipgretap.c | 59 + tests/test-create-ipip.c | 59 + tests/test-create-ipvlan.c | 51 + tests/test-create-ipvti.c | 58 + tests/test-create-macsec.c | 54 + tests/test-create-macvlan.c | 56 + tests/test-create-macvtap.c | 56 + tests/test-create-sit.c | 59 + tests/test-create-veth.c | 48 + tests/test-create-vlan.c | 6 + tests/test-create-vrf.c | 65 + tests/test-create-vxlan.c | 53 + tests/test-create-xfrmi.c | 52 + tests/test-delete-link.c | 6 + tests/test-genl.c | 13 +- tests/test-loopback-up-down.c | 59 + tests/test-nf-cache-mngr.c | 6 + tests/test-socket-creation.c | 5 +- tests/test-u32-filter-with-actions.c | 409 + tests/util.h | 5 - 567 files changed, 90701 insertions(+), 27496 deletions(-) create mode 100755 build-aux/test-driver delete mode 100644 include/Makefile.am delete mode 100644 include/Makefile.in create mode 100644 include/base/nl-base-utils.h rename lib/defs.h.in => include/config.h.in (70%) create mode 100644 include/linux-private/linux/atm.h create mode 100644 include/linux-private/linux/atmapi.h create mode 100644 include/linux-private/linux/atmioc.h create mode 100644 include/linux-private/linux/atmsap.h create mode 100644 include/linux-private/linux/byteorder/little_endian.h rename include/{ => linux-private}/linux/can/netlink.h (52%) create mode 100644 include/linux-private/linux/const.h create mode 100644 include/linux-private/linux/errno.h create mode 100644 include/linux-private/linux/ethtool.h create mode 100644 include/linux-private/linux/falloc.h rename include/{ => linux-private}/linux/fib_rules.h (72%) rename include/{ => linux-private}/linux/gen_stats.h (79%) rename include/{ => linux-private}/linux/genetlink.h (72%) create mode 100644 include/linux-private/linux/hdlc/ioctl.h create mode 100644 include/linux-private/linux/if.h rename include/{ => linux-private}/linux/if_addr.h (58%) rename include/{ => linux-private}/linux/if_arp.h (86%) create mode 100644 include/linux-private/linux/if_bridge.h rename include/{ => linux-private}/linux/if_ether.h (64%) create mode 100644 include/linux-private/linux/if_link.h create mode 100644 include/linux-private/linux/if_macsec.h create mode 100644 include/linux-private/linux/if_packet.h create mode 100644 include/linux-private/linux/if_tunnel.h rename include/{ => linux-private}/linux/if_vlan.h (83%) create mode 100644 include/linux-private/linux/in.h create mode 100644 include/linux-private/linux/in6.h create mode 100644 include/linux-private/linux/in_route.h create mode 100644 include/linux-private/linux/inet_diag.h create mode 100644 include/linux-private/linux/ioctl.h create mode 100644 include/linux-private/linux/ip.h rename include/{ => linux-private}/linux/ipv6.h (60%) create mode 100644 include/linux-private/linux/libc-compat.h create mode 100644 include/linux-private/linux/limits.h create mode 100644 include/linux-private/linux/lwtunnel.h create mode 100644 include/linux-private/linux/mpls.h create mode 100644 include/linux-private/linux/mpls_iptunnel.h rename include/{ => linux-private}/linux/neighbour.h (61%) create mode 100644 include/linux-private/linux/netconf.h create mode 100644 include/linux-private/linux/netdevice.h create mode 100644 include/linux-private/linux/netfilter.h rename include/{ => linux-private}/linux/netfilter/nf_conntrack_common.h (69%) create mode 100644 include/linux-private/linux/netfilter/nf_conntrack_tcp.h rename include/{ => linux-private}/linux/netfilter/nfnetlink.h (63%) rename include/{ => linux-private}/linux/netfilter/nfnetlink_compat.h (97%) rename include/{ => linux-private}/linux/netfilter/nfnetlink_conntrack.h (80%) rename include/{ => linux-private}/linux/netfilter/nfnetlink_log.h (82%) rename include/{ => linux-private}/linux/netfilter/nfnetlink_queue.h (67%) create mode 100644 include/linux-private/linux/netlink.h create mode 100644 include/linux-private/linux/nexthop.h create mode 100644 include/linux-private/linux/pkt_cls.h create mode 100644 include/linux-private/linux/pkt_sched.h create mode 100644 include/linux-private/linux/posix_types.h rename include/{ => linux-private}/linux/rtnetlink.h (65%) create mode 100644 include/linux-private/linux/seg6.h create mode 100644 include/linux-private/linux/seg6_hmac.h create mode 100644 include/linux-private/linux/seg6_iptunnel.h create mode 100644 include/linux-private/linux/seg6_local.h rename include/{ => linux-private}/linux/snmp.h (66%) create mode 100644 include/linux-private/linux/sock_diag.h create mode 100644 include/linux-private/linux/socket.h create mode 100644 include/linux-private/linux/stddef.h create mode 100644 include/linux-private/linux/swab.h create mode 100644 include/linux-private/linux/taskstats.h create mode 100644 include/linux-private/linux/tc_act/tc_gact.h create mode 100644 include/linux-private/linux/tc_act/tc_mirred.h create mode 100644 include/linux-private/linux/tc_act/tc_nat.h create mode 100644 include/linux-private/linux/tc_act/tc_skbedit.h create mode 100644 include/linux-private/linux/tc_act/tc_vlan.h create mode 100644 include/linux-private/linux/tc_ematch/tc_em_cmp.h rename include/{ => linux-private}/linux/tc_ematch/tc_em_meta.h (91%) create mode 100644 include/linux-private/linux/tc_ematch/tc_em_nbyte.h create mode 100644 include/linux-private/linux/tc_ematch/tc_em_text.h create mode 100644 include/linux-private/linux/types.h create mode 100644 include/linux-private/linux/version.h create mode 100644 include/linux-private/linux/veth.h create mode 100644 include/linux-private/linux/xfrm.h delete mode 100644 include/linux/if.h delete mode 100644 include/linux/if_bridge.h delete mode 100644 include/linux/if_link.h delete mode 100644 include/linux/inetdevice.h delete mode 100644 include/linux/ip_mp_alg.h delete mode 100644 include/linux/netfilter.h delete mode 100644 include/linux/netlink.h delete mode 100644 include/linux/pkt_cls.h delete mode 100644 include/linux/pkt_sched.h delete mode 100644 include/netlink-private/genl.h delete mode 100644 include/netlink-private/netlink.h delete mode 100644 include/netlink-private/route/tc-api.h delete mode 100644 include/netlink-private/tc.h delete mode 100644 include/netlink-private/types.h create mode 100644 include/netlink/cli/mdb.h create mode 100644 include/netlink/cli/nh.h create mode 100644 include/netlink/idiag/idiagnl.h create mode 100644 include/netlink/idiag/meminfo.h create mode 100644 include/netlink/idiag/msg.h create mode 100644 include/netlink/idiag/req.h create mode 100644 include/netlink/idiag/vegasinfo.h create mode 100644 include/netlink/route/act/gact.h create mode 100644 include/netlink/route/act/mirred.h create mode 100644 include/netlink/route/act/nat.h create mode 100644 include/netlink/route/act/skbedit.h create mode 100644 include/netlink/route/act/vlan.h create mode 100644 include/netlink/route/action.h create mode 100644 include/netlink/route/cls/flower.h create mode 100644 include/netlink/route/cls/matchall.h create mode 100644 include/netlink/route/link/bridge_info.h create mode 100644 include/netlink/route/link/geneve.h create mode 100644 include/netlink/route/link/inet6.h create mode 100644 include/netlink/route/link/ip6gre.h create mode 100644 include/netlink/route/link/ip6tnl.h create mode 100644 include/netlink/route/link/ip6vti.h create mode 100644 include/netlink/route/link/ipgre.h create mode 100644 include/netlink/route/link/ipip.h create mode 100644 include/netlink/route/link/ipvlan.h create mode 100644 include/netlink/route/link/ipvti.h create mode 100644 include/netlink/route/link/macsec.h create mode 100644 include/netlink/route/link/macvlan.h create mode 100644 include/netlink/route/link/macvtap.h create mode 100644 include/netlink/route/link/ppp.h create mode 100644 include/netlink/route/link/sit.h create mode 100644 include/netlink/route/link/sriov.h create mode 100644 include/netlink/route/link/team.h create mode 100644 include/netlink/route/link/veth.h create mode 100644 include/netlink/route/link/vrf.h create mode 100644 include/netlink/route/link/vxlan.h create mode 100644 include/netlink/route/link/xfrmi.h create mode 100644 include/netlink/route/mdb.h create mode 100644 include/netlink/route/netconf.h create mode 100644 include/netlink/route/nh.h create mode 100644 include/netlink/route/qdisc/fq_codel.h create mode 100644 include/netlink/route/qdisc/hfsc.h create mode 100644 include/netlink/route/qdisc/mqprio.h create mode 100644 include/netlink/xfrm/ae.h create mode 100644 include/netlink/xfrm/lifetime.h create mode 100644 include/netlink/xfrm/sa.h create mode 100644 include/netlink/xfrm/selector.h create mode 100644 include/netlink/xfrm/sp.h create mode 100644 include/netlink/xfrm/template.h create mode 100644 include/nl-aux-core/nl-core.h create mode 100644 include/nl-aux-route/nl-route.h create mode 100644 include/nl-aux-xfrm/nl-xfrm.h create mode 100644 include/nl-default.h rename include/{netlink-private => nl-priv-dynamic-core}/cache-api.h (92%) create mode 100644 include/nl-priv-dynamic-core/nl-core.h rename include/{netlink-private => nl-priv-dynamic-core}/object-api.h (94%) create mode 100644 include/nl-priv-dynamic-route/nl-priv-dynamic-route.h create mode 100644 include/nl-priv-static-route/nl-priv-static-route.h delete mode 100644 lib/Makefile.am delete mode 100644 lib/Makefile.in create mode 100644 lib/cli/qdisc/fq_codel.c create mode 100644 lib/cli/qdisc/hfsc.c create mode 100644 lib/cli/qdisc/ingress.c create mode 100644 lib/genl/nl-genl.h create mode 100644 lib/idiag/idiag.c create mode 100644 lib/idiag/idiag_meminfo_obj.c create mode 100644 lib/idiag/idiag_msg_obj.c create mode 100644 lib/idiag/idiag_req_obj.c create mode 100644 lib/idiag/idiag_vegasinfo_obj.c create mode 100644 lib/idiag/nl-idiag.h create mode 100644 lib/mpls.c create mode 100644 lib/mpls.h create mode 100644 lib/netfilter/nl-netfilter.h create mode 100644 lib/nl-core.h create mode 100644 lib/route/act.c create mode 100644 lib/route/act/gact.c create mode 100644 lib/route/act/mirred.c create mode 100644 lib/route/act/nat.c create mode 100644 lib/route/act/skbedit.c create mode 100644 lib/route/act/vlan.c create mode 100644 lib/route/cls/flower.c create mode 100644 lib/route/cls/mall.c create mode 100644 lib/route/link-sriov.h create mode 100644 lib/route/link/bridge_info.c create mode 100644 lib/route/link/geneve.c create mode 100644 lib/route/link/ifb.c create mode 100644 lib/route/link/ip6gre.c create mode 100644 lib/route/link/ip6tnl.c create mode 100644 lib/route/link/ip6vti.c create mode 100644 lib/route/link/ipgre.c create mode 100644 lib/route/link/ipip.c create mode 100644 lib/route/link/ipvlan.c create mode 100644 lib/route/link/ipvti.c rename include/netlink-private/route/link/api.h => lib/route/link/link-api.h (70%) create mode 100644 lib/route/link/macsec.c create mode 100644 lib/route/link/macvlan.c create mode 100644 lib/route/link/ppp.c create mode 100644 lib/route/link/sit.c create mode 100644 lib/route/link/sriov.c create mode 100644 lib/route/link/team.c create mode 100644 lib/route/link/veth.c create mode 100644 lib/route/link/vrf.c create mode 100644 lib/route/link/vxlan.c create mode 100644 lib/route/link/xfrmi.c create mode 100644 lib/route/mdb.c create mode 100644 lib/route/netconf.c create mode 100644 lib/route/nexthop-encap.h create mode 100644 lib/route/nexthop_encap.c create mode 100644 lib/route/nh.c create mode 100644 lib/route/nh_encap_mpls.c create mode 100644 lib/route/nl-route.h create mode 100644 lib/route/qdisc/fq_codel.c create mode 100644 lib/route/qdisc/hfsc.c create mode 100644 lib/route/qdisc/ingress.c create mode 100644 lib/route/qdisc/mqprio.c create mode 100644 lib/route/tc-api.h create mode 100644 lib/xfrm/ae.c create mode 100644 lib/xfrm/lifetime.c create mode 100644 lib/xfrm/nl-xfrm.h create mode 100644 lib/xfrm/sa.c create mode 100644 lib/xfrm/selector.c create mode 100644 lib/xfrm/sp.c create mode 100644 lib/xfrm/template.c delete mode 100644 libnl-3.9.0.tar.gz create mode 100644 libnl-3.sym create mode 100644 libnl-cli-3.sym create mode 100644 libnl-genl-3.sym create mode 100644 libnl-idiag-3.0.pc.in create mode 100644 libnl-idiag-3.sym create mode 100644 libnl-nf-3.sym create mode 100644 libnl-route-3.sym create mode 100644 libnl-xfrm-3.0.pc.in create mode 100644 libnl-xfrm-3.sym delete mode 100644 man/Makefile.am delete mode 100644 man/Makefile.in delete mode 100644 python/Makefile.am delete mode 100644 python/Makefile.in create mode 100644 python/doc/conf.py create mode 100644 python/doc/core.rst create mode 100644 python/doc/index.rst create mode 100644 python/doc/route.rst create mode 100644 python/doc/route_addr.rst create mode 100644 python/examples/iface.py create mode 100644 python/examples/nl80211.py create mode 100644 python/examples/wiphy.py delete mode 100644 python/netlink/Makefile.am delete mode 100644 python/netlink/Makefile.in delete mode 100644 python/netlink/fixes.h create mode 100644 python/netlink/genl/__init__.py create mode 100644 python/netlink/genl/capi.i delete mode 100644 python/netlink/route/Makefile.am delete mode 100644 python/netlink/route/Makefile.in create mode 100644 python/netlink/utils.h create mode 100644 python/tests/test-create-bridge.py delete mode 100644 src/Makefile.am delete mode 100644 src/Makefile.in create mode 100644 src/idiag-socket-details.c delete mode 100644 src/lib/Makefile.am delete mode 100644 src/lib/Makefile.in create mode 100644 src/lib/nh.c create mode 100644 src/nf-ct-add.c create mode 100644 src/nf-ct-events.c create mode 100644 src/nl-nh-list.c delete mode 100644 tests/Makefile.am delete mode 100644 tests/Makefile.in delete mode 100644 tests/check-addr.c delete mode 100644 tests/check-attr.c create mode 100644 tests/check-direct.c create mode 100644 tests/cksuite-all-addr.c create mode 100644 tests/cksuite-all-attr.c create mode 100644 tests/cksuite-all-ematch-tree-clone.c create mode 100644 tests/cksuite-all-netns.c create mode 100644 tests/cksuite-all.h create mode 100644 tests/nl-test-util.c create mode 100644 tests/nl-test-util.h create mode 100644 tests/test-create-bridge.c create mode 100644 tests/test-create-geneve.c create mode 100644 tests/test-create-ifb.c create mode 100644 tests/test-create-ip6tnl.c create mode 100644 tests/test-create-ipgre.c create mode 100644 tests/test-create-ipgretap.c create mode 100644 tests/test-create-ipip.c create mode 100644 tests/test-create-ipvlan.c create mode 100644 tests/test-create-ipvti.c create mode 100644 tests/test-create-macsec.c create mode 100644 tests/test-create-macvlan.c create mode 100644 tests/test-create-macvtap.c create mode 100644 tests/test-create-sit.c create mode 100644 tests/test-create-veth.c create mode 100644 tests/test-create-vrf.c create mode 100644 tests/test-create-vxlan.c create mode 100644 tests/test-create-xfrmi.c create mode 100644 tests/test-loopback-up-down.c create mode 100644 tests/test-u32-filter-with-actions.c delete mode 100644 tests/util.h diff --git a/ChangeLog b/ChangeLog index cdd78a8..3d93d1c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,5 @@ ChangeLog discontinued, git history can be found here: -http://git.infradead.org/users/tgr/libnl.git +https://github.com/thom311/libnl Summary of Changes from 1.0-pre6 to 1.0-pre7 ================================================ @@ -42,7 +42,7 @@ Summary of Changes from 1.0-pre6 to 1.0-pre7 NL_SKIP o Fixed nl_recvmsgs() to stop reading after parsing if not in the middle of a multipart message. - o Fixed nl_recvmsgs() to not stop after receving an ACK + o Fixed nl_recvmsgs() to not stop after receiving an ACK o Fixed nl_recvmsgs() to not blindly discard remaining messages if a NLMSG_DONE message is received. @@ -205,7 +205,7 @@ Summary of Changes from 1.0-pre1 to 1.0-pre2 o Removed non-reentrant translation routines, only bloating the code and too risky. o Fixed wrong version number from 1.0-pre1. - o Reenabled unfinished policer module. + o Re-enabled unfinished policer module. o Reworked TBF module, automatic caluclation of transmit times, limit setable via latency, automatic cell size calculation, options TLV generation. (untested) @@ -219,7 +219,7 @@ Summary of Changes from 1.0-pre1 to 1.0-pre2 o Add empty install target to src/Makefile Simon Stelling - o Use LIBDIR instead of $(prefix)/lib for users to alllow librariers + o Use LIBDIR instead of $(prefix)/lib for users to allow librariers into $(prefix)/lib64. Summary of Changes from 0.5.0 to 1.0-pre1 @@ -231,7 +231,7 @@ Summary of Changes from 0.5.0 to 1.0-pre1 Petr Gotthard , Siemens AG Oesterreich o added class_build, rtnl_class_build_add_request, rtnl_class_add - o added HTB (Hierachical Token Bucket) class support + o added HTB (Hierarchical Token Bucket) class support o added nl_xmittime, nl_build_rtable o added nl_data_append to realloc a nl_data structure o added rtnl_rcopy_ratespec as reverse to rtnl_copy_ratespec @@ -248,9 +248,9 @@ Summary of Changes from 0.4.4 to 0.5.0 o nl_cache_filter to manually filter on a object o partial routing support o routing rules support - o Propely set address family when setting addresses + o Properly set address family when setting addresses o debug flag and some rare messages, more to come - o make error mesage verboseness configureable + o make error message verboseness configurable o tc fixes to wait for ack o cleanup and adaption of address code to latest internal API o various cleanups diff --git a/Makefile.am b/Makefile.am index bc4266d..1e76649 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,21 +2,1188 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = include lib man python tests +lib_LTLIBRARIES = +noinst_LTLIBRARIES = +check_LTLIBRARIES = -pkgconfig_DATA = libnl-3.0.pc \ - libnl-route-3.0.pc \ - libnl-genl-3.0.pc \ - libnl-nf-3.0.pc +check_PROGRAMS = +check_programs = +check_local = + +bin_PROGRAMS = +sbin_PROGRAMS = +noinst_PROGRAMS = + +TESTS = + +CLEANFILES = +EXTRA_DIST = + +DISTCHECK_CONFIGURE_FLAGS = \ + --disable-dependency-tracking + +pkgconfig_DATA = \ + libnl-3.0.pc \ + libnl-genl-3.0.pc \ + libnl-idiag-3.0.pc \ + libnl-nf-3.0.pc \ + libnl-route-3.0.pc \ + libnl-xfrm-3.0.pc \ + $(NULL) + +warn_cppflags = \ + -Wall \ + -Wextra \ + -Wmissing-prototypes \ + -Wno-unused-parameter \ + -Wno-sign-compare \ + -Wno-missing-field-initializers \ + -Wpointer-arith \ + $(NULL) + +############################################################################### + +libnlincludedir = $(includedir)/libnl@MAJ_VERSION@ + +libnlinclude_netlinkdir = $(libnlincludedir)/netlink +libnlinclude_netlink_HEADERS = \ + include/netlink/addr.h \ + include/netlink/attr.h \ + include/netlink/cache-api.h \ + include/netlink/cache.h \ + include/netlink/data.h \ + include/netlink/errno.h \ + include/netlink/handlers.h \ + include/netlink/hash.h \ + include/netlink/hashtable.h \ + include/netlink/list.h \ + include/netlink/msg.h \ + include/netlink/netlink-compat.h \ + include/netlink/netlink-kernel.h \ + include/netlink/netlink.h \ + include/netlink/object-api.h \ + include/netlink/object.h \ + include/netlink/socket.h \ + include/netlink/types.h \ + include/netlink/utils.h \ + include/netlink/version.h \ + $(NULL) +libnlinclude_netlink_fib_lookupdir = $(libnlincludedir)/netlink/fib_lookup +libnlinclude_netlink_fib_lookup_HEADERS = \ + include/netlink/fib_lookup/lookup.h \ + include/netlink/fib_lookup/request.h \ + $(NULL) +libnlinclude_netlink_genldir = $(libnlincludedir)/netlink/genl +libnlinclude_netlink_genl_HEADERS = \ + include/netlink/genl/ctrl.h \ + include/netlink/genl/family.h \ + include/netlink/genl/genl.h \ + include/netlink/genl/mngt.h \ + $(NULL) +libnlinclude_netlink_idiagdir = $(libnlincludedir)/netlink/idiag +libnlinclude_netlink_idiag_HEADERS = \ + include/netlink/idiag/idiagnl.h \ + include/netlink/idiag/meminfo.h \ + include/netlink/idiag/msg.h \ + include/netlink/idiag/req.h \ + include/netlink/idiag/vegasinfo.h \ + $(NULL) +libnlinclude_netlink_netfilterdir = $(libnlincludedir)/netlink/netfilter +libnlinclude_netlink_netfilter_HEADERS = \ + include/netlink/netfilter/ct.h \ + include/netlink/netfilter/exp.h \ + include/netlink/netfilter/log.h \ + include/netlink/netfilter/log_msg.h \ + include/netlink/netfilter/netfilter.h \ + include/netlink/netfilter/nfnl.h \ + include/netlink/netfilter/queue.h \ + include/netlink/netfilter/queue_msg.h \ + $(NULL) +libnlinclude_netlink_routedir = $(libnlincludedir)/netlink/route +libnlinclude_netlink_route_HEADERS = \ + include/netlink/route/action.h \ + include/netlink/route/addr.h \ + include/netlink/route/class.h \ + include/netlink/route/classifier.h \ + include/netlink/route/link.h \ + include/netlink/route/mdb.h \ + include/netlink/route/neighbour.h \ + include/netlink/route/neightbl.h \ + include/netlink/route/netconf.h \ + include/netlink/route/nexthop.h \ + include/netlink/route/nh.h \ + include/netlink/route/pktloc.h \ + include/netlink/route/qdisc.h \ + include/netlink/route/route.h \ + include/netlink/route/rtnl.h \ + include/netlink/route/rule.h \ + include/netlink/route/tc-api.h \ + include/netlink/route/tc.h \ + $(NULL) +libnlinclude_netlink_route_actdir = $(libnlincludedir)/netlink/route/act +libnlinclude_netlink_route_act_HEADERS = \ + include/netlink/route/act/gact.h \ + include/netlink/route/act/mirred.h \ + include/netlink/route/act/nat.h \ + include/netlink/route/act/skbedit.h \ + include/netlink/route/act/vlan.h \ + $(NULL) +libnlinclude_netlink_route_clsdir = $(libnlincludedir)/netlink/route/cls +libnlinclude_netlink_route_cls_HEADERS = \ + include/netlink/route/cls/basic.h \ + include/netlink/route/cls/cgroup.h \ + include/netlink/route/cls/ematch.h \ + include/netlink/route/cls/flower.h \ + include/netlink/route/cls/fw.h \ + include/netlink/route/cls/matchall.h \ + include/netlink/route/cls/police.h \ + include/netlink/route/cls/u32.h \ + $(NULL) +libnlinclude_netlink_route_cls_ematchdir = $(libnlincludedir)/netlink/route/cls/ematch +libnlinclude_netlink_route_cls_ematch_HEADERS = \ + include/netlink/route/cls/ematch/cmp.h \ + include/netlink/route/cls/ematch/meta.h \ + include/netlink/route/cls/ematch/nbyte.h \ + include/netlink/route/cls/ematch/text.h \ + $(NULL) +libnlinclude_netlink_route_linkdir = $(libnlincludedir)/netlink/route/link +libnlinclude_netlink_route_link_HEADERS = \ + include/netlink/route/link/api.h \ + include/netlink/route/link/bonding.h \ + include/netlink/route/link/bridge_info.h \ + include/netlink/route/link/bridge.h \ + include/netlink/route/link/can.h \ + include/netlink/route/link/geneve.h \ + include/netlink/route/link/inet.h \ + include/netlink/route/link/inet6.h \ + include/netlink/route/link/info-api.h \ + include/netlink/route/link/ip6gre.h \ + include/netlink/route/link/ip6tnl.h \ + include/netlink/route/link/ip6vti.h \ + include/netlink/route/link/ipgre.h \ + include/netlink/route/link/ipip.h \ + include/netlink/route/link/ipvlan.h \ + include/netlink/route/link/ipvti.h \ + include/netlink/route/link/macsec.h \ + include/netlink/route/link/macvlan.h \ + include/netlink/route/link/macvtap.h \ + include/netlink/route/link/ppp.h \ + include/netlink/route/link/sit.h \ + include/netlink/route/link/sriov.h \ + include/netlink/route/link/team.h \ + include/netlink/route/link/veth.h \ + include/netlink/route/link/vlan.h \ + include/netlink/route/link/vrf.h \ + include/netlink/route/link/vxlan.h \ + include/netlink/route/link/xfrmi.h \ + $(NULL) +libnlinclude_netlink_route_qdiscdir = $(libnlincludedir)/netlink/route/qdisc +libnlinclude_netlink_route_qdisc_HEADERS = \ + include/netlink/route/qdisc/cbq.h \ + include/netlink/route/qdisc/dsmark.h \ + include/netlink/route/qdisc/fifo.h \ + include/netlink/route/qdisc/fq_codel.h \ + include/netlink/route/qdisc/hfsc.h \ + include/netlink/route/qdisc/htb.h \ + include/netlink/route/qdisc/mqprio.h \ + include/netlink/route/qdisc/netem.h \ + include/netlink/route/qdisc/plug.h \ + include/netlink/route/qdisc/prio.h \ + include/netlink/route/qdisc/red.h \ + include/netlink/route/qdisc/sfq.h \ + include/netlink/route/qdisc/tbf.h \ + $(NULL) +libnlinclude_netlink_xfrmdir = $(libnlincludedir)/netlink/xfrm +libnlinclude_netlink_xfrm_HEADERS = \ + include/netlink/xfrm/ae.h \ + include/netlink/xfrm/lifetime.h \ + include/netlink/xfrm/sa.h \ + include/netlink/xfrm/selector.h \ + include/netlink/xfrm/sp.h \ + include/netlink/xfrm/template.h \ + $(NULL) + +if ENABLE_CLI +libnlinclude_netlink_clidir = $(libnlincludedir)/netlink/cli +libnlinclude_netlink_cli_HEADERS = \ + include/netlink/cli/addr.h \ + include/netlink/cli/class.h \ + include/netlink/cli/cls.h \ + include/netlink/cli/ct.h \ + include/netlink/cli/exp.h \ + include/netlink/cli/link.h \ + include/netlink/cli/mdb.h \ + include/netlink/cli/neigh.h \ + include/netlink/cli/nh.h \ + include/netlink/cli/qdisc.h \ + include/netlink/cli/route.h \ + include/netlink/cli/rule.h \ + include/netlink/cli/tc.h \ + include/netlink/cli/utils.h \ + $(NULL) +endif + +public_headers = \ + $(libnlinclude_netlink_HEADERS) \ + $(libnlinclude_netlink_fib_lookup_HEADERS) \ + $(libnlinclude_netlink_genl_HEADERS) \ + $(libnlinclude_netlink_idiag_HEADERS) \ + $(libnlinclude_netlink_netfilter_HEADERS) \ + $(libnlinclude_netlink_route_HEADERS) \ + $(libnlinclude_netlink_route_act_HEADERS) \ + $(libnlinclude_netlink_route_cls_HEADERS) \ + $(libnlinclude_netlink_route_cls_ematch_HEADERS) \ + $(libnlinclude_netlink_route_link_HEADERS) \ + $(libnlinclude_netlink_route_qdisc_HEADERS) \ + $(libnlinclude_netlink_xfrm_HEADERS) \ + $(libnlinclude_netlink_cli_HEADERS) \ + $(NULL) + +noinst_HEADERS = \ + include/base/nl-base-utils.h \ + include/linux-private/linux/atm.h \ + include/linux-private/linux/atmapi.h \ + include/linux-private/linux/atmioc.h \ + include/linux-private/linux/atmsap.h \ + include/linux-private/linux/byteorder/little_endian.h \ + include/linux-private/linux/can/netlink.h \ + include/linux-private/linux/const.h \ + include/linux-private/linux/errno.h \ + include/linux-private/linux/ethtool.h \ + include/linux-private/linux/falloc.h \ + include/linux-private/linux/fib_rules.h \ + include/linux-private/linux/gen_stats.h \ + include/linux-private/linux/genetlink.h \ + include/linux-private/linux/hdlc/ioctl.h \ + include/linux-private/linux/if.h \ + include/linux-private/linux/if_addr.h \ + include/linux-private/linux/if_arp.h \ + include/linux-private/linux/if_bridge.h \ + include/linux-private/linux/if_ether.h \ + include/linux-private/linux/if_link.h \ + include/linux-private/linux/if_macsec.h \ + include/linux-private/linux/if_packet.h \ + include/linux-private/linux/if_tunnel.h \ + include/linux-private/linux/if_vlan.h \ + include/linux-private/linux/in.h \ + include/linux-private/linux/in6.h \ + include/linux-private/linux/in_route.h \ + include/linux-private/linux/inet_diag.h \ + include/linux-private/linux/ioctl.h \ + include/linux-private/linux/ip.h \ + include/linux-private/linux/ipv6.h \ + include/linux-private/linux/libc-compat.h \ + include/linux-private/linux/limits.h \ + include/linux-private/linux/lwtunnel.h \ + include/linux-private/linux/mpls.h \ + include/linux-private/linux/mpls_iptunnel.h \ + include/linux-private/linux/neighbour.h \ + include/linux-private/linux/netconf.h \ + include/linux-private/linux/netdevice.h \ + include/linux-private/linux/netfilter.h \ + include/linux-private/linux/netfilter/nf_conntrack_common.h \ + include/linux-private/linux/netfilter/nf_conntrack_tcp.h \ + include/linux-private/linux/netfilter/nfnetlink.h \ + include/linux-private/linux/netfilter/nfnetlink_compat.h \ + include/linux-private/linux/netfilter/nfnetlink_conntrack.h \ + include/linux-private/linux/netfilter/nfnetlink_log.h \ + include/linux-private/linux/netfilter/nfnetlink_queue.h \ + include/linux-private/linux/netlink.h \ + include/linux-private/linux/nexthop.h \ + include/linux-private/linux/pkt_cls.h \ + include/linux-private/linux/pkt_sched.h \ + include/linux-private/linux/posix_types.h \ + include/linux-private/linux/rtnetlink.h \ + include/linux-private/linux/seg6.h \ + include/linux-private/linux/seg6_hmac.h \ + include/linux-private/linux/seg6_iptunnel.h \ + include/linux-private/linux/seg6_local.h \ + include/linux-private/linux/snmp.h \ + include/linux-private/linux/sock_diag.h \ + include/linux-private/linux/socket.h \ + include/linux-private/linux/stddef.h \ + include/linux-private/linux/swab.h \ + include/linux-private/linux/taskstats.h \ + include/linux-private/linux/tc_act/tc_gact.h \ + include/linux-private/linux/tc_act/tc_mirred.h \ + include/linux-private/linux/tc_act/tc_nat.h \ + include/linux-private/linux/tc_act/tc_skbedit.h \ + include/linux-private/linux/tc_act/tc_vlan.h \ + include/linux-private/linux/tc_ematch/tc_em_cmp.h \ + include/linux-private/linux/tc_ematch/tc_em_meta.h \ + include/linux-private/linux/tc_ematch/tc_em_nbyte.h \ + include/linux-private/linux/tc_ematch/tc_em_text.h \ + include/linux-private/linux/types.h \ + include/linux-private/linux/version.h \ + include/linux-private/linux/veth.h \ + include/linux-private/linux/xfrm.h \ + include/nl-aux-core/nl-core.h \ + include/nl-aux-route/nl-route.h \ + include/nl-aux-xfrm/nl-xfrm.h \ + include/nl-default.h \ + include/nl-priv-dynamic-core/cache-api.h \ + include/nl-priv-dynamic-core/nl-core.h \ + include/nl-priv-dynamic-core/object-api.h \ + include/nl-priv-dynamic-route/nl-priv-dynamic-route.h \ + include/nl-priv-static-route/nl-priv-static-route.h \ + $(NULL) + +############################################################################### + +# Hack to avoid using ylwrap. It does not function correctly in combination +# with --header-file= + +lib/route/pktloc_grammar.h: lib/route/pktloc_grammar.c + @true + +lib/route/pktloc_grammar.c: lib/route/pktloc_grammar.l lib/route/.dirstamp + $(AM_V_GEN) $(FLEX) --header-file=lib/route/pktloc_grammar.h $(LFLAGS) -o $@ $< + +lib/route/pktloc_syntax.h: lib/route/pktloc_syntax.c + @true + +lib/route/pktloc_syntax.c: lib/route/pktloc_syntax.y lib/route/.dirstamp + $(AM_V_GEN) $(YACC) -d $(YFLAGS) -o $@ $< + +lib/route/cls/ematch_grammar.h: lib/route/cls/ematch_grammar.c + @true + +lib/route/cls/ematch_grammar.c: lib/route/cls/ematch_grammar.l lib/route/cls/.dirstamp + $(AM_V_GEN) $(FLEX) --header-file=lib/route/cls/ematch_grammar.h $(LFLAGS) -o $@ $< + +lib/route/cls/ematch_syntax.h: lib/route/cls/ematch_syntax.c + @true + +lib/route/cls/ematch_syntax.c: lib/route/cls/ematch_syntax.y lib/route/cls/.dirstamp + $(AM_V_GEN) $(YACC) -d $(YFLAGS) -o $@ $< + +grammar_files_sources = \ + lib/route/cls/ematch_grammar.c \ + lib/route/cls/ematch_syntax.c \ + lib/route/pktloc_grammar.c \ + lib/route/pktloc_syntax.c \ + $(NULL) + +grammar_files_headers = $(grammar_files_sources:%.c=%.h) + +CLEANFILES += \ + $(grammar_files_sources) \ + $(grammar_files_headers) + +EXTRA_DIST += \ + lib/route/cls/ematch_grammar.l \ + lib/route/cls/ematch_syntax.y \ + lib/route/pktloc_grammar.l \ + lib/route/pktloc_syntax.y \ + $(NULL) + +############################################################################### + +default_includes = \ + -I$(srcdir)/include/linux-private \ + -I$(srcdir)/include \ + -I$(builddir)/include \ + $(NULL) + +lib_cppflags = \ + $(warn_cppflags) \ + -D_GNU_SOURCE \ + -DSYSCONFDIR=\"$(sysconfdir)/libnl\" \ + $(default_includes) \ + $(NULL) + +lib_LTLIBRARIES += lib/libnl-3.la + +lib_libnl_3_la_SOURCES = \ + lib/addr.c \ + lib/attr.c \ + lib/cache.c \ + lib/cache_mngr.c \ + lib/cache_mngt.c \ + lib/data.c \ + lib/error.c \ + lib/handlers.c \ + lib/hash.c \ + lib/hashtable.c \ + lib/mpls.c \ + lib/mpls.h \ + lib/msg.c \ + lib/nl-core.h \ + lib/nl.c \ + lib/object.c \ + lib/socket.c \ + lib/utils.c \ + lib/version.c \ + $(NULL) +EXTRA_lib_libnl_3_la_DEPENDENCIES = \ + libnl-3.sym +lib_libnl_3_la_CPPFLAGS = \ + $(lib_cppflags) +lib_libnl_3_la_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -Wl,--version-script=$(srcdir)/libnl-3.sym + +lib_LTLIBRARIES += lib/libnl-route-3.la + +lib_libnl_route_3_la_SOURCES = \ + lib/fib_lookup/lookup.c \ + lib/fib_lookup/request.c \ + lib/route/act.c \ + lib/route/act/gact.c \ + lib/route/act/mirred.c \ + lib/route/act/nat.c \ + lib/route/act/skbedit.c \ + lib/route/act/vlan.c \ + lib/route/addr.c \ + lib/route/class.c \ + lib/route/classid.c \ + lib/route/cls.c \ + lib/route/cls/basic.c \ + lib/route/cls/cgroup.c \ + lib/route/cls/ematch.c \ + lib/route/cls/ematch/cmp.c \ + lib/route/cls/ematch/container.c \ + lib/route/cls/ematch/meta.c \ + lib/route/cls/ematch/nbyte.c \ + lib/route/cls/ematch/text.c \ + lib/route/cls/flower.c \ + lib/route/cls/fw.c \ + lib/route/cls/mall.c \ + lib/route/cls/police.c \ + lib/route/cls/u32.c \ + lib/route/link-sriov.h \ + lib/route/link.c \ + lib/route/link/api.c \ + lib/route/link/bonding.c \ + lib/route/link/bridge.c \ + lib/route/link/bridge_info.c \ + lib/route/link/can.c \ + lib/route/link/dummy.c \ + lib/route/link/geneve.c \ + lib/route/link/ifb.c \ + lib/route/link/inet.c \ + lib/route/link/inet6.c \ + lib/route/link/ip6gre.c \ + lib/route/link/ip6tnl.c \ + lib/route/link/ip6vti.c \ + lib/route/link/ipgre.c \ + lib/route/link/ipip.c \ + lib/route/link/ipvlan.c \ + lib/route/link/ipvti.c \ + lib/route/link/link-api.h \ + lib/route/link/macsec.c \ + lib/route/link/macvlan.c \ + lib/route/link/ppp.c \ + lib/route/link/sit.c \ + lib/route/link/sriov.c \ + lib/route/link/team.c \ + lib/route/link/veth.c \ + lib/route/link/vlan.c \ + lib/route/link/vrf.c \ + lib/route/link/vxlan.c \ + lib/route/link/xfrmi.c \ + lib/route/mdb.c \ + lib/route/neigh.c \ + lib/route/neightbl.c \ + lib/route/netconf.c \ + lib/route/nexthop-encap.h \ + lib/route/nexthop.c \ + lib/route/nexthop_encap.c \ + lib/route/nh.c \ + lib/route/nh_encap_mpls.c \ + lib/route/nl-route.h \ + lib/route/pktloc.c \ + lib/route/qdisc.c \ + lib/route/qdisc/blackhole.c \ + lib/route/qdisc/cbq.c \ + lib/route/qdisc/dsmark.c \ + lib/route/qdisc/fifo.c \ + lib/route/qdisc/fq_codel.c \ + lib/route/qdisc/hfsc.c \ + lib/route/qdisc/htb.c \ + lib/route/qdisc/ingress.c \ + lib/route/qdisc/mqprio.c \ + lib/route/qdisc/netem.c \ + lib/route/qdisc/plug.c \ + lib/route/qdisc/prio.c \ + lib/route/qdisc/red.c \ + lib/route/qdisc/sfq.c \ + lib/route/qdisc/tbf.c \ + lib/route/route.c \ + lib/route/route_obj.c \ + lib/route/route_utils.c \ + lib/route/rtnl.c \ + lib/route/rule.c \ + lib/route/tc-api.h \ + lib/route/tc.c \ + $(NULL) +nodist_lib_libnl_route_3_la_SOURCES = \ + $(grammar_files_sources) +EXTRA_lib_libnl_route_3_la_DEPENDENCIES = \ + libnl-route-3.sym +lib_libnl_route_3_la_CPPFLAGS = \ + $(lib_cppflags) \ + -I$(srcdir)/lib/route \ + -I$(builddir)/lib/route \ + -I$(builddir)/lib/route/cls \ + $(NULL) +lib_libnl_route_3_la_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -Wl,--version-script=$(srcdir)/libnl-route-3.sym +lib_libnl_route_3_la_LIBADD = \ + lib/libnl-3.la + +$(lib_libnl_route_3_la_OBJECTS): $(grammar_files_headers) + +lib_LTLIBRARIES += lib/libnl-idiag-3.la + +lib_libnl_idiag_3_la_SOURCES = \ + lib/idiag/idiag.c \ + lib/idiag/idiag_meminfo_obj.c \ + lib/idiag/idiag_msg_obj.c \ + lib/idiag/idiag_req_obj.c \ + lib/idiag/idiag_vegasinfo_obj.c \ + lib/idiag/nl-idiag.h \ + $(NULL) +EXTRA_lib_libnl_idiag_3_la_DEPENDENCIES = \ + libnl-idiag-3.sym +lib_libnl_idiag_3_la_CPPFLAGS = \ + $(lib_cppflags) +lib_libnl_idiag_3_la_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -Wl,--version-script=$(srcdir)/libnl-idiag-3.sym +lib_libnl_idiag_3_la_LIBADD = \ + lib/libnl-3.la + +lib_LTLIBRARIES += lib/libnl-genl-3.la + +lib_libnl_genl_3_la_SOURCES = \ + lib/genl/ctrl.c \ + lib/genl/family.c \ + lib/genl/genl.c \ + lib/genl/mngt.c \ + lib/genl/nl-genl.h \ + $(NULL) +EXTRA_lib_libnl_genl_3_la_DEPENDENCIES = \ + libnl-genl-3.sym +lib_libnl_genl_3_la_CPPFLAGS = \ + $(lib_cppflags) +lib_libnl_genl_3_la_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -Wl,--version-script=$(srcdir)/libnl-genl-3.sym +lib_libnl_genl_3_la_LIBADD = \ + lib/libnl-3.la + +lib_LTLIBRARIES += lib/libnl-nf-3.la + +lib_libnl_nf_3_la_SOURCES = \ + lib/netfilter/ct.c \ + lib/netfilter/ct_obj.c \ + lib/netfilter/exp.c \ + lib/netfilter/exp_obj.c \ + lib/netfilter/log.c \ + lib/netfilter/log_msg.c \ + lib/netfilter/log_msg_obj.c \ + lib/netfilter/log_obj.c \ + lib/netfilter/netfilter.c \ + lib/netfilter/nfnl.c \ + lib/netfilter/nl-netfilter.h \ + lib/netfilter/queue.c \ + lib/netfilter/queue_msg.c \ + lib/netfilter/queue_msg_obj.c \ + lib/netfilter/queue_obj.c \ + $(NULL) +lib_libnl_nf_3_la_CPPFLAGS = \ + $(lib_cppflags) +EXTRA_lib_libnl_nf_3_la_DEPENDENCIES = \ + libnl-nf-3.sym +lib_libnl_nf_3_la_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -Wl,--version-script=$(srcdir)/libnl-nf-3.sym +lib_libnl_nf_3_la_LIBADD = \ + lib/libnl-3.la \ + lib/libnl-route-3.la + +lib_LTLIBRARIES += lib/libnl-xfrm-3.la + +lib_libnl_xfrm_3_la_SOURCES = \ + lib/xfrm/ae.c \ + lib/xfrm/lifetime.c \ + lib/xfrm/nl-xfrm.h \ + lib/xfrm/sa.c \ + lib/xfrm/selector.c \ + lib/xfrm/sp.c \ + lib/xfrm/template.c \ + $(NULL) +lib_libnl_xfrm_3_la_CPPFLAGS = \ + $(lib_cppflags) +lib_libnl_xfrm_3_la_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -Wl,--version-script=$(srcdir)/libnl-xfrm-3.sym +EXTRA_lib_libnl_xfrm_3_la_DEPENDENCIES = \ + libnl-xfrm-3.sym +lib_libnl_xfrm_3_la_LIBADD = \ + lib/libnl-3.la + +lib_cli_ltlibraries_cls = \ + lib/cli/cls/basic.la \ + lib/cli/cls/cgroup.la \ + $(NULL) +lib_cli_ltlibraries_qdisc = \ + lib/cli/qdisc/bfifo.la \ + lib/cli/qdisc/blackhole.la \ + lib/cli/qdisc/fq_codel.la \ + lib/cli/qdisc/hfsc.la \ + lib/cli/qdisc/htb.la \ + lib/cli/qdisc/ingress.la \ + lib/cli/qdisc/pfifo.la \ + lib/cli/qdisc/plug.la \ + $(NULL) + +if ENABLE_CLI +pkglib_clsdir = $(pkglibdir)/cli/cls +pkglib_qdiscdir = $(pkglibdir)/cli/qdisc +pkglib_cls_LTLIBRARIES = $(lib_cli_ltlibraries_cls) +pkglib_qdisc_LTLIBRARIES = $(lib_cli_ltlibraries_qdisc) +else +check_LTLIBRARIES += \ + $(lib_cli_ltlibraries_cls) \ + $(lib_cli_ltlibraries_qdisc) +endif + +lib_cli_ldflags = \ + -module -avoid-version + +lib_cli_cls_basic_la_CPPFLAGS = $(lib_cppflags) +lib_cli_cls_basic_la_LDFLAGS = $(lib_cli_ldflags) +lib_cli_cls_cgroup_la_CPPFLAGS = $(lib_cppflags) +lib_cli_cls_cgroup_la_LDFLAGS = $(lib_cli_ldflags) +lib_cli_qdisc_bfifo_la_CPPFLAGS = $(lib_cppflags) +lib_cli_qdisc_bfifo_la_LDFLAGS = $(lib_cli_ldflags) +lib_cli_qdisc_blackhole_la_CPPFLAGS = $(lib_cppflags) +lib_cli_qdisc_blackhole_la_LDFLAGS = $(lib_cli_ldflags) +lib_cli_qdisc_fq_codel_la_CPPFLAGS = $(lib_cppflags) +lib_cli_qdisc_fq_codel_la_LDFLAGS = $(lib_cli_ldflags) +lib_cli_qdisc_hfsc_la_CPPFLAGS = $(lib_cppflags) +lib_cli_qdisc_hfsc_la_LDFLAGS = $(lib_cli_ldflags) +lib_cli_qdisc_htb_la_CPPFLAGS = $(lib_cppflags) +lib_cli_qdisc_htb_la_LDFLAGS = $(lib_cli_ldflags) +lib_cli_qdisc_ingress_la_CPPFLAGS = $(lib_cppflags) +lib_cli_qdisc_ingress_la_LDFLAGS = $(lib_cli_ldflags) +lib_cli_qdisc_pfifo_la_CPPFLAGS = $(lib_cppflags) +lib_cli_qdisc_pfifo_la_LDFLAGS = $(lib_cli_ldflags) +lib_cli_qdisc_plug_la_CPPFLAGS = $(lib_cppflags) +lib_cli_qdisc_plug_la_LDFLAGS = $(lib_cli_ldflags) + +############################################################################### + +src_lib_ldflags = + +if ENABLE_CLI +lib_LTLIBRARIES += src/lib/libnl-cli-3.la +src_lib_ldflags += -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) +else +check_LTLIBRARIES += src/lib/libnl-cli-3.la +endif + +src_lib_libnl_cli_3_la_SOURCES = \ + src/lib/addr.c \ + src/lib/class.c \ + src/lib/cls.c \ + src/lib/ct.c \ + src/lib/exp.c \ + src/lib/link.c \ + src/lib/neigh.c \ + src/lib/nh.c \ + src/lib/qdisc.c \ + src/lib/route.c \ + src/lib/rule.c \ + src/lib/tc.c \ + src/lib/utils.c \ + $(NULL) +EXTRA_src_lib_libnl_cli_3_la_DEPENDENCIES = \ + libnl-cli-3.sym +src_lib_libnl_cli_3_la_CPPFLAGS = \ + $(warn_cppflags) \ + -D_GNU_SOURCE \ + -DPKGLIBDIR=\"$(pkglibdir)\" \ + -DSYSCONFDIR=\"$(sysconfdir)\" \ + $(default_includes) \ + $(NULL) +src_lib_libnl_cli_3_la_LDFLAGS = \ + $(src_lib_ldflags) \ + -Wl,--version-script=$(srcdir)/libnl-cli-3.sym +src_lib_libnl_cli_3_la_LIBADD = \ + lib/libnl-3.la \ + lib/libnl-route-3.la \ + lib/libnl-nf-3.la \ + lib/libnl-genl-3.la \ + -ldl \ + $(NULL) + +############################################################################### + +src_cppflags = \ + $(warn_cppflags) \ + -D_GNU_SOURCE \ + -DSYSCONFDIR=\"$(sysconfdir)/libnl\" \ + $(default_includes) \ + $(NULL) + +src_ldadd = \ + src/lib/libnl-cli-3.la \ + lib/libnl-3.la \ + lib/libnl-nf-3.la \ + lib/libnl-genl-3.la \ + lib/libnl-route-3.la \ + lib/libnl-idiag-3.la \ + $(NULL) + +cli_programs = \ + src/genl-ctrl-list \ + src/idiag-socket-details \ + src/nf-ct-add \ + src/nf-ct-events \ + src/nf-ct-list \ + src/nf-exp-add \ + src/nf-exp-delete \ + src/nf-exp-list \ + src/nf-log \ + src/nf-monitor \ + src/nf-queue \ + src/nl-addr-add \ + src/nl-addr-delete \ + src/nl-addr-list \ + src/nl-class-add \ + src/nl-class-delete \ + src/nl-class-list \ + src/nl-classid-lookup \ + src/nl-cls-add \ + src/nl-cls-delete \ + src/nl-cls-list \ + src/nl-fib-lookup \ + src/nl-link-enslave \ + src/nl-link-ifindex2name \ + src/nl-link-list \ + src/nl-link-name2ifindex \ + src/nl-link-release \ + src/nl-link-set \ + src/nl-link-stats \ + src/nl-list-caches \ + src/nl-list-sockets \ + src/nl-monitor \ + src/nl-neigh-add \ + src/nl-neigh-delete \ + src/nl-neigh-list \ + src/nl-neightbl-list \ + src/nl-nh-list \ + src/nl-pktloc-lookup \ + src/nl-qdisc-add \ + src/nl-qdisc-delete \ + src/nl-qdisc-list \ + src/nl-route-add \ + src/nl-route-delete \ + src/nl-route-get \ + src/nl-route-list \ + src/nl-rule-list \ + src/nl-tctree-list \ + src/nl-util-addr \ + $(NULL) + +if ENABLE_CLI +if ENABLE_CLI_INSTALL_BIN +bin_PROGRAMS += $(cli_programs) +else +if ENABLE_CLI_INSTALL_SBIN +sbin_PROGRAMS += $(cli_programs) +else +noinst_PROGRAMS += $(cli_programs) +endif +endif +else +check_PROGRAMS += $(cli_programs) +endif + +src_genl_ctrl_list_CPPFLAGS = $(src_cppflags) +src_genl_ctrl_list_LDADD = $(src_ldadd) +src_idiag_socket_details_CPPFLAGS = $(src_cppflags) +src_idiag_socket_details_LDADD = $(src_ldadd) +src_nf_ct_add_CPPFLAGS = $(src_cppflags) +src_nf_ct_add_LDADD = $(src_ldadd) +src_nf_ct_events_CPPFLAGS = $(src_cppflags) +src_nf_ct_events_LDADD = $(src_ldadd) +src_nf_ct_list_CPPFLAGS = $(src_cppflags) +src_nf_ct_list_LDADD = $(src_ldadd) +src_nf_exp_add_CPPFLAGS = $(src_cppflags) +src_nf_exp_add_LDADD = $(src_ldadd) +src_nf_exp_delete_CPPFLAGS = $(src_cppflags) +src_nf_exp_delete_LDADD = $(src_ldadd) +src_nf_exp_list_CPPFLAGS = $(src_cppflags) +src_nf_exp_list_LDADD = $(src_ldadd) +src_nf_log_CPPFLAGS = $(src_cppflags) +src_nf_log_LDADD = $(src_ldadd) +src_nf_monitor_CPPFLAGS = $(src_cppflags) +src_nf_monitor_LDADD = $(src_ldadd) +src_nf_queue_CPPFLAGS = $(src_cppflags) +src_nf_queue_LDADD = $(src_ldadd) +src_nl_addr_add_CPPFLAGS = $(src_cppflags) +src_nl_addr_add_LDADD = $(src_ldadd) +src_nl_addr_delete_CPPFLAGS = $(src_cppflags) +src_nl_addr_delete_LDADD = $(src_ldadd) +src_nl_addr_list_CPPFLAGS = $(src_cppflags) +src_nl_addr_list_LDADD = $(src_ldadd) +src_nl_class_add_CPPFLAGS = $(src_cppflags) +src_nl_class_add_LDADD = $(src_ldadd) +src_nl_class_delete_CPPFLAGS = $(src_cppflags) +src_nl_class_delete_LDADD = $(src_ldadd) +src_nl_class_list_CPPFLAGS = $(src_cppflags) +src_nl_class_list_LDADD = $(src_ldadd) +src_nl_classid_lookup_CPPFLAGS = $(src_cppflags) +src_nl_classid_lookup_LDADD = $(src_ldadd) +src_nl_cls_add_CPPFLAGS = $(src_cppflags) +src_nl_cls_add_LDADD = $(src_ldadd) +src_nl_cls_delete_CPPFLAGS = $(src_cppflags) +src_nl_cls_delete_LDADD = $(src_ldadd) +src_nl_cls_list_CPPFLAGS = $(src_cppflags) +src_nl_cls_list_LDADD = $(src_ldadd) +src_nl_fib_lookup_CPPFLAGS = $(src_cppflags) +src_nl_fib_lookup_LDADD = $(src_ldadd) +src_nl_link_enslave_CPPFLAGS = $(src_cppflags) +src_nl_link_enslave_LDADD = $(src_ldadd) +src_nl_link_ifindex2name_CPPFLAGS = $(src_cppflags) +src_nl_link_ifindex2name_LDADD = $(src_ldadd) +src_nl_link_list_CPPFLAGS = $(src_cppflags) +src_nl_link_list_LDADD = $(src_ldadd) +src_nl_link_name2ifindex_CPPFLAGS = $(src_cppflags) +src_nl_link_name2ifindex_LDADD = $(src_ldadd) +src_nl_link_release_CPPFLAGS = $(src_cppflags) +src_nl_link_release_LDADD = $(src_ldadd) +src_nl_link_set_CPPFLAGS = $(src_cppflags) +src_nl_link_set_LDADD = $(src_ldadd) +src_nl_link_stats_CPPFLAGS = $(src_cppflags) +src_nl_link_stats_LDADD = $(src_ldadd) +src_nl_list_caches_CPPFLAGS = $(src_cppflags) +src_nl_list_caches_LDADD = $(src_ldadd) +src_nl_list_sockets_CPPFLAGS = $(src_cppflags) +src_nl_list_sockets_LDADD = $(src_ldadd) +src_nl_monitor_CPPFLAGS = $(src_cppflags) +src_nl_monitor_LDADD = $(src_ldadd) +src_nl_neigh_add_CPPFLAGS = $(src_cppflags) +src_nl_neigh_add_LDADD = $(src_ldadd) +src_nl_neigh_delete_CPPFLAGS = $(src_cppflags) +src_nl_neigh_delete_LDADD = $(src_ldadd) +src_nl_neigh_list_CPPFLAGS = $(src_cppflags) +src_nl_neigh_list_LDADD = $(src_ldadd) +src_nl_neightbl_list_CPPFLAGS = $(src_cppflags) +src_nl_neightbl_list_LDADD = $(src_ldadd) +src_nl_nh_list_CPPFLAGS = $(src_cppflags) +src_nl_nh_list_LDADD = $(src_ldadd) +src_nl_pktloc_lookup_CPPFLAGS = $(src_cppflags) +src_nl_pktloc_lookup_LDADD = $(src_ldadd) +src_nl_qdisc_add_CPPFLAGS = $(src_cppflags) +src_nl_qdisc_add_LDADD = $(src_ldadd) +src_nl_qdisc_delete_CPPFLAGS = $(src_cppflags) +src_nl_qdisc_delete_LDADD = $(src_ldadd) +src_nl_qdisc_list_CPPFLAGS = $(src_cppflags) +src_nl_qdisc_list_LDADD = $(src_ldadd) +src_nl_route_add_CPPFLAGS = $(src_cppflags) +src_nl_route_add_LDADD = $(src_ldadd) +src_nl_route_delete_CPPFLAGS = $(src_cppflags) +src_nl_route_delete_LDADD = $(src_ldadd) +src_nl_route_get_CPPFLAGS = $(src_cppflags) +src_nl_route_get_LDADD = $(src_ldadd) +src_nl_route_list_CPPFLAGS = $(src_cppflags) +src_nl_route_list_LDADD = $(src_ldadd) +src_nl_rule_list_CPPFLAGS = $(src_cppflags) +src_nl_rule_list_LDADD = $(src_ldadd) +src_nl_tctree_list_CPPFLAGS = $(src_cppflags) +src_nl_tctree_list_LDADD = $(src_ldadd) +src_nl_util_addr_CPPFLAGS = $(src_cppflags) +src_nl_util_addr_LDADD = $(src_ldadd) + +############################################################################### + +tests_cppflags = \ + $(warn_cppflags) \ + -D_GNU_SOURCE \ + -DSYSCONFDIR=\"$(sysconfdir)/libnl\" \ + $(default_includes) \ + $(NULL) + +tests_ldadd = \ + lib/libnl-3.la \ + lib/libnl-nf-3.la \ + lib/libnl-genl-3.la \ + lib/libnl-route-3.la \ + $(NULL) + +if WITH_CHECK +check_LTLIBRARIES += tests/libnl-test-util.la +endif + +tests_libnl_test_util_la_SOURCES = \ + tests/nl-test-util.h \ + tests/nl-test-util.c \ + $(NULL) +tests_libnl_test_util_la_CPPFLAGS = \ + $(tests_cppflags) \ + $(CHECK_CFLAGS) \ + $(NULL) +tests_libnl_test_util_la_LIBADD = \ + $(tests_ldadd) \ + $(CHECK_LIBS) \ + $(NULL) + +check_PROGRAMS += \ + tests/test-complex-HTB-with-hash-filters \ + tests/test-create-bond \ + tests/test-create-bridge \ + tests/test-create-geneve \ + tests/test-create-ifb \ + tests/test-create-ip6tnl \ + tests/test-create-ipgre \ + tests/test-create-ipgretap \ + tests/test-create-ipip \ + tests/test-create-ipvlan \ + tests/test-create-ipvti \ + tests/test-create-macsec \ + tests/test-create-macvlan \ + tests/test-create-macvtap \ + tests/test-create-sit \ + tests/test-create-veth \ + tests/test-create-vlan \ + tests/test-create-vrf \ + tests/test-create-vxlan \ + tests/test-create-xfrmi \ + tests/test-delete-link \ + tests/test-loopback-up-down \ + tests/test-socket-creation \ + tests/test-u32-filter-with-actions \ + $(NULL) + +tests_test_complex_HTB_with_hash_filters_CPPFLAGS = $(tests_cppflags) +tests_test_complex_HTB_with_hash_filters_LDADD = $(tests_ldadd) +tests_test_create_bond_CPPFLAGS = $(tests_cppflags) +tests_test_create_bond_LDADD = $(tests_ldadd) +tests_test_create_bridge_CPPFLAGS = $(tests_cppflags) +tests_test_create_bridge_LDADD = $(tests_ldadd) +tests_test_create_geneve_CPPFLAGS = $(tests_cppflags) +tests_test_create_geneve_LDADD = $(tests_ldadd) +tests_test_create_ifb_CPPFLAGS = $(tests_cppflags) +tests_test_create_ifb_LDADD = $(tests_ldadd) +tests_test_create_ip6tnl_CPPFLAGS = $(tests_cppflags) +tests_test_create_ip6tnl_LDADD = $(tests_ldadd) +tests_test_create_ipgre_CPPFLAGS = $(tests_cppflags) +tests_test_create_ipgre_LDADD = $(tests_ldadd) +tests_test_create_ipgretap_CPPFLAGS = $(tests_cppflags) +tests_test_create_ipgretap_LDADD = $(tests_ldadd) +tests_test_create_ipip_CPPFLAGS = $(tests_cppflags) +tests_test_create_ipip_LDADD = $(tests_ldadd) +tests_test_create_ipvlan_CPPFLAGS = $(tests_cppflags) +tests_test_create_ipvlan_LDADD = $(tests_ldadd) +tests_test_create_ipvti_CPPFLAGS = $(tests_cppflags) +tests_test_create_ipvti_LDADD = $(tests_ldadd) +tests_test_create_macsec_CPPFLAGS = $(tests_cppflags) +tests_test_create_macsec_LDADD = $(tests_ldadd) +tests_test_create_macvlan_CPPFLAGS = $(tests_cppflags) +tests_test_create_macvlan_LDADD = $(tests_ldadd) +tests_test_create_macvtap_CPPFLAGS = $(tests_cppflags) +tests_test_create_macvtap_LDADD = $(tests_ldadd) +tests_test_create_sit_CPPFLAGS = $(tests_cppflags) +tests_test_create_sit_LDADD = $(tests_ldadd) +tests_test_create_veth_CPPFLAGS = $(tests_cppflags) +tests_test_create_veth_LDADD = $(tests_ldadd) +tests_test_create_vlan_CPPFLAGS = $(tests_cppflags) +tests_test_create_vlan_LDADD = $(tests_ldadd) +tests_test_create_vrf_CPPFLAGS = $(tests_cppflags) +tests_test_create_vrf_LDADD = $(tests_ldadd) +tests_test_create_vxlan_CPPFLAGS = $(tests_cppflags) +tests_test_create_vxlan_LDADD = $(tests_ldadd) +tests_test_create_xfrmi_CPPFLAGS = $(tests_cppflags) +tests_test_create_xfrmi_LDADD = $(tests_ldadd) +tests_test_delete_link_CPPFLAGS = $(tests_cppflags) +tests_test_delete_link_LDADD = $(tests_ldadd) +tests_test_loopback_up_down_CPPFLAGS = $(tests_cppflags) +tests_test_loopback_up_down_LDADD = $(tests_ldadd) +tests_test_socket_creation_CPPFLAGS = $(tests_cppflags) +tests_test_socket_creation_LDADD = $(tests_ldadd) +tests_test_u32_filter_with_actions_CPPFLAGS = $(tests_cppflags) +tests_test_u32_filter_with_actions_LDADD = $(tests_ldadd) + +check_PROGRAMS += \ + tests/test-cache-mngr \ + tests/test-genl \ + tests/test-nf-cache-mngr \ + $(NULL) + +tests_cli_ldadd = \ + $(tests_ldadd) \ + src/lib/libnl-cli-3.la \ + $(NULL) + +tests_test_cache_mngr_CPPFLAGS = $(tests_cppflags) +tests_test_cache_mngr_LDADD = $(tests_cli_ldadd) +tests_test_genl_CPPFLAGS = $(tests_cppflags) +tests_test_genl_LDADD = $(tests_cli_ldadd) +tests_test_nf_cache_mngr_CPPFLAGS = $(tests_cppflags) +tests_test_nf_cache_mngr_LDADD = $(tests_cli_ldadd) + + +if WITH_CHECK +check_programs += tests/check-all +endif + +tests_check_all_SOURCES = \ + tests/check-all.c \ + tests/cksuite-all-addr.c \ + tests/cksuite-all-attr.c \ + tests/cksuite-all-ematch-tree-clone.c \ + tests/cksuite-all-netns.c \ + tests/cksuite-all.h \ + $(NULL) + +tests_check_all_CPPFLAGS = \ + $(tests_cppflags) \ + $(CHECK_CFLAGS) + +tests_check_all_LDADD = \ + $(tests_ldadd) \ + tests/libnl-test-util.la \ + $(CHECK_LIBS) \ + $(NULL) + +if WITH_CHECK +if ENABLE_STATIC +check_programs += tests/check-direct +endif +endif + +tests_check_direct_SOURCES = \ + tests/check-direct.c \ + $(NULL) + +tests_check_direct_CPPFLAGS = \ + $(tests_cppflags) \ + $(CHECK_CFLAGS) \ + $(NULL) + +tests_check_direct_LDFLAGS = \ + -static \ + $(NULL) + +tests_check_direct_LDADD = \ + $(tests_ldadd) \ + tests/libnl-test-util.la \ + $(CHECK_LIBS) \ + $(NULL) + +############################################################################### + +dist_man8_MANS = \ + man/genl-ctrl-list.8 \ + man/nl-classid-lookup.8 \ + man/nl-pktloc-lookup.8 \ + man/nl-qdisc-add.8 \ + man/nl-qdisc-delete.8 \ + man/nl-qdisc-list.8 \ + $(NULL) + +############################################################################### + +python-build: + cd "$(srcdir)/python"; \ + python setup.py build + +.PHONY: python-build + +EXTRA_DIST += \ + python/README \ + \ + python/doc/conf.py \ + python/doc/core.rst \ + python/doc/index.rst \ + python/doc/route_addr.rst \ + python/doc/route.rst \ + \ + python/examples/iface.py \ + python/examples/nl80211.py \ + python/examples/wiphy.py \ + \ + python/netlink/capi.i \ + python/netlink/__init__.py \ + python/netlink/core.py \ + python/netlink/util.py \ + python/netlink/utils.h \ + \ + python/netlink/genl/capi.i \ + python/netlink/genl/__init__.py \ + \ + python/netlink/route/capi.i \ + python/netlink/route/__init__.py \ + python/netlink/route/address.py \ + python/netlink/route/link.py \ + python/netlink/route/tc.py \ + python/netlink/route/links/__init__.py \ + python/netlink/route/links/dummy.py \ + python/netlink/route/links/inet.py \ + python/netlink/route/links/vlan.py \ + python/netlink/route/qdisc/__init__.py \ + python/netlink/route/qdisc/htb.py \ + \ + python/tests/test-create-bridge.py + +############################################################################### + +%.build-headers-test.c: % + mkdir -p "$(dir $@)" + printf "#include <$$(echo "$<" | sed 's|.*\\nint main(int argc, char **argv) { return 0; }" > $@ + +%.build-headers-test.o: %.build-headers-test.c + $(COMPILE) -Wall -Werror -Wno-error=cpp -I$(srcdir)/include -I$(builddir)/include -c -o $@ $< + +BUILD_HEADERS_OBJS = $(patsubst %,%.build-headers-test.o,$(public_headers)) + +# Test whether the public headers are all self-contained and can be build. +# This test is not hooked up as `make check`. +check-local-build-headers: $(BUILD_HEADERS_OBJS) + +CLEANFILES += $(BUILD_HEADERS_OBJS) + +check_local += check-local-build-headers + +############################################################################### + +check-local: $(check_local) + +.PHONY: $(check_local) + +check_PROGRAMS += $(check_programs) +TESTS += $(check_programs) if ENABLE_CLI -SUBDIRS += src pkgconfig_DATA += libnl-cli-3.0.pc endif +pkgsysconfdir = $(sysconfdir)/libnl +pkgsysconf_DATA = \ + etc/pktloc \ + etc/classid + +EXTRA_DIST += \ + $(pkgsysconf_DATA) \ + libnl-3.sym \ + libnl-cli-3.sym \ + libnl-genl-3.sym \ + libnl-idiag-3.sym \ + libnl-nf-3.sym \ + libnl-route-3.sym \ + libnl-xfrm-3.sym \ + $(NULL) + +############################################################################### + +check-progs: all $(check_PROGRAMS) $(check_LTLIBRARIES) -pkgsysconfdir = ${sysconfdir}/libnl -pkgsysconf_DATA = etc/pktloc etc/classid +.PHONY: check-progs -EXTRA_DIST = \ - $(pkgsysconf_DATA) +############################################################################### diff --git a/Makefile.in b/Makefile.in index 03c8d14..3ee9634 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,9 +1,8 @@ -# Makefile.in generated by automake 1.11.6 from Makefile.am. +# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -17,24 +16,65 @@ # -*- Makefile -*- + + + VPATH = @srcdir@ -am__make_dryrun = \ - { \ - am__dry=no; \ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ - test $$am__dry = yes; \ - } + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -53,18 +93,49 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -@ENABLE_CLI_TRUE@am__append_1 = src -@ENABLE_CLI_TRUE@am__append_2 = libnl-cli-3.0.pc +check_PROGRAMS = $(am__EXEEXT_3) \ + tests/test-complex-HTB-with-hash-filters$(EXEEXT) \ + tests/test-create-bond$(EXEEXT) \ + tests/test-create-bridge$(EXEEXT) \ + tests/test-create-geneve$(EXEEXT) \ + tests/test-create-ifb$(EXEEXT) \ + tests/test-create-ip6tnl$(EXEEXT) \ + tests/test-create-ipgre$(EXEEXT) \ + tests/test-create-ipgretap$(EXEEXT) \ + tests/test-create-ipip$(EXEEXT) \ + tests/test-create-ipvlan$(EXEEXT) \ + tests/test-create-ipvti$(EXEEXT) \ + tests/test-create-macsec$(EXEEXT) \ + tests/test-create-macvlan$(EXEEXT) \ + tests/test-create-macvtap$(EXEEXT) \ + tests/test-create-sit$(EXEEXT) tests/test-create-veth$(EXEEXT) \ + tests/test-create-vlan$(EXEEXT) tests/test-create-vrf$(EXEEXT) \ + tests/test-create-vxlan$(EXEEXT) \ + tests/test-create-xfrmi$(EXEEXT) \ + tests/test-delete-link$(EXEEXT) \ + tests/test-loopback-up-down$(EXEEXT) \ + tests/test-socket-creation$(EXEEXT) \ + tests/test-u32-filter-with-actions$(EXEEXT) \ + tests/test-cache-mngr$(EXEEXT) tests/test-genl$(EXEEXT) \ + tests/test-nf-cache-mngr$(EXEEXT) $(am__EXEEXT_6) +bin_PROGRAMS = $(am__EXEEXT_2) +sbin_PROGRAMS = $(am__EXEEXT_8) +noinst_PROGRAMS = $(am__EXEEXT_7) +TESTS = $(am__EXEEXT_6) +@ENABLE_CLI_FALSE@am__append_1 = $(lib_cli_ltlibraries_cls) \ +@ENABLE_CLI_FALSE@ $(lib_cli_ltlibraries_qdisc) \ +@ENABLE_CLI_FALSE@ src/lib/libnl-cli-3.la +@ENABLE_CLI_TRUE@am__append_2 = src/lib/libnl-cli-3.la +@ENABLE_CLI_TRUE@am__append_3 = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) +@ENABLE_CLI_INSTALL_BIN_TRUE@@ENABLE_CLI_TRUE@am__append_4 = $(cli_programs) +@ENABLE_CLI_INSTALL_BIN_FALSE@@ENABLE_CLI_INSTALL_SBIN_TRUE@@ENABLE_CLI_TRUE@am__append_5 = $(cli_programs) +@ENABLE_CLI_INSTALL_BIN_FALSE@@ENABLE_CLI_INSTALL_SBIN_FALSE@@ENABLE_CLI_TRUE@am__append_6 = $(cli_programs) +@ENABLE_CLI_FALSE@am__append_7 = $(cli_programs) +@WITH_CHECK_TRUE@am__append_8 = tests/libnl-test-util.la +@WITH_CHECK_TRUE@am__append_9 = tests/check-all +@ENABLE_STATIC_TRUE@@WITH_CHECK_TRUE@am__append_10 = tests/check-direct +@ENABLE_CLI_TRUE@am__append_11 = libnl-cli-3.0.pc subdir = . -DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in $(srcdir)/libnl-3.0.pc.in \ - $(srcdir)/libnl-cli-3.0.pc.in $(srcdir)/libnl-genl-3.0.pc.in \ - $(srcdir)/libnl-nf-3.0.pc.in $(srcdir)/libnl-route-3.0.pc.in \ - $(top_srcdir)/configure \ - $(top_srcdir)/include/netlink/version.h.in COPYING ChangeLog \ - build-aux/ar-lib build-aux/compile build-aux/config.guess \ - build-aux/config.sub build-aux/depcomp build-aux/install-sh \ - build-aux/ltmain.sh build-aux/missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ @@ -72,33 +143,80 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(libnlinclude_netlink_HEADERS) \ + $(am__libnlinclude_netlink_cli_HEADERS_DIST) \ + $(libnlinclude_netlink_fib_lookup_HEADERS) \ + $(libnlinclude_netlink_genl_HEADERS) \ + $(libnlinclude_netlink_idiag_HEADERS) \ + $(libnlinclude_netlink_netfilter_HEADERS) \ + $(libnlinclude_netlink_route_HEADERS) \ + $(libnlinclude_netlink_route_act_HEADERS) \ + $(libnlinclude_netlink_route_cls_HEADERS) \ + $(libnlinclude_netlink_route_cls_ematch_HEADERS) \ + $(libnlinclude_netlink_route_link_HEADERS) \ + $(libnlinclude_netlink_route_qdisc_HEADERS) \ + $(libnlinclude_netlink_xfrm_HEADERS) $(noinst_HEADERS) \ + $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/lib/defs.h +CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = libnl-3.0.pc libnl-route-3.0.pc libnl-genl-3.0.pc \ - libnl-nf-3.0.pc libnl-cli-3.0.pc include/netlink/version.h + libnl-nf-3.0.pc libnl-cli-3.0.pc libnl-xfrm-3.0.pc \ + libnl-idiag-3.0.pc python/setup.py include/netlink/version.h CONFIG_CLEAN_VPATH_FILES = -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -SOURCES = -DIST_SOURCES = -RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ - html-recursive info-recursive install-data-recursive \ - install-dvi-recursive install-exec-recursive \ - install-html-recursive install-info-recursive \ - install-pdf-recursive install-ps-recursive install-recursive \ - installcheck-recursive installdirs-recursive pdf-recursive \ - ps-recursive uninstall-recursive -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac +am__EXEEXT_1 = src/genl-ctrl-list$(EXEEXT) \ + src/idiag-socket-details$(EXEEXT) src/nf-ct-add$(EXEEXT) \ + src/nf-ct-events$(EXEEXT) src/nf-ct-list$(EXEEXT) \ + src/nf-exp-add$(EXEEXT) src/nf-exp-delete$(EXEEXT) \ + src/nf-exp-list$(EXEEXT) src/nf-log$(EXEEXT) \ + src/nf-monitor$(EXEEXT) src/nf-queue$(EXEEXT) \ + src/nl-addr-add$(EXEEXT) src/nl-addr-delete$(EXEEXT) \ + src/nl-addr-list$(EXEEXT) src/nl-class-add$(EXEEXT) \ + src/nl-class-delete$(EXEEXT) src/nl-class-list$(EXEEXT) \ + src/nl-classid-lookup$(EXEEXT) src/nl-cls-add$(EXEEXT) \ + src/nl-cls-delete$(EXEEXT) src/nl-cls-list$(EXEEXT) \ + src/nl-fib-lookup$(EXEEXT) src/nl-link-enslave$(EXEEXT) \ + src/nl-link-ifindex2name$(EXEEXT) src/nl-link-list$(EXEEXT) \ + src/nl-link-name2ifindex$(EXEEXT) src/nl-link-release$(EXEEXT) \ + src/nl-link-set$(EXEEXT) src/nl-link-stats$(EXEEXT) \ + src/nl-list-caches$(EXEEXT) src/nl-list-sockets$(EXEEXT) \ + src/nl-monitor$(EXEEXT) src/nl-neigh-add$(EXEEXT) \ + src/nl-neigh-delete$(EXEEXT) src/nl-neigh-list$(EXEEXT) \ + src/nl-neightbl-list$(EXEEXT) src/nl-nh-list$(EXEEXT) \ + src/nl-pktloc-lookup$(EXEEXT) src/nl-qdisc-add$(EXEEXT) \ + src/nl-qdisc-delete$(EXEEXT) src/nl-qdisc-list$(EXEEXT) \ + src/nl-route-add$(EXEEXT) src/nl-route-delete$(EXEEXT) \ + src/nl-route-get$(EXEEXT) src/nl-route-list$(EXEEXT) \ + src/nl-rule-list$(EXEEXT) src/nl-tctree-list$(EXEEXT) \ + src/nl-util-addr$(EXEEXT) +@ENABLE_CLI_INSTALL_BIN_TRUE@@ENABLE_CLI_TRUE@am__EXEEXT_2 = \ +@ENABLE_CLI_INSTALL_BIN_TRUE@@ENABLE_CLI_TRUE@ $(am__EXEEXT_1) +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" \ + "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkglib_clsdir)" \ + "$(DESTDIR)$(pkglib_qdiscdir)" "$(DESTDIR)$(man8dir)" \ + "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(pkgsysconfdir)" \ + "$(DESTDIR)$(libnlinclude_netlinkdir)" \ + "$(DESTDIR)$(libnlinclude_netlink_clidir)" \ + "$(DESTDIR)$(libnlinclude_netlink_fib_lookupdir)" \ + "$(DESTDIR)$(libnlinclude_netlink_genldir)" \ + "$(DESTDIR)$(libnlinclude_netlink_idiagdir)" \ + "$(DESTDIR)$(libnlinclude_netlink_netfilterdir)" \ + "$(DESTDIR)$(libnlinclude_netlink_routedir)" \ + "$(DESTDIR)$(libnlinclude_netlink_route_actdir)" \ + "$(DESTDIR)$(libnlinclude_netlink_route_clsdir)" \ + "$(DESTDIR)$(libnlinclude_netlink_route_cls_ematchdir)" \ + "$(DESTDIR)$(libnlinclude_netlink_route_linkdir)" \ + "$(DESTDIR)$(libnlinclude_netlink_route_qdiscdir)" \ + "$(DESTDIR)$(libnlinclude_netlink_xfrmdir)" +@ENABLE_CLI_FALSE@am__EXEEXT_3 = $(am__EXEEXT_1) +@WITH_CHECK_TRUE@am__EXEEXT_4 = tests/check-all$(EXEEXT) +@ENABLE_STATIC_TRUE@@WITH_CHECK_TRUE@am__EXEEXT_5 = tests/check-direct$(EXEEXT) +am__EXEEXT_6 = $(am__EXEEXT_4) $(am__EXEEXT_5) +@ENABLE_CLI_INSTALL_BIN_FALSE@@ENABLE_CLI_INSTALL_SBIN_FALSE@@ENABLE_CLI_TRUE@am__EXEEXT_7 = $(am__EXEEXT_1) +@ENABLE_CLI_INSTALL_BIN_FALSE@@ENABLE_CLI_INSTALL_SBIN_TRUE@@ENABLE_CLI_TRUE@am__EXEEXT_8 = $(am__EXEEXT_1) +PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) $(sbin_PROGRAMS) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -126,17 +244,1203 @@ am__uninstall_files_from_dir = { \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } -am__installdirs = "$(DESTDIR)$(pkgconfigdir)" \ - "$(DESTDIR)$(pkgsysconfdir)" +LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) \ + $(pkglib_cls_LTLIBRARIES) $(pkglib_qdisc_LTLIBRARIES) +lib_cli_cls_basic_la_LIBADD = +lib_cli_cls_basic_la_SOURCES = lib/cli/cls/basic.c +am__dirstamp = $(am__leading_dot)dirstamp +lib_cli_cls_basic_la_OBJECTS = lib/cli/cls/basic_la-basic.lo +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +lib_cli_cls_basic_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib_cli_cls_basic_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@ENABLE_CLI_FALSE@am_lib_cli_cls_basic_la_rpath = +@ENABLE_CLI_TRUE@am_lib_cli_cls_basic_la_rpath = -rpath \ +@ENABLE_CLI_TRUE@ $(pkglib_clsdir) +lib_cli_cls_cgroup_la_LIBADD = +lib_cli_cls_cgroup_la_SOURCES = lib/cli/cls/cgroup.c +lib_cli_cls_cgroup_la_OBJECTS = lib/cli/cls/cgroup_la-cgroup.lo +lib_cli_cls_cgroup_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib_cli_cls_cgroup_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@ENABLE_CLI_FALSE@am_lib_cli_cls_cgroup_la_rpath = +@ENABLE_CLI_TRUE@am_lib_cli_cls_cgroup_la_rpath = -rpath \ +@ENABLE_CLI_TRUE@ $(pkglib_clsdir) +lib_cli_qdisc_bfifo_la_LIBADD = +lib_cli_qdisc_bfifo_la_SOURCES = lib/cli/qdisc/bfifo.c +lib_cli_qdisc_bfifo_la_OBJECTS = lib/cli/qdisc/bfifo_la-bfifo.lo +lib_cli_qdisc_bfifo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib_cli_qdisc_bfifo_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@ENABLE_CLI_FALSE@am_lib_cli_qdisc_bfifo_la_rpath = +@ENABLE_CLI_TRUE@am_lib_cli_qdisc_bfifo_la_rpath = -rpath \ +@ENABLE_CLI_TRUE@ $(pkglib_qdiscdir) +lib_cli_qdisc_blackhole_la_LIBADD = +lib_cli_qdisc_blackhole_la_SOURCES = lib/cli/qdisc/blackhole.c +lib_cli_qdisc_blackhole_la_OBJECTS = \ + lib/cli/qdisc/blackhole_la-blackhole.lo +lib_cli_qdisc_blackhole_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib_cli_qdisc_blackhole_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@ENABLE_CLI_FALSE@am_lib_cli_qdisc_blackhole_la_rpath = +@ENABLE_CLI_TRUE@am_lib_cli_qdisc_blackhole_la_rpath = -rpath \ +@ENABLE_CLI_TRUE@ $(pkglib_qdiscdir) +lib_cli_qdisc_fq_codel_la_LIBADD = +lib_cli_qdisc_fq_codel_la_SOURCES = lib/cli/qdisc/fq_codel.c +lib_cli_qdisc_fq_codel_la_OBJECTS = \ + lib/cli/qdisc/fq_codel_la-fq_codel.lo +lib_cli_qdisc_fq_codel_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib_cli_qdisc_fq_codel_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@ENABLE_CLI_FALSE@am_lib_cli_qdisc_fq_codel_la_rpath = +@ENABLE_CLI_TRUE@am_lib_cli_qdisc_fq_codel_la_rpath = -rpath \ +@ENABLE_CLI_TRUE@ $(pkglib_qdiscdir) +lib_cli_qdisc_hfsc_la_LIBADD = +lib_cli_qdisc_hfsc_la_SOURCES = lib/cli/qdisc/hfsc.c +lib_cli_qdisc_hfsc_la_OBJECTS = lib/cli/qdisc/hfsc_la-hfsc.lo +lib_cli_qdisc_hfsc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib_cli_qdisc_hfsc_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@ENABLE_CLI_FALSE@am_lib_cli_qdisc_hfsc_la_rpath = +@ENABLE_CLI_TRUE@am_lib_cli_qdisc_hfsc_la_rpath = -rpath \ +@ENABLE_CLI_TRUE@ $(pkglib_qdiscdir) +lib_cli_qdisc_htb_la_LIBADD = +lib_cli_qdisc_htb_la_SOURCES = lib/cli/qdisc/htb.c +lib_cli_qdisc_htb_la_OBJECTS = lib/cli/qdisc/htb_la-htb.lo +lib_cli_qdisc_htb_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib_cli_qdisc_htb_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@ENABLE_CLI_FALSE@am_lib_cli_qdisc_htb_la_rpath = +@ENABLE_CLI_TRUE@am_lib_cli_qdisc_htb_la_rpath = -rpath \ +@ENABLE_CLI_TRUE@ $(pkglib_qdiscdir) +lib_cli_qdisc_ingress_la_LIBADD = +lib_cli_qdisc_ingress_la_SOURCES = lib/cli/qdisc/ingress.c +lib_cli_qdisc_ingress_la_OBJECTS = \ + lib/cli/qdisc/ingress_la-ingress.lo +lib_cli_qdisc_ingress_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib_cli_qdisc_ingress_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@ENABLE_CLI_FALSE@am_lib_cli_qdisc_ingress_la_rpath = +@ENABLE_CLI_TRUE@am_lib_cli_qdisc_ingress_la_rpath = -rpath \ +@ENABLE_CLI_TRUE@ $(pkglib_qdiscdir) +lib_cli_qdisc_pfifo_la_LIBADD = +lib_cli_qdisc_pfifo_la_SOURCES = lib/cli/qdisc/pfifo.c +lib_cli_qdisc_pfifo_la_OBJECTS = lib/cli/qdisc/pfifo_la-pfifo.lo +lib_cli_qdisc_pfifo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib_cli_qdisc_pfifo_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@ENABLE_CLI_FALSE@am_lib_cli_qdisc_pfifo_la_rpath = +@ENABLE_CLI_TRUE@am_lib_cli_qdisc_pfifo_la_rpath = -rpath \ +@ENABLE_CLI_TRUE@ $(pkglib_qdiscdir) +lib_cli_qdisc_plug_la_LIBADD = +lib_cli_qdisc_plug_la_SOURCES = lib/cli/qdisc/plug.c +lib_cli_qdisc_plug_la_OBJECTS = lib/cli/qdisc/plug_la-plug.lo +lib_cli_qdisc_plug_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib_cli_qdisc_plug_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@ENABLE_CLI_FALSE@am_lib_cli_qdisc_plug_la_rpath = +@ENABLE_CLI_TRUE@am_lib_cli_qdisc_plug_la_rpath = -rpath \ +@ENABLE_CLI_TRUE@ $(pkglib_qdiscdir) +lib_libnl_3_la_LIBADD = +am_lib_libnl_3_la_OBJECTS = lib/libnl_3_la-addr.lo \ + lib/libnl_3_la-attr.lo lib/libnl_3_la-cache.lo \ + lib/libnl_3_la-cache_mngr.lo lib/libnl_3_la-cache_mngt.lo \ + lib/libnl_3_la-data.lo lib/libnl_3_la-error.lo \ + lib/libnl_3_la-handlers.lo lib/libnl_3_la-hash.lo \ + lib/libnl_3_la-hashtable.lo lib/libnl_3_la-mpls.lo \ + lib/libnl_3_la-msg.lo lib/libnl_3_la-nl.lo \ + lib/libnl_3_la-object.lo lib/libnl_3_la-socket.lo \ + lib/libnl_3_la-utils.lo lib/libnl_3_la-version.lo +lib_libnl_3_la_OBJECTS = $(am_lib_libnl_3_la_OBJECTS) +lib_libnl_3_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib_libnl_3_la_LDFLAGS) $(LDFLAGS) -o \ + $@ +lib_libnl_genl_3_la_DEPENDENCIES = lib/libnl-3.la +am_lib_libnl_genl_3_la_OBJECTS = lib/genl/libnl_genl_3_la-ctrl.lo \ + lib/genl/libnl_genl_3_la-family.lo \ + lib/genl/libnl_genl_3_la-genl.lo \ + lib/genl/libnl_genl_3_la-mngt.lo +lib_libnl_genl_3_la_OBJECTS = $(am_lib_libnl_genl_3_la_OBJECTS) +lib_libnl_genl_3_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib_libnl_genl_3_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +lib_libnl_idiag_3_la_DEPENDENCIES = lib/libnl-3.la +am_lib_libnl_idiag_3_la_OBJECTS = lib/idiag/libnl_idiag_3_la-idiag.lo \ + lib/idiag/libnl_idiag_3_la-idiag_meminfo_obj.lo \ + lib/idiag/libnl_idiag_3_la-idiag_msg_obj.lo \ + lib/idiag/libnl_idiag_3_la-idiag_req_obj.lo \ + lib/idiag/libnl_idiag_3_la-idiag_vegasinfo_obj.lo +lib_libnl_idiag_3_la_OBJECTS = $(am_lib_libnl_idiag_3_la_OBJECTS) +lib_libnl_idiag_3_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib_libnl_idiag_3_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +lib_libnl_nf_3_la_DEPENDENCIES = lib/libnl-3.la lib/libnl-route-3.la +am_lib_libnl_nf_3_la_OBJECTS = lib/netfilter/libnl_nf_3_la-ct.lo \ + lib/netfilter/libnl_nf_3_la-ct_obj.lo \ + lib/netfilter/libnl_nf_3_la-exp.lo \ + lib/netfilter/libnl_nf_3_la-exp_obj.lo \ + lib/netfilter/libnl_nf_3_la-log.lo \ + lib/netfilter/libnl_nf_3_la-log_msg.lo \ + lib/netfilter/libnl_nf_3_la-log_msg_obj.lo \ + lib/netfilter/libnl_nf_3_la-log_obj.lo \ + lib/netfilter/libnl_nf_3_la-netfilter.lo \ + lib/netfilter/libnl_nf_3_la-nfnl.lo \ + lib/netfilter/libnl_nf_3_la-queue.lo \ + lib/netfilter/libnl_nf_3_la-queue_msg.lo \ + lib/netfilter/libnl_nf_3_la-queue_msg_obj.lo \ + lib/netfilter/libnl_nf_3_la-queue_obj.lo +lib_libnl_nf_3_la_OBJECTS = $(am_lib_libnl_nf_3_la_OBJECTS) +lib_libnl_nf_3_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib_libnl_nf_3_la_LDFLAGS) $(LDFLAGS) \ + -o $@ +lib_libnl_route_3_la_DEPENDENCIES = lib/libnl-3.la +am_lib_libnl_route_3_la_OBJECTS = \ + lib/fib_lookup/libnl_route_3_la-lookup.lo \ + lib/fib_lookup/libnl_route_3_la-request.lo \ + lib/route/libnl_route_3_la-act.lo \ + lib/route/act/libnl_route_3_la-gact.lo \ + lib/route/act/libnl_route_3_la-mirred.lo \ + lib/route/act/libnl_route_3_la-nat.lo \ + lib/route/act/libnl_route_3_la-skbedit.lo \ + lib/route/act/libnl_route_3_la-vlan.lo \ + lib/route/libnl_route_3_la-addr.lo \ + lib/route/libnl_route_3_la-class.lo \ + lib/route/libnl_route_3_la-classid.lo \ + lib/route/libnl_route_3_la-cls.lo \ + lib/route/cls/libnl_route_3_la-basic.lo \ + lib/route/cls/libnl_route_3_la-cgroup.lo \ + lib/route/cls/libnl_route_3_la-ematch.lo \ + lib/route/cls/ematch/libnl_route_3_la-cmp.lo \ + lib/route/cls/ematch/libnl_route_3_la-container.lo \ + lib/route/cls/ematch/libnl_route_3_la-meta.lo \ + lib/route/cls/ematch/libnl_route_3_la-nbyte.lo \ + lib/route/cls/ematch/libnl_route_3_la-text.lo \ + lib/route/cls/libnl_route_3_la-flower.lo \ + lib/route/cls/libnl_route_3_la-fw.lo \ + lib/route/cls/libnl_route_3_la-mall.lo \ + lib/route/cls/libnl_route_3_la-police.lo \ + lib/route/cls/libnl_route_3_la-u32.lo \ + lib/route/libnl_route_3_la-link.lo \ + lib/route/link/libnl_route_3_la-api.lo \ + lib/route/link/libnl_route_3_la-bonding.lo \ + lib/route/link/libnl_route_3_la-bridge.lo \ + lib/route/link/libnl_route_3_la-bridge_info.lo \ + lib/route/link/libnl_route_3_la-can.lo \ + lib/route/link/libnl_route_3_la-dummy.lo \ + lib/route/link/libnl_route_3_la-geneve.lo \ + lib/route/link/libnl_route_3_la-ifb.lo \ + lib/route/link/libnl_route_3_la-inet.lo \ + lib/route/link/libnl_route_3_la-inet6.lo \ + lib/route/link/libnl_route_3_la-ip6gre.lo \ + lib/route/link/libnl_route_3_la-ip6tnl.lo \ + lib/route/link/libnl_route_3_la-ip6vti.lo \ + lib/route/link/libnl_route_3_la-ipgre.lo \ + lib/route/link/libnl_route_3_la-ipip.lo \ + lib/route/link/libnl_route_3_la-ipvlan.lo \ + lib/route/link/libnl_route_3_la-ipvti.lo \ + lib/route/link/libnl_route_3_la-macsec.lo \ + lib/route/link/libnl_route_3_la-macvlan.lo \ + lib/route/link/libnl_route_3_la-ppp.lo \ + lib/route/link/libnl_route_3_la-sit.lo \ + lib/route/link/libnl_route_3_la-sriov.lo \ + lib/route/link/libnl_route_3_la-team.lo \ + lib/route/link/libnl_route_3_la-veth.lo \ + lib/route/link/libnl_route_3_la-vlan.lo \ + lib/route/link/libnl_route_3_la-vrf.lo \ + lib/route/link/libnl_route_3_la-vxlan.lo \ + lib/route/link/libnl_route_3_la-xfrmi.lo \ + lib/route/libnl_route_3_la-mdb.lo \ + lib/route/libnl_route_3_la-neigh.lo \ + lib/route/libnl_route_3_la-neightbl.lo \ + lib/route/libnl_route_3_la-netconf.lo \ + lib/route/libnl_route_3_la-nexthop.lo \ + lib/route/libnl_route_3_la-nexthop_encap.lo \ + lib/route/libnl_route_3_la-nh.lo \ + lib/route/libnl_route_3_la-nh_encap_mpls.lo \ + lib/route/libnl_route_3_la-pktloc.lo \ + lib/route/libnl_route_3_la-qdisc.lo \ + lib/route/qdisc/libnl_route_3_la-blackhole.lo \ + lib/route/qdisc/libnl_route_3_la-cbq.lo \ + lib/route/qdisc/libnl_route_3_la-dsmark.lo \ + lib/route/qdisc/libnl_route_3_la-fifo.lo \ + lib/route/qdisc/libnl_route_3_la-fq_codel.lo \ + lib/route/qdisc/libnl_route_3_la-hfsc.lo \ + lib/route/qdisc/libnl_route_3_la-htb.lo \ + lib/route/qdisc/libnl_route_3_la-ingress.lo \ + lib/route/qdisc/libnl_route_3_la-mqprio.lo \ + lib/route/qdisc/libnl_route_3_la-netem.lo \ + lib/route/qdisc/libnl_route_3_la-plug.lo \ + lib/route/qdisc/libnl_route_3_la-prio.lo \ + lib/route/qdisc/libnl_route_3_la-red.lo \ + lib/route/qdisc/libnl_route_3_la-sfq.lo \ + lib/route/qdisc/libnl_route_3_la-tbf.lo \ + lib/route/libnl_route_3_la-route.lo \ + lib/route/libnl_route_3_la-route_obj.lo \ + lib/route/libnl_route_3_la-route_utils.lo \ + lib/route/libnl_route_3_la-rtnl.lo \ + lib/route/libnl_route_3_la-rule.lo \ + lib/route/libnl_route_3_la-tc.lo +am__objects_1 = lib/route/cls/libnl_route_3_la-ematch_grammar.lo \ + lib/route/cls/libnl_route_3_la-ematch_syntax.lo \ + lib/route/libnl_route_3_la-pktloc_grammar.lo \ + lib/route/libnl_route_3_la-pktloc_syntax.lo +nodist_lib_libnl_route_3_la_OBJECTS = $(am__objects_1) +lib_libnl_route_3_la_OBJECTS = $(am_lib_libnl_route_3_la_OBJECTS) \ + $(nodist_lib_libnl_route_3_la_OBJECTS) +lib_libnl_route_3_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib_libnl_route_3_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +lib_libnl_xfrm_3_la_DEPENDENCIES = lib/libnl-3.la +am_lib_libnl_xfrm_3_la_OBJECTS = lib/xfrm/libnl_xfrm_3_la-ae.lo \ + lib/xfrm/libnl_xfrm_3_la-lifetime.lo \ + lib/xfrm/libnl_xfrm_3_la-sa.lo \ + lib/xfrm/libnl_xfrm_3_la-selector.lo \ + lib/xfrm/libnl_xfrm_3_la-sp.lo \ + lib/xfrm/libnl_xfrm_3_la-template.lo +lib_libnl_xfrm_3_la_OBJECTS = $(am_lib_libnl_xfrm_3_la_OBJECTS) +lib_libnl_xfrm_3_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib_libnl_xfrm_3_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +src_lib_libnl_cli_3_la_DEPENDENCIES = lib/libnl-3.la \ + lib/libnl-route-3.la lib/libnl-nf-3.la lib/libnl-genl-3.la +am_src_lib_libnl_cli_3_la_OBJECTS = src/lib/libnl_cli_3_la-addr.lo \ + src/lib/libnl_cli_3_la-class.lo src/lib/libnl_cli_3_la-cls.lo \ + src/lib/libnl_cli_3_la-ct.lo src/lib/libnl_cli_3_la-exp.lo \ + src/lib/libnl_cli_3_la-link.lo src/lib/libnl_cli_3_la-neigh.lo \ + src/lib/libnl_cli_3_la-nh.lo src/lib/libnl_cli_3_la-qdisc.lo \ + src/lib/libnl_cli_3_la-route.lo src/lib/libnl_cli_3_la-rule.lo \ + src/lib/libnl_cli_3_la-tc.lo src/lib/libnl_cli_3_la-utils.lo +src_lib_libnl_cli_3_la_OBJECTS = $(am_src_lib_libnl_cli_3_la_OBJECTS) +src_lib_libnl_cli_3_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(src_lib_libnl_cli_3_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@ENABLE_CLI_FALSE@am_src_lib_libnl_cli_3_la_rpath = +@ENABLE_CLI_TRUE@am_src_lib_libnl_cli_3_la_rpath = -rpath $(libdir) +am__DEPENDENCIES_1 = lib/libnl-3.la lib/libnl-nf-3.la \ + lib/libnl-genl-3.la lib/libnl-route-3.la +am__DEPENDENCIES_2 = +tests_libnl_test_util_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_2) +am_tests_libnl_test_util_la_OBJECTS = \ + tests/libnl_test_util_la-nl-test-util.lo +tests_libnl_test_util_la_OBJECTS = \ + $(am_tests_libnl_test_util_la_OBJECTS) +@WITH_CHECK_TRUE@am_tests_libnl_test_util_la_rpath = +src_genl_ctrl_list_SOURCES = src/genl-ctrl-list.c +src_genl_ctrl_list_OBJECTS = \ + src/genl_ctrl_list-genl-ctrl-list.$(OBJEXT) +am__DEPENDENCIES_3 = src/lib/libnl-cli-3.la lib/libnl-3.la \ + lib/libnl-nf-3.la lib/libnl-genl-3.la lib/libnl-route-3.la \ + lib/libnl-idiag-3.la +src_genl_ctrl_list_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_idiag_socket_details_SOURCES = src/idiag-socket-details.c +src_idiag_socket_details_OBJECTS = \ + src/idiag_socket_details-idiag-socket-details.$(OBJEXT) +src_idiag_socket_details_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nf_ct_add_SOURCES = src/nf-ct-add.c +src_nf_ct_add_OBJECTS = src/nf_ct_add-nf-ct-add.$(OBJEXT) +src_nf_ct_add_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nf_ct_events_SOURCES = src/nf-ct-events.c +src_nf_ct_events_OBJECTS = src/nf_ct_events-nf-ct-events.$(OBJEXT) +src_nf_ct_events_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nf_ct_list_SOURCES = src/nf-ct-list.c +src_nf_ct_list_OBJECTS = src/nf_ct_list-nf-ct-list.$(OBJEXT) +src_nf_ct_list_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nf_exp_add_SOURCES = src/nf-exp-add.c +src_nf_exp_add_OBJECTS = src/nf_exp_add-nf-exp-add.$(OBJEXT) +src_nf_exp_add_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nf_exp_delete_SOURCES = src/nf-exp-delete.c +src_nf_exp_delete_OBJECTS = src/nf_exp_delete-nf-exp-delete.$(OBJEXT) +src_nf_exp_delete_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nf_exp_list_SOURCES = src/nf-exp-list.c +src_nf_exp_list_OBJECTS = src/nf_exp_list-nf-exp-list.$(OBJEXT) +src_nf_exp_list_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nf_log_SOURCES = src/nf-log.c +src_nf_log_OBJECTS = src/nf_log-nf-log.$(OBJEXT) +src_nf_log_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nf_monitor_SOURCES = src/nf-monitor.c +src_nf_monitor_OBJECTS = src/nf_monitor-nf-monitor.$(OBJEXT) +src_nf_monitor_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nf_queue_SOURCES = src/nf-queue.c +src_nf_queue_OBJECTS = src/nf_queue-nf-queue.$(OBJEXT) +src_nf_queue_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_addr_add_SOURCES = src/nl-addr-add.c +src_nl_addr_add_OBJECTS = src/nl_addr_add-nl-addr-add.$(OBJEXT) +src_nl_addr_add_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_addr_delete_SOURCES = src/nl-addr-delete.c +src_nl_addr_delete_OBJECTS = \ + src/nl_addr_delete-nl-addr-delete.$(OBJEXT) +src_nl_addr_delete_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_addr_list_SOURCES = src/nl-addr-list.c +src_nl_addr_list_OBJECTS = src/nl_addr_list-nl-addr-list.$(OBJEXT) +src_nl_addr_list_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_class_add_SOURCES = src/nl-class-add.c +src_nl_class_add_OBJECTS = src/nl_class_add-nl-class-add.$(OBJEXT) +src_nl_class_add_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_class_delete_SOURCES = src/nl-class-delete.c +src_nl_class_delete_OBJECTS = \ + src/nl_class_delete-nl-class-delete.$(OBJEXT) +src_nl_class_delete_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_class_list_SOURCES = src/nl-class-list.c +src_nl_class_list_OBJECTS = src/nl_class_list-nl-class-list.$(OBJEXT) +src_nl_class_list_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_classid_lookup_SOURCES = src/nl-classid-lookup.c +src_nl_classid_lookup_OBJECTS = \ + src/nl_classid_lookup-nl-classid-lookup.$(OBJEXT) +src_nl_classid_lookup_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_cls_add_SOURCES = src/nl-cls-add.c +src_nl_cls_add_OBJECTS = src/nl_cls_add-nl-cls-add.$(OBJEXT) +src_nl_cls_add_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_cls_delete_SOURCES = src/nl-cls-delete.c +src_nl_cls_delete_OBJECTS = src/nl_cls_delete-nl-cls-delete.$(OBJEXT) +src_nl_cls_delete_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_cls_list_SOURCES = src/nl-cls-list.c +src_nl_cls_list_OBJECTS = src/nl_cls_list-nl-cls-list.$(OBJEXT) +src_nl_cls_list_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_fib_lookup_SOURCES = src/nl-fib-lookup.c +src_nl_fib_lookup_OBJECTS = src/nl_fib_lookup-nl-fib-lookup.$(OBJEXT) +src_nl_fib_lookup_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_link_enslave_SOURCES = src/nl-link-enslave.c +src_nl_link_enslave_OBJECTS = \ + src/nl_link_enslave-nl-link-enslave.$(OBJEXT) +src_nl_link_enslave_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_link_ifindex2name_SOURCES = src/nl-link-ifindex2name.c +src_nl_link_ifindex2name_OBJECTS = \ + src/nl_link_ifindex2name-nl-link-ifindex2name.$(OBJEXT) +src_nl_link_ifindex2name_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_link_list_SOURCES = src/nl-link-list.c +src_nl_link_list_OBJECTS = src/nl_link_list-nl-link-list.$(OBJEXT) +src_nl_link_list_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_link_name2ifindex_SOURCES = src/nl-link-name2ifindex.c +src_nl_link_name2ifindex_OBJECTS = \ + src/nl_link_name2ifindex-nl-link-name2ifindex.$(OBJEXT) +src_nl_link_name2ifindex_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_link_release_SOURCES = src/nl-link-release.c +src_nl_link_release_OBJECTS = \ + src/nl_link_release-nl-link-release.$(OBJEXT) +src_nl_link_release_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_link_set_SOURCES = src/nl-link-set.c +src_nl_link_set_OBJECTS = src/nl_link_set-nl-link-set.$(OBJEXT) +src_nl_link_set_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_link_stats_SOURCES = src/nl-link-stats.c +src_nl_link_stats_OBJECTS = src/nl_link_stats-nl-link-stats.$(OBJEXT) +src_nl_link_stats_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_list_caches_SOURCES = src/nl-list-caches.c +src_nl_list_caches_OBJECTS = \ + src/nl_list_caches-nl-list-caches.$(OBJEXT) +src_nl_list_caches_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_list_sockets_SOURCES = src/nl-list-sockets.c +src_nl_list_sockets_OBJECTS = \ + src/nl_list_sockets-nl-list-sockets.$(OBJEXT) +src_nl_list_sockets_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_monitor_SOURCES = src/nl-monitor.c +src_nl_monitor_OBJECTS = src/nl_monitor-nl-monitor.$(OBJEXT) +src_nl_monitor_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_neigh_add_SOURCES = src/nl-neigh-add.c +src_nl_neigh_add_OBJECTS = src/nl_neigh_add-nl-neigh-add.$(OBJEXT) +src_nl_neigh_add_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_neigh_delete_SOURCES = src/nl-neigh-delete.c +src_nl_neigh_delete_OBJECTS = \ + src/nl_neigh_delete-nl-neigh-delete.$(OBJEXT) +src_nl_neigh_delete_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_neigh_list_SOURCES = src/nl-neigh-list.c +src_nl_neigh_list_OBJECTS = src/nl_neigh_list-nl-neigh-list.$(OBJEXT) +src_nl_neigh_list_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_neightbl_list_SOURCES = src/nl-neightbl-list.c +src_nl_neightbl_list_OBJECTS = \ + src/nl_neightbl_list-nl-neightbl-list.$(OBJEXT) +src_nl_neightbl_list_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_nh_list_SOURCES = src/nl-nh-list.c +src_nl_nh_list_OBJECTS = src/nl_nh_list-nl-nh-list.$(OBJEXT) +src_nl_nh_list_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_pktloc_lookup_SOURCES = src/nl-pktloc-lookup.c +src_nl_pktloc_lookup_OBJECTS = \ + src/nl_pktloc_lookup-nl-pktloc-lookup.$(OBJEXT) +src_nl_pktloc_lookup_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_qdisc_add_SOURCES = src/nl-qdisc-add.c +src_nl_qdisc_add_OBJECTS = src/nl_qdisc_add-nl-qdisc-add.$(OBJEXT) +src_nl_qdisc_add_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_qdisc_delete_SOURCES = src/nl-qdisc-delete.c +src_nl_qdisc_delete_OBJECTS = \ + src/nl_qdisc_delete-nl-qdisc-delete.$(OBJEXT) +src_nl_qdisc_delete_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_qdisc_list_SOURCES = src/nl-qdisc-list.c +src_nl_qdisc_list_OBJECTS = src/nl_qdisc_list-nl-qdisc-list.$(OBJEXT) +src_nl_qdisc_list_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_route_add_SOURCES = src/nl-route-add.c +src_nl_route_add_OBJECTS = src/nl_route_add-nl-route-add.$(OBJEXT) +src_nl_route_add_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_route_delete_SOURCES = src/nl-route-delete.c +src_nl_route_delete_OBJECTS = \ + src/nl_route_delete-nl-route-delete.$(OBJEXT) +src_nl_route_delete_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_route_get_SOURCES = src/nl-route-get.c +src_nl_route_get_OBJECTS = src/nl_route_get-nl-route-get.$(OBJEXT) +src_nl_route_get_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_route_list_SOURCES = src/nl-route-list.c +src_nl_route_list_OBJECTS = src/nl_route_list-nl-route-list.$(OBJEXT) +src_nl_route_list_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_rule_list_SOURCES = src/nl-rule-list.c +src_nl_rule_list_OBJECTS = src/nl_rule_list-nl-rule-list.$(OBJEXT) +src_nl_rule_list_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_tctree_list_SOURCES = src/nl-tctree-list.c +src_nl_tctree_list_OBJECTS = \ + src/nl_tctree_list-nl-tctree-list.$(OBJEXT) +src_nl_tctree_list_DEPENDENCIES = $(am__DEPENDENCIES_3) +src_nl_util_addr_SOURCES = src/nl-util-addr.c +src_nl_util_addr_OBJECTS = src/nl_util_addr-nl-util-addr.$(OBJEXT) +src_nl_util_addr_DEPENDENCIES = $(am__DEPENDENCIES_3) +am_tests_check_all_OBJECTS = tests/check_all-check-all.$(OBJEXT) \ + tests/check_all-cksuite-all-addr.$(OBJEXT) \ + tests/check_all-cksuite-all-attr.$(OBJEXT) \ + tests/check_all-cksuite-all-ematch-tree-clone.$(OBJEXT) \ + tests/check_all-cksuite-all-netns.$(OBJEXT) +tests_check_all_OBJECTS = $(am_tests_check_all_OBJECTS) +tests_check_all_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + tests/libnl-test-util.la $(am__DEPENDENCIES_2) +am_tests_check_direct_OBJECTS = \ + tests/check_direct-check-direct.$(OBJEXT) +tests_check_direct_OBJECTS = $(am_tests_check_direct_OBJECTS) +tests_check_direct_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + tests/libnl-test-util.la $(am__DEPENDENCIES_2) +tests_check_direct_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(tests_check_direct_LDFLAGS) \ + $(LDFLAGS) -o $@ +tests_test_cache_mngr_SOURCES = tests/test-cache-mngr.c +tests_test_cache_mngr_OBJECTS = \ + tests/test_cache_mngr-test-cache-mngr.$(OBJEXT) +am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1) src/lib/libnl-cli-3.la +tests_test_cache_mngr_DEPENDENCIES = $(am__DEPENDENCIES_4) +tests_test_complex_HTB_with_hash_filters_SOURCES = \ + tests/test-complex-HTB-with-hash-filters.c +tests_test_complex_HTB_with_hash_filters_OBJECTS = tests/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.$(OBJEXT) +tests_test_complex_HTB_with_hash_filters_DEPENDENCIES = \ + $(am__DEPENDENCIES_1) +tests_test_create_bond_SOURCES = tests/test-create-bond.c +tests_test_create_bond_OBJECTS = \ + tests/test_create_bond-test-create-bond.$(OBJEXT) +tests_test_create_bond_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_create_bridge_SOURCES = tests/test-create-bridge.c +tests_test_create_bridge_OBJECTS = \ + tests/test_create_bridge-test-create-bridge.$(OBJEXT) +tests_test_create_bridge_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_create_geneve_SOURCES = tests/test-create-geneve.c +tests_test_create_geneve_OBJECTS = \ + tests/test_create_geneve-test-create-geneve.$(OBJEXT) +tests_test_create_geneve_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_create_ifb_SOURCES = tests/test-create-ifb.c +tests_test_create_ifb_OBJECTS = \ + tests/test_create_ifb-test-create-ifb.$(OBJEXT) +tests_test_create_ifb_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_create_ip6tnl_SOURCES = tests/test-create-ip6tnl.c +tests_test_create_ip6tnl_OBJECTS = \ + tests/test_create_ip6tnl-test-create-ip6tnl.$(OBJEXT) +tests_test_create_ip6tnl_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_create_ipgre_SOURCES = tests/test-create-ipgre.c +tests_test_create_ipgre_OBJECTS = \ + tests/test_create_ipgre-test-create-ipgre.$(OBJEXT) +tests_test_create_ipgre_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_create_ipgretap_SOURCES = tests/test-create-ipgretap.c +tests_test_create_ipgretap_OBJECTS = \ + tests/test_create_ipgretap-test-create-ipgretap.$(OBJEXT) +tests_test_create_ipgretap_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_create_ipip_SOURCES = tests/test-create-ipip.c +tests_test_create_ipip_OBJECTS = \ + tests/test_create_ipip-test-create-ipip.$(OBJEXT) +tests_test_create_ipip_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_create_ipvlan_SOURCES = tests/test-create-ipvlan.c +tests_test_create_ipvlan_OBJECTS = \ + tests/test_create_ipvlan-test-create-ipvlan.$(OBJEXT) +tests_test_create_ipvlan_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_create_ipvti_SOURCES = tests/test-create-ipvti.c +tests_test_create_ipvti_OBJECTS = \ + tests/test_create_ipvti-test-create-ipvti.$(OBJEXT) +tests_test_create_ipvti_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_create_macsec_SOURCES = tests/test-create-macsec.c +tests_test_create_macsec_OBJECTS = \ + tests/test_create_macsec-test-create-macsec.$(OBJEXT) +tests_test_create_macsec_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_create_macvlan_SOURCES = tests/test-create-macvlan.c +tests_test_create_macvlan_OBJECTS = \ + tests/test_create_macvlan-test-create-macvlan.$(OBJEXT) +tests_test_create_macvlan_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_create_macvtap_SOURCES = tests/test-create-macvtap.c +tests_test_create_macvtap_OBJECTS = \ + tests/test_create_macvtap-test-create-macvtap.$(OBJEXT) +tests_test_create_macvtap_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_create_sit_SOURCES = tests/test-create-sit.c +tests_test_create_sit_OBJECTS = \ + tests/test_create_sit-test-create-sit.$(OBJEXT) +tests_test_create_sit_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_create_veth_SOURCES = tests/test-create-veth.c +tests_test_create_veth_OBJECTS = \ + tests/test_create_veth-test-create-veth.$(OBJEXT) +tests_test_create_veth_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_create_vlan_SOURCES = tests/test-create-vlan.c +tests_test_create_vlan_OBJECTS = \ + tests/test_create_vlan-test-create-vlan.$(OBJEXT) +tests_test_create_vlan_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_create_vrf_SOURCES = tests/test-create-vrf.c +tests_test_create_vrf_OBJECTS = \ + tests/test_create_vrf-test-create-vrf.$(OBJEXT) +tests_test_create_vrf_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_create_vxlan_SOURCES = tests/test-create-vxlan.c +tests_test_create_vxlan_OBJECTS = \ + tests/test_create_vxlan-test-create-vxlan.$(OBJEXT) +tests_test_create_vxlan_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_create_xfrmi_SOURCES = tests/test-create-xfrmi.c +tests_test_create_xfrmi_OBJECTS = \ + tests/test_create_xfrmi-test-create-xfrmi.$(OBJEXT) +tests_test_create_xfrmi_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_delete_link_SOURCES = tests/test-delete-link.c +tests_test_delete_link_OBJECTS = \ + tests/test_delete_link-test-delete-link.$(OBJEXT) +tests_test_delete_link_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_genl_SOURCES = tests/test-genl.c +tests_test_genl_OBJECTS = tests/test_genl-test-genl.$(OBJEXT) +tests_test_genl_DEPENDENCIES = $(am__DEPENDENCIES_4) +tests_test_loopback_up_down_SOURCES = tests/test-loopback-up-down.c +tests_test_loopback_up_down_OBJECTS = \ + tests/test_loopback_up_down-test-loopback-up-down.$(OBJEXT) +tests_test_loopback_up_down_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_nf_cache_mngr_SOURCES = tests/test-nf-cache-mngr.c +tests_test_nf_cache_mngr_OBJECTS = \ + tests/test_nf_cache_mngr-test-nf-cache-mngr.$(OBJEXT) +tests_test_nf_cache_mngr_DEPENDENCIES = $(am__DEPENDENCIES_4) +tests_test_socket_creation_SOURCES = tests/test-socket-creation.c +tests_test_socket_creation_OBJECTS = \ + tests/test_socket_creation-test-socket-creation.$(OBJEXT) +tests_test_socket_creation_DEPENDENCIES = $(am__DEPENDENCIES_1) +tests_test_u32_filter_with_actions_SOURCES = \ + tests/test-u32-filter-with-actions.c +tests_test_u32_filter_with_actions_OBJECTS = tests/test_u32_filter_with_actions-test-u32-filter-with-actions.$(OBJEXT) +tests_test_u32_filter_with_actions_DEPENDENCIES = \ + $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = lib/$(DEPDIR)/libnl_3_la-addr.Plo \ + lib/$(DEPDIR)/libnl_3_la-attr.Plo \ + lib/$(DEPDIR)/libnl_3_la-cache.Plo \ + lib/$(DEPDIR)/libnl_3_la-cache_mngr.Plo \ + lib/$(DEPDIR)/libnl_3_la-cache_mngt.Plo \ + lib/$(DEPDIR)/libnl_3_la-data.Plo \ + lib/$(DEPDIR)/libnl_3_la-error.Plo \ + lib/$(DEPDIR)/libnl_3_la-handlers.Plo \ + lib/$(DEPDIR)/libnl_3_la-hash.Plo \ + lib/$(DEPDIR)/libnl_3_la-hashtable.Plo \ + lib/$(DEPDIR)/libnl_3_la-mpls.Plo \ + lib/$(DEPDIR)/libnl_3_la-msg.Plo \ + lib/$(DEPDIR)/libnl_3_la-nl.Plo \ + lib/$(DEPDIR)/libnl_3_la-object.Plo \ + lib/$(DEPDIR)/libnl_3_la-socket.Plo \ + lib/$(DEPDIR)/libnl_3_la-utils.Plo \ + lib/$(DEPDIR)/libnl_3_la-version.Plo \ + lib/cli/cls/$(DEPDIR)/basic_la-basic.Plo \ + lib/cli/cls/$(DEPDIR)/cgroup_la-cgroup.Plo \ + lib/cli/qdisc/$(DEPDIR)/bfifo_la-bfifo.Plo \ + lib/cli/qdisc/$(DEPDIR)/blackhole_la-blackhole.Plo \ + lib/cli/qdisc/$(DEPDIR)/fq_codel_la-fq_codel.Plo \ + lib/cli/qdisc/$(DEPDIR)/hfsc_la-hfsc.Plo \ + lib/cli/qdisc/$(DEPDIR)/htb_la-htb.Plo \ + lib/cli/qdisc/$(DEPDIR)/ingress_la-ingress.Plo \ + lib/cli/qdisc/$(DEPDIR)/pfifo_la-pfifo.Plo \ + lib/cli/qdisc/$(DEPDIR)/plug_la-plug.Plo \ + lib/fib_lookup/$(DEPDIR)/libnl_route_3_la-lookup.Plo \ + lib/fib_lookup/$(DEPDIR)/libnl_route_3_la-request.Plo \ + lib/genl/$(DEPDIR)/libnl_genl_3_la-ctrl.Plo \ + lib/genl/$(DEPDIR)/libnl_genl_3_la-family.Plo \ + lib/genl/$(DEPDIR)/libnl_genl_3_la-genl.Plo \ + lib/genl/$(DEPDIR)/libnl_genl_3_la-mngt.Plo \ + lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag.Plo \ + lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_meminfo_obj.Plo \ + lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_msg_obj.Plo \ + lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_req_obj.Plo \ + lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_vegasinfo_obj.Plo \ + lib/netfilter/$(DEPDIR)/libnl_nf_3_la-ct.Plo \ + lib/netfilter/$(DEPDIR)/libnl_nf_3_la-ct_obj.Plo \ + lib/netfilter/$(DEPDIR)/libnl_nf_3_la-exp.Plo \ + lib/netfilter/$(DEPDIR)/libnl_nf_3_la-exp_obj.Plo \ + lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log.Plo \ + lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_msg.Plo \ + lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_msg_obj.Plo \ + lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_obj.Plo \ + lib/netfilter/$(DEPDIR)/libnl_nf_3_la-netfilter.Plo \ + lib/netfilter/$(DEPDIR)/libnl_nf_3_la-nfnl.Plo \ + lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue.Plo \ + lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_msg.Plo \ + lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_msg_obj.Plo \ + lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_obj.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-act.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-addr.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-class.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-classid.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-cls.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-link.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-mdb.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-neigh.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-neightbl.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-netconf.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-nexthop.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-nexthop_encap.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-nh.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-nh_encap_mpls.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-pktloc.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-pktloc_grammar.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-pktloc_syntax.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-qdisc.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-route.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-route_obj.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-route_utils.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-rtnl.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-rule.Plo \ + lib/route/$(DEPDIR)/libnl_route_3_la-tc.Plo \ + lib/route/act/$(DEPDIR)/libnl_route_3_la-gact.Plo \ + lib/route/act/$(DEPDIR)/libnl_route_3_la-mirred.Plo \ + lib/route/act/$(DEPDIR)/libnl_route_3_la-nat.Plo \ + lib/route/act/$(DEPDIR)/libnl_route_3_la-skbedit.Plo \ + lib/route/act/$(DEPDIR)/libnl_route_3_la-vlan.Plo \ + lib/route/cls/$(DEPDIR)/libnl_route_3_la-basic.Plo \ + lib/route/cls/$(DEPDIR)/libnl_route_3_la-cgroup.Plo \ + lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch.Plo \ + lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch_grammar.Plo \ + lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch_syntax.Plo \ + lib/route/cls/$(DEPDIR)/libnl_route_3_la-flower.Plo \ + lib/route/cls/$(DEPDIR)/libnl_route_3_la-fw.Plo \ + lib/route/cls/$(DEPDIR)/libnl_route_3_la-mall.Plo \ + lib/route/cls/$(DEPDIR)/libnl_route_3_la-police.Plo \ + lib/route/cls/$(DEPDIR)/libnl_route_3_la-u32.Plo \ + lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-cmp.Plo \ + lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-container.Plo \ + lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-meta.Plo \ + lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-nbyte.Plo \ + lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-text.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-api.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-bonding.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-bridge.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-bridge_info.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-can.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-dummy.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-geneve.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-ifb.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-inet.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-inet6.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6gre.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6tnl.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6vti.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-ipgre.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-ipip.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-ipvlan.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-ipvti.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-macsec.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-macvlan.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-ppp.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-sit.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-sriov.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-team.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-veth.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-vlan.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-vrf.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-vxlan.Plo \ + lib/route/link/$(DEPDIR)/libnl_route_3_la-xfrmi.Plo \ + lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-blackhole.Plo \ + lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-cbq.Plo \ + lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-dsmark.Plo \ + lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-fifo.Plo \ + lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-fq_codel.Plo \ + lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-hfsc.Plo \ + lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-htb.Plo \ + lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-ingress.Plo \ + lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-mqprio.Plo \ + lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-netem.Plo \ + lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-plug.Plo \ + lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-prio.Plo \ + lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-red.Plo \ + lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-sfq.Plo \ + lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-tbf.Plo \ + lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-ae.Plo \ + lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-lifetime.Plo \ + lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-sa.Plo \ + lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-selector.Plo \ + lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-sp.Plo \ + lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-template.Plo \ + src/$(DEPDIR)/genl_ctrl_list-genl-ctrl-list.Po \ + src/$(DEPDIR)/idiag_socket_details-idiag-socket-details.Po \ + src/$(DEPDIR)/nf_ct_add-nf-ct-add.Po \ + src/$(DEPDIR)/nf_ct_events-nf-ct-events.Po \ + src/$(DEPDIR)/nf_ct_list-nf-ct-list.Po \ + src/$(DEPDIR)/nf_exp_add-nf-exp-add.Po \ + src/$(DEPDIR)/nf_exp_delete-nf-exp-delete.Po \ + src/$(DEPDIR)/nf_exp_list-nf-exp-list.Po \ + src/$(DEPDIR)/nf_log-nf-log.Po \ + src/$(DEPDIR)/nf_monitor-nf-monitor.Po \ + src/$(DEPDIR)/nf_queue-nf-queue.Po \ + src/$(DEPDIR)/nl_addr_add-nl-addr-add.Po \ + src/$(DEPDIR)/nl_addr_delete-nl-addr-delete.Po \ + src/$(DEPDIR)/nl_addr_list-nl-addr-list.Po \ + src/$(DEPDIR)/nl_class_add-nl-class-add.Po \ + src/$(DEPDIR)/nl_class_delete-nl-class-delete.Po \ + src/$(DEPDIR)/nl_class_list-nl-class-list.Po \ + src/$(DEPDIR)/nl_classid_lookup-nl-classid-lookup.Po \ + src/$(DEPDIR)/nl_cls_add-nl-cls-add.Po \ + src/$(DEPDIR)/nl_cls_delete-nl-cls-delete.Po \ + src/$(DEPDIR)/nl_cls_list-nl-cls-list.Po \ + src/$(DEPDIR)/nl_fib_lookup-nl-fib-lookup.Po \ + src/$(DEPDIR)/nl_link_enslave-nl-link-enslave.Po \ + src/$(DEPDIR)/nl_link_ifindex2name-nl-link-ifindex2name.Po \ + src/$(DEPDIR)/nl_link_list-nl-link-list.Po \ + src/$(DEPDIR)/nl_link_name2ifindex-nl-link-name2ifindex.Po \ + src/$(DEPDIR)/nl_link_release-nl-link-release.Po \ + src/$(DEPDIR)/nl_link_set-nl-link-set.Po \ + src/$(DEPDIR)/nl_link_stats-nl-link-stats.Po \ + src/$(DEPDIR)/nl_list_caches-nl-list-caches.Po \ + src/$(DEPDIR)/nl_list_sockets-nl-list-sockets.Po \ + src/$(DEPDIR)/nl_monitor-nl-monitor.Po \ + src/$(DEPDIR)/nl_neigh_add-nl-neigh-add.Po \ + src/$(DEPDIR)/nl_neigh_delete-nl-neigh-delete.Po \ + src/$(DEPDIR)/nl_neigh_list-nl-neigh-list.Po \ + src/$(DEPDIR)/nl_neightbl_list-nl-neightbl-list.Po \ + src/$(DEPDIR)/nl_nh_list-nl-nh-list.Po \ + src/$(DEPDIR)/nl_pktloc_lookup-nl-pktloc-lookup.Po \ + src/$(DEPDIR)/nl_qdisc_add-nl-qdisc-add.Po \ + src/$(DEPDIR)/nl_qdisc_delete-nl-qdisc-delete.Po \ + src/$(DEPDIR)/nl_qdisc_list-nl-qdisc-list.Po \ + src/$(DEPDIR)/nl_route_add-nl-route-add.Po \ + src/$(DEPDIR)/nl_route_delete-nl-route-delete.Po \ + src/$(DEPDIR)/nl_route_get-nl-route-get.Po \ + src/$(DEPDIR)/nl_route_list-nl-route-list.Po \ + src/$(DEPDIR)/nl_rule_list-nl-rule-list.Po \ + src/$(DEPDIR)/nl_tctree_list-nl-tctree-list.Po \ + src/$(DEPDIR)/nl_util_addr-nl-util-addr.Po \ + src/lib/$(DEPDIR)/libnl_cli_3_la-addr.Plo \ + src/lib/$(DEPDIR)/libnl_cli_3_la-class.Plo \ + src/lib/$(DEPDIR)/libnl_cli_3_la-cls.Plo \ + src/lib/$(DEPDIR)/libnl_cli_3_la-ct.Plo \ + src/lib/$(DEPDIR)/libnl_cli_3_la-exp.Plo \ + src/lib/$(DEPDIR)/libnl_cli_3_la-link.Plo \ + src/lib/$(DEPDIR)/libnl_cli_3_la-neigh.Plo \ + src/lib/$(DEPDIR)/libnl_cli_3_la-nh.Plo \ + src/lib/$(DEPDIR)/libnl_cli_3_la-qdisc.Plo \ + src/lib/$(DEPDIR)/libnl_cli_3_la-route.Plo \ + src/lib/$(DEPDIR)/libnl_cli_3_la-rule.Plo \ + src/lib/$(DEPDIR)/libnl_cli_3_la-tc.Plo \ + src/lib/$(DEPDIR)/libnl_cli_3_la-utils.Plo \ + tests/$(DEPDIR)/check_all-check-all.Po \ + tests/$(DEPDIR)/check_all-cksuite-all-addr.Po \ + tests/$(DEPDIR)/check_all-cksuite-all-attr.Po \ + tests/$(DEPDIR)/check_all-cksuite-all-ematch-tree-clone.Po \ + tests/$(DEPDIR)/check_all-cksuite-all-netns.Po \ + tests/$(DEPDIR)/check_direct-check-direct.Po \ + tests/$(DEPDIR)/libnl_test_util_la-nl-test-util.Plo \ + tests/$(DEPDIR)/test_cache_mngr-test-cache-mngr.Po \ + tests/$(DEPDIR)/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.Po \ + tests/$(DEPDIR)/test_create_bond-test-create-bond.Po \ + tests/$(DEPDIR)/test_create_bridge-test-create-bridge.Po \ + tests/$(DEPDIR)/test_create_geneve-test-create-geneve.Po \ + tests/$(DEPDIR)/test_create_ifb-test-create-ifb.Po \ + tests/$(DEPDIR)/test_create_ip6tnl-test-create-ip6tnl.Po \ + tests/$(DEPDIR)/test_create_ipgre-test-create-ipgre.Po \ + tests/$(DEPDIR)/test_create_ipgretap-test-create-ipgretap.Po \ + tests/$(DEPDIR)/test_create_ipip-test-create-ipip.Po \ + tests/$(DEPDIR)/test_create_ipvlan-test-create-ipvlan.Po \ + tests/$(DEPDIR)/test_create_ipvti-test-create-ipvti.Po \ + tests/$(DEPDIR)/test_create_macsec-test-create-macsec.Po \ + tests/$(DEPDIR)/test_create_macvlan-test-create-macvlan.Po \ + tests/$(DEPDIR)/test_create_macvtap-test-create-macvtap.Po \ + tests/$(DEPDIR)/test_create_sit-test-create-sit.Po \ + tests/$(DEPDIR)/test_create_veth-test-create-veth.Po \ + tests/$(DEPDIR)/test_create_vlan-test-create-vlan.Po \ + tests/$(DEPDIR)/test_create_vrf-test-create-vrf.Po \ + tests/$(DEPDIR)/test_create_vxlan-test-create-vxlan.Po \ + tests/$(DEPDIR)/test_create_xfrmi-test-create-xfrmi.Po \ + tests/$(DEPDIR)/test_delete_link-test-delete-link.Po \ + tests/$(DEPDIR)/test_genl-test-genl.Po \ + tests/$(DEPDIR)/test_loopback_up_down-test-loopback-up-down.Po \ + tests/$(DEPDIR)/test_nf_cache_mngr-test-nf-cache-mngr.Po \ + tests/$(DEPDIR)/test_socket_creation-test-socket-creation.Po \ + tests/$(DEPDIR)/test_u32_filter_with_actions-test-u32-filter-with-actions.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = lib/cli/cls/basic.c lib/cli/cls/cgroup.c \ + lib/cli/qdisc/bfifo.c lib/cli/qdisc/blackhole.c \ + lib/cli/qdisc/fq_codel.c lib/cli/qdisc/hfsc.c \ + lib/cli/qdisc/htb.c lib/cli/qdisc/ingress.c \ + lib/cli/qdisc/pfifo.c lib/cli/qdisc/plug.c \ + $(lib_libnl_3_la_SOURCES) $(lib_libnl_genl_3_la_SOURCES) \ + $(lib_libnl_idiag_3_la_SOURCES) $(lib_libnl_nf_3_la_SOURCES) \ + $(lib_libnl_route_3_la_SOURCES) \ + $(nodist_lib_libnl_route_3_la_SOURCES) \ + $(lib_libnl_xfrm_3_la_SOURCES) \ + $(src_lib_libnl_cli_3_la_SOURCES) \ + $(tests_libnl_test_util_la_SOURCES) src/genl-ctrl-list.c \ + src/idiag-socket-details.c src/nf-ct-add.c src/nf-ct-events.c \ + src/nf-ct-list.c src/nf-exp-add.c src/nf-exp-delete.c \ + src/nf-exp-list.c src/nf-log.c src/nf-monitor.c src/nf-queue.c \ + src/nl-addr-add.c src/nl-addr-delete.c src/nl-addr-list.c \ + src/nl-class-add.c src/nl-class-delete.c src/nl-class-list.c \ + src/nl-classid-lookup.c src/nl-cls-add.c src/nl-cls-delete.c \ + src/nl-cls-list.c src/nl-fib-lookup.c src/nl-link-enslave.c \ + src/nl-link-ifindex2name.c src/nl-link-list.c \ + src/nl-link-name2ifindex.c src/nl-link-release.c \ + src/nl-link-set.c src/nl-link-stats.c src/nl-list-caches.c \ + src/nl-list-sockets.c src/nl-monitor.c src/nl-neigh-add.c \ + src/nl-neigh-delete.c src/nl-neigh-list.c \ + src/nl-neightbl-list.c src/nl-nh-list.c src/nl-pktloc-lookup.c \ + src/nl-qdisc-add.c src/nl-qdisc-delete.c src/nl-qdisc-list.c \ + src/nl-route-add.c src/nl-route-delete.c src/nl-route-get.c \ + src/nl-route-list.c src/nl-rule-list.c src/nl-tctree-list.c \ + src/nl-util-addr.c $(tests_check_all_SOURCES) \ + $(tests_check_direct_SOURCES) tests/test-cache-mngr.c \ + tests/test-complex-HTB-with-hash-filters.c \ + tests/test-create-bond.c tests/test-create-bridge.c \ + tests/test-create-geneve.c tests/test-create-ifb.c \ + tests/test-create-ip6tnl.c tests/test-create-ipgre.c \ + tests/test-create-ipgretap.c tests/test-create-ipip.c \ + tests/test-create-ipvlan.c tests/test-create-ipvti.c \ + tests/test-create-macsec.c tests/test-create-macvlan.c \ + tests/test-create-macvtap.c tests/test-create-sit.c \ + tests/test-create-veth.c tests/test-create-vlan.c \ + tests/test-create-vrf.c tests/test-create-vxlan.c \ + tests/test-create-xfrmi.c tests/test-delete-link.c \ + tests/test-genl.c tests/test-loopback-up-down.c \ + tests/test-nf-cache-mngr.c tests/test-socket-creation.c \ + tests/test-u32-filter-with-actions.c +DIST_SOURCES = lib/cli/cls/basic.c lib/cli/cls/cgroup.c \ + lib/cli/qdisc/bfifo.c lib/cli/qdisc/blackhole.c \ + lib/cli/qdisc/fq_codel.c lib/cli/qdisc/hfsc.c \ + lib/cli/qdisc/htb.c lib/cli/qdisc/ingress.c \ + lib/cli/qdisc/pfifo.c lib/cli/qdisc/plug.c \ + $(lib_libnl_3_la_SOURCES) $(lib_libnl_genl_3_la_SOURCES) \ + $(lib_libnl_idiag_3_la_SOURCES) $(lib_libnl_nf_3_la_SOURCES) \ + $(lib_libnl_route_3_la_SOURCES) $(lib_libnl_xfrm_3_la_SOURCES) \ + $(src_lib_libnl_cli_3_la_SOURCES) \ + $(tests_libnl_test_util_la_SOURCES) src/genl-ctrl-list.c \ + src/idiag-socket-details.c src/nf-ct-add.c src/nf-ct-events.c \ + src/nf-ct-list.c src/nf-exp-add.c src/nf-exp-delete.c \ + src/nf-exp-list.c src/nf-log.c src/nf-monitor.c src/nf-queue.c \ + src/nl-addr-add.c src/nl-addr-delete.c src/nl-addr-list.c \ + src/nl-class-add.c src/nl-class-delete.c src/nl-class-list.c \ + src/nl-classid-lookup.c src/nl-cls-add.c src/nl-cls-delete.c \ + src/nl-cls-list.c src/nl-fib-lookup.c src/nl-link-enslave.c \ + src/nl-link-ifindex2name.c src/nl-link-list.c \ + src/nl-link-name2ifindex.c src/nl-link-release.c \ + src/nl-link-set.c src/nl-link-stats.c src/nl-list-caches.c \ + src/nl-list-sockets.c src/nl-monitor.c src/nl-neigh-add.c \ + src/nl-neigh-delete.c src/nl-neigh-list.c \ + src/nl-neightbl-list.c src/nl-nh-list.c src/nl-pktloc-lookup.c \ + src/nl-qdisc-add.c src/nl-qdisc-delete.c src/nl-qdisc-list.c \ + src/nl-route-add.c src/nl-route-delete.c src/nl-route-get.c \ + src/nl-route-list.c src/nl-rule-list.c src/nl-tctree-list.c \ + src/nl-util-addr.c $(tests_check_all_SOURCES) \ + $(tests_check_direct_SOURCES) tests/test-cache-mngr.c \ + tests/test-complex-HTB-with-hash-filters.c \ + tests/test-create-bond.c tests/test-create-bridge.c \ + tests/test-create-geneve.c tests/test-create-ifb.c \ + tests/test-create-ip6tnl.c tests/test-create-ipgre.c \ + tests/test-create-ipgretap.c tests/test-create-ipip.c \ + tests/test-create-ipvlan.c tests/test-create-ipvti.c \ + tests/test-create-macsec.c tests/test-create-macvlan.c \ + tests/test-create-macvtap.c tests/test-create-sit.c \ + tests/test-create-veth.c tests/test-create-vlan.c \ + tests/test-create-vrf.c tests/test-create-vxlan.c \ + tests/test-create-xfrmi.c tests/test-delete-link.c \ + tests/test-genl.c tests/test-loopback-up-down.c \ + tests/test-nf-cache-mngr.c tests/test-socket-creation.c \ + tests/test-u32-filter-with-actions.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +man8dir = $(mandir)/man8 +NROFF = nroff +MANS = $(dist_man8_MANS) DATA = $(pkgconfig_DATA) $(pkgsysconf_DATA) -RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ - distclean-recursive maintainer-clean-recursive -AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ - $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ - distdir dist dist-all distcheck -ETAGS = etags -CTAGS = ctags -DIST_SUBDIRS = include lib man python tests src +am__libnlinclude_netlink_cli_HEADERS_DIST = \ + include/netlink/cli/addr.h include/netlink/cli/class.h \ + include/netlink/cli/cls.h include/netlink/cli/ct.h \ + include/netlink/cli/exp.h include/netlink/cli/link.h \ + include/netlink/cli/mdb.h include/netlink/cli/neigh.h \ + include/netlink/cli/nh.h include/netlink/cli/qdisc.h \ + include/netlink/cli/route.h include/netlink/cli/rule.h \ + include/netlink/cli/tc.h include/netlink/cli/utils.h +HEADERS = $(libnlinclude_netlink_HEADERS) \ + $(libnlinclude_netlink_cli_HEADERS) \ + $(libnlinclude_netlink_fib_lookup_HEADERS) \ + $(libnlinclude_netlink_genl_HEADERS) \ + $(libnlinclude_netlink_idiag_HEADERS) \ + $(libnlinclude_netlink_netfilter_HEADERS) \ + $(libnlinclude_netlink_route_HEADERS) \ + $(libnlinclude_netlink_route_act_HEADERS) \ + $(libnlinclude_netlink_route_cls_HEADERS) \ + $(libnlinclude_netlink_route_cls_ematch_HEADERS) \ + $(libnlinclude_netlink_route_link_HEADERS) \ + $(libnlinclude_netlink_route_qdisc_HEADERS) \ + $(libnlinclude_netlink_xfrm_HEADERS) $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +AM_RECURSIVE_TARGETS = cscope check recheck +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' +RECHECK_LOGS = $(TEST_LOGS) +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(dist_man8_MANS) $(srcdir)/Makefile.in \ + $(srcdir)/libnl-3.0.pc.in $(srcdir)/libnl-cli-3.0.pc.in \ + $(srcdir)/libnl-genl-3.0.pc.in $(srcdir)/libnl-idiag-3.0.pc.in \ + $(srcdir)/libnl-nf-3.0.pc.in $(srcdir)/libnl-route-3.0.pc.in \ + $(srcdir)/libnl-xfrm-3.0.pc.in $(top_srcdir)/build-aux/ar-lib \ + $(top_srcdir)/build-aux/compile \ + $(top_srcdir)/build-aux/config.guess \ + $(top_srcdir)/build-aux/config.sub \ + $(top_srcdir)/build-aux/depcomp \ + $(top_srcdir)/build-aux/install-sh \ + $(top_srcdir)/build-aux/ltmain.sh \ + $(top_srcdir)/build-aux/missing \ + $(top_srcdir)/build-aux/test-driver \ + $(top_srcdir)/include/config.h.in \ + $(top_srcdir)/include/netlink/version.h.in \ + $(top_srcdir)/python/setup.py.in COPYING ChangeLog \ + build-aux/ar-lib build-aux/compile build-aux/config.guess \ + build-aux/config.sub build-aux/depcomp build-aux/install-sh \ + build-aux/ltmain.sh build-aux/missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) @@ -146,33 +1450,12 @@ am__remove_distdir = \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi -am__relativize = \ - dir0=`pwd`; \ - sed_first='s,^\([^/]*\)/.*$$,\1,'; \ - sed_rest='s,^[^/]*/*,,'; \ - sed_last='s,^.*/\([^/]*\)$$,\1,'; \ - sed_butlast='s,/*[^/]*$$,,'; \ - while test -n "$$dir1"; do \ - first=`echo "$$dir1" | sed -e "$$sed_first"`; \ - if test "$$first" != "."; then \ - if test "$$first" = ".."; then \ - dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ - dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ - else \ - first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ - if test "$$first2" = "$$first"; then \ - dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ - else \ - dir2="../$$dir2"; \ - fi; \ - dir0="$$dir0"/"$$first"; \ - fi; \ - fi; \ - dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ - done; \ - reldir="$$dir2" +am__post_remove_distdir = $(am__remove_distdir) DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best +DIST_TARGETS = dist-gzip +# Exists only to be overridden by the user if desired. +AM_DISTCHECK_DVI_TARGET = dvi distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' @@ -190,8 +1473,9 @@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ -CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ @@ -202,8 +1486,10 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FILECMD = @FILECMD@ FLEX = @FLEX@ GREP = @GREP@ INSTALL = @INSTALL@ @@ -223,6 +1509,7 @@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_REVISION = @LT_REVISION@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAJ_VERSION = @MAJ_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ @@ -298,6 +1585,7 @@ pkgconfigdir = @pkgconfigdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -308,17 +1596,1013 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = include lib man python tests $(am__append_1) -pkgconfig_DATA = libnl-3.0.pc libnl-route-3.0.pc libnl-genl-3.0.pc \ - libnl-nf-3.0.pc $(am__append_2) -pkgsysconfdir = ${sysconfdir}/libnl -pkgsysconf_DATA = etc/pktloc etc/classid -EXTRA_DIST = \ - $(pkgsysconf_DATA) +lib_LTLIBRARIES = lib/libnl-3.la lib/libnl-route-3.la \ + lib/libnl-idiag-3.la lib/libnl-genl-3.la lib/libnl-nf-3.la \ + lib/libnl-xfrm-3.la $(am__append_2) +noinst_LTLIBRARIES = +check_LTLIBRARIES = $(am__append_1) $(am__append_8) +check_programs = $(am__append_9) $(am__append_10) +check_local = check-local-build-headers +CLEANFILES = $(grammar_files_sources) $(grammar_files_headers) \ + $(BUILD_HEADERS_OBJS) +EXTRA_DIST = lib/route/cls/ematch_grammar.l \ + lib/route/cls/ematch_syntax.y lib/route/pktloc_grammar.l \ + lib/route/pktloc_syntax.y $(NULL) python/README \ + python/doc/conf.py python/doc/core.rst python/doc/index.rst \ + python/doc/route_addr.rst python/doc/route.rst \ + python/examples/iface.py python/examples/nl80211.py \ + python/examples/wiphy.py python/netlink/capi.i \ + python/netlink/__init__.py python/netlink/core.py \ + python/netlink/util.py python/netlink/utils.h \ + python/netlink/genl/capi.i python/netlink/genl/__init__.py \ + python/netlink/route/capi.i python/netlink/route/__init__.py \ + python/netlink/route/address.py python/netlink/route/link.py \ + python/netlink/route/tc.py \ + python/netlink/route/links/__init__.py \ + python/netlink/route/links/dummy.py \ + python/netlink/route/links/inet.py \ + python/netlink/route/links/vlan.py \ + python/netlink/route/qdisc/__init__.py \ + python/netlink/route/qdisc/htb.py \ + python/tests/test-create-bridge.py $(pkgsysconf_DATA) \ + libnl-3.sym libnl-cli-3.sym libnl-genl-3.sym libnl-idiag-3.sym \ + libnl-nf-3.sym libnl-route-3.sym libnl-xfrm-3.sym $(NULL) +DISTCHECK_CONFIGURE_FLAGS = \ + --disable-dependency-tracking + +pkgconfig_DATA = libnl-3.0.pc libnl-genl-3.0.pc libnl-idiag-3.0.pc \ + libnl-nf-3.0.pc libnl-route-3.0.pc libnl-xfrm-3.0.pc $(NULL) \ + $(am__append_11) +warn_cppflags = \ + -Wall \ + -Wextra \ + -Wmissing-prototypes \ + -Wno-unused-parameter \ + -Wno-sign-compare \ + -Wno-missing-field-initializers \ + -Wpointer-arith \ + $(NULL) + + +############################################################################### +libnlincludedir = $(includedir)/libnl@MAJ_VERSION@ +libnlinclude_netlinkdir = $(libnlincludedir)/netlink +libnlinclude_netlink_HEADERS = \ + include/netlink/addr.h \ + include/netlink/attr.h \ + include/netlink/cache-api.h \ + include/netlink/cache.h \ + include/netlink/data.h \ + include/netlink/errno.h \ + include/netlink/handlers.h \ + include/netlink/hash.h \ + include/netlink/hashtable.h \ + include/netlink/list.h \ + include/netlink/msg.h \ + include/netlink/netlink-compat.h \ + include/netlink/netlink-kernel.h \ + include/netlink/netlink.h \ + include/netlink/object-api.h \ + include/netlink/object.h \ + include/netlink/socket.h \ + include/netlink/types.h \ + include/netlink/utils.h \ + include/netlink/version.h \ + $(NULL) + +libnlinclude_netlink_fib_lookupdir = $(libnlincludedir)/netlink/fib_lookup +libnlinclude_netlink_fib_lookup_HEADERS = \ + include/netlink/fib_lookup/lookup.h \ + include/netlink/fib_lookup/request.h \ + $(NULL) + +libnlinclude_netlink_genldir = $(libnlincludedir)/netlink/genl +libnlinclude_netlink_genl_HEADERS = \ + include/netlink/genl/ctrl.h \ + include/netlink/genl/family.h \ + include/netlink/genl/genl.h \ + include/netlink/genl/mngt.h \ + $(NULL) + +libnlinclude_netlink_idiagdir = $(libnlincludedir)/netlink/idiag +libnlinclude_netlink_idiag_HEADERS = \ + include/netlink/idiag/idiagnl.h \ + include/netlink/idiag/meminfo.h \ + include/netlink/idiag/msg.h \ + include/netlink/idiag/req.h \ + include/netlink/idiag/vegasinfo.h \ + $(NULL) + +libnlinclude_netlink_netfilterdir = $(libnlincludedir)/netlink/netfilter +libnlinclude_netlink_netfilter_HEADERS = \ + include/netlink/netfilter/ct.h \ + include/netlink/netfilter/exp.h \ + include/netlink/netfilter/log.h \ + include/netlink/netfilter/log_msg.h \ + include/netlink/netfilter/netfilter.h \ + include/netlink/netfilter/nfnl.h \ + include/netlink/netfilter/queue.h \ + include/netlink/netfilter/queue_msg.h \ + $(NULL) + +libnlinclude_netlink_routedir = $(libnlincludedir)/netlink/route +libnlinclude_netlink_route_HEADERS = \ + include/netlink/route/action.h \ + include/netlink/route/addr.h \ + include/netlink/route/class.h \ + include/netlink/route/classifier.h \ + include/netlink/route/link.h \ + include/netlink/route/mdb.h \ + include/netlink/route/neighbour.h \ + include/netlink/route/neightbl.h \ + include/netlink/route/netconf.h \ + include/netlink/route/nexthop.h \ + include/netlink/route/nh.h \ + include/netlink/route/pktloc.h \ + include/netlink/route/qdisc.h \ + include/netlink/route/route.h \ + include/netlink/route/rtnl.h \ + include/netlink/route/rule.h \ + include/netlink/route/tc-api.h \ + include/netlink/route/tc.h \ + $(NULL) + +libnlinclude_netlink_route_actdir = $(libnlincludedir)/netlink/route/act +libnlinclude_netlink_route_act_HEADERS = \ + include/netlink/route/act/gact.h \ + include/netlink/route/act/mirred.h \ + include/netlink/route/act/nat.h \ + include/netlink/route/act/skbedit.h \ + include/netlink/route/act/vlan.h \ + $(NULL) + +libnlinclude_netlink_route_clsdir = $(libnlincludedir)/netlink/route/cls +libnlinclude_netlink_route_cls_HEADERS = \ + include/netlink/route/cls/basic.h \ + include/netlink/route/cls/cgroup.h \ + include/netlink/route/cls/ematch.h \ + include/netlink/route/cls/flower.h \ + include/netlink/route/cls/fw.h \ + include/netlink/route/cls/matchall.h \ + include/netlink/route/cls/police.h \ + include/netlink/route/cls/u32.h \ + $(NULL) + +libnlinclude_netlink_route_cls_ematchdir = $(libnlincludedir)/netlink/route/cls/ematch +libnlinclude_netlink_route_cls_ematch_HEADERS = \ + include/netlink/route/cls/ematch/cmp.h \ + include/netlink/route/cls/ematch/meta.h \ + include/netlink/route/cls/ematch/nbyte.h \ + include/netlink/route/cls/ematch/text.h \ + $(NULL) + +libnlinclude_netlink_route_linkdir = $(libnlincludedir)/netlink/route/link +libnlinclude_netlink_route_link_HEADERS = \ + include/netlink/route/link/api.h \ + include/netlink/route/link/bonding.h \ + include/netlink/route/link/bridge_info.h \ + include/netlink/route/link/bridge.h \ + include/netlink/route/link/can.h \ + include/netlink/route/link/geneve.h \ + include/netlink/route/link/inet.h \ + include/netlink/route/link/inet6.h \ + include/netlink/route/link/info-api.h \ + include/netlink/route/link/ip6gre.h \ + include/netlink/route/link/ip6tnl.h \ + include/netlink/route/link/ip6vti.h \ + include/netlink/route/link/ipgre.h \ + include/netlink/route/link/ipip.h \ + include/netlink/route/link/ipvlan.h \ + include/netlink/route/link/ipvti.h \ + include/netlink/route/link/macsec.h \ + include/netlink/route/link/macvlan.h \ + include/netlink/route/link/macvtap.h \ + include/netlink/route/link/ppp.h \ + include/netlink/route/link/sit.h \ + include/netlink/route/link/sriov.h \ + include/netlink/route/link/team.h \ + include/netlink/route/link/veth.h \ + include/netlink/route/link/vlan.h \ + include/netlink/route/link/vrf.h \ + include/netlink/route/link/vxlan.h \ + include/netlink/route/link/xfrmi.h \ + $(NULL) + +libnlinclude_netlink_route_qdiscdir = $(libnlincludedir)/netlink/route/qdisc +libnlinclude_netlink_route_qdisc_HEADERS = \ + include/netlink/route/qdisc/cbq.h \ + include/netlink/route/qdisc/dsmark.h \ + include/netlink/route/qdisc/fifo.h \ + include/netlink/route/qdisc/fq_codel.h \ + include/netlink/route/qdisc/hfsc.h \ + include/netlink/route/qdisc/htb.h \ + include/netlink/route/qdisc/mqprio.h \ + include/netlink/route/qdisc/netem.h \ + include/netlink/route/qdisc/plug.h \ + include/netlink/route/qdisc/prio.h \ + include/netlink/route/qdisc/red.h \ + include/netlink/route/qdisc/sfq.h \ + include/netlink/route/qdisc/tbf.h \ + $(NULL) + +libnlinclude_netlink_xfrmdir = $(libnlincludedir)/netlink/xfrm +libnlinclude_netlink_xfrm_HEADERS = \ + include/netlink/xfrm/ae.h \ + include/netlink/xfrm/lifetime.h \ + include/netlink/xfrm/sa.h \ + include/netlink/xfrm/selector.h \ + include/netlink/xfrm/sp.h \ + include/netlink/xfrm/template.h \ + $(NULL) + +@ENABLE_CLI_TRUE@libnlinclude_netlink_clidir = $(libnlincludedir)/netlink/cli +@ENABLE_CLI_TRUE@libnlinclude_netlink_cli_HEADERS = \ +@ENABLE_CLI_TRUE@ include/netlink/cli/addr.h \ +@ENABLE_CLI_TRUE@ include/netlink/cli/class.h \ +@ENABLE_CLI_TRUE@ include/netlink/cli/cls.h \ +@ENABLE_CLI_TRUE@ include/netlink/cli/ct.h \ +@ENABLE_CLI_TRUE@ include/netlink/cli/exp.h \ +@ENABLE_CLI_TRUE@ include/netlink/cli/link.h \ +@ENABLE_CLI_TRUE@ include/netlink/cli/mdb.h \ +@ENABLE_CLI_TRUE@ include/netlink/cli/neigh.h \ +@ENABLE_CLI_TRUE@ include/netlink/cli/nh.h \ +@ENABLE_CLI_TRUE@ include/netlink/cli/qdisc.h \ +@ENABLE_CLI_TRUE@ include/netlink/cli/route.h \ +@ENABLE_CLI_TRUE@ include/netlink/cli/rule.h \ +@ENABLE_CLI_TRUE@ include/netlink/cli/tc.h \ +@ENABLE_CLI_TRUE@ include/netlink/cli/utils.h \ +@ENABLE_CLI_TRUE@ $(NULL) + +public_headers = \ + $(libnlinclude_netlink_HEADERS) \ + $(libnlinclude_netlink_fib_lookup_HEADERS) \ + $(libnlinclude_netlink_genl_HEADERS) \ + $(libnlinclude_netlink_idiag_HEADERS) \ + $(libnlinclude_netlink_netfilter_HEADERS) \ + $(libnlinclude_netlink_route_HEADERS) \ + $(libnlinclude_netlink_route_act_HEADERS) \ + $(libnlinclude_netlink_route_cls_HEADERS) \ + $(libnlinclude_netlink_route_cls_ematch_HEADERS) \ + $(libnlinclude_netlink_route_link_HEADERS) \ + $(libnlinclude_netlink_route_qdisc_HEADERS) \ + $(libnlinclude_netlink_xfrm_HEADERS) \ + $(libnlinclude_netlink_cli_HEADERS) \ + $(NULL) + +noinst_HEADERS = \ + include/base/nl-base-utils.h \ + include/linux-private/linux/atm.h \ + include/linux-private/linux/atmapi.h \ + include/linux-private/linux/atmioc.h \ + include/linux-private/linux/atmsap.h \ + include/linux-private/linux/byteorder/little_endian.h \ + include/linux-private/linux/can/netlink.h \ + include/linux-private/linux/const.h \ + include/linux-private/linux/errno.h \ + include/linux-private/linux/ethtool.h \ + include/linux-private/linux/falloc.h \ + include/linux-private/linux/fib_rules.h \ + include/linux-private/linux/gen_stats.h \ + include/linux-private/linux/genetlink.h \ + include/linux-private/linux/hdlc/ioctl.h \ + include/linux-private/linux/if.h \ + include/linux-private/linux/if_addr.h \ + include/linux-private/linux/if_arp.h \ + include/linux-private/linux/if_bridge.h \ + include/linux-private/linux/if_ether.h \ + include/linux-private/linux/if_link.h \ + include/linux-private/linux/if_macsec.h \ + include/linux-private/linux/if_packet.h \ + include/linux-private/linux/if_tunnel.h \ + include/linux-private/linux/if_vlan.h \ + include/linux-private/linux/in.h \ + include/linux-private/linux/in6.h \ + include/linux-private/linux/in_route.h \ + include/linux-private/linux/inet_diag.h \ + include/linux-private/linux/ioctl.h \ + include/linux-private/linux/ip.h \ + include/linux-private/linux/ipv6.h \ + include/linux-private/linux/libc-compat.h \ + include/linux-private/linux/limits.h \ + include/linux-private/linux/lwtunnel.h \ + include/linux-private/linux/mpls.h \ + include/linux-private/linux/mpls_iptunnel.h \ + include/linux-private/linux/neighbour.h \ + include/linux-private/linux/netconf.h \ + include/linux-private/linux/netdevice.h \ + include/linux-private/linux/netfilter.h \ + include/linux-private/linux/netfilter/nf_conntrack_common.h \ + include/linux-private/linux/netfilter/nf_conntrack_tcp.h \ + include/linux-private/linux/netfilter/nfnetlink.h \ + include/linux-private/linux/netfilter/nfnetlink_compat.h \ + include/linux-private/linux/netfilter/nfnetlink_conntrack.h \ + include/linux-private/linux/netfilter/nfnetlink_log.h \ + include/linux-private/linux/netfilter/nfnetlink_queue.h \ + include/linux-private/linux/netlink.h \ + include/linux-private/linux/nexthop.h \ + include/linux-private/linux/pkt_cls.h \ + include/linux-private/linux/pkt_sched.h \ + include/linux-private/linux/posix_types.h \ + include/linux-private/linux/rtnetlink.h \ + include/linux-private/linux/seg6.h \ + include/linux-private/linux/seg6_hmac.h \ + include/linux-private/linux/seg6_iptunnel.h \ + include/linux-private/linux/seg6_local.h \ + include/linux-private/linux/snmp.h \ + include/linux-private/linux/sock_diag.h \ + include/linux-private/linux/socket.h \ + include/linux-private/linux/stddef.h \ + include/linux-private/linux/swab.h \ + include/linux-private/linux/taskstats.h \ + include/linux-private/linux/tc_act/tc_gact.h \ + include/linux-private/linux/tc_act/tc_mirred.h \ + include/linux-private/linux/tc_act/tc_nat.h \ + include/linux-private/linux/tc_act/tc_skbedit.h \ + include/linux-private/linux/tc_act/tc_vlan.h \ + include/linux-private/linux/tc_ematch/tc_em_cmp.h \ + include/linux-private/linux/tc_ematch/tc_em_meta.h \ + include/linux-private/linux/tc_ematch/tc_em_nbyte.h \ + include/linux-private/linux/tc_ematch/tc_em_text.h \ + include/linux-private/linux/types.h \ + include/linux-private/linux/version.h \ + include/linux-private/linux/veth.h \ + include/linux-private/linux/xfrm.h \ + include/nl-aux-core/nl-core.h \ + include/nl-aux-route/nl-route.h \ + include/nl-aux-xfrm/nl-xfrm.h \ + include/nl-default.h \ + include/nl-priv-dynamic-core/cache-api.h \ + include/nl-priv-dynamic-core/nl-core.h \ + include/nl-priv-dynamic-core/object-api.h \ + include/nl-priv-dynamic-route/nl-priv-dynamic-route.h \ + include/nl-priv-static-route/nl-priv-static-route.h \ + $(NULL) + +grammar_files_sources = \ + lib/route/cls/ematch_grammar.c \ + lib/route/cls/ematch_syntax.c \ + lib/route/pktloc_grammar.c \ + lib/route/pktloc_syntax.c \ + $(NULL) + +grammar_files_headers = $(grammar_files_sources:%.c=%.h) + +############################################################################### +default_includes = \ + -I$(srcdir)/include/linux-private \ + -I$(srcdir)/include \ + -I$(builddir)/include \ + $(NULL) + +lib_cppflags = \ + $(warn_cppflags) \ + -D_GNU_SOURCE \ + -DSYSCONFDIR=\"$(sysconfdir)/libnl\" \ + $(default_includes) \ + $(NULL) + +lib_libnl_3_la_SOURCES = \ + lib/addr.c \ + lib/attr.c \ + lib/cache.c \ + lib/cache_mngr.c \ + lib/cache_mngt.c \ + lib/data.c \ + lib/error.c \ + lib/handlers.c \ + lib/hash.c \ + lib/hashtable.c \ + lib/mpls.c \ + lib/mpls.h \ + lib/msg.c \ + lib/nl-core.h \ + lib/nl.c \ + lib/object.c \ + lib/socket.c \ + lib/utils.c \ + lib/version.c \ + $(NULL) + +EXTRA_lib_libnl_3_la_DEPENDENCIES = \ + libnl-3.sym + +lib_libnl_3_la_CPPFLAGS = \ + $(lib_cppflags) -all: all-recursive +lib_libnl_3_la_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -Wl,--version-script=$(srcdir)/libnl-3.sym + +lib_libnl_route_3_la_SOURCES = \ + lib/fib_lookup/lookup.c \ + lib/fib_lookup/request.c \ + lib/route/act.c \ + lib/route/act/gact.c \ + lib/route/act/mirred.c \ + lib/route/act/nat.c \ + lib/route/act/skbedit.c \ + lib/route/act/vlan.c \ + lib/route/addr.c \ + lib/route/class.c \ + lib/route/classid.c \ + lib/route/cls.c \ + lib/route/cls/basic.c \ + lib/route/cls/cgroup.c \ + lib/route/cls/ematch.c \ + lib/route/cls/ematch/cmp.c \ + lib/route/cls/ematch/container.c \ + lib/route/cls/ematch/meta.c \ + lib/route/cls/ematch/nbyte.c \ + lib/route/cls/ematch/text.c \ + lib/route/cls/flower.c \ + lib/route/cls/fw.c \ + lib/route/cls/mall.c \ + lib/route/cls/police.c \ + lib/route/cls/u32.c \ + lib/route/link-sriov.h \ + lib/route/link.c \ + lib/route/link/api.c \ + lib/route/link/bonding.c \ + lib/route/link/bridge.c \ + lib/route/link/bridge_info.c \ + lib/route/link/can.c \ + lib/route/link/dummy.c \ + lib/route/link/geneve.c \ + lib/route/link/ifb.c \ + lib/route/link/inet.c \ + lib/route/link/inet6.c \ + lib/route/link/ip6gre.c \ + lib/route/link/ip6tnl.c \ + lib/route/link/ip6vti.c \ + lib/route/link/ipgre.c \ + lib/route/link/ipip.c \ + lib/route/link/ipvlan.c \ + lib/route/link/ipvti.c \ + lib/route/link/link-api.h \ + lib/route/link/macsec.c \ + lib/route/link/macvlan.c \ + lib/route/link/ppp.c \ + lib/route/link/sit.c \ + lib/route/link/sriov.c \ + lib/route/link/team.c \ + lib/route/link/veth.c \ + lib/route/link/vlan.c \ + lib/route/link/vrf.c \ + lib/route/link/vxlan.c \ + lib/route/link/xfrmi.c \ + lib/route/mdb.c \ + lib/route/neigh.c \ + lib/route/neightbl.c \ + lib/route/netconf.c \ + lib/route/nexthop-encap.h \ + lib/route/nexthop.c \ + lib/route/nexthop_encap.c \ + lib/route/nh.c \ + lib/route/nh_encap_mpls.c \ + lib/route/nl-route.h \ + lib/route/pktloc.c \ + lib/route/qdisc.c \ + lib/route/qdisc/blackhole.c \ + lib/route/qdisc/cbq.c \ + lib/route/qdisc/dsmark.c \ + lib/route/qdisc/fifo.c \ + lib/route/qdisc/fq_codel.c \ + lib/route/qdisc/hfsc.c \ + lib/route/qdisc/htb.c \ + lib/route/qdisc/ingress.c \ + lib/route/qdisc/mqprio.c \ + lib/route/qdisc/netem.c \ + lib/route/qdisc/plug.c \ + lib/route/qdisc/prio.c \ + lib/route/qdisc/red.c \ + lib/route/qdisc/sfq.c \ + lib/route/qdisc/tbf.c \ + lib/route/route.c \ + lib/route/route_obj.c \ + lib/route/route_utils.c \ + lib/route/rtnl.c \ + lib/route/rule.c \ + lib/route/tc-api.h \ + lib/route/tc.c \ + $(NULL) + +nodist_lib_libnl_route_3_la_SOURCES = \ + $(grammar_files_sources) + +EXTRA_lib_libnl_route_3_la_DEPENDENCIES = \ + libnl-route-3.sym + +lib_libnl_route_3_la_CPPFLAGS = \ + $(lib_cppflags) \ + -I$(srcdir)/lib/route \ + -I$(builddir)/lib/route \ + -I$(builddir)/lib/route/cls \ + $(NULL) + +lib_libnl_route_3_la_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -Wl,--version-script=$(srcdir)/libnl-route-3.sym + +lib_libnl_route_3_la_LIBADD = \ + lib/libnl-3.la + +lib_libnl_idiag_3_la_SOURCES = \ + lib/idiag/idiag.c \ + lib/idiag/idiag_meminfo_obj.c \ + lib/idiag/idiag_msg_obj.c \ + lib/idiag/idiag_req_obj.c \ + lib/idiag/idiag_vegasinfo_obj.c \ + lib/idiag/nl-idiag.h \ + $(NULL) + +EXTRA_lib_libnl_idiag_3_la_DEPENDENCIES = \ + libnl-idiag-3.sym + +lib_libnl_idiag_3_la_CPPFLAGS = \ + $(lib_cppflags) + +lib_libnl_idiag_3_la_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -Wl,--version-script=$(srcdir)/libnl-idiag-3.sym + +lib_libnl_idiag_3_la_LIBADD = \ + lib/libnl-3.la + +lib_libnl_genl_3_la_SOURCES = \ + lib/genl/ctrl.c \ + lib/genl/family.c \ + lib/genl/genl.c \ + lib/genl/mngt.c \ + lib/genl/nl-genl.h \ + $(NULL) + +EXTRA_lib_libnl_genl_3_la_DEPENDENCIES = \ + libnl-genl-3.sym + +lib_libnl_genl_3_la_CPPFLAGS = \ + $(lib_cppflags) + +lib_libnl_genl_3_la_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -Wl,--version-script=$(srcdir)/libnl-genl-3.sym + +lib_libnl_genl_3_la_LIBADD = \ + lib/libnl-3.la + +lib_libnl_nf_3_la_SOURCES = \ + lib/netfilter/ct.c \ + lib/netfilter/ct_obj.c \ + lib/netfilter/exp.c \ + lib/netfilter/exp_obj.c \ + lib/netfilter/log.c \ + lib/netfilter/log_msg.c \ + lib/netfilter/log_msg_obj.c \ + lib/netfilter/log_obj.c \ + lib/netfilter/netfilter.c \ + lib/netfilter/nfnl.c \ + lib/netfilter/nl-netfilter.h \ + lib/netfilter/queue.c \ + lib/netfilter/queue_msg.c \ + lib/netfilter/queue_msg_obj.c \ + lib/netfilter/queue_obj.c \ + $(NULL) + +lib_libnl_nf_3_la_CPPFLAGS = \ + $(lib_cppflags) + +EXTRA_lib_libnl_nf_3_la_DEPENDENCIES = \ + libnl-nf-3.sym + +lib_libnl_nf_3_la_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -Wl,--version-script=$(srcdir)/libnl-nf-3.sym + +lib_libnl_nf_3_la_LIBADD = \ + lib/libnl-3.la \ + lib/libnl-route-3.la + +lib_libnl_xfrm_3_la_SOURCES = \ + lib/xfrm/ae.c \ + lib/xfrm/lifetime.c \ + lib/xfrm/nl-xfrm.h \ + lib/xfrm/sa.c \ + lib/xfrm/selector.c \ + lib/xfrm/sp.c \ + lib/xfrm/template.c \ + $(NULL) + +lib_libnl_xfrm_3_la_CPPFLAGS = \ + $(lib_cppflags) + +lib_libnl_xfrm_3_la_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -Wl,--version-script=$(srcdir)/libnl-xfrm-3.sym + +EXTRA_lib_libnl_xfrm_3_la_DEPENDENCIES = \ + libnl-xfrm-3.sym + +lib_libnl_xfrm_3_la_LIBADD = \ + lib/libnl-3.la + +lib_cli_ltlibraries_cls = \ + lib/cli/cls/basic.la \ + lib/cli/cls/cgroup.la \ + $(NULL) + +lib_cli_ltlibraries_qdisc = \ + lib/cli/qdisc/bfifo.la \ + lib/cli/qdisc/blackhole.la \ + lib/cli/qdisc/fq_codel.la \ + lib/cli/qdisc/hfsc.la \ + lib/cli/qdisc/htb.la \ + lib/cli/qdisc/ingress.la \ + lib/cli/qdisc/pfifo.la \ + lib/cli/qdisc/plug.la \ + $(NULL) + +@ENABLE_CLI_TRUE@pkglib_clsdir = $(pkglibdir)/cli/cls +@ENABLE_CLI_TRUE@pkglib_qdiscdir = $(pkglibdir)/cli/qdisc +@ENABLE_CLI_TRUE@pkglib_cls_LTLIBRARIES = $(lib_cli_ltlibraries_cls) +@ENABLE_CLI_TRUE@pkglib_qdisc_LTLIBRARIES = $(lib_cli_ltlibraries_qdisc) +lib_cli_ldflags = \ + -module -avoid-version + +lib_cli_cls_basic_la_CPPFLAGS = $(lib_cppflags) +lib_cli_cls_basic_la_LDFLAGS = $(lib_cli_ldflags) +lib_cli_cls_cgroup_la_CPPFLAGS = $(lib_cppflags) +lib_cli_cls_cgroup_la_LDFLAGS = $(lib_cli_ldflags) +lib_cli_qdisc_bfifo_la_CPPFLAGS = $(lib_cppflags) +lib_cli_qdisc_bfifo_la_LDFLAGS = $(lib_cli_ldflags) +lib_cli_qdisc_blackhole_la_CPPFLAGS = $(lib_cppflags) +lib_cli_qdisc_blackhole_la_LDFLAGS = $(lib_cli_ldflags) +lib_cli_qdisc_fq_codel_la_CPPFLAGS = $(lib_cppflags) +lib_cli_qdisc_fq_codel_la_LDFLAGS = $(lib_cli_ldflags) +lib_cli_qdisc_hfsc_la_CPPFLAGS = $(lib_cppflags) +lib_cli_qdisc_hfsc_la_LDFLAGS = $(lib_cli_ldflags) +lib_cli_qdisc_htb_la_CPPFLAGS = $(lib_cppflags) +lib_cli_qdisc_htb_la_LDFLAGS = $(lib_cli_ldflags) +lib_cli_qdisc_ingress_la_CPPFLAGS = $(lib_cppflags) +lib_cli_qdisc_ingress_la_LDFLAGS = $(lib_cli_ldflags) +lib_cli_qdisc_pfifo_la_CPPFLAGS = $(lib_cppflags) +lib_cli_qdisc_pfifo_la_LDFLAGS = $(lib_cli_ldflags) +lib_cli_qdisc_plug_la_CPPFLAGS = $(lib_cppflags) +lib_cli_qdisc_plug_la_LDFLAGS = $(lib_cli_ldflags) + +############################################################################### +src_lib_ldflags = $(am__append_3) +src_lib_libnl_cli_3_la_SOURCES = \ + src/lib/addr.c \ + src/lib/class.c \ + src/lib/cls.c \ + src/lib/ct.c \ + src/lib/exp.c \ + src/lib/link.c \ + src/lib/neigh.c \ + src/lib/nh.c \ + src/lib/qdisc.c \ + src/lib/route.c \ + src/lib/rule.c \ + src/lib/tc.c \ + src/lib/utils.c \ + $(NULL) + +EXTRA_src_lib_libnl_cli_3_la_DEPENDENCIES = \ + libnl-cli-3.sym + +src_lib_libnl_cli_3_la_CPPFLAGS = \ + $(warn_cppflags) \ + -D_GNU_SOURCE \ + -DPKGLIBDIR=\"$(pkglibdir)\" \ + -DSYSCONFDIR=\"$(sysconfdir)\" \ + $(default_includes) \ + $(NULL) + +src_lib_libnl_cli_3_la_LDFLAGS = \ + $(src_lib_ldflags) \ + -Wl,--version-script=$(srcdir)/libnl-cli-3.sym + +src_lib_libnl_cli_3_la_LIBADD = \ + lib/libnl-3.la \ + lib/libnl-route-3.la \ + lib/libnl-nf-3.la \ + lib/libnl-genl-3.la \ + -ldl \ + $(NULL) + + +############################################################################### +src_cppflags = \ + $(warn_cppflags) \ + -D_GNU_SOURCE \ + -DSYSCONFDIR=\"$(sysconfdir)/libnl\" \ + $(default_includes) \ + $(NULL) + +src_ldadd = \ + src/lib/libnl-cli-3.la \ + lib/libnl-3.la \ + lib/libnl-nf-3.la \ + lib/libnl-genl-3.la \ + lib/libnl-route-3.la \ + lib/libnl-idiag-3.la \ + $(NULL) + +cli_programs = \ + src/genl-ctrl-list \ + src/idiag-socket-details \ + src/nf-ct-add \ + src/nf-ct-events \ + src/nf-ct-list \ + src/nf-exp-add \ + src/nf-exp-delete \ + src/nf-exp-list \ + src/nf-log \ + src/nf-monitor \ + src/nf-queue \ + src/nl-addr-add \ + src/nl-addr-delete \ + src/nl-addr-list \ + src/nl-class-add \ + src/nl-class-delete \ + src/nl-class-list \ + src/nl-classid-lookup \ + src/nl-cls-add \ + src/nl-cls-delete \ + src/nl-cls-list \ + src/nl-fib-lookup \ + src/nl-link-enslave \ + src/nl-link-ifindex2name \ + src/nl-link-list \ + src/nl-link-name2ifindex \ + src/nl-link-release \ + src/nl-link-set \ + src/nl-link-stats \ + src/nl-list-caches \ + src/nl-list-sockets \ + src/nl-monitor \ + src/nl-neigh-add \ + src/nl-neigh-delete \ + src/nl-neigh-list \ + src/nl-neightbl-list \ + src/nl-nh-list \ + src/nl-pktloc-lookup \ + src/nl-qdisc-add \ + src/nl-qdisc-delete \ + src/nl-qdisc-list \ + src/nl-route-add \ + src/nl-route-delete \ + src/nl-route-get \ + src/nl-route-list \ + src/nl-rule-list \ + src/nl-tctree-list \ + src/nl-util-addr \ + $(NULL) + +src_genl_ctrl_list_CPPFLAGS = $(src_cppflags) +src_genl_ctrl_list_LDADD = $(src_ldadd) +src_idiag_socket_details_CPPFLAGS = $(src_cppflags) +src_idiag_socket_details_LDADD = $(src_ldadd) +src_nf_ct_add_CPPFLAGS = $(src_cppflags) +src_nf_ct_add_LDADD = $(src_ldadd) +src_nf_ct_events_CPPFLAGS = $(src_cppflags) +src_nf_ct_events_LDADD = $(src_ldadd) +src_nf_ct_list_CPPFLAGS = $(src_cppflags) +src_nf_ct_list_LDADD = $(src_ldadd) +src_nf_exp_add_CPPFLAGS = $(src_cppflags) +src_nf_exp_add_LDADD = $(src_ldadd) +src_nf_exp_delete_CPPFLAGS = $(src_cppflags) +src_nf_exp_delete_LDADD = $(src_ldadd) +src_nf_exp_list_CPPFLAGS = $(src_cppflags) +src_nf_exp_list_LDADD = $(src_ldadd) +src_nf_log_CPPFLAGS = $(src_cppflags) +src_nf_log_LDADD = $(src_ldadd) +src_nf_monitor_CPPFLAGS = $(src_cppflags) +src_nf_monitor_LDADD = $(src_ldadd) +src_nf_queue_CPPFLAGS = $(src_cppflags) +src_nf_queue_LDADD = $(src_ldadd) +src_nl_addr_add_CPPFLAGS = $(src_cppflags) +src_nl_addr_add_LDADD = $(src_ldadd) +src_nl_addr_delete_CPPFLAGS = $(src_cppflags) +src_nl_addr_delete_LDADD = $(src_ldadd) +src_nl_addr_list_CPPFLAGS = $(src_cppflags) +src_nl_addr_list_LDADD = $(src_ldadd) +src_nl_class_add_CPPFLAGS = $(src_cppflags) +src_nl_class_add_LDADD = $(src_ldadd) +src_nl_class_delete_CPPFLAGS = $(src_cppflags) +src_nl_class_delete_LDADD = $(src_ldadd) +src_nl_class_list_CPPFLAGS = $(src_cppflags) +src_nl_class_list_LDADD = $(src_ldadd) +src_nl_classid_lookup_CPPFLAGS = $(src_cppflags) +src_nl_classid_lookup_LDADD = $(src_ldadd) +src_nl_cls_add_CPPFLAGS = $(src_cppflags) +src_nl_cls_add_LDADD = $(src_ldadd) +src_nl_cls_delete_CPPFLAGS = $(src_cppflags) +src_nl_cls_delete_LDADD = $(src_ldadd) +src_nl_cls_list_CPPFLAGS = $(src_cppflags) +src_nl_cls_list_LDADD = $(src_ldadd) +src_nl_fib_lookup_CPPFLAGS = $(src_cppflags) +src_nl_fib_lookup_LDADD = $(src_ldadd) +src_nl_link_enslave_CPPFLAGS = $(src_cppflags) +src_nl_link_enslave_LDADD = $(src_ldadd) +src_nl_link_ifindex2name_CPPFLAGS = $(src_cppflags) +src_nl_link_ifindex2name_LDADD = $(src_ldadd) +src_nl_link_list_CPPFLAGS = $(src_cppflags) +src_nl_link_list_LDADD = $(src_ldadd) +src_nl_link_name2ifindex_CPPFLAGS = $(src_cppflags) +src_nl_link_name2ifindex_LDADD = $(src_ldadd) +src_nl_link_release_CPPFLAGS = $(src_cppflags) +src_nl_link_release_LDADD = $(src_ldadd) +src_nl_link_set_CPPFLAGS = $(src_cppflags) +src_nl_link_set_LDADD = $(src_ldadd) +src_nl_link_stats_CPPFLAGS = $(src_cppflags) +src_nl_link_stats_LDADD = $(src_ldadd) +src_nl_list_caches_CPPFLAGS = $(src_cppflags) +src_nl_list_caches_LDADD = $(src_ldadd) +src_nl_list_sockets_CPPFLAGS = $(src_cppflags) +src_nl_list_sockets_LDADD = $(src_ldadd) +src_nl_monitor_CPPFLAGS = $(src_cppflags) +src_nl_monitor_LDADD = $(src_ldadd) +src_nl_neigh_add_CPPFLAGS = $(src_cppflags) +src_nl_neigh_add_LDADD = $(src_ldadd) +src_nl_neigh_delete_CPPFLAGS = $(src_cppflags) +src_nl_neigh_delete_LDADD = $(src_ldadd) +src_nl_neigh_list_CPPFLAGS = $(src_cppflags) +src_nl_neigh_list_LDADD = $(src_ldadd) +src_nl_neightbl_list_CPPFLAGS = $(src_cppflags) +src_nl_neightbl_list_LDADD = $(src_ldadd) +src_nl_nh_list_CPPFLAGS = $(src_cppflags) +src_nl_nh_list_LDADD = $(src_ldadd) +src_nl_pktloc_lookup_CPPFLAGS = $(src_cppflags) +src_nl_pktloc_lookup_LDADD = $(src_ldadd) +src_nl_qdisc_add_CPPFLAGS = $(src_cppflags) +src_nl_qdisc_add_LDADD = $(src_ldadd) +src_nl_qdisc_delete_CPPFLAGS = $(src_cppflags) +src_nl_qdisc_delete_LDADD = $(src_ldadd) +src_nl_qdisc_list_CPPFLAGS = $(src_cppflags) +src_nl_qdisc_list_LDADD = $(src_ldadd) +src_nl_route_add_CPPFLAGS = $(src_cppflags) +src_nl_route_add_LDADD = $(src_ldadd) +src_nl_route_delete_CPPFLAGS = $(src_cppflags) +src_nl_route_delete_LDADD = $(src_ldadd) +src_nl_route_get_CPPFLAGS = $(src_cppflags) +src_nl_route_get_LDADD = $(src_ldadd) +src_nl_route_list_CPPFLAGS = $(src_cppflags) +src_nl_route_list_LDADD = $(src_ldadd) +src_nl_rule_list_CPPFLAGS = $(src_cppflags) +src_nl_rule_list_LDADD = $(src_ldadd) +src_nl_tctree_list_CPPFLAGS = $(src_cppflags) +src_nl_tctree_list_LDADD = $(src_ldadd) +src_nl_util_addr_CPPFLAGS = $(src_cppflags) +src_nl_util_addr_LDADD = $(src_ldadd) + +############################################################################### +tests_cppflags = \ + $(warn_cppflags) \ + -D_GNU_SOURCE \ + -DSYSCONFDIR=\"$(sysconfdir)/libnl\" \ + $(default_includes) \ + $(NULL) + +tests_ldadd = \ + lib/libnl-3.la \ + lib/libnl-nf-3.la \ + lib/libnl-genl-3.la \ + lib/libnl-route-3.la \ + $(NULL) + +tests_libnl_test_util_la_SOURCES = \ + tests/nl-test-util.h \ + tests/nl-test-util.c \ + $(NULL) + +tests_libnl_test_util_la_CPPFLAGS = \ + $(tests_cppflags) \ + $(CHECK_CFLAGS) \ + $(NULL) + +tests_libnl_test_util_la_LIBADD = \ + $(tests_ldadd) \ + $(CHECK_LIBS) \ + $(NULL) + +tests_test_complex_HTB_with_hash_filters_CPPFLAGS = $(tests_cppflags) +tests_test_complex_HTB_with_hash_filters_LDADD = $(tests_ldadd) +tests_test_create_bond_CPPFLAGS = $(tests_cppflags) +tests_test_create_bond_LDADD = $(tests_ldadd) +tests_test_create_bridge_CPPFLAGS = $(tests_cppflags) +tests_test_create_bridge_LDADD = $(tests_ldadd) +tests_test_create_geneve_CPPFLAGS = $(tests_cppflags) +tests_test_create_geneve_LDADD = $(tests_ldadd) +tests_test_create_ifb_CPPFLAGS = $(tests_cppflags) +tests_test_create_ifb_LDADD = $(tests_ldadd) +tests_test_create_ip6tnl_CPPFLAGS = $(tests_cppflags) +tests_test_create_ip6tnl_LDADD = $(tests_ldadd) +tests_test_create_ipgre_CPPFLAGS = $(tests_cppflags) +tests_test_create_ipgre_LDADD = $(tests_ldadd) +tests_test_create_ipgretap_CPPFLAGS = $(tests_cppflags) +tests_test_create_ipgretap_LDADD = $(tests_ldadd) +tests_test_create_ipip_CPPFLAGS = $(tests_cppflags) +tests_test_create_ipip_LDADD = $(tests_ldadd) +tests_test_create_ipvlan_CPPFLAGS = $(tests_cppflags) +tests_test_create_ipvlan_LDADD = $(tests_ldadd) +tests_test_create_ipvti_CPPFLAGS = $(tests_cppflags) +tests_test_create_ipvti_LDADD = $(tests_ldadd) +tests_test_create_macsec_CPPFLAGS = $(tests_cppflags) +tests_test_create_macsec_LDADD = $(tests_ldadd) +tests_test_create_macvlan_CPPFLAGS = $(tests_cppflags) +tests_test_create_macvlan_LDADD = $(tests_ldadd) +tests_test_create_macvtap_CPPFLAGS = $(tests_cppflags) +tests_test_create_macvtap_LDADD = $(tests_ldadd) +tests_test_create_sit_CPPFLAGS = $(tests_cppflags) +tests_test_create_sit_LDADD = $(tests_ldadd) +tests_test_create_veth_CPPFLAGS = $(tests_cppflags) +tests_test_create_veth_LDADD = $(tests_ldadd) +tests_test_create_vlan_CPPFLAGS = $(tests_cppflags) +tests_test_create_vlan_LDADD = $(tests_ldadd) +tests_test_create_vrf_CPPFLAGS = $(tests_cppflags) +tests_test_create_vrf_LDADD = $(tests_ldadd) +tests_test_create_vxlan_CPPFLAGS = $(tests_cppflags) +tests_test_create_vxlan_LDADD = $(tests_ldadd) +tests_test_create_xfrmi_CPPFLAGS = $(tests_cppflags) +tests_test_create_xfrmi_LDADD = $(tests_ldadd) +tests_test_delete_link_CPPFLAGS = $(tests_cppflags) +tests_test_delete_link_LDADD = $(tests_ldadd) +tests_test_loopback_up_down_CPPFLAGS = $(tests_cppflags) +tests_test_loopback_up_down_LDADD = $(tests_ldadd) +tests_test_socket_creation_CPPFLAGS = $(tests_cppflags) +tests_test_socket_creation_LDADD = $(tests_ldadd) +tests_test_u32_filter_with_actions_CPPFLAGS = $(tests_cppflags) +tests_test_u32_filter_with_actions_LDADD = $(tests_ldadd) +tests_cli_ldadd = \ + $(tests_ldadd) \ + src/lib/libnl-cli-3.la \ + $(NULL) + +tests_test_cache_mngr_CPPFLAGS = $(tests_cppflags) +tests_test_cache_mngr_LDADD = $(tests_cli_ldadd) +tests_test_genl_CPPFLAGS = $(tests_cppflags) +tests_test_genl_LDADD = $(tests_cli_ldadd) +tests_test_nf_cache_mngr_CPPFLAGS = $(tests_cppflags) +tests_test_nf_cache_mngr_LDADD = $(tests_cli_ldadd) +tests_check_all_SOURCES = \ + tests/check-all.c \ + tests/cksuite-all-addr.c \ + tests/cksuite-all-attr.c \ + tests/cksuite-all-ematch-tree-clone.c \ + tests/cksuite-all-netns.c \ + tests/cksuite-all.h \ + $(NULL) + +tests_check_all_CPPFLAGS = \ + $(tests_cppflags) \ + $(CHECK_CFLAGS) + +tests_check_all_LDADD = \ + $(tests_ldadd) \ + tests/libnl-test-util.la \ + $(CHECK_LIBS) \ + $(NULL) + +tests_check_direct_SOURCES = \ + tests/check-direct.c \ + $(NULL) + +tests_check_direct_CPPFLAGS = \ + $(tests_cppflags) \ + $(CHECK_CFLAGS) \ + $(NULL) + +tests_check_direct_LDFLAGS = \ + -static \ + $(NULL) + +tests_check_direct_LDADD = \ + $(tests_ldadd) \ + tests/libnl-test-util.la \ + $(CHECK_LIBS) \ + $(NULL) + + +############################################################################### +dist_man8_MANS = \ + man/genl-ctrl-list.8 \ + man/nl-classid-lookup.8 \ + man/nl-pktloc-lookup.8 \ + man/nl-qdisc-add.8 \ + man/nl-qdisc-delete.8 \ + man/nl-qdisc-list.8 \ + $(NULL) + +BUILD_HEADERS_OBJS = $(patsubst %,%.build-headers-test.o,$(public_headers)) +pkgsysconfdir = $(sysconfdir)/libnl +pkgsysconf_DATA = \ + etc/pktloc \ + etc/classid + +all: all-am .SUFFIXES: +.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @@ -334,15 +2618,14 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -353,6 +2636,21 @@ $(top_srcdir)/configure: $(am__configure_deps) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): + +include/config.h: include/stamp-h1 + @test -f $@ || rm -f include/stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) include/stamp-h1 + +include/stamp-h1: $(top_srcdir)/include/config.h.in $(top_builddir)/config.status + @rm -f include/stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status include/config.h +$(top_srcdir)/include/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f include/stamp-h1 + touch $@ + +distclean-hdr: + -rm -f include/config.h include/stamp-h1 libnl-3.0.pc: $(top_builddir)/config.status $(srcdir)/libnl-3.0.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ libnl-route-3.0.pc: $(top_builddir)/config.status $(srcdir)/libnl-route-3.0.pc.in @@ -363,17 +2661,3890 @@ libnl-nf-3.0.pc: $(top_builddir)/config.status $(srcdir)/libnl-nf-3.0.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ libnl-cli-3.0.pc: $(top_builddir)/config.status $(srcdir)/libnl-cli-3.0.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ +libnl-xfrm-3.0.pc: $(top_builddir)/config.status $(srcdir)/libnl-xfrm-3.0.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +libnl-idiag-3.0.pc: $(top_builddir)/config.status $(srcdir)/libnl-idiag-3.0.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +python/setup.py: $(top_builddir)/config.status $(top_srcdir)/python/setup.py.in + cd $(top_builddir) && $(SHELL) ./config.status $@ include/netlink/version.h: $(top_builddir)/config.status $(top_srcdir)/include/netlink/version.h.in cd $(top_builddir) && $(SHELL) ./config.status $@ +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sbindir)" && rm -f $$files + +clean-sbinPROGRAMS: + @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-checkLTLIBRARIES: + -test -z "$(check_LTLIBRARIES)" || rm -f $(check_LTLIBRARIES) + @list='$(check_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-pkglib_clsLTLIBRARIES: $(pkglib_cls_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_cls_LTLIBRARIES)'; test -n "$(pkglib_clsdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglib_clsdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglib_clsdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglib_clsdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglib_clsdir)"; \ + } + +uninstall-pkglib_clsLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_cls_LTLIBRARIES)'; test -n "$(pkglib_clsdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglib_clsdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglib_clsdir)/$$f"; \ + done + +clean-pkglib_clsLTLIBRARIES: + -test -z "$(pkglib_cls_LTLIBRARIES)" || rm -f $(pkglib_cls_LTLIBRARIES) + @list='$(pkglib_cls_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-pkglib_qdiscLTLIBRARIES: $(pkglib_qdisc_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_qdisc_LTLIBRARIES)'; test -n "$(pkglib_qdiscdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglib_qdiscdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglib_qdiscdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglib_qdiscdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglib_qdiscdir)"; \ + } + +uninstall-pkglib_qdiscLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_qdisc_LTLIBRARIES)'; test -n "$(pkglib_qdiscdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglib_qdiscdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglib_qdiscdir)/$$f"; \ + done + +clean-pkglib_qdiscLTLIBRARIES: + -test -z "$(pkglib_qdisc_LTLIBRARIES)" || rm -f $(pkglib_qdisc_LTLIBRARIES) + @list='$(pkglib_qdisc_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +lib/cli/cls/$(am__dirstamp): + @$(MKDIR_P) lib/cli/cls + @: > lib/cli/cls/$(am__dirstamp) +lib/cli/cls/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/cli/cls/$(DEPDIR) + @: > lib/cli/cls/$(DEPDIR)/$(am__dirstamp) +lib/cli/cls/basic_la-basic.lo: lib/cli/cls/$(am__dirstamp) \ + lib/cli/cls/$(DEPDIR)/$(am__dirstamp) + +lib/cli/cls/basic.la: $(lib_cli_cls_basic_la_OBJECTS) $(lib_cli_cls_basic_la_DEPENDENCIES) $(EXTRA_lib_cli_cls_basic_la_DEPENDENCIES) lib/cli/cls/$(am__dirstamp) + $(AM_V_CCLD)$(lib_cli_cls_basic_la_LINK) $(am_lib_cli_cls_basic_la_rpath) $(lib_cli_cls_basic_la_OBJECTS) $(lib_cli_cls_basic_la_LIBADD) $(LIBS) +lib/cli/cls/cgroup_la-cgroup.lo: lib/cli/cls/$(am__dirstamp) \ + lib/cli/cls/$(DEPDIR)/$(am__dirstamp) + +lib/cli/cls/cgroup.la: $(lib_cli_cls_cgroup_la_OBJECTS) $(lib_cli_cls_cgroup_la_DEPENDENCIES) $(EXTRA_lib_cli_cls_cgroup_la_DEPENDENCIES) lib/cli/cls/$(am__dirstamp) + $(AM_V_CCLD)$(lib_cli_cls_cgroup_la_LINK) $(am_lib_cli_cls_cgroup_la_rpath) $(lib_cli_cls_cgroup_la_OBJECTS) $(lib_cli_cls_cgroup_la_LIBADD) $(LIBS) +lib/cli/qdisc/$(am__dirstamp): + @$(MKDIR_P) lib/cli/qdisc + @: > lib/cli/qdisc/$(am__dirstamp) +lib/cli/qdisc/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/cli/qdisc/$(DEPDIR) + @: > lib/cli/qdisc/$(DEPDIR)/$(am__dirstamp) +lib/cli/qdisc/bfifo_la-bfifo.lo: lib/cli/qdisc/$(am__dirstamp) \ + lib/cli/qdisc/$(DEPDIR)/$(am__dirstamp) + +lib/cli/qdisc/bfifo.la: $(lib_cli_qdisc_bfifo_la_OBJECTS) $(lib_cli_qdisc_bfifo_la_DEPENDENCIES) $(EXTRA_lib_cli_qdisc_bfifo_la_DEPENDENCIES) lib/cli/qdisc/$(am__dirstamp) + $(AM_V_CCLD)$(lib_cli_qdisc_bfifo_la_LINK) $(am_lib_cli_qdisc_bfifo_la_rpath) $(lib_cli_qdisc_bfifo_la_OBJECTS) $(lib_cli_qdisc_bfifo_la_LIBADD) $(LIBS) +lib/cli/qdisc/blackhole_la-blackhole.lo: \ + lib/cli/qdisc/$(am__dirstamp) \ + lib/cli/qdisc/$(DEPDIR)/$(am__dirstamp) + +lib/cli/qdisc/blackhole.la: $(lib_cli_qdisc_blackhole_la_OBJECTS) $(lib_cli_qdisc_blackhole_la_DEPENDENCIES) $(EXTRA_lib_cli_qdisc_blackhole_la_DEPENDENCIES) lib/cli/qdisc/$(am__dirstamp) + $(AM_V_CCLD)$(lib_cli_qdisc_blackhole_la_LINK) $(am_lib_cli_qdisc_blackhole_la_rpath) $(lib_cli_qdisc_blackhole_la_OBJECTS) $(lib_cli_qdisc_blackhole_la_LIBADD) $(LIBS) +lib/cli/qdisc/fq_codel_la-fq_codel.lo: lib/cli/qdisc/$(am__dirstamp) \ + lib/cli/qdisc/$(DEPDIR)/$(am__dirstamp) + +lib/cli/qdisc/fq_codel.la: $(lib_cli_qdisc_fq_codel_la_OBJECTS) $(lib_cli_qdisc_fq_codel_la_DEPENDENCIES) $(EXTRA_lib_cli_qdisc_fq_codel_la_DEPENDENCIES) lib/cli/qdisc/$(am__dirstamp) + $(AM_V_CCLD)$(lib_cli_qdisc_fq_codel_la_LINK) $(am_lib_cli_qdisc_fq_codel_la_rpath) $(lib_cli_qdisc_fq_codel_la_OBJECTS) $(lib_cli_qdisc_fq_codel_la_LIBADD) $(LIBS) +lib/cli/qdisc/hfsc_la-hfsc.lo: lib/cli/qdisc/$(am__dirstamp) \ + lib/cli/qdisc/$(DEPDIR)/$(am__dirstamp) + +lib/cli/qdisc/hfsc.la: $(lib_cli_qdisc_hfsc_la_OBJECTS) $(lib_cli_qdisc_hfsc_la_DEPENDENCIES) $(EXTRA_lib_cli_qdisc_hfsc_la_DEPENDENCIES) lib/cli/qdisc/$(am__dirstamp) + $(AM_V_CCLD)$(lib_cli_qdisc_hfsc_la_LINK) $(am_lib_cli_qdisc_hfsc_la_rpath) $(lib_cli_qdisc_hfsc_la_OBJECTS) $(lib_cli_qdisc_hfsc_la_LIBADD) $(LIBS) +lib/cli/qdisc/htb_la-htb.lo: lib/cli/qdisc/$(am__dirstamp) \ + lib/cli/qdisc/$(DEPDIR)/$(am__dirstamp) + +lib/cli/qdisc/htb.la: $(lib_cli_qdisc_htb_la_OBJECTS) $(lib_cli_qdisc_htb_la_DEPENDENCIES) $(EXTRA_lib_cli_qdisc_htb_la_DEPENDENCIES) lib/cli/qdisc/$(am__dirstamp) + $(AM_V_CCLD)$(lib_cli_qdisc_htb_la_LINK) $(am_lib_cli_qdisc_htb_la_rpath) $(lib_cli_qdisc_htb_la_OBJECTS) $(lib_cli_qdisc_htb_la_LIBADD) $(LIBS) +lib/cli/qdisc/ingress_la-ingress.lo: lib/cli/qdisc/$(am__dirstamp) \ + lib/cli/qdisc/$(DEPDIR)/$(am__dirstamp) + +lib/cli/qdisc/ingress.la: $(lib_cli_qdisc_ingress_la_OBJECTS) $(lib_cli_qdisc_ingress_la_DEPENDENCIES) $(EXTRA_lib_cli_qdisc_ingress_la_DEPENDENCIES) lib/cli/qdisc/$(am__dirstamp) + $(AM_V_CCLD)$(lib_cli_qdisc_ingress_la_LINK) $(am_lib_cli_qdisc_ingress_la_rpath) $(lib_cli_qdisc_ingress_la_OBJECTS) $(lib_cli_qdisc_ingress_la_LIBADD) $(LIBS) +lib/cli/qdisc/pfifo_la-pfifo.lo: lib/cli/qdisc/$(am__dirstamp) \ + lib/cli/qdisc/$(DEPDIR)/$(am__dirstamp) + +lib/cli/qdisc/pfifo.la: $(lib_cli_qdisc_pfifo_la_OBJECTS) $(lib_cli_qdisc_pfifo_la_DEPENDENCIES) $(EXTRA_lib_cli_qdisc_pfifo_la_DEPENDENCIES) lib/cli/qdisc/$(am__dirstamp) + $(AM_V_CCLD)$(lib_cli_qdisc_pfifo_la_LINK) $(am_lib_cli_qdisc_pfifo_la_rpath) $(lib_cli_qdisc_pfifo_la_OBJECTS) $(lib_cli_qdisc_pfifo_la_LIBADD) $(LIBS) +lib/cli/qdisc/plug_la-plug.lo: lib/cli/qdisc/$(am__dirstamp) \ + lib/cli/qdisc/$(DEPDIR)/$(am__dirstamp) + +lib/cli/qdisc/plug.la: $(lib_cli_qdisc_plug_la_OBJECTS) $(lib_cli_qdisc_plug_la_DEPENDENCIES) $(EXTRA_lib_cli_qdisc_plug_la_DEPENDENCIES) lib/cli/qdisc/$(am__dirstamp) + $(AM_V_CCLD)$(lib_cli_qdisc_plug_la_LINK) $(am_lib_cli_qdisc_plug_la_rpath) $(lib_cli_qdisc_plug_la_OBJECTS) $(lib_cli_qdisc_plug_la_LIBADD) $(LIBS) +lib/$(am__dirstamp): + @$(MKDIR_P) lib + @: > lib/$(am__dirstamp) +lib/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/$(DEPDIR) + @: > lib/$(DEPDIR)/$(am__dirstamp) +lib/libnl_3_la-addr.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libnl_3_la-attr.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libnl_3_la-cache.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libnl_3_la-cache_mngr.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libnl_3_la-cache_mngt.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libnl_3_la-data.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libnl_3_la-error.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libnl_3_la-handlers.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libnl_3_la-hash.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libnl_3_la-hashtable.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libnl_3_la-mpls.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libnl_3_la-msg.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libnl_3_la-nl.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libnl_3_la-object.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libnl_3_la-socket.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libnl_3_la-utils.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libnl_3_la-version.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +lib/libnl-3.la: $(lib_libnl_3_la_OBJECTS) $(lib_libnl_3_la_DEPENDENCIES) $(EXTRA_lib_libnl_3_la_DEPENDENCIES) lib/$(am__dirstamp) + $(AM_V_CCLD)$(lib_libnl_3_la_LINK) -rpath $(libdir) $(lib_libnl_3_la_OBJECTS) $(lib_libnl_3_la_LIBADD) $(LIBS) +lib/genl/$(am__dirstamp): + @$(MKDIR_P) lib/genl + @: > lib/genl/$(am__dirstamp) +lib/genl/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/genl/$(DEPDIR) + @: > lib/genl/$(DEPDIR)/$(am__dirstamp) +lib/genl/libnl_genl_3_la-ctrl.lo: lib/genl/$(am__dirstamp) \ + lib/genl/$(DEPDIR)/$(am__dirstamp) +lib/genl/libnl_genl_3_la-family.lo: lib/genl/$(am__dirstamp) \ + lib/genl/$(DEPDIR)/$(am__dirstamp) +lib/genl/libnl_genl_3_la-genl.lo: lib/genl/$(am__dirstamp) \ + lib/genl/$(DEPDIR)/$(am__dirstamp) +lib/genl/libnl_genl_3_la-mngt.lo: lib/genl/$(am__dirstamp) \ + lib/genl/$(DEPDIR)/$(am__dirstamp) + +lib/libnl-genl-3.la: $(lib_libnl_genl_3_la_OBJECTS) $(lib_libnl_genl_3_la_DEPENDENCIES) $(EXTRA_lib_libnl_genl_3_la_DEPENDENCIES) lib/$(am__dirstamp) + $(AM_V_CCLD)$(lib_libnl_genl_3_la_LINK) -rpath $(libdir) $(lib_libnl_genl_3_la_OBJECTS) $(lib_libnl_genl_3_la_LIBADD) $(LIBS) +lib/idiag/$(am__dirstamp): + @$(MKDIR_P) lib/idiag + @: > lib/idiag/$(am__dirstamp) +lib/idiag/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/idiag/$(DEPDIR) + @: > lib/idiag/$(DEPDIR)/$(am__dirstamp) +lib/idiag/libnl_idiag_3_la-idiag.lo: lib/idiag/$(am__dirstamp) \ + lib/idiag/$(DEPDIR)/$(am__dirstamp) +lib/idiag/libnl_idiag_3_la-idiag_meminfo_obj.lo: \ + lib/idiag/$(am__dirstamp) lib/idiag/$(DEPDIR)/$(am__dirstamp) +lib/idiag/libnl_idiag_3_la-idiag_msg_obj.lo: \ + lib/idiag/$(am__dirstamp) lib/idiag/$(DEPDIR)/$(am__dirstamp) +lib/idiag/libnl_idiag_3_la-idiag_req_obj.lo: \ + lib/idiag/$(am__dirstamp) lib/idiag/$(DEPDIR)/$(am__dirstamp) +lib/idiag/libnl_idiag_3_la-idiag_vegasinfo_obj.lo: \ + lib/idiag/$(am__dirstamp) lib/idiag/$(DEPDIR)/$(am__dirstamp) + +lib/libnl-idiag-3.la: $(lib_libnl_idiag_3_la_OBJECTS) $(lib_libnl_idiag_3_la_DEPENDENCIES) $(EXTRA_lib_libnl_idiag_3_la_DEPENDENCIES) lib/$(am__dirstamp) + $(AM_V_CCLD)$(lib_libnl_idiag_3_la_LINK) -rpath $(libdir) $(lib_libnl_idiag_3_la_OBJECTS) $(lib_libnl_idiag_3_la_LIBADD) $(LIBS) +lib/netfilter/$(am__dirstamp): + @$(MKDIR_P) lib/netfilter + @: > lib/netfilter/$(am__dirstamp) +lib/netfilter/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/netfilter/$(DEPDIR) + @: > lib/netfilter/$(DEPDIR)/$(am__dirstamp) +lib/netfilter/libnl_nf_3_la-ct.lo: lib/netfilter/$(am__dirstamp) \ + lib/netfilter/$(DEPDIR)/$(am__dirstamp) +lib/netfilter/libnl_nf_3_la-ct_obj.lo: lib/netfilter/$(am__dirstamp) \ + lib/netfilter/$(DEPDIR)/$(am__dirstamp) +lib/netfilter/libnl_nf_3_la-exp.lo: lib/netfilter/$(am__dirstamp) \ + lib/netfilter/$(DEPDIR)/$(am__dirstamp) +lib/netfilter/libnl_nf_3_la-exp_obj.lo: lib/netfilter/$(am__dirstamp) \ + lib/netfilter/$(DEPDIR)/$(am__dirstamp) +lib/netfilter/libnl_nf_3_la-log.lo: lib/netfilter/$(am__dirstamp) \ + lib/netfilter/$(DEPDIR)/$(am__dirstamp) +lib/netfilter/libnl_nf_3_la-log_msg.lo: lib/netfilter/$(am__dirstamp) \ + lib/netfilter/$(DEPDIR)/$(am__dirstamp) +lib/netfilter/libnl_nf_3_la-log_msg_obj.lo: \ + lib/netfilter/$(am__dirstamp) \ + lib/netfilter/$(DEPDIR)/$(am__dirstamp) +lib/netfilter/libnl_nf_3_la-log_obj.lo: lib/netfilter/$(am__dirstamp) \ + lib/netfilter/$(DEPDIR)/$(am__dirstamp) +lib/netfilter/libnl_nf_3_la-netfilter.lo: \ + lib/netfilter/$(am__dirstamp) \ + lib/netfilter/$(DEPDIR)/$(am__dirstamp) +lib/netfilter/libnl_nf_3_la-nfnl.lo: lib/netfilter/$(am__dirstamp) \ + lib/netfilter/$(DEPDIR)/$(am__dirstamp) +lib/netfilter/libnl_nf_3_la-queue.lo: lib/netfilter/$(am__dirstamp) \ + lib/netfilter/$(DEPDIR)/$(am__dirstamp) +lib/netfilter/libnl_nf_3_la-queue_msg.lo: \ + lib/netfilter/$(am__dirstamp) \ + lib/netfilter/$(DEPDIR)/$(am__dirstamp) +lib/netfilter/libnl_nf_3_la-queue_msg_obj.lo: \ + lib/netfilter/$(am__dirstamp) \ + lib/netfilter/$(DEPDIR)/$(am__dirstamp) +lib/netfilter/libnl_nf_3_la-queue_obj.lo: \ + lib/netfilter/$(am__dirstamp) \ + lib/netfilter/$(DEPDIR)/$(am__dirstamp) + +lib/libnl-nf-3.la: $(lib_libnl_nf_3_la_OBJECTS) $(lib_libnl_nf_3_la_DEPENDENCIES) $(EXTRA_lib_libnl_nf_3_la_DEPENDENCIES) lib/$(am__dirstamp) + $(AM_V_CCLD)$(lib_libnl_nf_3_la_LINK) -rpath $(libdir) $(lib_libnl_nf_3_la_OBJECTS) $(lib_libnl_nf_3_la_LIBADD) $(LIBS) +lib/fib_lookup/$(am__dirstamp): + @$(MKDIR_P) lib/fib_lookup + @: > lib/fib_lookup/$(am__dirstamp) +lib/fib_lookup/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/fib_lookup/$(DEPDIR) + @: > lib/fib_lookup/$(DEPDIR)/$(am__dirstamp) +lib/fib_lookup/libnl_route_3_la-lookup.lo: \ + lib/fib_lookup/$(am__dirstamp) \ + lib/fib_lookup/$(DEPDIR)/$(am__dirstamp) +lib/fib_lookup/libnl_route_3_la-request.lo: \ + lib/fib_lookup/$(am__dirstamp) \ + lib/fib_lookup/$(DEPDIR)/$(am__dirstamp) +lib/route/$(am__dirstamp): + @$(MKDIR_P) lib/route + @: > lib/route/$(am__dirstamp) +lib/route/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/route/$(DEPDIR) + @: > lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-act.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/act/$(am__dirstamp): + @$(MKDIR_P) lib/route/act + @: > lib/route/act/$(am__dirstamp) +lib/route/act/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/route/act/$(DEPDIR) + @: > lib/route/act/$(DEPDIR)/$(am__dirstamp) +lib/route/act/libnl_route_3_la-gact.lo: lib/route/act/$(am__dirstamp) \ + lib/route/act/$(DEPDIR)/$(am__dirstamp) +lib/route/act/libnl_route_3_la-mirred.lo: \ + lib/route/act/$(am__dirstamp) \ + lib/route/act/$(DEPDIR)/$(am__dirstamp) +lib/route/act/libnl_route_3_la-nat.lo: lib/route/act/$(am__dirstamp) \ + lib/route/act/$(DEPDIR)/$(am__dirstamp) +lib/route/act/libnl_route_3_la-skbedit.lo: \ + lib/route/act/$(am__dirstamp) \ + lib/route/act/$(DEPDIR)/$(am__dirstamp) +lib/route/act/libnl_route_3_la-vlan.lo: lib/route/act/$(am__dirstamp) \ + lib/route/act/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-addr.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-class.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-classid.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-cls.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/cls/$(am__dirstamp): + @$(MKDIR_P) lib/route/cls + @: > lib/route/cls/$(am__dirstamp) +lib/route/cls/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/route/cls/$(DEPDIR) + @: > lib/route/cls/$(DEPDIR)/$(am__dirstamp) +lib/route/cls/libnl_route_3_la-basic.lo: \ + lib/route/cls/$(am__dirstamp) \ + lib/route/cls/$(DEPDIR)/$(am__dirstamp) +lib/route/cls/libnl_route_3_la-cgroup.lo: \ + lib/route/cls/$(am__dirstamp) \ + lib/route/cls/$(DEPDIR)/$(am__dirstamp) +lib/route/cls/libnl_route_3_la-ematch.lo: \ + lib/route/cls/$(am__dirstamp) \ + lib/route/cls/$(DEPDIR)/$(am__dirstamp) +lib/route/cls/ematch/$(am__dirstamp): + @$(MKDIR_P) lib/route/cls/ematch + @: > lib/route/cls/ematch/$(am__dirstamp) +lib/route/cls/ematch/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/route/cls/ematch/$(DEPDIR) + @: > lib/route/cls/ematch/$(DEPDIR)/$(am__dirstamp) +lib/route/cls/ematch/libnl_route_3_la-cmp.lo: \ + lib/route/cls/ematch/$(am__dirstamp) \ + lib/route/cls/ematch/$(DEPDIR)/$(am__dirstamp) +lib/route/cls/ematch/libnl_route_3_la-container.lo: \ + lib/route/cls/ematch/$(am__dirstamp) \ + lib/route/cls/ematch/$(DEPDIR)/$(am__dirstamp) +lib/route/cls/ematch/libnl_route_3_la-meta.lo: \ + lib/route/cls/ematch/$(am__dirstamp) \ + lib/route/cls/ematch/$(DEPDIR)/$(am__dirstamp) +lib/route/cls/ematch/libnl_route_3_la-nbyte.lo: \ + lib/route/cls/ematch/$(am__dirstamp) \ + lib/route/cls/ematch/$(DEPDIR)/$(am__dirstamp) +lib/route/cls/ematch/libnl_route_3_la-text.lo: \ + lib/route/cls/ematch/$(am__dirstamp) \ + lib/route/cls/ematch/$(DEPDIR)/$(am__dirstamp) +lib/route/cls/libnl_route_3_la-flower.lo: \ + lib/route/cls/$(am__dirstamp) \ + lib/route/cls/$(DEPDIR)/$(am__dirstamp) +lib/route/cls/libnl_route_3_la-fw.lo: lib/route/cls/$(am__dirstamp) \ + lib/route/cls/$(DEPDIR)/$(am__dirstamp) +lib/route/cls/libnl_route_3_la-mall.lo: lib/route/cls/$(am__dirstamp) \ + lib/route/cls/$(DEPDIR)/$(am__dirstamp) +lib/route/cls/libnl_route_3_la-police.lo: \ + lib/route/cls/$(am__dirstamp) \ + lib/route/cls/$(DEPDIR)/$(am__dirstamp) +lib/route/cls/libnl_route_3_la-u32.lo: lib/route/cls/$(am__dirstamp) \ + lib/route/cls/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-link.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/link/$(am__dirstamp): + @$(MKDIR_P) lib/route/link + @: > lib/route/link/$(am__dirstamp) +lib/route/link/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/route/link/$(DEPDIR) + @: > lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-api.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-bonding.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-bridge.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-bridge_info.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-can.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-dummy.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-geneve.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-ifb.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-inet.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-inet6.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-ip6gre.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-ip6tnl.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-ip6vti.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-ipgre.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-ipip.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-ipvlan.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-ipvti.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-macsec.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-macvlan.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-ppp.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-sit.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-sriov.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-team.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-veth.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-vlan.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-vrf.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-vxlan.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/link/libnl_route_3_la-xfrmi.lo: \ + lib/route/link/$(am__dirstamp) \ + lib/route/link/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-mdb.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-neigh.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-neightbl.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-netconf.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-nexthop.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-nexthop_encap.lo: \ + lib/route/$(am__dirstamp) lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-nh.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-nh_encap_mpls.lo: \ + lib/route/$(am__dirstamp) lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-pktloc.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-qdisc.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/qdisc/$(am__dirstamp): + @$(MKDIR_P) lib/route/qdisc + @: > lib/route/qdisc/$(am__dirstamp) +lib/route/qdisc/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/route/qdisc/$(DEPDIR) + @: > lib/route/qdisc/$(DEPDIR)/$(am__dirstamp) +lib/route/qdisc/libnl_route_3_la-blackhole.lo: \ + lib/route/qdisc/$(am__dirstamp) \ + lib/route/qdisc/$(DEPDIR)/$(am__dirstamp) +lib/route/qdisc/libnl_route_3_la-cbq.lo: \ + lib/route/qdisc/$(am__dirstamp) \ + lib/route/qdisc/$(DEPDIR)/$(am__dirstamp) +lib/route/qdisc/libnl_route_3_la-dsmark.lo: \ + lib/route/qdisc/$(am__dirstamp) \ + lib/route/qdisc/$(DEPDIR)/$(am__dirstamp) +lib/route/qdisc/libnl_route_3_la-fifo.lo: \ + lib/route/qdisc/$(am__dirstamp) \ + lib/route/qdisc/$(DEPDIR)/$(am__dirstamp) +lib/route/qdisc/libnl_route_3_la-fq_codel.lo: \ + lib/route/qdisc/$(am__dirstamp) \ + lib/route/qdisc/$(DEPDIR)/$(am__dirstamp) +lib/route/qdisc/libnl_route_3_la-hfsc.lo: \ + lib/route/qdisc/$(am__dirstamp) \ + lib/route/qdisc/$(DEPDIR)/$(am__dirstamp) +lib/route/qdisc/libnl_route_3_la-htb.lo: \ + lib/route/qdisc/$(am__dirstamp) \ + lib/route/qdisc/$(DEPDIR)/$(am__dirstamp) +lib/route/qdisc/libnl_route_3_la-ingress.lo: \ + lib/route/qdisc/$(am__dirstamp) \ + lib/route/qdisc/$(DEPDIR)/$(am__dirstamp) +lib/route/qdisc/libnl_route_3_la-mqprio.lo: \ + lib/route/qdisc/$(am__dirstamp) \ + lib/route/qdisc/$(DEPDIR)/$(am__dirstamp) +lib/route/qdisc/libnl_route_3_la-netem.lo: \ + lib/route/qdisc/$(am__dirstamp) \ + lib/route/qdisc/$(DEPDIR)/$(am__dirstamp) +lib/route/qdisc/libnl_route_3_la-plug.lo: \ + lib/route/qdisc/$(am__dirstamp) \ + lib/route/qdisc/$(DEPDIR)/$(am__dirstamp) +lib/route/qdisc/libnl_route_3_la-prio.lo: \ + lib/route/qdisc/$(am__dirstamp) \ + lib/route/qdisc/$(DEPDIR)/$(am__dirstamp) +lib/route/qdisc/libnl_route_3_la-red.lo: \ + lib/route/qdisc/$(am__dirstamp) \ + lib/route/qdisc/$(DEPDIR)/$(am__dirstamp) +lib/route/qdisc/libnl_route_3_la-sfq.lo: \ + lib/route/qdisc/$(am__dirstamp) \ + lib/route/qdisc/$(DEPDIR)/$(am__dirstamp) +lib/route/qdisc/libnl_route_3_la-tbf.lo: \ + lib/route/qdisc/$(am__dirstamp) \ + lib/route/qdisc/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-route.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-route_obj.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-route_utils.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-rtnl.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-rule.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-tc.lo: lib/route/$(am__dirstamp) \ + lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/cls/libnl_route_3_la-ematch_grammar.lo: \ + lib/route/cls/$(am__dirstamp) \ + lib/route/cls/$(DEPDIR)/$(am__dirstamp) +lib/route/cls/libnl_route_3_la-ematch_syntax.lo: \ + lib/route/cls/$(am__dirstamp) \ + lib/route/cls/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-pktloc_grammar.lo: \ + lib/route/$(am__dirstamp) lib/route/$(DEPDIR)/$(am__dirstamp) +lib/route/libnl_route_3_la-pktloc_syntax.lo: \ + lib/route/$(am__dirstamp) lib/route/$(DEPDIR)/$(am__dirstamp) + +lib/libnl-route-3.la: $(lib_libnl_route_3_la_OBJECTS) $(lib_libnl_route_3_la_DEPENDENCIES) $(EXTRA_lib_libnl_route_3_la_DEPENDENCIES) lib/$(am__dirstamp) + $(AM_V_CCLD)$(lib_libnl_route_3_la_LINK) -rpath $(libdir) $(lib_libnl_route_3_la_OBJECTS) $(lib_libnl_route_3_la_LIBADD) $(LIBS) +lib/xfrm/$(am__dirstamp): + @$(MKDIR_P) lib/xfrm + @: > lib/xfrm/$(am__dirstamp) +lib/xfrm/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/xfrm/$(DEPDIR) + @: > lib/xfrm/$(DEPDIR)/$(am__dirstamp) +lib/xfrm/libnl_xfrm_3_la-ae.lo: lib/xfrm/$(am__dirstamp) \ + lib/xfrm/$(DEPDIR)/$(am__dirstamp) +lib/xfrm/libnl_xfrm_3_la-lifetime.lo: lib/xfrm/$(am__dirstamp) \ + lib/xfrm/$(DEPDIR)/$(am__dirstamp) +lib/xfrm/libnl_xfrm_3_la-sa.lo: lib/xfrm/$(am__dirstamp) \ + lib/xfrm/$(DEPDIR)/$(am__dirstamp) +lib/xfrm/libnl_xfrm_3_la-selector.lo: lib/xfrm/$(am__dirstamp) \ + lib/xfrm/$(DEPDIR)/$(am__dirstamp) +lib/xfrm/libnl_xfrm_3_la-sp.lo: lib/xfrm/$(am__dirstamp) \ + lib/xfrm/$(DEPDIR)/$(am__dirstamp) +lib/xfrm/libnl_xfrm_3_la-template.lo: lib/xfrm/$(am__dirstamp) \ + lib/xfrm/$(DEPDIR)/$(am__dirstamp) + +lib/libnl-xfrm-3.la: $(lib_libnl_xfrm_3_la_OBJECTS) $(lib_libnl_xfrm_3_la_DEPENDENCIES) $(EXTRA_lib_libnl_xfrm_3_la_DEPENDENCIES) lib/$(am__dirstamp) + $(AM_V_CCLD)$(lib_libnl_xfrm_3_la_LINK) -rpath $(libdir) $(lib_libnl_xfrm_3_la_OBJECTS) $(lib_libnl_xfrm_3_la_LIBADD) $(LIBS) +src/lib/$(am__dirstamp): + @$(MKDIR_P) src/lib + @: > src/lib/$(am__dirstamp) +src/lib/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/lib/$(DEPDIR) + @: > src/lib/$(DEPDIR)/$(am__dirstamp) +src/lib/libnl_cli_3_la-addr.lo: src/lib/$(am__dirstamp) \ + src/lib/$(DEPDIR)/$(am__dirstamp) +src/lib/libnl_cli_3_la-class.lo: src/lib/$(am__dirstamp) \ + src/lib/$(DEPDIR)/$(am__dirstamp) +src/lib/libnl_cli_3_la-cls.lo: src/lib/$(am__dirstamp) \ + src/lib/$(DEPDIR)/$(am__dirstamp) +src/lib/libnl_cli_3_la-ct.lo: src/lib/$(am__dirstamp) \ + src/lib/$(DEPDIR)/$(am__dirstamp) +src/lib/libnl_cli_3_la-exp.lo: src/lib/$(am__dirstamp) \ + src/lib/$(DEPDIR)/$(am__dirstamp) +src/lib/libnl_cli_3_la-link.lo: src/lib/$(am__dirstamp) \ + src/lib/$(DEPDIR)/$(am__dirstamp) +src/lib/libnl_cli_3_la-neigh.lo: src/lib/$(am__dirstamp) \ + src/lib/$(DEPDIR)/$(am__dirstamp) +src/lib/libnl_cli_3_la-nh.lo: src/lib/$(am__dirstamp) \ + src/lib/$(DEPDIR)/$(am__dirstamp) +src/lib/libnl_cli_3_la-qdisc.lo: src/lib/$(am__dirstamp) \ + src/lib/$(DEPDIR)/$(am__dirstamp) +src/lib/libnl_cli_3_la-route.lo: src/lib/$(am__dirstamp) \ + src/lib/$(DEPDIR)/$(am__dirstamp) +src/lib/libnl_cli_3_la-rule.lo: src/lib/$(am__dirstamp) \ + src/lib/$(DEPDIR)/$(am__dirstamp) +src/lib/libnl_cli_3_la-tc.lo: src/lib/$(am__dirstamp) \ + src/lib/$(DEPDIR)/$(am__dirstamp) +src/lib/libnl_cli_3_la-utils.lo: src/lib/$(am__dirstamp) \ + src/lib/$(DEPDIR)/$(am__dirstamp) + +src/lib/libnl-cli-3.la: $(src_lib_libnl_cli_3_la_OBJECTS) $(src_lib_libnl_cli_3_la_DEPENDENCIES) $(EXTRA_src_lib_libnl_cli_3_la_DEPENDENCIES) src/lib/$(am__dirstamp) + $(AM_V_CCLD)$(src_lib_libnl_cli_3_la_LINK) $(am_src_lib_libnl_cli_3_la_rpath) $(src_lib_libnl_cli_3_la_OBJECTS) $(src_lib_libnl_cli_3_la_LIBADD) $(LIBS) +tests/$(am__dirstamp): + @$(MKDIR_P) tests + @: > tests/$(am__dirstamp) +tests/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) tests/$(DEPDIR) + @: > tests/$(DEPDIR)/$(am__dirstamp) +tests/libnl_test_util_la-nl-test-util.lo: tests/$(am__dirstamp) \ + tests/$(DEPDIR)/$(am__dirstamp) + +tests/libnl-test-util.la: $(tests_libnl_test_util_la_OBJECTS) $(tests_libnl_test_util_la_DEPENDENCIES) $(EXTRA_tests_libnl_test_util_la_DEPENDENCIES) tests/$(am__dirstamp) + $(AM_V_CCLD)$(LINK) $(am_tests_libnl_test_util_la_rpath) $(tests_libnl_test_util_la_OBJECTS) $(tests_libnl_test_util_la_LIBADD) $(LIBS) +src/$(am__dirstamp): + @$(MKDIR_P) src + @: > src/$(am__dirstamp) +src/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/$(DEPDIR) + @: > src/$(DEPDIR)/$(am__dirstamp) +src/genl_ctrl_list-genl-ctrl-list.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/genl-ctrl-list$(EXEEXT): $(src_genl_ctrl_list_OBJECTS) $(src_genl_ctrl_list_DEPENDENCIES) $(EXTRA_src_genl_ctrl_list_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/genl-ctrl-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_genl_ctrl_list_OBJECTS) $(src_genl_ctrl_list_LDADD) $(LIBS) +src/idiag_socket_details-idiag-socket-details.$(OBJEXT): \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) + +src/idiag-socket-details$(EXEEXT): $(src_idiag_socket_details_OBJECTS) $(src_idiag_socket_details_DEPENDENCIES) $(EXTRA_src_idiag_socket_details_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/idiag-socket-details$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_idiag_socket_details_OBJECTS) $(src_idiag_socket_details_LDADD) $(LIBS) +src/nf_ct_add-nf-ct-add.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nf-ct-add$(EXEEXT): $(src_nf_ct_add_OBJECTS) $(src_nf_ct_add_DEPENDENCIES) $(EXTRA_src_nf_ct_add_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nf-ct-add$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nf_ct_add_OBJECTS) $(src_nf_ct_add_LDADD) $(LIBS) +src/nf_ct_events-nf-ct-events.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nf-ct-events$(EXEEXT): $(src_nf_ct_events_OBJECTS) $(src_nf_ct_events_DEPENDENCIES) $(EXTRA_src_nf_ct_events_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nf-ct-events$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nf_ct_events_OBJECTS) $(src_nf_ct_events_LDADD) $(LIBS) +src/nf_ct_list-nf-ct-list.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nf-ct-list$(EXEEXT): $(src_nf_ct_list_OBJECTS) $(src_nf_ct_list_DEPENDENCIES) $(EXTRA_src_nf_ct_list_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nf-ct-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nf_ct_list_OBJECTS) $(src_nf_ct_list_LDADD) $(LIBS) +src/nf_exp_add-nf-exp-add.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nf-exp-add$(EXEEXT): $(src_nf_exp_add_OBJECTS) $(src_nf_exp_add_DEPENDENCIES) $(EXTRA_src_nf_exp_add_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nf-exp-add$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nf_exp_add_OBJECTS) $(src_nf_exp_add_LDADD) $(LIBS) +src/nf_exp_delete-nf-exp-delete.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nf-exp-delete$(EXEEXT): $(src_nf_exp_delete_OBJECTS) $(src_nf_exp_delete_DEPENDENCIES) $(EXTRA_src_nf_exp_delete_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nf-exp-delete$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nf_exp_delete_OBJECTS) $(src_nf_exp_delete_LDADD) $(LIBS) +src/nf_exp_list-nf-exp-list.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nf-exp-list$(EXEEXT): $(src_nf_exp_list_OBJECTS) $(src_nf_exp_list_DEPENDENCIES) $(EXTRA_src_nf_exp_list_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nf-exp-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nf_exp_list_OBJECTS) $(src_nf_exp_list_LDADD) $(LIBS) +src/nf_log-nf-log.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nf-log$(EXEEXT): $(src_nf_log_OBJECTS) $(src_nf_log_DEPENDENCIES) $(EXTRA_src_nf_log_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nf-log$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nf_log_OBJECTS) $(src_nf_log_LDADD) $(LIBS) +src/nf_monitor-nf-monitor.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nf-monitor$(EXEEXT): $(src_nf_monitor_OBJECTS) $(src_nf_monitor_DEPENDENCIES) $(EXTRA_src_nf_monitor_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nf-monitor$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nf_monitor_OBJECTS) $(src_nf_monitor_LDADD) $(LIBS) +src/nf_queue-nf-queue.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nf-queue$(EXEEXT): $(src_nf_queue_OBJECTS) $(src_nf_queue_DEPENDENCIES) $(EXTRA_src_nf_queue_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nf-queue$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nf_queue_OBJECTS) $(src_nf_queue_LDADD) $(LIBS) +src/nl_addr_add-nl-addr-add.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-addr-add$(EXEEXT): $(src_nl_addr_add_OBJECTS) $(src_nl_addr_add_DEPENDENCIES) $(EXTRA_src_nl_addr_add_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-addr-add$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_addr_add_OBJECTS) $(src_nl_addr_add_LDADD) $(LIBS) +src/nl_addr_delete-nl-addr-delete.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-addr-delete$(EXEEXT): $(src_nl_addr_delete_OBJECTS) $(src_nl_addr_delete_DEPENDENCIES) $(EXTRA_src_nl_addr_delete_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-addr-delete$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_addr_delete_OBJECTS) $(src_nl_addr_delete_LDADD) $(LIBS) +src/nl_addr_list-nl-addr-list.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-addr-list$(EXEEXT): $(src_nl_addr_list_OBJECTS) $(src_nl_addr_list_DEPENDENCIES) $(EXTRA_src_nl_addr_list_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-addr-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_addr_list_OBJECTS) $(src_nl_addr_list_LDADD) $(LIBS) +src/nl_class_add-nl-class-add.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-class-add$(EXEEXT): $(src_nl_class_add_OBJECTS) $(src_nl_class_add_DEPENDENCIES) $(EXTRA_src_nl_class_add_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-class-add$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_class_add_OBJECTS) $(src_nl_class_add_LDADD) $(LIBS) +src/nl_class_delete-nl-class-delete.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-class-delete$(EXEEXT): $(src_nl_class_delete_OBJECTS) $(src_nl_class_delete_DEPENDENCIES) $(EXTRA_src_nl_class_delete_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-class-delete$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_class_delete_OBJECTS) $(src_nl_class_delete_LDADD) $(LIBS) +src/nl_class_list-nl-class-list.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-class-list$(EXEEXT): $(src_nl_class_list_OBJECTS) $(src_nl_class_list_DEPENDENCIES) $(EXTRA_src_nl_class_list_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-class-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_class_list_OBJECTS) $(src_nl_class_list_LDADD) $(LIBS) +src/nl_classid_lookup-nl-classid-lookup.$(OBJEXT): \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) + +src/nl-classid-lookup$(EXEEXT): $(src_nl_classid_lookup_OBJECTS) $(src_nl_classid_lookup_DEPENDENCIES) $(EXTRA_src_nl_classid_lookup_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-classid-lookup$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_classid_lookup_OBJECTS) $(src_nl_classid_lookup_LDADD) $(LIBS) +src/nl_cls_add-nl-cls-add.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-cls-add$(EXEEXT): $(src_nl_cls_add_OBJECTS) $(src_nl_cls_add_DEPENDENCIES) $(EXTRA_src_nl_cls_add_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-cls-add$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_cls_add_OBJECTS) $(src_nl_cls_add_LDADD) $(LIBS) +src/nl_cls_delete-nl-cls-delete.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-cls-delete$(EXEEXT): $(src_nl_cls_delete_OBJECTS) $(src_nl_cls_delete_DEPENDENCIES) $(EXTRA_src_nl_cls_delete_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-cls-delete$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_cls_delete_OBJECTS) $(src_nl_cls_delete_LDADD) $(LIBS) +src/nl_cls_list-nl-cls-list.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-cls-list$(EXEEXT): $(src_nl_cls_list_OBJECTS) $(src_nl_cls_list_DEPENDENCIES) $(EXTRA_src_nl_cls_list_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-cls-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_cls_list_OBJECTS) $(src_nl_cls_list_LDADD) $(LIBS) +src/nl_fib_lookup-nl-fib-lookup.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-fib-lookup$(EXEEXT): $(src_nl_fib_lookup_OBJECTS) $(src_nl_fib_lookup_DEPENDENCIES) $(EXTRA_src_nl_fib_lookup_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-fib-lookup$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_fib_lookup_OBJECTS) $(src_nl_fib_lookup_LDADD) $(LIBS) +src/nl_link_enslave-nl-link-enslave.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-link-enslave$(EXEEXT): $(src_nl_link_enslave_OBJECTS) $(src_nl_link_enslave_DEPENDENCIES) $(EXTRA_src_nl_link_enslave_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-link-enslave$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_link_enslave_OBJECTS) $(src_nl_link_enslave_LDADD) $(LIBS) +src/nl_link_ifindex2name-nl-link-ifindex2name.$(OBJEXT): \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) + +src/nl-link-ifindex2name$(EXEEXT): $(src_nl_link_ifindex2name_OBJECTS) $(src_nl_link_ifindex2name_DEPENDENCIES) $(EXTRA_src_nl_link_ifindex2name_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-link-ifindex2name$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_link_ifindex2name_OBJECTS) $(src_nl_link_ifindex2name_LDADD) $(LIBS) +src/nl_link_list-nl-link-list.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-link-list$(EXEEXT): $(src_nl_link_list_OBJECTS) $(src_nl_link_list_DEPENDENCIES) $(EXTRA_src_nl_link_list_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-link-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_link_list_OBJECTS) $(src_nl_link_list_LDADD) $(LIBS) +src/nl_link_name2ifindex-nl-link-name2ifindex.$(OBJEXT): \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) + +src/nl-link-name2ifindex$(EXEEXT): $(src_nl_link_name2ifindex_OBJECTS) $(src_nl_link_name2ifindex_DEPENDENCIES) $(EXTRA_src_nl_link_name2ifindex_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-link-name2ifindex$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_link_name2ifindex_OBJECTS) $(src_nl_link_name2ifindex_LDADD) $(LIBS) +src/nl_link_release-nl-link-release.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-link-release$(EXEEXT): $(src_nl_link_release_OBJECTS) $(src_nl_link_release_DEPENDENCIES) $(EXTRA_src_nl_link_release_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-link-release$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_link_release_OBJECTS) $(src_nl_link_release_LDADD) $(LIBS) +src/nl_link_set-nl-link-set.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-link-set$(EXEEXT): $(src_nl_link_set_OBJECTS) $(src_nl_link_set_DEPENDENCIES) $(EXTRA_src_nl_link_set_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-link-set$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_link_set_OBJECTS) $(src_nl_link_set_LDADD) $(LIBS) +src/nl_link_stats-nl-link-stats.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-link-stats$(EXEEXT): $(src_nl_link_stats_OBJECTS) $(src_nl_link_stats_DEPENDENCIES) $(EXTRA_src_nl_link_stats_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-link-stats$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_link_stats_OBJECTS) $(src_nl_link_stats_LDADD) $(LIBS) +src/nl_list_caches-nl-list-caches.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-list-caches$(EXEEXT): $(src_nl_list_caches_OBJECTS) $(src_nl_list_caches_DEPENDENCIES) $(EXTRA_src_nl_list_caches_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-list-caches$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_list_caches_OBJECTS) $(src_nl_list_caches_LDADD) $(LIBS) +src/nl_list_sockets-nl-list-sockets.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-list-sockets$(EXEEXT): $(src_nl_list_sockets_OBJECTS) $(src_nl_list_sockets_DEPENDENCIES) $(EXTRA_src_nl_list_sockets_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-list-sockets$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_list_sockets_OBJECTS) $(src_nl_list_sockets_LDADD) $(LIBS) +src/nl_monitor-nl-monitor.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-monitor$(EXEEXT): $(src_nl_monitor_OBJECTS) $(src_nl_monitor_DEPENDENCIES) $(EXTRA_src_nl_monitor_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-monitor$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_monitor_OBJECTS) $(src_nl_monitor_LDADD) $(LIBS) +src/nl_neigh_add-nl-neigh-add.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-neigh-add$(EXEEXT): $(src_nl_neigh_add_OBJECTS) $(src_nl_neigh_add_DEPENDENCIES) $(EXTRA_src_nl_neigh_add_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-neigh-add$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_neigh_add_OBJECTS) $(src_nl_neigh_add_LDADD) $(LIBS) +src/nl_neigh_delete-nl-neigh-delete.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-neigh-delete$(EXEEXT): $(src_nl_neigh_delete_OBJECTS) $(src_nl_neigh_delete_DEPENDENCIES) $(EXTRA_src_nl_neigh_delete_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-neigh-delete$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_neigh_delete_OBJECTS) $(src_nl_neigh_delete_LDADD) $(LIBS) +src/nl_neigh_list-nl-neigh-list.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-neigh-list$(EXEEXT): $(src_nl_neigh_list_OBJECTS) $(src_nl_neigh_list_DEPENDENCIES) $(EXTRA_src_nl_neigh_list_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-neigh-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_neigh_list_OBJECTS) $(src_nl_neigh_list_LDADD) $(LIBS) +src/nl_neightbl_list-nl-neightbl-list.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-neightbl-list$(EXEEXT): $(src_nl_neightbl_list_OBJECTS) $(src_nl_neightbl_list_DEPENDENCIES) $(EXTRA_src_nl_neightbl_list_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-neightbl-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_neightbl_list_OBJECTS) $(src_nl_neightbl_list_LDADD) $(LIBS) +src/nl_nh_list-nl-nh-list.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-nh-list$(EXEEXT): $(src_nl_nh_list_OBJECTS) $(src_nl_nh_list_DEPENDENCIES) $(EXTRA_src_nl_nh_list_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-nh-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_nh_list_OBJECTS) $(src_nl_nh_list_LDADD) $(LIBS) +src/nl_pktloc_lookup-nl-pktloc-lookup.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-pktloc-lookup$(EXEEXT): $(src_nl_pktloc_lookup_OBJECTS) $(src_nl_pktloc_lookup_DEPENDENCIES) $(EXTRA_src_nl_pktloc_lookup_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-pktloc-lookup$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_pktloc_lookup_OBJECTS) $(src_nl_pktloc_lookup_LDADD) $(LIBS) +src/nl_qdisc_add-nl-qdisc-add.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-qdisc-add$(EXEEXT): $(src_nl_qdisc_add_OBJECTS) $(src_nl_qdisc_add_DEPENDENCIES) $(EXTRA_src_nl_qdisc_add_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-qdisc-add$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_qdisc_add_OBJECTS) $(src_nl_qdisc_add_LDADD) $(LIBS) +src/nl_qdisc_delete-nl-qdisc-delete.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-qdisc-delete$(EXEEXT): $(src_nl_qdisc_delete_OBJECTS) $(src_nl_qdisc_delete_DEPENDENCIES) $(EXTRA_src_nl_qdisc_delete_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-qdisc-delete$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_qdisc_delete_OBJECTS) $(src_nl_qdisc_delete_LDADD) $(LIBS) +src/nl_qdisc_list-nl-qdisc-list.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-qdisc-list$(EXEEXT): $(src_nl_qdisc_list_OBJECTS) $(src_nl_qdisc_list_DEPENDENCIES) $(EXTRA_src_nl_qdisc_list_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-qdisc-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_qdisc_list_OBJECTS) $(src_nl_qdisc_list_LDADD) $(LIBS) +src/nl_route_add-nl-route-add.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-route-add$(EXEEXT): $(src_nl_route_add_OBJECTS) $(src_nl_route_add_DEPENDENCIES) $(EXTRA_src_nl_route_add_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-route-add$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_route_add_OBJECTS) $(src_nl_route_add_LDADD) $(LIBS) +src/nl_route_delete-nl-route-delete.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-route-delete$(EXEEXT): $(src_nl_route_delete_OBJECTS) $(src_nl_route_delete_DEPENDENCIES) $(EXTRA_src_nl_route_delete_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-route-delete$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_route_delete_OBJECTS) $(src_nl_route_delete_LDADD) $(LIBS) +src/nl_route_get-nl-route-get.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-route-get$(EXEEXT): $(src_nl_route_get_OBJECTS) $(src_nl_route_get_DEPENDENCIES) $(EXTRA_src_nl_route_get_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-route-get$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_route_get_OBJECTS) $(src_nl_route_get_LDADD) $(LIBS) +src/nl_route_list-nl-route-list.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-route-list$(EXEEXT): $(src_nl_route_list_OBJECTS) $(src_nl_route_list_DEPENDENCIES) $(EXTRA_src_nl_route_list_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-route-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_route_list_OBJECTS) $(src_nl_route_list_LDADD) $(LIBS) +src/nl_rule_list-nl-rule-list.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-rule-list$(EXEEXT): $(src_nl_rule_list_OBJECTS) $(src_nl_rule_list_DEPENDENCIES) $(EXTRA_src_nl_rule_list_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-rule-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_rule_list_OBJECTS) $(src_nl_rule_list_LDADD) $(LIBS) +src/nl_tctree_list-nl-tctree-list.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-tctree-list$(EXEEXT): $(src_nl_tctree_list_OBJECTS) $(src_nl_tctree_list_DEPENDENCIES) $(EXTRA_src_nl_tctree_list_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-tctree-list$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_tctree_list_OBJECTS) $(src_nl_tctree_list_LDADD) $(LIBS) +src/nl_util_addr-nl-util-addr.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +src/nl-util-addr$(EXEEXT): $(src_nl_util_addr_OBJECTS) $(src_nl_util_addr_DEPENDENCIES) $(EXTRA_src_nl_util_addr_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/nl-util-addr$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(src_nl_util_addr_OBJECTS) $(src_nl_util_addr_LDADD) $(LIBS) +tests/check_all-check-all.$(OBJEXT): tests/$(am__dirstamp) \ + tests/$(DEPDIR)/$(am__dirstamp) +tests/check_all-cksuite-all-addr.$(OBJEXT): tests/$(am__dirstamp) \ + tests/$(DEPDIR)/$(am__dirstamp) +tests/check_all-cksuite-all-attr.$(OBJEXT): tests/$(am__dirstamp) \ + tests/$(DEPDIR)/$(am__dirstamp) +tests/check_all-cksuite-all-ematch-tree-clone.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) +tests/check_all-cksuite-all-netns.$(OBJEXT): tests/$(am__dirstamp) \ + tests/$(DEPDIR)/$(am__dirstamp) + +tests/check-all$(EXEEXT): $(tests_check_all_OBJECTS) $(tests_check_all_DEPENDENCIES) $(EXTRA_tests_check_all_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/check-all$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_check_all_OBJECTS) $(tests_check_all_LDADD) $(LIBS) +tests/check_direct-check-direct.$(OBJEXT): tests/$(am__dirstamp) \ + tests/$(DEPDIR)/$(am__dirstamp) + +tests/check-direct$(EXEEXT): $(tests_check_direct_OBJECTS) $(tests_check_direct_DEPENDENCIES) $(EXTRA_tests_check_direct_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/check-direct$(EXEEXT) + $(AM_V_CCLD)$(tests_check_direct_LINK) $(tests_check_direct_OBJECTS) $(tests_check_direct_LDADD) $(LIBS) +tests/test_cache_mngr-test-cache-mngr.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-cache-mngr$(EXEEXT): $(tests_test_cache_mngr_OBJECTS) $(tests_test_cache_mngr_DEPENDENCIES) $(EXTRA_tests_test_cache_mngr_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-cache-mngr$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_cache_mngr_OBJECTS) $(tests_test_cache_mngr_LDADD) $(LIBS) +tests/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-complex-HTB-with-hash-filters$(EXEEXT): $(tests_test_complex_HTB_with_hash_filters_OBJECTS) $(tests_test_complex_HTB_with_hash_filters_DEPENDENCIES) $(EXTRA_tests_test_complex_HTB_with_hash_filters_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-complex-HTB-with-hash-filters$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_complex_HTB_with_hash_filters_OBJECTS) $(tests_test_complex_HTB_with_hash_filters_LDADD) $(LIBS) +tests/test_create_bond-test-create-bond.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-bond$(EXEEXT): $(tests_test_create_bond_OBJECTS) $(tests_test_create_bond_DEPENDENCIES) $(EXTRA_tests_test_create_bond_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-bond$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_bond_OBJECTS) $(tests_test_create_bond_LDADD) $(LIBS) +tests/test_create_bridge-test-create-bridge.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-bridge$(EXEEXT): $(tests_test_create_bridge_OBJECTS) $(tests_test_create_bridge_DEPENDENCIES) $(EXTRA_tests_test_create_bridge_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-bridge$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_bridge_OBJECTS) $(tests_test_create_bridge_LDADD) $(LIBS) +tests/test_create_geneve-test-create-geneve.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-geneve$(EXEEXT): $(tests_test_create_geneve_OBJECTS) $(tests_test_create_geneve_DEPENDENCIES) $(EXTRA_tests_test_create_geneve_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-geneve$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_geneve_OBJECTS) $(tests_test_create_geneve_LDADD) $(LIBS) +tests/test_create_ifb-test-create-ifb.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-ifb$(EXEEXT): $(tests_test_create_ifb_OBJECTS) $(tests_test_create_ifb_DEPENDENCIES) $(EXTRA_tests_test_create_ifb_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-ifb$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_ifb_OBJECTS) $(tests_test_create_ifb_LDADD) $(LIBS) +tests/test_create_ip6tnl-test-create-ip6tnl.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-ip6tnl$(EXEEXT): $(tests_test_create_ip6tnl_OBJECTS) $(tests_test_create_ip6tnl_DEPENDENCIES) $(EXTRA_tests_test_create_ip6tnl_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-ip6tnl$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_ip6tnl_OBJECTS) $(tests_test_create_ip6tnl_LDADD) $(LIBS) +tests/test_create_ipgre-test-create-ipgre.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-ipgre$(EXEEXT): $(tests_test_create_ipgre_OBJECTS) $(tests_test_create_ipgre_DEPENDENCIES) $(EXTRA_tests_test_create_ipgre_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-ipgre$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_ipgre_OBJECTS) $(tests_test_create_ipgre_LDADD) $(LIBS) +tests/test_create_ipgretap-test-create-ipgretap.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-ipgretap$(EXEEXT): $(tests_test_create_ipgretap_OBJECTS) $(tests_test_create_ipgretap_DEPENDENCIES) $(EXTRA_tests_test_create_ipgretap_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-ipgretap$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_ipgretap_OBJECTS) $(tests_test_create_ipgretap_LDADD) $(LIBS) +tests/test_create_ipip-test-create-ipip.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-ipip$(EXEEXT): $(tests_test_create_ipip_OBJECTS) $(tests_test_create_ipip_DEPENDENCIES) $(EXTRA_tests_test_create_ipip_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-ipip$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_ipip_OBJECTS) $(tests_test_create_ipip_LDADD) $(LIBS) +tests/test_create_ipvlan-test-create-ipvlan.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-ipvlan$(EXEEXT): $(tests_test_create_ipvlan_OBJECTS) $(tests_test_create_ipvlan_DEPENDENCIES) $(EXTRA_tests_test_create_ipvlan_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-ipvlan$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_ipvlan_OBJECTS) $(tests_test_create_ipvlan_LDADD) $(LIBS) +tests/test_create_ipvti-test-create-ipvti.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-ipvti$(EXEEXT): $(tests_test_create_ipvti_OBJECTS) $(tests_test_create_ipvti_DEPENDENCIES) $(EXTRA_tests_test_create_ipvti_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-ipvti$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_ipvti_OBJECTS) $(tests_test_create_ipvti_LDADD) $(LIBS) +tests/test_create_macsec-test-create-macsec.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-macsec$(EXEEXT): $(tests_test_create_macsec_OBJECTS) $(tests_test_create_macsec_DEPENDENCIES) $(EXTRA_tests_test_create_macsec_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-macsec$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_macsec_OBJECTS) $(tests_test_create_macsec_LDADD) $(LIBS) +tests/test_create_macvlan-test-create-macvlan.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-macvlan$(EXEEXT): $(tests_test_create_macvlan_OBJECTS) $(tests_test_create_macvlan_DEPENDENCIES) $(EXTRA_tests_test_create_macvlan_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-macvlan$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_macvlan_OBJECTS) $(tests_test_create_macvlan_LDADD) $(LIBS) +tests/test_create_macvtap-test-create-macvtap.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-macvtap$(EXEEXT): $(tests_test_create_macvtap_OBJECTS) $(tests_test_create_macvtap_DEPENDENCIES) $(EXTRA_tests_test_create_macvtap_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-macvtap$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_macvtap_OBJECTS) $(tests_test_create_macvtap_LDADD) $(LIBS) +tests/test_create_sit-test-create-sit.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-sit$(EXEEXT): $(tests_test_create_sit_OBJECTS) $(tests_test_create_sit_DEPENDENCIES) $(EXTRA_tests_test_create_sit_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-sit$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_sit_OBJECTS) $(tests_test_create_sit_LDADD) $(LIBS) +tests/test_create_veth-test-create-veth.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-veth$(EXEEXT): $(tests_test_create_veth_OBJECTS) $(tests_test_create_veth_DEPENDENCIES) $(EXTRA_tests_test_create_veth_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-veth$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_veth_OBJECTS) $(tests_test_create_veth_LDADD) $(LIBS) +tests/test_create_vlan-test-create-vlan.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-vlan$(EXEEXT): $(tests_test_create_vlan_OBJECTS) $(tests_test_create_vlan_DEPENDENCIES) $(EXTRA_tests_test_create_vlan_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-vlan$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_vlan_OBJECTS) $(tests_test_create_vlan_LDADD) $(LIBS) +tests/test_create_vrf-test-create-vrf.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-vrf$(EXEEXT): $(tests_test_create_vrf_OBJECTS) $(tests_test_create_vrf_DEPENDENCIES) $(EXTRA_tests_test_create_vrf_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-vrf$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_vrf_OBJECTS) $(tests_test_create_vrf_LDADD) $(LIBS) +tests/test_create_vxlan-test-create-vxlan.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-vxlan$(EXEEXT): $(tests_test_create_vxlan_OBJECTS) $(tests_test_create_vxlan_DEPENDENCIES) $(EXTRA_tests_test_create_vxlan_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-vxlan$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_vxlan_OBJECTS) $(tests_test_create_vxlan_LDADD) $(LIBS) +tests/test_create_xfrmi-test-create-xfrmi.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-create-xfrmi$(EXEEXT): $(tests_test_create_xfrmi_OBJECTS) $(tests_test_create_xfrmi_DEPENDENCIES) $(EXTRA_tests_test_create_xfrmi_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-create-xfrmi$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_create_xfrmi_OBJECTS) $(tests_test_create_xfrmi_LDADD) $(LIBS) +tests/test_delete_link-test-delete-link.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-delete-link$(EXEEXT): $(tests_test_delete_link_OBJECTS) $(tests_test_delete_link_DEPENDENCIES) $(EXTRA_tests_test_delete_link_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-delete-link$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_delete_link_OBJECTS) $(tests_test_delete_link_LDADD) $(LIBS) +tests/test_genl-test-genl.$(OBJEXT): tests/$(am__dirstamp) \ + tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-genl$(EXEEXT): $(tests_test_genl_OBJECTS) $(tests_test_genl_DEPENDENCIES) $(EXTRA_tests_test_genl_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-genl$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_genl_OBJECTS) $(tests_test_genl_LDADD) $(LIBS) +tests/test_loopback_up_down-test-loopback-up-down.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-loopback-up-down$(EXEEXT): $(tests_test_loopback_up_down_OBJECTS) $(tests_test_loopback_up_down_DEPENDENCIES) $(EXTRA_tests_test_loopback_up_down_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-loopback-up-down$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_loopback_up_down_OBJECTS) $(tests_test_loopback_up_down_LDADD) $(LIBS) +tests/test_nf_cache_mngr-test-nf-cache-mngr.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-nf-cache-mngr$(EXEEXT): $(tests_test_nf_cache_mngr_OBJECTS) $(tests_test_nf_cache_mngr_DEPENDENCIES) $(EXTRA_tests_test_nf_cache_mngr_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-nf-cache-mngr$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_nf_cache_mngr_OBJECTS) $(tests_test_nf_cache_mngr_LDADD) $(LIBS) +tests/test_socket_creation-test-socket-creation.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-socket-creation$(EXEEXT): $(tests_test_socket_creation_OBJECTS) $(tests_test_socket_creation_DEPENDENCIES) $(EXTRA_tests_test_socket_creation_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-socket-creation$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_socket_creation_OBJECTS) $(tests_test_socket_creation_LDADD) $(LIBS) +tests/test_u32_filter_with_actions-test-u32-filter-with-actions.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-u32-filter-with-actions$(EXEEXT): $(tests_test_u32_filter_with_actions_OBJECTS) $(tests_test_u32_filter_with_actions_DEPENDENCIES) $(EXTRA_tests_test_u32_filter_with_actions_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-u32-filter-with-actions$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tests_test_u32_filter_with_actions_OBJECTS) $(tests_test_u32_filter_with_actions_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f lib/*.$(OBJEXT) + -rm -f lib/*.lo + -rm -f lib/cli/cls/*.$(OBJEXT) + -rm -f lib/cli/cls/*.lo + -rm -f lib/cli/qdisc/*.$(OBJEXT) + -rm -f lib/cli/qdisc/*.lo + -rm -f lib/fib_lookup/*.$(OBJEXT) + -rm -f lib/fib_lookup/*.lo + -rm -f lib/genl/*.$(OBJEXT) + -rm -f lib/genl/*.lo + -rm -f lib/idiag/*.$(OBJEXT) + -rm -f lib/idiag/*.lo + -rm -f lib/netfilter/*.$(OBJEXT) + -rm -f lib/netfilter/*.lo + -rm -f lib/route/*.$(OBJEXT) + -rm -f lib/route/*.lo + -rm -f lib/route/act/*.$(OBJEXT) + -rm -f lib/route/act/*.lo + -rm -f lib/route/cls/*.$(OBJEXT) + -rm -f lib/route/cls/*.lo + -rm -f lib/route/cls/ematch/*.$(OBJEXT) + -rm -f lib/route/cls/ematch/*.lo + -rm -f lib/route/link/*.$(OBJEXT) + -rm -f lib/route/link/*.lo + -rm -f lib/route/qdisc/*.$(OBJEXT) + -rm -f lib/route/qdisc/*.lo + -rm -f lib/xfrm/*.$(OBJEXT) + -rm -f lib/xfrm/*.lo + -rm -f src/*.$(OBJEXT) + -rm -f src/lib/*.$(OBJEXT) + -rm -f src/lib/*.lo + -rm -f tests/*.$(OBJEXT) + -rm -f tests/*.lo + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libnl_3_la-addr.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libnl_3_la-attr.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libnl_3_la-cache.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libnl_3_la-cache_mngr.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libnl_3_la-cache_mngt.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libnl_3_la-data.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libnl_3_la-error.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libnl_3_la-handlers.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libnl_3_la-hash.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libnl_3_la-hashtable.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libnl_3_la-mpls.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libnl_3_la-msg.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libnl_3_la-nl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libnl_3_la-object.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libnl_3_la-socket.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libnl_3_la-utils.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libnl_3_la-version.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/cli/cls/$(DEPDIR)/basic_la-basic.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/cli/cls/$(DEPDIR)/cgroup_la-cgroup.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/cli/qdisc/$(DEPDIR)/bfifo_la-bfifo.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/cli/qdisc/$(DEPDIR)/blackhole_la-blackhole.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/cli/qdisc/$(DEPDIR)/fq_codel_la-fq_codel.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/cli/qdisc/$(DEPDIR)/hfsc_la-hfsc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/cli/qdisc/$(DEPDIR)/htb_la-htb.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/cli/qdisc/$(DEPDIR)/ingress_la-ingress.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/cli/qdisc/$(DEPDIR)/pfifo_la-pfifo.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/cli/qdisc/$(DEPDIR)/plug_la-plug.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/fib_lookup/$(DEPDIR)/libnl_route_3_la-lookup.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/fib_lookup/$(DEPDIR)/libnl_route_3_la-request.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/genl/$(DEPDIR)/libnl_genl_3_la-ctrl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/genl/$(DEPDIR)/libnl_genl_3_la-family.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/genl/$(DEPDIR)/libnl_genl_3_la-genl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/genl/$(DEPDIR)/libnl_genl_3_la-mngt.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_meminfo_obj.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_msg_obj.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_req_obj.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_vegasinfo_obj.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/netfilter/$(DEPDIR)/libnl_nf_3_la-ct.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/netfilter/$(DEPDIR)/libnl_nf_3_la-ct_obj.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/netfilter/$(DEPDIR)/libnl_nf_3_la-exp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/netfilter/$(DEPDIR)/libnl_nf_3_la-exp_obj.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_msg.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_msg_obj.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_obj.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/netfilter/$(DEPDIR)/libnl_nf_3_la-netfilter.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/netfilter/$(DEPDIR)/libnl_nf_3_la-nfnl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_msg.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_msg_obj.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_obj.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-act.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-addr.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-class.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-classid.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-cls.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-link.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-mdb.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-neigh.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-neightbl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-netconf.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-nexthop.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-nexthop_encap.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-nh.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-nh_encap_mpls.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-pktloc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-pktloc_grammar.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-pktloc_syntax.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-qdisc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-route.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-route_obj.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-route_utils.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-rtnl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-rule.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/$(DEPDIR)/libnl_route_3_la-tc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/act/$(DEPDIR)/libnl_route_3_la-gact.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/act/$(DEPDIR)/libnl_route_3_la-mirred.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/act/$(DEPDIR)/libnl_route_3_la-nat.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/act/$(DEPDIR)/libnl_route_3_la-skbedit.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/act/$(DEPDIR)/libnl_route_3_la-vlan.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/cls/$(DEPDIR)/libnl_route_3_la-basic.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/cls/$(DEPDIR)/libnl_route_3_la-cgroup.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch_grammar.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch_syntax.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/cls/$(DEPDIR)/libnl_route_3_la-flower.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/cls/$(DEPDIR)/libnl_route_3_la-fw.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/cls/$(DEPDIR)/libnl_route_3_la-mall.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/cls/$(DEPDIR)/libnl_route_3_la-police.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/cls/$(DEPDIR)/libnl_route_3_la-u32.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-cmp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-container.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-meta.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-nbyte.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-text.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-api.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-bonding.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-bridge.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-bridge_info.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-can.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-dummy.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-geneve.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-ifb.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-inet.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-inet6.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6gre.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6tnl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6vti.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-ipgre.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-ipip.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-ipvlan.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-ipvti.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-macsec.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-macvlan.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-ppp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-sit.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-sriov.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-team.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-veth.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-vlan.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-vrf.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-vxlan.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/link/$(DEPDIR)/libnl_route_3_la-xfrmi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-blackhole.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-cbq.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-dsmark.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-fifo.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-fq_codel.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-hfsc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-htb.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-ingress.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-mqprio.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-netem.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-plug.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-prio.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-red.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-sfq.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-tbf.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-ae.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-lifetime.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-sa.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-selector.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-sp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-template.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/genl_ctrl_list-genl-ctrl-list.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/idiag_socket_details-idiag-socket-details.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nf_ct_add-nf-ct-add.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nf_ct_events-nf-ct-events.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nf_ct_list-nf-ct-list.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nf_exp_add-nf-exp-add.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nf_exp_delete-nf-exp-delete.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nf_exp_list-nf-exp-list.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nf_log-nf-log.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nf_monitor-nf-monitor.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nf_queue-nf-queue.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_addr_add-nl-addr-add.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_addr_delete-nl-addr-delete.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_addr_list-nl-addr-list.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_class_add-nl-class-add.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_class_delete-nl-class-delete.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_class_list-nl-class-list.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_classid_lookup-nl-classid-lookup.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_cls_add-nl-cls-add.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_cls_delete-nl-cls-delete.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_cls_list-nl-cls-list.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_fib_lookup-nl-fib-lookup.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_link_enslave-nl-link-enslave.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_link_ifindex2name-nl-link-ifindex2name.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_link_list-nl-link-list.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_link_name2ifindex-nl-link-name2ifindex.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_link_release-nl-link-release.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_link_set-nl-link-set.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_link_stats-nl-link-stats.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_list_caches-nl-list-caches.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_list_sockets-nl-list-sockets.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_monitor-nl-monitor.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_neigh_add-nl-neigh-add.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_neigh_delete-nl-neigh-delete.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_neigh_list-nl-neigh-list.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_neightbl_list-nl-neightbl-list.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_nh_list-nl-nh-list.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_pktloc_lookup-nl-pktloc-lookup.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_qdisc_add-nl-qdisc-add.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_qdisc_delete-nl-qdisc-delete.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_qdisc_list-nl-qdisc-list.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_route_add-nl-route-add.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_route_delete-nl-route-delete.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_route_get-nl-route-get.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_route_list-nl-route-list.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_rule_list-nl-rule-list.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_tctree_list-nl-tctree-list.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nl_util_addr-nl-util-addr.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/$(DEPDIR)/libnl_cli_3_la-addr.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/$(DEPDIR)/libnl_cli_3_la-class.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/$(DEPDIR)/libnl_cli_3_la-cls.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/$(DEPDIR)/libnl_cli_3_la-ct.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/$(DEPDIR)/libnl_cli_3_la-exp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/$(DEPDIR)/libnl_cli_3_la-link.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/$(DEPDIR)/libnl_cli_3_la-neigh.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/$(DEPDIR)/libnl_cli_3_la-nh.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/$(DEPDIR)/libnl_cli_3_la-qdisc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/$(DEPDIR)/libnl_cli_3_la-route.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/$(DEPDIR)/libnl_cli_3_la-rule.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/$(DEPDIR)/libnl_cli_3_la-tc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/lib/$(DEPDIR)/libnl_cli_3_la-utils.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/check_all-check-all.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/check_all-cksuite-all-addr.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/check_all-cksuite-all-attr.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/check_all-cksuite-all-ematch-tree-clone.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/check_all-cksuite-all-netns.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/check_direct-check-direct.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/libnl_test_util_la-nl-test-util.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_cache_mngr-test-cache-mngr.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_bond-test-create-bond.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_bridge-test-create-bridge.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_geneve-test-create-geneve.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_ifb-test-create-ifb.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_ip6tnl-test-create-ip6tnl.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_ipgre-test-create-ipgre.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_ipgretap-test-create-ipgretap.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_ipip-test-create-ipip.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_ipvlan-test-create-ipvlan.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_ipvti-test-create-ipvti.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_macsec-test-create-macsec.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_macvlan-test-create-macvlan.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_macvtap-test-create-macvtap.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_sit-test-create-sit.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_veth-test-create-veth.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_vlan-test-create-vlan.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_vrf-test-create-vrf.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_vxlan-test-create-vxlan.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_create_xfrmi-test-create-xfrmi.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_delete_link-test-delete-link.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_genl-test-genl.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_loopback_up_down-test-loopback-up-down.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_nf_cache_mngr-test-nf-cache-mngr.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_socket_creation-test-socket-creation.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_u32_filter_with_actions-test-u32-filter-with-actions.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +lib/cli/cls/basic_la-basic.lo: lib/cli/cls/basic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_cls_basic_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/cli/cls/basic_la-basic.lo -MD -MP -MF lib/cli/cls/$(DEPDIR)/basic_la-basic.Tpo -c -o lib/cli/cls/basic_la-basic.lo `test -f 'lib/cli/cls/basic.c' || echo '$(srcdir)/'`lib/cli/cls/basic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/cli/cls/$(DEPDIR)/basic_la-basic.Tpo lib/cli/cls/$(DEPDIR)/basic_la-basic.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/cli/cls/basic.c' object='lib/cli/cls/basic_la-basic.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_cls_basic_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/cli/cls/basic_la-basic.lo `test -f 'lib/cli/cls/basic.c' || echo '$(srcdir)/'`lib/cli/cls/basic.c + +lib/cli/cls/cgroup_la-cgroup.lo: lib/cli/cls/cgroup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_cls_cgroup_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/cli/cls/cgroup_la-cgroup.lo -MD -MP -MF lib/cli/cls/$(DEPDIR)/cgroup_la-cgroup.Tpo -c -o lib/cli/cls/cgroup_la-cgroup.lo `test -f 'lib/cli/cls/cgroup.c' || echo '$(srcdir)/'`lib/cli/cls/cgroup.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/cli/cls/$(DEPDIR)/cgroup_la-cgroup.Tpo lib/cli/cls/$(DEPDIR)/cgroup_la-cgroup.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/cli/cls/cgroup.c' object='lib/cli/cls/cgroup_la-cgroup.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_cls_cgroup_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/cli/cls/cgroup_la-cgroup.lo `test -f 'lib/cli/cls/cgroup.c' || echo '$(srcdir)/'`lib/cli/cls/cgroup.c + +lib/cli/qdisc/bfifo_la-bfifo.lo: lib/cli/qdisc/bfifo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_qdisc_bfifo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/cli/qdisc/bfifo_la-bfifo.lo -MD -MP -MF lib/cli/qdisc/$(DEPDIR)/bfifo_la-bfifo.Tpo -c -o lib/cli/qdisc/bfifo_la-bfifo.lo `test -f 'lib/cli/qdisc/bfifo.c' || echo '$(srcdir)/'`lib/cli/qdisc/bfifo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/cli/qdisc/$(DEPDIR)/bfifo_la-bfifo.Tpo lib/cli/qdisc/$(DEPDIR)/bfifo_la-bfifo.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/cli/qdisc/bfifo.c' object='lib/cli/qdisc/bfifo_la-bfifo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_qdisc_bfifo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/cli/qdisc/bfifo_la-bfifo.lo `test -f 'lib/cli/qdisc/bfifo.c' || echo '$(srcdir)/'`lib/cli/qdisc/bfifo.c + +lib/cli/qdisc/blackhole_la-blackhole.lo: lib/cli/qdisc/blackhole.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_qdisc_blackhole_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/cli/qdisc/blackhole_la-blackhole.lo -MD -MP -MF lib/cli/qdisc/$(DEPDIR)/blackhole_la-blackhole.Tpo -c -o lib/cli/qdisc/blackhole_la-blackhole.lo `test -f 'lib/cli/qdisc/blackhole.c' || echo '$(srcdir)/'`lib/cli/qdisc/blackhole.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/cli/qdisc/$(DEPDIR)/blackhole_la-blackhole.Tpo lib/cli/qdisc/$(DEPDIR)/blackhole_la-blackhole.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/cli/qdisc/blackhole.c' object='lib/cli/qdisc/blackhole_la-blackhole.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_qdisc_blackhole_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/cli/qdisc/blackhole_la-blackhole.lo `test -f 'lib/cli/qdisc/blackhole.c' || echo '$(srcdir)/'`lib/cli/qdisc/blackhole.c + +lib/cli/qdisc/fq_codel_la-fq_codel.lo: lib/cli/qdisc/fq_codel.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_qdisc_fq_codel_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/cli/qdisc/fq_codel_la-fq_codel.lo -MD -MP -MF lib/cli/qdisc/$(DEPDIR)/fq_codel_la-fq_codel.Tpo -c -o lib/cli/qdisc/fq_codel_la-fq_codel.lo `test -f 'lib/cli/qdisc/fq_codel.c' || echo '$(srcdir)/'`lib/cli/qdisc/fq_codel.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/cli/qdisc/$(DEPDIR)/fq_codel_la-fq_codel.Tpo lib/cli/qdisc/$(DEPDIR)/fq_codel_la-fq_codel.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/cli/qdisc/fq_codel.c' object='lib/cli/qdisc/fq_codel_la-fq_codel.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_qdisc_fq_codel_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/cli/qdisc/fq_codel_la-fq_codel.lo `test -f 'lib/cli/qdisc/fq_codel.c' || echo '$(srcdir)/'`lib/cli/qdisc/fq_codel.c + +lib/cli/qdisc/hfsc_la-hfsc.lo: lib/cli/qdisc/hfsc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_qdisc_hfsc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/cli/qdisc/hfsc_la-hfsc.lo -MD -MP -MF lib/cli/qdisc/$(DEPDIR)/hfsc_la-hfsc.Tpo -c -o lib/cli/qdisc/hfsc_la-hfsc.lo `test -f 'lib/cli/qdisc/hfsc.c' || echo '$(srcdir)/'`lib/cli/qdisc/hfsc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/cli/qdisc/$(DEPDIR)/hfsc_la-hfsc.Tpo lib/cli/qdisc/$(DEPDIR)/hfsc_la-hfsc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/cli/qdisc/hfsc.c' object='lib/cli/qdisc/hfsc_la-hfsc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_qdisc_hfsc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/cli/qdisc/hfsc_la-hfsc.lo `test -f 'lib/cli/qdisc/hfsc.c' || echo '$(srcdir)/'`lib/cli/qdisc/hfsc.c + +lib/cli/qdisc/htb_la-htb.lo: lib/cli/qdisc/htb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_qdisc_htb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/cli/qdisc/htb_la-htb.lo -MD -MP -MF lib/cli/qdisc/$(DEPDIR)/htb_la-htb.Tpo -c -o lib/cli/qdisc/htb_la-htb.lo `test -f 'lib/cli/qdisc/htb.c' || echo '$(srcdir)/'`lib/cli/qdisc/htb.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/cli/qdisc/$(DEPDIR)/htb_la-htb.Tpo lib/cli/qdisc/$(DEPDIR)/htb_la-htb.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/cli/qdisc/htb.c' object='lib/cli/qdisc/htb_la-htb.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_qdisc_htb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/cli/qdisc/htb_la-htb.lo `test -f 'lib/cli/qdisc/htb.c' || echo '$(srcdir)/'`lib/cli/qdisc/htb.c + +lib/cli/qdisc/ingress_la-ingress.lo: lib/cli/qdisc/ingress.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_qdisc_ingress_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/cli/qdisc/ingress_la-ingress.lo -MD -MP -MF lib/cli/qdisc/$(DEPDIR)/ingress_la-ingress.Tpo -c -o lib/cli/qdisc/ingress_la-ingress.lo `test -f 'lib/cli/qdisc/ingress.c' || echo '$(srcdir)/'`lib/cli/qdisc/ingress.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/cli/qdisc/$(DEPDIR)/ingress_la-ingress.Tpo lib/cli/qdisc/$(DEPDIR)/ingress_la-ingress.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/cli/qdisc/ingress.c' object='lib/cli/qdisc/ingress_la-ingress.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_qdisc_ingress_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/cli/qdisc/ingress_la-ingress.lo `test -f 'lib/cli/qdisc/ingress.c' || echo '$(srcdir)/'`lib/cli/qdisc/ingress.c + +lib/cli/qdisc/pfifo_la-pfifo.lo: lib/cli/qdisc/pfifo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_qdisc_pfifo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/cli/qdisc/pfifo_la-pfifo.lo -MD -MP -MF lib/cli/qdisc/$(DEPDIR)/pfifo_la-pfifo.Tpo -c -o lib/cli/qdisc/pfifo_la-pfifo.lo `test -f 'lib/cli/qdisc/pfifo.c' || echo '$(srcdir)/'`lib/cli/qdisc/pfifo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/cli/qdisc/$(DEPDIR)/pfifo_la-pfifo.Tpo lib/cli/qdisc/$(DEPDIR)/pfifo_la-pfifo.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/cli/qdisc/pfifo.c' object='lib/cli/qdisc/pfifo_la-pfifo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_qdisc_pfifo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/cli/qdisc/pfifo_la-pfifo.lo `test -f 'lib/cli/qdisc/pfifo.c' || echo '$(srcdir)/'`lib/cli/qdisc/pfifo.c + +lib/cli/qdisc/plug_la-plug.lo: lib/cli/qdisc/plug.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_qdisc_plug_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/cli/qdisc/plug_la-plug.lo -MD -MP -MF lib/cli/qdisc/$(DEPDIR)/plug_la-plug.Tpo -c -o lib/cli/qdisc/plug_la-plug.lo `test -f 'lib/cli/qdisc/plug.c' || echo '$(srcdir)/'`lib/cli/qdisc/plug.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/cli/qdisc/$(DEPDIR)/plug_la-plug.Tpo lib/cli/qdisc/$(DEPDIR)/plug_la-plug.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/cli/qdisc/plug.c' object='lib/cli/qdisc/plug_la-plug.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_cli_qdisc_plug_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/cli/qdisc/plug_la-plug.lo `test -f 'lib/cli/qdisc/plug.c' || echo '$(srcdir)/'`lib/cli/qdisc/plug.c + +lib/libnl_3_la-addr.lo: lib/addr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/libnl_3_la-addr.lo -MD -MP -MF lib/$(DEPDIR)/libnl_3_la-addr.Tpo -c -o lib/libnl_3_la-addr.lo `test -f 'lib/addr.c' || echo '$(srcdir)/'`lib/addr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libnl_3_la-addr.Tpo lib/$(DEPDIR)/libnl_3_la-addr.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/addr.c' object='lib/libnl_3_la-addr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/libnl_3_la-addr.lo `test -f 'lib/addr.c' || echo '$(srcdir)/'`lib/addr.c + +lib/libnl_3_la-attr.lo: lib/attr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/libnl_3_la-attr.lo -MD -MP -MF lib/$(DEPDIR)/libnl_3_la-attr.Tpo -c -o lib/libnl_3_la-attr.lo `test -f 'lib/attr.c' || echo '$(srcdir)/'`lib/attr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libnl_3_la-attr.Tpo lib/$(DEPDIR)/libnl_3_la-attr.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/attr.c' object='lib/libnl_3_la-attr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/libnl_3_la-attr.lo `test -f 'lib/attr.c' || echo '$(srcdir)/'`lib/attr.c + +lib/libnl_3_la-cache.lo: lib/cache.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/libnl_3_la-cache.lo -MD -MP -MF lib/$(DEPDIR)/libnl_3_la-cache.Tpo -c -o lib/libnl_3_la-cache.lo `test -f 'lib/cache.c' || echo '$(srcdir)/'`lib/cache.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libnl_3_la-cache.Tpo lib/$(DEPDIR)/libnl_3_la-cache.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/cache.c' object='lib/libnl_3_la-cache.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/libnl_3_la-cache.lo `test -f 'lib/cache.c' || echo '$(srcdir)/'`lib/cache.c + +lib/libnl_3_la-cache_mngr.lo: lib/cache_mngr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/libnl_3_la-cache_mngr.lo -MD -MP -MF lib/$(DEPDIR)/libnl_3_la-cache_mngr.Tpo -c -o lib/libnl_3_la-cache_mngr.lo `test -f 'lib/cache_mngr.c' || echo '$(srcdir)/'`lib/cache_mngr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libnl_3_la-cache_mngr.Tpo lib/$(DEPDIR)/libnl_3_la-cache_mngr.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/cache_mngr.c' object='lib/libnl_3_la-cache_mngr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/libnl_3_la-cache_mngr.lo `test -f 'lib/cache_mngr.c' || echo '$(srcdir)/'`lib/cache_mngr.c + +lib/libnl_3_la-cache_mngt.lo: lib/cache_mngt.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/libnl_3_la-cache_mngt.lo -MD -MP -MF lib/$(DEPDIR)/libnl_3_la-cache_mngt.Tpo -c -o lib/libnl_3_la-cache_mngt.lo `test -f 'lib/cache_mngt.c' || echo '$(srcdir)/'`lib/cache_mngt.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libnl_3_la-cache_mngt.Tpo lib/$(DEPDIR)/libnl_3_la-cache_mngt.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/cache_mngt.c' object='lib/libnl_3_la-cache_mngt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/libnl_3_la-cache_mngt.lo `test -f 'lib/cache_mngt.c' || echo '$(srcdir)/'`lib/cache_mngt.c + +lib/libnl_3_la-data.lo: lib/data.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/libnl_3_la-data.lo -MD -MP -MF lib/$(DEPDIR)/libnl_3_la-data.Tpo -c -o lib/libnl_3_la-data.lo `test -f 'lib/data.c' || echo '$(srcdir)/'`lib/data.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libnl_3_la-data.Tpo lib/$(DEPDIR)/libnl_3_la-data.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/data.c' object='lib/libnl_3_la-data.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/libnl_3_la-data.lo `test -f 'lib/data.c' || echo '$(srcdir)/'`lib/data.c + +lib/libnl_3_la-error.lo: lib/error.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/libnl_3_la-error.lo -MD -MP -MF lib/$(DEPDIR)/libnl_3_la-error.Tpo -c -o lib/libnl_3_la-error.lo `test -f 'lib/error.c' || echo '$(srcdir)/'`lib/error.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libnl_3_la-error.Tpo lib/$(DEPDIR)/libnl_3_la-error.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/error.c' object='lib/libnl_3_la-error.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/libnl_3_la-error.lo `test -f 'lib/error.c' || echo '$(srcdir)/'`lib/error.c + +lib/libnl_3_la-handlers.lo: lib/handlers.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/libnl_3_la-handlers.lo -MD -MP -MF lib/$(DEPDIR)/libnl_3_la-handlers.Tpo -c -o lib/libnl_3_la-handlers.lo `test -f 'lib/handlers.c' || echo '$(srcdir)/'`lib/handlers.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libnl_3_la-handlers.Tpo lib/$(DEPDIR)/libnl_3_la-handlers.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/handlers.c' object='lib/libnl_3_la-handlers.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/libnl_3_la-handlers.lo `test -f 'lib/handlers.c' || echo '$(srcdir)/'`lib/handlers.c + +lib/libnl_3_la-hash.lo: lib/hash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/libnl_3_la-hash.lo -MD -MP -MF lib/$(DEPDIR)/libnl_3_la-hash.Tpo -c -o lib/libnl_3_la-hash.lo `test -f 'lib/hash.c' || echo '$(srcdir)/'`lib/hash.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libnl_3_la-hash.Tpo lib/$(DEPDIR)/libnl_3_la-hash.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/hash.c' object='lib/libnl_3_la-hash.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/libnl_3_la-hash.lo `test -f 'lib/hash.c' || echo '$(srcdir)/'`lib/hash.c + +lib/libnl_3_la-hashtable.lo: lib/hashtable.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/libnl_3_la-hashtable.lo -MD -MP -MF lib/$(DEPDIR)/libnl_3_la-hashtable.Tpo -c -o lib/libnl_3_la-hashtable.lo `test -f 'lib/hashtable.c' || echo '$(srcdir)/'`lib/hashtable.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libnl_3_la-hashtable.Tpo lib/$(DEPDIR)/libnl_3_la-hashtable.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/hashtable.c' object='lib/libnl_3_la-hashtable.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/libnl_3_la-hashtable.lo `test -f 'lib/hashtable.c' || echo '$(srcdir)/'`lib/hashtable.c + +lib/libnl_3_la-mpls.lo: lib/mpls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/libnl_3_la-mpls.lo -MD -MP -MF lib/$(DEPDIR)/libnl_3_la-mpls.Tpo -c -o lib/libnl_3_la-mpls.lo `test -f 'lib/mpls.c' || echo '$(srcdir)/'`lib/mpls.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libnl_3_la-mpls.Tpo lib/$(DEPDIR)/libnl_3_la-mpls.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/mpls.c' object='lib/libnl_3_la-mpls.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/libnl_3_la-mpls.lo `test -f 'lib/mpls.c' || echo '$(srcdir)/'`lib/mpls.c + +lib/libnl_3_la-msg.lo: lib/msg.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/libnl_3_la-msg.lo -MD -MP -MF lib/$(DEPDIR)/libnl_3_la-msg.Tpo -c -o lib/libnl_3_la-msg.lo `test -f 'lib/msg.c' || echo '$(srcdir)/'`lib/msg.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libnl_3_la-msg.Tpo lib/$(DEPDIR)/libnl_3_la-msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/msg.c' object='lib/libnl_3_la-msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/libnl_3_la-msg.lo `test -f 'lib/msg.c' || echo '$(srcdir)/'`lib/msg.c + +lib/libnl_3_la-nl.lo: lib/nl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/libnl_3_la-nl.lo -MD -MP -MF lib/$(DEPDIR)/libnl_3_la-nl.Tpo -c -o lib/libnl_3_la-nl.lo `test -f 'lib/nl.c' || echo '$(srcdir)/'`lib/nl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libnl_3_la-nl.Tpo lib/$(DEPDIR)/libnl_3_la-nl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/nl.c' object='lib/libnl_3_la-nl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/libnl_3_la-nl.lo `test -f 'lib/nl.c' || echo '$(srcdir)/'`lib/nl.c + +lib/libnl_3_la-object.lo: lib/object.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/libnl_3_la-object.lo -MD -MP -MF lib/$(DEPDIR)/libnl_3_la-object.Tpo -c -o lib/libnl_3_la-object.lo `test -f 'lib/object.c' || echo '$(srcdir)/'`lib/object.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libnl_3_la-object.Tpo lib/$(DEPDIR)/libnl_3_la-object.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/object.c' object='lib/libnl_3_la-object.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/libnl_3_la-object.lo `test -f 'lib/object.c' || echo '$(srcdir)/'`lib/object.c + +lib/libnl_3_la-socket.lo: lib/socket.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/libnl_3_la-socket.lo -MD -MP -MF lib/$(DEPDIR)/libnl_3_la-socket.Tpo -c -o lib/libnl_3_la-socket.lo `test -f 'lib/socket.c' || echo '$(srcdir)/'`lib/socket.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libnl_3_la-socket.Tpo lib/$(DEPDIR)/libnl_3_la-socket.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/socket.c' object='lib/libnl_3_la-socket.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/libnl_3_la-socket.lo `test -f 'lib/socket.c' || echo '$(srcdir)/'`lib/socket.c + +lib/libnl_3_la-utils.lo: lib/utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/libnl_3_la-utils.lo -MD -MP -MF lib/$(DEPDIR)/libnl_3_la-utils.Tpo -c -o lib/libnl_3_la-utils.lo `test -f 'lib/utils.c' || echo '$(srcdir)/'`lib/utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libnl_3_la-utils.Tpo lib/$(DEPDIR)/libnl_3_la-utils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/utils.c' object='lib/libnl_3_la-utils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/libnl_3_la-utils.lo `test -f 'lib/utils.c' || echo '$(srcdir)/'`lib/utils.c + +lib/libnl_3_la-version.lo: lib/version.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/libnl_3_la-version.lo -MD -MP -MF lib/$(DEPDIR)/libnl_3_la-version.Tpo -c -o lib/libnl_3_la-version.lo `test -f 'lib/version.c' || echo '$(srcdir)/'`lib/version.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libnl_3_la-version.Tpo lib/$(DEPDIR)/libnl_3_la-version.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/version.c' object='lib/libnl_3_la-version.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/libnl_3_la-version.lo `test -f 'lib/version.c' || echo '$(srcdir)/'`lib/version.c + +lib/genl/libnl_genl_3_la-ctrl.lo: lib/genl/ctrl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_genl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/genl/libnl_genl_3_la-ctrl.lo -MD -MP -MF lib/genl/$(DEPDIR)/libnl_genl_3_la-ctrl.Tpo -c -o lib/genl/libnl_genl_3_la-ctrl.lo `test -f 'lib/genl/ctrl.c' || echo '$(srcdir)/'`lib/genl/ctrl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/genl/$(DEPDIR)/libnl_genl_3_la-ctrl.Tpo lib/genl/$(DEPDIR)/libnl_genl_3_la-ctrl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/genl/ctrl.c' object='lib/genl/libnl_genl_3_la-ctrl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_genl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/genl/libnl_genl_3_la-ctrl.lo `test -f 'lib/genl/ctrl.c' || echo '$(srcdir)/'`lib/genl/ctrl.c + +lib/genl/libnl_genl_3_la-family.lo: lib/genl/family.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_genl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/genl/libnl_genl_3_la-family.lo -MD -MP -MF lib/genl/$(DEPDIR)/libnl_genl_3_la-family.Tpo -c -o lib/genl/libnl_genl_3_la-family.lo `test -f 'lib/genl/family.c' || echo '$(srcdir)/'`lib/genl/family.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/genl/$(DEPDIR)/libnl_genl_3_la-family.Tpo lib/genl/$(DEPDIR)/libnl_genl_3_la-family.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/genl/family.c' object='lib/genl/libnl_genl_3_la-family.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_genl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/genl/libnl_genl_3_la-family.lo `test -f 'lib/genl/family.c' || echo '$(srcdir)/'`lib/genl/family.c + +lib/genl/libnl_genl_3_la-genl.lo: lib/genl/genl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_genl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/genl/libnl_genl_3_la-genl.lo -MD -MP -MF lib/genl/$(DEPDIR)/libnl_genl_3_la-genl.Tpo -c -o lib/genl/libnl_genl_3_la-genl.lo `test -f 'lib/genl/genl.c' || echo '$(srcdir)/'`lib/genl/genl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/genl/$(DEPDIR)/libnl_genl_3_la-genl.Tpo lib/genl/$(DEPDIR)/libnl_genl_3_la-genl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/genl/genl.c' object='lib/genl/libnl_genl_3_la-genl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_genl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/genl/libnl_genl_3_la-genl.lo `test -f 'lib/genl/genl.c' || echo '$(srcdir)/'`lib/genl/genl.c + +lib/genl/libnl_genl_3_la-mngt.lo: lib/genl/mngt.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_genl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/genl/libnl_genl_3_la-mngt.lo -MD -MP -MF lib/genl/$(DEPDIR)/libnl_genl_3_la-mngt.Tpo -c -o lib/genl/libnl_genl_3_la-mngt.lo `test -f 'lib/genl/mngt.c' || echo '$(srcdir)/'`lib/genl/mngt.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/genl/$(DEPDIR)/libnl_genl_3_la-mngt.Tpo lib/genl/$(DEPDIR)/libnl_genl_3_la-mngt.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/genl/mngt.c' object='lib/genl/libnl_genl_3_la-mngt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_genl_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/genl/libnl_genl_3_la-mngt.lo `test -f 'lib/genl/mngt.c' || echo '$(srcdir)/'`lib/genl/mngt.c + +lib/idiag/libnl_idiag_3_la-idiag.lo: lib/idiag/idiag.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_idiag_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/idiag/libnl_idiag_3_la-idiag.lo -MD -MP -MF lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag.Tpo -c -o lib/idiag/libnl_idiag_3_la-idiag.lo `test -f 'lib/idiag/idiag.c' || echo '$(srcdir)/'`lib/idiag/idiag.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag.Tpo lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/idiag/idiag.c' object='lib/idiag/libnl_idiag_3_la-idiag.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_idiag_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/idiag/libnl_idiag_3_la-idiag.lo `test -f 'lib/idiag/idiag.c' || echo '$(srcdir)/'`lib/idiag/idiag.c + +lib/idiag/libnl_idiag_3_la-idiag_meminfo_obj.lo: lib/idiag/idiag_meminfo_obj.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_idiag_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/idiag/libnl_idiag_3_la-idiag_meminfo_obj.lo -MD -MP -MF lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_meminfo_obj.Tpo -c -o lib/idiag/libnl_idiag_3_la-idiag_meminfo_obj.lo `test -f 'lib/idiag/idiag_meminfo_obj.c' || echo '$(srcdir)/'`lib/idiag/idiag_meminfo_obj.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_meminfo_obj.Tpo lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_meminfo_obj.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/idiag/idiag_meminfo_obj.c' object='lib/idiag/libnl_idiag_3_la-idiag_meminfo_obj.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_idiag_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/idiag/libnl_idiag_3_la-idiag_meminfo_obj.lo `test -f 'lib/idiag/idiag_meminfo_obj.c' || echo '$(srcdir)/'`lib/idiag/idiag_meminfo_obj.c + +lib/idiag/libnl_idiag_3_la-idiag_msg_obj.lo: lib/idiag/idiag_msg_obj.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_idiag_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/idiag/libnl_idiag_3_la-idiag_msg_obj.lo -MD -MP -MF lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_msg_obj.Tpo -c -o lib/idiag/libnl_idiag_3_la-idiag_msg_obj.lo `test -f 'lib/idiag/idiag_msg_obj.c' || echo '$(srcdir)/'`lib/idiag/idiag_msg_obj.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_msg_obj.Tpo lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_msg_obj.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/idiag/idiag_msg_obj.c' object='lib/idiag/libnl_idiag_3_la-idiag_msg_obj.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_idiag_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/idiag/libnl_idiag_3_la-idiag_msg_obj.lo `test -f 'lib/idiag/idiag_msg_obj.c' || echo '$(srcdir)/'`lib/idiag/idiag_msg_obj.c + +lib/idiag/libnl_idiag_3_la-idiag_req_obj.lo: lib/idiag/idiag_req_obj.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_idiag_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/idiag/libnl_idiag_3_la-idiag_req_obj.lo -MD -MP -MF lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_req_obj.Tpo -c -o lib/idiag/libnl_idiag_3_la-idiag_req_obj.lo `test -f 'lib/idiag/idiag_req_obj.c' || echo '$(srcdir)/'`lib/idiag/idiag_req_obj.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_req_obj.Tpo lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_req_obj.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/idiag/idiag_req_obj.c' object='lib/idiag/libnl_idiag_3_la-idiag_req_obj.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_idiag_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/idiag/libnl_idiag_3_la-idiag_req_obj.lo `test -f 'lib/idiag/idiag_req_obj.c' || echo '$(srcdir)/'`lib/idiag/idiag_req_obj.c + +lib/idiag/libnl_idiag_3_la-idiag_vegasinfo_obj.lo: lib/idiag/idiag_vegasinfo_obj.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_idiag_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/idiag/libnl_idiag_3_la-idiag_vegasinfo_obj.lo -MD -MP -MF lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_vegasinfo_obj.Tpo -c -o lib/idiag/libnl_idiag_3_la-idiag_vegasinfo_obj.lo `test -f 'lib/idiag/idiag_vegasinfo_obj.c' || echo '$(srcdir)/'`lib/idiag/idiag_vegasinfo_obj.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_vegasinfo_obj.Tpo lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_vegasinfo_obj.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/idiag/idiag_vegasinfo_obj.c' object='lib/idiag/libnl_idiag_3_la-idiag_vegasinfo_obj.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_idiag_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/idiag/libnl_idiag_3_la-idiag_vegasinfo_obj.lo `test -f 'lib/idiag/idiag_vegasinfo_obj.c' || echo '$(srcdir)/'`lib/idiag/idiag_vegasinfo_obj.c + +lib/netfilter/libnl_nf_3_la-ct.lo: lib/netfilter/ct.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/netfilter/libnl_nf_3_la-ct.lo -MD -MP -MF lib/netfilter/$(DEPDIR)/libnl_nf_3_la-ct.Tpo -c -o lib/netfilter/libnl_nf_3_la-ct.lo `test -f 'lib/netfilter/ct.c' || echo '$(srcdir)/'`lib/netfilter/ct.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/netfilter/$(DEPDIR)/libnl_nf_3_la-ct.Tpo lib/netfilter/$(DEPDIR)/libnl_nf_3_la-ct.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/netfilter/ct.c' object='lib/netfilter/libnl_nf_3_la-ct.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/netfilter/libnl_nf_3_la-ct.lo `test -f 'lib/netfilter/ct.c' || echo '$(srcdir)/'`lib/netfilter/ct.c + +lib/netfilter/libnl_nf_3_la-ct_obj.lo: lib/netfilter/ct_obj.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/netfilter/libnl_nf_3_la-ct_obj.lo -MD -MP -MF lib/netfilter/$(DEPDIR)/libnl_nf_3_la-ct_obj.Tpo -c -o lib/netfilter/libnl_nf_3_la-ct_obj.lo `test -f 'lib/netfilter/ct_obj.c' || echo '$(srcdir)/'`lib/netfilter/ct_obj.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/netfilter/$(DEPDIR)/libnl_nf_3_la-ct_obj.Tpo lib/netfilter/$(DEPDIR)/libnl_nf_3_la-ct_obj.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/netfilter/ct_obj.c' object='lib/netfilter/libnl_nf_3_la-ct_obj.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/netfilter/libnl_nf_3_la-ct_obj.lo `test -f 'lib/netfilter/ct_obj.c' || echo '$(srcdir)/'`lib/netfilter/ct_obj.c + +lib/netfilter/libnl_nf_3_la-exp.lo: lib/netfilter/exp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/netfilter/libnl_nf_3_la-exp.lo -MD -MP -MF lib/netfilter/$(DEPDIR)/libnl_nf_3_la-exp.Tpo -c -o lib/netfilter/libnl_nf_3_la-exp.lo `test -f 'lib/netfilter/exp.c' || echo '$(srcdir)/'`lib/netfilter/exp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/netfilter/$(DEPDIR)/libnl_nf_3_la-exp.Tpo lib/netfilter/$(DEPDIR)/libnl_nf_3_la-exp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/netfilter/exp.c' object='lib/netfilter/libnl_nf_3_la-exp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/netfilter/libnl_nf_3_la-exp.lo `test -f 'lib/netfilter/exp.c' || echo '$(srcdir)/'`lib/netfilter/exp.c + +lib/netfilter/libnl_nf_3_la-exp_obj.lo: lib/netfilter/exp_obj.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/netfilter/libnl_nf_3_la-exp_obj.lo -MD -MP -MF lib/netfilter/$(DEPDIR)/libnl_nf_3_la-exp_obj.Tpo -c -o lib/netfilter/libnl_nf_3_la-exp_obj.lo `test -f 'lib/netfilter/exp_obj.c' || echo '$(srcdir)/'`lib/netfilter/exp_obj.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/netfilter/$(DEPDIR)/libnl_nf_3_la-exp_obj.Tpo lib/netfilter/$(DEPDIR)/libnl_nf_3_la-exp_obj.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/netfilter/exp_obj.c' object='lib/netfilter/libnl_nf_3_la-exp_obj.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/netfilter/libnl_nf_3_la-exp_obj.lo `test -f 'lib/netfilter/exp_obj.c' || echo '$(srcdir)/'`lib/netfilter/exp_obj.c + +lib/netfilter/libnl_nf_3_la-log.lo: lib/netfilter/log.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/netfilter/libnl_nf_3_la-log.lo -MD -MP -MF lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log.Tpo -c -o lib/netfilter/libnl_nf_3_la-log.lo `test -f 'lib/netfilter/log.c' || echo '$(srcdir)/'`lib/netfilter/log.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log.Tpo lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/netfilter/log.c' object='lib/netfilter/libnl_nf_3_la-log.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/netfilter/libnl_nf_3_la-log.lo `test -f 'lib/netfilter/log.c' || echo '$(srcdir)/'`lib/netfilter/log.c + +lib/netfilter/libnl_nf_3_la-log_msg.lo: lib/netfilter/log_msg.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/netfilter/libnl_nf_3_la-log_msg.lo -MD -MP -MF lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_msg.Tpo -c -o lib/netfilter/libnl_nf_3_la-log_msg.lo `test -f 'lib/netfilter/log_msg.c' || echo '$(srcdir)/'`lib/netfilter/log_msg.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_msg.Tpo lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/netfilter/log_msg.c' object='lib/netfilter/libnl_nf_3_la-log_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/netfilter/libnl_nf_3_la-log_msg.lo `test -f 'lib/netfilter/log_msg.c' || echo '$(srcdir)/'`lib/netfilter/log_msg.c + +lib/netfilter/libnl_nf_3_la-log_msg_obj.lo: lib/netfilter/log_msg_obj.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/netfilter/libnl_nf_3_la-log_msg_obj.lo -MD -MP -MF lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_msg_obj.Tpo -c -o lib/netfilter/libnl_nf_3_la-log_msg_obj.lo `test -f 'lib/netfilter/log_msg_obj.c' || echo '$(srcdir)/'`lib/netfilter/log_msg_obj.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_msg_obj.Tpo lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_msg_obj.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/netfilter/log_msg_obj.c' object='lib/netfilter/libnl_nf_3_la-log_msg_obj.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/netfilter/libnl_nf_3_la-log_msg_obj.lo `test -f 'lib/netfilter/log_msg_obj.c' || echo '$(srcdir)/'`lib/netfilter/log_msg_obj.c + +lib/netfilter/libnl_nf_3_la-log_obj.lo: lib/netfilter/log_obj.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/netfilter/libnl_nf_3_la-log_obj.lo -MD -MP -MF lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_obj.Tpo -c -o lib/netfilter/libnl_nf_3_la-log_obj.lo `test -f 'lib/netfilter/log_obj.c' || echo '$(srcdir)/'`lib/netfilter/log_obj.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_obj.Tpo lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_obj.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/netfilter/log_obj.c' object='lib/netfilter/libnl_nf_3_la-log_obj.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/netfilter/libnl_nf_3_la-log_obj.lo `test -f 'lib/netfilter/log_obj.c' || echo '$(srcdir)/'`lib/netfilter/log_obj.c + +lib/netfilter/libnl_nf_3_la-netfilter.lo: lib/netfilter/netfilter.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/netfilter/libnl_nf_3_la-netfilter.lo -MD -MP -MF lib/netfilter/$(DEPDIR)/libnl_nf_3_la-netfilter.Tpo -c -o lib/netfilter/libnl_nf_3_la-netfilter.lo `test -f 'lib/netfilter/netfilter.c' || echo '$(srcdir)/'`lib/netfilter/netfilter.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/netfilter/$(DEPDIR)/libnl_nf_3_la-netfilter.Tpo lib/netfilter/$(DEPDIR)/libnl_nf_3_la-netfilter.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/netfilter/netfilter.c' object='lib/netfilter/libnl_nf_3_la-netfilter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/netfilter/libnl_nf_3_la-netfilter.lo `test -f 'lib/netfilter/netfilter.c' || echo '$(srcdir)/'`lib/netfilter/netfilter.c + +lib/netfilter/libnl_nf_3_la-nfnl.lo: lib/netfilter/nfnl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/netfilter/libnl_nf_3_la-nfnl.lo -MD -MP -MF lib/netfilter/$(DEPDIR)/libnl_nf_3_la-nfnl.Tpo -c -o lib/netfilter/libnl_nf_3_la-nfnl.lo `test -f 'lib/netfilter/nfnl.c' || echo '$(srcdir)/'`lib/netfilter/nfnl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/netfilter/$(DEPDIR)/libnl_nf_3_la-nfnl.Tpo lib/netfilter/$(DEPDIR)/libnl_nf_3_la-nfnl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/netfilter/nfnl.c' object='lib/netfilter/libnl_nf_3_la-nfnl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/netfilter/libnl_nf_3_la-nfnl.lo `test -f 'lib/netfilter/nfnl.c' || echo '$(srcdir)/'`lib/netfilter/nfnl.c + +lib/netfilter/libnl_nf_3_la-queue.lo: lib/netfilter/queue.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/netfilter/libnl_nf_3_la-queue.lo -MD -MP -MF lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue.Tpo -c -o lib/netfilter/libnl_nf_3_la-queue.lo `test -f 'lib/netfilter/queue.c' || echo '$(srcdir)/'`lib/netfilter/queue.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue.Tpo lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/netfilter/queue.c' object='lib/netfilter/libnl_nf_3_la-queue.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/netfilter/libnl_nf_3_la-queue.lo `test -f 'lib/netfilter/queue.c' || echo '$(srcdir)/'`lib/netfilter/queue.c + +lib/netfilter/libnl_nf_3_la-queue_msg.lo: lib/netfilter/queue_msg.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/netfilter/libnl_nf_3_la-queue_msg.lo -MD -MP -MF lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_msg.Tpo -c -o lib/netfilter/libnl_nf_3_la-queue_msg.lo `test -f 'lib/netfilter/queue_msg.c' || echo '$(srcdir)/'`lib/netfilter/queue_msg.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_msg.Tpo lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/netfilter/queue_msg.c' object='lib/netfilter/libnl_nf_3_la-queue_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/netfilter/libnl_nf_3_la-queue_msg.lo `test -f 'lib/netfilter/queue_msg.c' || echo '$(srcdir)/'`lib/netfilter/queue_msg.c + +lib/netfilter/libnl_nf_3_la-queue_msg_obj.lo: lib/netfilter/queue_msg_obj.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/netfilter/libnl_nf_3_la-queue_msg_obj.lo -MD -MP -MF lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_msg_obj.Tpo -c -o lib/netfilter/libnl_nf_3_la-queue_msg_obj.lo `test -f 'lib/netfilter/queue_msg_obj.c' || echo '$(srcdir)/'`lib/netfilter/queue_msg_obj.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_msg_obj.Tpo lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_msg_obj.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/netfilter/queue_msg_obj.c' object='lib/netfilter/libnl_nf_3_la-queue_msg_obj.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/netfilter/libnl_nf_3_la-queue_msg_obj.lo `test -f 'lib/netfilter/queue_msg_obj.c' || echo '$(srcdir)/'`lib/netfilter/queue_msg_obj.c + +lib/netfilter/libnl_nf_3_la-queue_obj.lo: lib/netfilter/queue_obj.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/netfilter/libnl_nf_3_la-queue_obj.lo -MD -MP -MF lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_obj.Tpo -c -o lib/netfilter/libnl_nf_3_la-queue_obj.lo `test -f 'lib/netfilter/queue_obj.c' || echo '$(srcdir)/'`lib/netfilter/queue_obj.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_obj.Tpo lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_obj.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/netfilter/queue_obj.c' object='lib/netfilter/libnl_nf_3_la-queue_obj.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_nf_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/netfilter/libnl_nf_3_la-queue_obj.lo `test -f 'lib/netfilter/queue_obj.c' || echo '$(srcdir)/'`lib/netfilter/queue_obj.c + +lib/fib_lookup/libnl_route_3_la-lookup.lo: lib/fib_lookup/lookup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/fib_lookup/libnl_route_3_la-lookup.lo -MD -MP -MF lib/fib_lookup/$(DEPDIR)/libnl_route_3_la-lookup.Tpo -c -o lib/fib_lookup/libnl_route_3_la-lookup.lo `test -f 'lib/fib_lookup/lookup.c' || echo '$(srcdir)/'`lib/fib_lookup/lookup.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/fib_lookup/$(DEPDIR)/libnl_route_3_la-lookup.Tpo lib/fib_lookup/$(DEPDIR)/libnl_route_3_la-lookup.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/fib_lookup/lookup.c' object='lib/fib_lookup/libnl_route_3_la-lookup.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/fib_lookup/libnl_route_3_la-lookup.lo `test -f 'lib/fib_lookup/lookup.c' || echo '$(srcdir)/'`lib/fib_lookup/lookup.c + +lib/fib_lookup/libnl_route_3_la-request.lo: lib/fib_lookup/request.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/fib_lookup/libnl_route_3_la-request.lo -MD -MP -MF lib/fib_lookup/$(DEPDIR)/libnl_route_3_la-request.Tpo -c -o lib/fib_lookup/libnl_route_3_la-request.lo `test -f 'lib/fib_lookup/request.c' || echo '$(srcdir)/'`lib/fib_lookup/request.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/fib_lookup/$(DEPDIR)/libnl_route_3_la-request.Tpo lib/fib_lookup/$(DEPDIR)/libnl_route_3_la-request.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/fib_lookup/request.c' object='lib/fib_lookup/libnl_route_3_la-request.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/fib_lookup/libnl_route_3_la-request.lo `test -f 'lib/fib_lookup/request.c' || echo '$(srcdir)/'`lib/fib_lookup/request.c + +lib/route/libnl_route_3_la-act.lo: lib/route/act.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-act.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-act.Tpo -c -o lib/route/libnl_route_3_la-act.lo `test -f 'lib/route/act.c' || echo '$(srcdir)/'`lib/route/act.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-act.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-act.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/act.c' object='lib/route/libnl_route_3_la-act.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-act.lo `test -f 'lib/route/act.c' || echo '$(srcdir)/'`lib/route/act.c + +lib/route/act/libnl_route_3_la-gact.lo: lib/route/act/gact.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/act/libnl_route_3_la-gact.lo -MD -MP -MF lib/route/act/$(DEPDIR)/libnl_route_3_la-gact.Tpo -c -o lib/route/act/libnl_route_3_la-gact.lo `test -f 'lib/route/act/gact.c' || echo '$(srcdir)/'`lib/route/act/gact.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/act/$(DEPDIR)/libnl_route_3_la-gact.Tpo lib/route/act/$(DEPDIR)/libnl_route_3_la-gact.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/act/gact.c' object='lib/route/act/libnl_route_3_la-gact.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/act/libnl_route_3_la-gact.lo `test -f 'lib/route/act/gact.c' || echo '$(srcdir)/'`lib/route/act/gact.c + +lib/route/act/libnl_route_3_la-mirred.lo: lib/route/act/mirred.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/act/libnl_route_3_la-mirred.lo -MD -MP -MF lib/route/act/$(DEPDIR)/libnl_route_3_la-mirred.Tpo -c -o lib/route/act/libnl_route_3_la-mirred.lo `test -f 'lib/route/act/mirred.c' || echo '$(srcdir)/'`lib/route/act/mirred.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/act/$(DEPDIR)/libnl_route_3_la-mirred.Tpo lib/route/act/$(DEPDIR)/libnl_route_3_la-mirred.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/act/mirred.c' object='lib/route/act/libnl_route_3_la-mirred.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/act/libnl_route_3_la-mirred.lo `test -f 'lib/route/act/mirred.c' || echo '$(srcdir)/'`lib/route/act/mirred.c + +lib/route/act/libnl_route_3_la-nat.lo: lib/route/act/nat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/act/libnl_route_3_la-nat.lo -MD -MP -MF lib/route/act/$(DEPDIR)/libnl_route_3_la-nat.Tpo -c -o lib/route/act/libnl_route_3_la-nat.lo `test -f 'lib/route/act/nat.c' || echo '$(srcdir)/'`lib/route/act/nat.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/act/$(DEPDIR)/libnl_route_3_la-nat.Tpo lib/route/act/$(DEPDIR)/libnl_route_3_la-nat.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/act/nat.c' object='lib/route/act/libnl_route_3_la-nat.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/act/libnl_route_3_la-nat.lo `test -f 'lib/route/act/nat.c' || echo '$(srcdir)/'`lib/route/act/nat.c + +lib/route/act/libnl_route_3_la-skbedit.lo: lib/route/act/skbedit.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/act/libnl_route_3_la-skbedit.lo -MD -MP -MF lib/route/act/$(DEPDIR)/libnl_route_3_la-skbedit.Tpo -c -o lib/route/act/libnl_route_3_la-skbedit.lo `test -f 'lib/route/act/skbedit.c' || echo '$(srcdir)/'`lib/route/act/skbedit.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/act/$(DEPDIR)/libnl_route_3_la-skbedit.Tpo lib/route/act/$(DEPDIR)/libnl_route_3_la-skbedit.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/act/skbedit.c' object='lib/route/act/libnl_route_3_la-skbedit.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/act/libnl_route_3_la-skbedit.lo `test -f 'lib/route/act/skbedit.c' || echo '$(srcdir)/'`lib/route/act/skbedit.c + +lib/route/act/libnl_route_3_la-vlan.lo: lib/route/act/vlan.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/act/libnl_route_3_la-vlan.lo -MD -MP -MF lib/route/act/$(DEPDIR)/libnl_route_3_la-vlan.Tpo -c -o lib/route/act/libnl_route_3_la-vlan.lo `test -f 'lib/route/act/vlan.c' || echo '$(srcdir)/'`lib/route/act/vlan.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/act/$(DEPDIR)/libnl_route_3_la-vlan.Tpo lib/route/act/$(DEPDIR)/libnl_route_3_la-vlan.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/act/vlan.c' object='lib/route/act/libnl_route_3_la-vlan.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/act/libnl_route_3_la-vlan.lo `test -f 'lib/route/act/vlan.c' || echo '$(srcdir)/'`lib/route/act/vlan.c + +lib/route/libnl_route_3_la-addr.lo: lib/route/addr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-addr.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-addr.Tpo -c -o lib/route/libnl_route_3_la-addr.lo `test -f 'lib/route/addr.c' || echo '$(srcdir)/'`lib/route/addr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-addr.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-addr.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/addr.c' object='lib/route/libnl_route_3_la-addr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-addr.lo `test -f 'lib/route/addr.c' || echo '$(srcdir)/'`lib/route/addr.c + +lib/route/libnl_route_3_la-class.lo: lib/route/class.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-class.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-class.Tpo -c -o lib/route/libnl_route_3_la-class.lo `test -f 'lib/route/class.c' || echo '$(srcdir)/'`lib/route/class.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-class.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-class.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/class.c' object='lib/route/libnl_route_3_la-class.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-class.lo `test -f 'lib/route/class.c' || echo '$(srcdir)/'`lib/route/class.c + +lib/route/libnl_route_3_la-classid.lo: lib/route/classid.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-classid.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-classid.Tpo -c -o lib/route/libnl_route_3_la-classid.lo `test -f 'lib/route/classid.c' || echo '$(srcdir)/'`lib/route/classid.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-classid.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-classid.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/classid.c' object='lib/route/libnl_route_3_la-classid.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-classid.lo `test -f 'lib/route/classid.c' || echo '$(srcdir)/'`lib/route/classid.c + +lib/route/libnl_route_3_la-cls.lo: lib/route/cls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-cls.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-cls.Tpo -c -o lib/route/libnl_route_3_la-cls.lo `test -f 'lib/route/cls.c' || echo '$(srcdir)/'`lib/route/cls.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-cls.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-cls.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/cls.c' object='lib/route/libnl_route_3_la-cls.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-cls.lo `test -f 'lib/route/cls.c' || echo '$(srcdir)/'`lib/route/cls.c + +lib/route/cls/libnl_route_3_la-basic.lo: lib/route/cls/basic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/cls/libnl_route_3_la-basic.lo -MD -MP -MF lib/route/cls/$(DEPDIR)/libnl_route_3_la-basic.Tpo -c -o lib/route/cls/libnl_route_3_la-basic.lo `test -f 'lib/route/cls/basic.c' || echo '$(srcdir)/'`lib/route/cls/basic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/cls/$(DEPDIR)/libnl_route_3_la-basic.Tpo lib/route/cls/$(DEPDIR)/libnl_route_3_la-basic.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/cls/basic.c' object='lib/route/cls/libnl_route_3_la-basic.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/cls/libnl_route_3_la-basic.lo `test -f 'lib/route/cls/basic.c' || echo '$(srcdir)/'`lib/route/cls/basic.c + +lib/route/cls/libnl_route_3_la-cgroup.lo: lib/route/cls/cgroup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/cls/libnl_route_3_la-cgroup.lo -MD -MP -MF lib/route/cls/$(DEPDIR)/libnl_route_3_la-cgroup.Tpo -c -o lib/route/cls/libnl_route_3_la-cgroup.lo `test -f 'lib/route/cls/cgroup.c' || echo '$(srcdir)/'`lib/route/cls/cgroup.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/cls/$(DEPDIR)/libnl_route_3_la-cgroup.Tpo lib/route/cls/$(DEPDIR)/libnl_route_3_la-cgroup.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/cls/cgroup.c' object='lib/route/cls/libnl_route_3_la-cgroup.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/cls/libnl_route_3_la-cgroup.lo `test -f 'lib/route/cls/cgroup.c' || echo '$(srcdir)/'`lib/route/cls/cgroup.c + +lib/route/cls/libnl_route_3_la-ematch.lo: lib/route/cls/ematch.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/cls/libnl_route_3_la-ematch.lo -MD -MP -MF lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch.Tpo -c -o lib/route/cls/libnl_route_3_la-ematch.lo `test -f 'lib/route/cls/ematch.c' || echo '$(srcdir)/'`lib/route/cls/ematch.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch.Tpo lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/cls/ematch.c' object='lib/route/cls/libnl_route_3_la-ematch.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/cls/libnl_route_3_la-ematch.lo `test -f 'lib/route/cls/ematch.c' || echo '$(srcdir)/'`lib/route/cls/ematch.c + +lib/route/cls/ematch/libnl_route_3_la-cmp.lo: lib/route/cls/ematch/cmp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/cls/ematch/libnl_route_3_la-cmp.lo -MD -MP -MF lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-cmp.Tpo -c -o lib/route/cls/ematch/libnl_route_3_la-cmp.lo `test -f 'lib/route/cls/ematch/cmp.c' || echo '$(srcdir)/'`lib/route/cls/ematch/cmp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-cmp.Tpo lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-cmp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/cls/ematch/cmp.c' object='lib/route/cls/ematch/libnl_route_3_la-cmp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/cls/ematch/libnl_route_3_la-cmp.lo `test -f 'lib/route/cls/ematch/cmp.c' || echo '$(srcdir)/'`lib/route/cls/ematch/cmp.c + +lib/route/cls/ematch/libnl_route_3_la-container.lo: lib/route/cls/ematch/container.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/cls/ematch/libnl_route_3_la-container.lo -MD -MP -MF lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-container.Tpo -c -o lib/route/cls/ematch/libnl_route_3_la-container.lo `test -f 'lib/route/cls/ematch/container.c' || echo '$(srcdir)/'`lib/route/cls/ematch/container.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-container.Tpo lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-container.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/cls/ematch/container.c' object='lib/route/cls/ematch/libnl_route_3_la-container.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/cls/ematch/libnl_route_3_la-container.lo `test -f 'lib/route/cls/ematch/container.c' || echo '$(srcdir)/'`lib/route/cls/ematch/container.c + +lib/route/cls/ematch/libnl_route_3_la-meta.lo: lib/route/cls/ematch/meta.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/cls/ematch/libnl_route_3_la-meta.lo -MD -MP -MF lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-meta.Tpo -c -o lib/route/cls/ematch/libnl_route_3_la-meta.lo `test -f 'lib/route/cls/ematch/meta.c' || echo '$(srcdir)/'`lib/route/cls/ematch/meta.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-meta.Tpo lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-meta.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/cls/ematch/meta.c' object='lib/route/cls/ematch/libnl_route_3_la-meta.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/cls/ematch/libnl_route_3_la-meta.lo `test -f 'lib/route/cls/ematch/meta.c' || echo '$(srcdir)/'`lib/route/cls/ematch/meta.c + +lib/route/cls/ematch/libnl_route_3_la-nbyte.lo: lib/route/cls/ematch/nbyte.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/cls/ematch/libnl_route_3_la-nbyte.lo -MD -MP -MF lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-nbyte.Tpo -c -o lib/route/cls/ematch/libnl_route_3_la-nbyte.lo `test -f 'lib/route/cls/ematch/nbyte.c' || echo '$(srcdir)/'`lib/route/cls/ematch/nbyte.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-nbyte.Tpo lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-nbyte.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/cls/ematch/nbyte.c' object='lib/route/cls/ematch/libnl_route_3_la-nbyte.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/cls/ematch/libnl_route_3_la-nbyte.lo `test -f 'lib/route/cls/ematch/nbyte.c' || echo '$(srcdir)/'`lib/route/cls/ematch/nbyte.c + +lib/route/cls/ematch/libnl_route_3_la-text.lo: lib/route/cls/ematch/text.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/cls/ematch/libnl_route_3_la-text.lo -MD -MP -MF lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-text.Tpo -c -o lib/route/cls/ematch/libnl_route_3_la-text.lo `test -f 'lib/route/cls/ematch/text.c' || echo '$(srcdir)/'`lib/route/cls/ematch/text.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-text.Tpo lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-text.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/cls/ematch/text.c' object='lib/route/cls/ematch/libnl_route_3_la-text.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/cls/ematch/libnl_route_3_la-text.lo `test -f 'lib/route/cls/ematch/text.c' || echo '$(srcdir)/'`lib/route/cls/ematch/text.c + +lib/route/cls/libnl_route_3_la-flower.lo: lib/route/cls/flower.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/cls/libnl_route_3_la-flower.lo -MD -MP -MF lib/route/cls/$(DEPDIR)/libnl_route_3_la-flower.Tpo -c -o lib/route/cls/libnl_route_3_la-flower.lo `test -f 'lib/route/cls/flower.c' || echo '$(srcdir)/'`lib/route/cls/flower.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/cls/$(DEPDIR)/libnl_route_3_la-flower.Tpo lib/route/cls/$(DEPDIR)/libnl_route_3_la-flower.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/cls/flower.c' object='lib/route/cls/libnl_route_3_la-flower.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/cls/libnl_route_3_la-flower.lo `test -f 'lib/route/cls/flower.c' || echo '$(srcdir)/'`lib/route/cls/flower.c + +lib/route/cls/libnl_route_3_la-fw.lo: lib/route/cls/fw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/cls/libnl_route_3_la-fw.lo -MD -MP -MF lib/route/cls/$(DEPDIR)/libnl_route_3_la-fw.Tpo -c -o lib/route/cls/libnl_route_3_la-fw.lo `test -f 'lib/route/cls/fw.c' || echo '$(srcdir)/'`lib/route/cls/fw.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/cls/$(DEPDIR)/libnl_route_3_la-fw.Tpo lib/route/cls/$(DEPDIR)/libnl_route_3_la-fw.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/cls/fw.c' object='lib/route/cls/libnl_route_3_la-fw.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/cls/libnl_route_3_la-fw.lo `test -f 'lib/route/cls/fw.c' || echo '$(srcdir)/'`lib/route/cls/fw.c + +lib/route/cls/libnl_route_3_la-mall.lo: lib/route/cls/mall.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/cls/libnl_route_3_la-mall.lo -MD -MP -MF lib/route/cls/$(DEPDIR)/libnl_route_3_la-mall.Tpo -c -o lib/route/cls/libnl_route_3_la-mall.lo `test -f 'lib/route/cls/mall.c' || echo '$(srcdir)/'`lib/route/cls/mall.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/cls/$(DEPDIR)/libnl_route_3_la-mall.Tpo lib/route/cls/$(DEPDIR)/libnl_route_3_la-mall.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/cls/mall.c' object='lib/route/cls/libnl_route_3_la-mall.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/cls/libnl_route_3_la-mall.lo `test -f 'lib/route/cls/mall.c' || echo '$(srcdir)/'`lib/route/cls/mall.c + +lib/route/cls/libnl_route_3_la-police.lo: lib/route/cls/police.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/cls/libnl_route_3_la-police.lo -MD -MP -MF lib/route/cls/$(DEPDIR)/libnl_route_3_la-police.Tpo -c -o lib/route/cls/libnl_route_3_la-police.lo `test -f 'lib/route/cls/police.c' || echo '$(srcdir)/'`lib/route/cls/police.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/cls/$(DEPDIR)/libnl_route_3_la-police.Tpo lib/route/cls/$(DEPDIR)/libnl_route_3_la-police.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/cls/police.c' object='lib/route/cls/libnl_route_3_la-police.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/cls/libnl_route_3_la-police.lo `test -f 'lib/route/cls/police.c' || echo '$(srcdir)/'`lib/route/cls/police.c + +lib/route/cls/libnl_route_3_la-u32.lo: lib/route/cls/u32.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/cls/libnl_route_3_la-u32.lo -MD -MP -MF lib/route/cls/$(DEPDIR)/libnl_route_3_la-u32.Tpo -c -o lib/route/cls/libnl_route_3_la-u32.lo `test -f 'lib/route/cls/u32.c' || echo '$(srcdir)/'`lib/route/cls/u32.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/cls/$(DEPDIR)/libnl_route_3_la-u32.Tpo lib/route/cls/$(DEPDIR)/libnl_route_3_la-u32.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/cls/u32.c' object='lib/route/cls/libnl_route_3_la-u32.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/cls/libnl_route_3_la-u32.lo `test -f 'lib/route/cls/u32.c' || echo '$(srcdir)/'`lib/route/cls/u32.c + +lib/route/libnl_route_3_la-link.lo: lib/route/link.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-link.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-link.Tpo -c -o lib/route/libnl_route_3_la-link.lo `test -f 'lib/route/link.c' || echo '$(srcdir)/'`lib/route/link.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-link.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-link.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link.c' object='lib/route/libnl_route_3_la-link.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-link.lo `test -f 'lib/route/link.c' || echo '$(srcdir)/'`lib/route/link.c + +lib/route/link/libnl_route_3_la-api.lo: lib/route/link/api.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-api.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-api.Tpo -c -o lib/route/link/libnl_route_3_la-api.lo `test -f 'lib/route/link/api.c' || echo '$(srcdir)/'`lib/route/link/api.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-api.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-api.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/api.c' object='lib/route/link/libnl_route_3_la-api.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-api.lo `test -f 'lib/route/link/api.c' || echo '$(srcdir)/'`lib/route/link/api.c + +lib/route/link/libnl_route_3_la-bonding.lo: lib/route/link/bonding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-bonding.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-bonding.Tpo -c -o lib/route/link/libnl_route_3_la-bonding.lo `test -f 'lib/route/link/bonding.c' || echo '$(srcdir)/'`lib/route/link/bonding.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-bonding.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-bonding.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/bonding.c' object='lib/route/link/libnl_route_3_la-bonding.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-bonding.lo `test -f 'lib/route/link/bonding.c' || echo '$(srcdir)/'`lib/route/link/bonding.c + +lib/route/link/libnl_route_3_la-bridge.lo: lib/route/link/bridge.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-bridge.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-bridge.Tpo -c -o lib/route/link/libnl_route_3_la-bridge.lo `test -f 'lib/route/link/bridge.c' || echo '$(srcdir)/'`lib/route/link/bridge.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-bridge.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-bridge.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/bridge.c' object='lib/route/link/libnl_route_3_la-bridge.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-bridge.lo `test -f 'lib/route/link/bridge.c' || echo '$(srcdir)/'`lib/route/link/bridge.c + +lib/route/link/libnl_route_3_la-bridge_info.lo: lib/route/link/bridge_info.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-bridge_info.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-bridge_info.Tpo -c -o lib/route/link/libnl_route_3_la-bridge_info.lo `test -f 'lib/route/link/bridge_info.c' || echo '$(srcdir)/'`lib/route/link/bridge_info.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-bridge_info.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-bridge_info.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/bridge_info.c' object='lib/route/link/libnl_route_3_la-bridge_info.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-bridge_info.lo `test -f 'lib/route/link/bridge_info.c' || echo '$(srcdir)/'`lib/route/link/bridge_info.c + +lib/route/link/libnl_route_3_la-can.lo: lib/route/link/can.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-can.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-can.Tpo -c -o lib/route/link/libnl_route_3_la-can.lo `test -f 'lib/route/link/can.c' || echo '$(srcdir)/'`lib/route/link/can.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-can.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-can.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/can.c' object='lib/route/link/libnl_route_3_la-can.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-can.lo `test -f 'lib/route/link/can.c' || echo '$(srcdir)/'`lib/route/link/can.c + +lib/route/link/libnl_route_3_la-dummy.lo: lib/route/link/dummy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-dummy.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-dummy.Tpo -c -o lib/route/link/libnl_route_3_la-dummy.lo `test -f 'lib/route/link/dummy.c' || echo '$(srcdir)/'`lib/route/link/dummy.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-dummy.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-dummy.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/dummy.c' object='lib/route/link/libnl_route_3_la-dummy.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-dummy.lo `test -f 'lib/route/link/dummy.c' || echo '$(srcdir)/'`lib/route/link/dummy.c + +lib/route/link/libnl_route_3_la-geneve.lo: lib/route/link/geneve.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-geneve.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-geneve.Tpo -c -o lib/route/link/libnl_route_3_la-geneve.lo `test -f 'lib/route/link/geneve.c' || echo '$(srcdir)/'`lib/route/link/geneve.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-geneve.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-geneve.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/geneve.c' object='lib/route/link/libnl_route_3_la-geneve.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-geneve.lo `test -f 'lib/route/link/geneve.c' || echo '$(srcdir)/'`lib/route/link/geneve.c + +lib/route/link/libnl_route_3_la-ifb.lo: lib/route/link/ifb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-ifb.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-ifb.Tpo -c -o lib/route/link/libnl_route_3_la-ifb.lo `test -f 'lib/route/link/ifb.c' || echo '$(srcdir)/'`lib/route/link/ifb.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-ifb.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-ifb.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/ifb.c' object='lib/route/link/libnl_route_3_la-ifb.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-ifb.lo `test -f 'lib/route/link/ifb.c' || echo '$(srcdir)/'`lib/route/link/ifb.c + +lib/route/link/libnl_route_3_la-inet.lo: lib/route/link/inet.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-inet.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-inet.Tpo -c -o lib/route/link/libnl_route_3_la-inet.lo `test -f 'lib/route/link/inet.c' || echo '$(srcdir)/'`lib/route/link/inet.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-inet.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-inet.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/inet.c' object='lib/route/link/libnl_route_3_la-inet.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-inet.lo `test -f 'lib/route/link/inet.c' || echo '$(srcdir)/'`lib/route/link/inet.c + +lib/route/link/libnl_route_3_la-inet6.lo: lib/route/link/inet6.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-inet6.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-inet6.Tpo -c -o lib/route/link/libnl_route_3_la-inet6.lo `test -f 'lib/route/link/inet6.c' || echo '$(srcdir)/'`lib/route/link/inet6.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-inet6.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-inet6.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/inet6.c' object='lib/route/link/libnl_route_3_la-inet6.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-inet6.lo `test -f 'lib/route/link/inet6.c' || echo '$(srcdir)/'`lib/route/link/inet6.c + +lib/route/link/libnl_route_3_la-ip6gre.lo: lib/route/link/ip6gre.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-ip6gre.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6gre.Tpo -c -o lib/route/link/libnl_route_3_la-ip6gre.lo `test -f 'lib/route/link/ip6gre.c' || echo '$(srcdir)/'`lib/route/link/ip6gre.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6gre.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6gre.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/ip6gre.c' object='lib/route/link/libnl_route_3_la-ip6gre.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-ip6gre.lo `test -f 'lib/route/link/ip6gre.c' || echo '$(srcdir)/'`lib/route/link/ip6gre.c + +lib/route/link/libnl_route_3_la-ip6tnl.lo: lib/route/link/ip6tnl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-ip6tnl.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6tnl.Tpo -c -o lib/route/link/libnl_route_3_la-ip6tnl.lo `test -f 'lib/route/link/ip6tnl.c' || echo '$(srcdir)/'`lib/route/link/ip6tnl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6tnl.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6tnl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/ip6tnl.c' object='lib/route/link/libnl_route_3_la-ip6tnl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-ip6tnl.lo `test -f 'lib/route/link/ip6tnl.c' || echo '$(srcdir)/'`lib/route/link/ip6tnl.c + +lib/route/link/libnl_route_3_la-ip6vti.lo: lib/route/link/ip6vti.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-ip6vti.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6vti.Tpo -c -o lib/route/link/libnl_route_3_la-ip6vti.lo `test -f 'lib/route/link/ip6vti.c' || echo '$(srcdir)/'`lib/route/link/ip6vti.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6vti.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6vti.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/ip6vti.c' object='lib/route/link/libnl_route_3_la-ip6vti.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-ip6vti.lo `test -f 'lib/route/link/ip6vti.c' || echo '$(srcdir)/'`lib/route/link/ip6vti.c + +lib/route/link/libnl_route_3_la-ipgre.lo: lib/route/link/ipgre.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-ipgre.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-ipgre.Tpo -c -o lib/route/link/libnl_route_3_la-ipgre.lo `test -f 'lib/route/link/ipgre.c' || echo '$(srcdir)/'`lib/route/link/ipgre.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-ipgre.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-ipgre.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/ipgre.c' object='lib/route/link/libnl_route_3_la-ipgre.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-ipgre.lo `test -f 'lib/route/link/ipgre.c' || echo '$(srcdir)/'`lib/route/link/ipgre.c + +lib/route/link/libnl_route_3_la-ipip.lo: lib/route/link/ipip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-ipip.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-ipip.Tpo -c -o lib/route/link/libnl_route_3_la-ipip.lo `test -f 'lib/route/link/ipip.c' || echo '$(srcdir)/'`lib/route/link/ipip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-ipip.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-ipip.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/ipip.c' object='lib/route/link/libnl_route_3_la-ipip.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-ipip.lo `test -f 'lib/route/link/ipip.c' || echo '$(srcdir)/'`lib/route/link/ipip.c + +lib/route/link/libnl_route_3_la-ipvlan.lo: lib/route/link/ipvlan.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-ipvlan.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-ipvlan.Tpo -c -o lib/route/link/libnl_route_3_la-ipvlan.lo `test -f 'lib/route/link/ipvlan.c' || echo '$(srcdir)/'`lib/route/link/ipvlan.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-ipvlan.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-ipvlan.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/ipvlan.c' object='lib/route/link/libnl_route_3_la-ipvlan.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-ipvlan.lo `test -f 'lib/route/link/ipvlan.c' || echo '$(srcdir)/'`lib/route/link/ipvlan.c + +lib/route/link/libnl_route_3_la-ipvti.lo: lib/route/link/ipvti.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-ipvti.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-ipvti.Tpo -c -o lib/route/link/libnl_route_3_la-ipvti.lo `test -f 'lib/route/link/ipvti.c' || echo '$(srcdir)/'`lib/route/link/ipvti.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-ipvti.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-ipvti.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/ipvti.c' object='lib/route/link/libnl_route_3_la-ipvti.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-ipvti.lo `test -f 'lib/route/link/ipvti.c' || echo '$(srcdir)/'`lib/route/link/ipvti.c + +lib/route/link/libnl_route_3_la-macsec.lo: lib/route/link/macsec.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-macsec.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-macsec.Tpo -c -o lib/route/link/libnl_route_3_la-macsec.lo `test -f 'lib/route/link/macsec.c' || echo '$(srcdir)/'`lib/route/link/macsec.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-macsec.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-macsec.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/macsec.c' object='lib/route/link/libnl_route_3_la-macsec.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-macsec.lo `test -f 'lib/route/link/macsec.c' || echo '$(srcdir)/'`lib/route/link/macsec.c + +lib/route/link/libnl_route_3_la-macvlan.lo: lib/route/link/macvlan.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-macvlan.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-macvlan.Tpo -c -o lib/route/link/libnl_route_3_la-macvlan.lo `test -f 'lib/route/link/macvlan.c' || echo '$(srcdir)/'`lib/route/link/macvlan.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-macvlan.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-macvlan.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/macvlan.c' object='lib/route/link/libnl_route_3_la-macvlan.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-macvlan.lo `test -f 'lib/route/link/macvlan.c' || echo '$(srcdir)/'`lib/route/link/macvlan.c + +lib/route/link/libnl_route_3_la-ppp.lo: lib/route/link/ppp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-ppp.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-ppp.Tpo -c -o lib/route/link/libnl_route_3_la-ppp.lo `test -f 'lib/route/link/ppp.c' || echo '$(srcdir)/'`lib/route/link/ppp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-ppp.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-ppp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/ppp.c' object='lib/route/link/libnl_route_3_la-ppp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-ppp.lo `test -f 'lib/route/link/ppp.c' || echo '$(srcdir)/'`lib/route/link/ppp.c + +lib/route/link/libnl_route_3_la-sit.lo: lib/route/link/sit.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-sit.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-sit.Tpo -c -o lib/route/link/libnl_route_3_la-sit.lo `test -f 'lib/route/link/sit.c' || echo '$(srcdir)/'`lib/route/link/sit.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-sit.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-sit.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/sit.c' object='lib/route/link/libnl_route_3_la-sit.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-sit.lo `test -f 'lib/route/link/sit.c' || echo '$(srcdir)/'`lib/route/link/sit.c + +lib/route/link/libnl_route_3_la-sriov.lo: lib/route/link/sriov.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-sriov.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-sriov.Tpo -c -o lib/route/link/libnl_route_3_la-sriov.lo `test -f 'lib/route/link/sriov.c' || echo '$(srcdir)/'`lib/route/link/sriov.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-sriov.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-sriov.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/sriov.c' object='lib/route/link/libnl_route_3_la-sriov.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-sriov.lo `test -f 'lib/route/link/sriov.c' || echo '$(srcdir)/'`lib/route/link/sriov.c + +lib/route/link/libnl_route_3_la-team.lo: lib/route/link/team.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-team.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-team.Tpo -c -o lib/route/link/libnl_route_3_la-team.lo `test -f 'lib/route/link/team.c' || echo '$(srcdir)/'`lib/route/link/team.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-team.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-team.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/team.c' object='lib/route/link/libnl_route_3_la-team.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-team.lo `test -f 'lib/route/link/team.c' || echo '$(srcdir)/'`lib/route/link/team.c + +lib/route/link/libnl_route_3_la-veth.lo: lib/route/link/veth.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-veth.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-veth.Tpo -c -o lib/route/link/libnl_route_3_la-veth.lo `test -f 'lib/route/link/veth.c' || echo '$(srcdir)/'`lib/route/link/veth.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-veth.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-veth.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/veth.c' object='lib/route/link/libnl_route_3_la-veth.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-veth.lo `test -f 'lib/route/link/veth.c' || echo '$(srcdir)/'`lib/route/link/veth.c + +lib/route/link/libnl_route_3_la-vlan.lo: lib/route/link/vlan.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-vlan.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-vlan.Tpo -c -o lib/route/link/libnl_route_3_la-vlan.lo `test -f 'lib/route/link/vlan.c' || echo '$(srcdir)/'`lib/route/link/vlan.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-vlan.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-vlan.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/vlan.c' object='lib/route/link/libnl_route_3_la-vlan.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-vlan.lo `test -f 'lib/route/link/vlan.c' || echo '$(srcdir)/'`lib/route/link/vlan.c + +lib/route/link/libnl_route_3_la-vrf.lo: lib/route/link/vrf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-vrf.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-vrf.Tpo -c -o lib/route/link/libnl_route_3_la-vrf.lo `test -f 'lib/route/link/vrf.c' || echo '$(srcdir)/'`lib/route/link/vrf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-vrf.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-vrf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/vrf.c' object='lib/route/link/libnl_route_3_la-vrf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-vrf.lo `test -f 'lib/route/link/vrf.c' || echo '$(srcdir)/'`lib/route/link/vrf.c + +lib/route/link/libnl_route_3_la-vxlan.lo: lib/route/link/vxlan.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-vxlan.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-vxlan.Tpo -c -o lib/route/link/libnl_route_3_la-vxlan.lo `test -f 'lib/route/link/vxlan.c' || echo '$(srcdir)/'`lib/route/link/vxlan.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-vxlan.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-vxlan.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/vxlan.c' object='lib/route/link/libnl_route_3_la-vxlan.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-vxlan.lo `test -f 'lib/route/link/vxlan.c' || echo '$(srcdir)/'`lib/route/link/vxlan.c + +lib/route/link/libnl_route_3_la-xfrmi.lo: lib/route/link/xfrmi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/link/libnl_route_3_la-xfrmi.lo -MD -MP -MF lib/route/link/$(DEPDIR)/libnl_route_3_la-xfrmi.Tpo -c -o lib/route/link/libnl_route_3_la-xfrmi.lo `test -f 'lib/route/link/xfrmi.c' || echo '$(srcdir)/'`lib/route/link/xfrmi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/link/$(DEPDIR)/libnl_route_3_la-xfrmi.Tpo lib/route/link/$(DEPDIR)/libnl_route_3_la-xfrmi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/link/xfrmi.c' object='lib/route/link/libnl_route_3_la-xfrmi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/link/libnl_route_3_la-xfrmi.lo `test -f 'lib/route/link/xfrmi.c' || echo '$(srcdir)/'`lib/route/link/xfrmi.c + +lib/route/libnl_route_3_la-mdb.lo: lib/route/mdb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-mdb.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-mdb.Tpo -c -o lib/route/libnl_route_3_la-mdb.lo `test -f 'lib/route/mdb.c' || echo '$(srcdir)/'`lib/route/mdb.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-mdb.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-mdb.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/mdb.c' object='lib/route/libnl_route_3_la-mdb.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-mdb.lo `test -f 'lib/route/mdb.c' || echo '$(srcdir)/'`lib/route/mdb.c + +lib/route/libnl_route_3_la-neigh.lo: lib/route/neigh.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-neigh.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-neigh.Tpo -c -o lib/route/libnl_route_3_la-neigh.lo `test -f 'lib/route/neigh.c' || echo '$(srcdir)/'`lib/route/neigh.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-neigh.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-neigh.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/neigh.c' object='lib/route/libnl_route_3_la-neigh.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-neigh.lo `test -f 'lib/route/neigh.c' || echo '$(srcdir)/'`lib/route/neigh.c + +lib/route/libnl_route_3_la-neightbl.lo: lib/route/neightbl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-neightbl.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-neightbl.Tpo -c -o lib/route/libnl_route_3_la-neightbl.lo `test -f 'lib/route/neightbl.c' || echo '$(srcdir)/'`lib/route/neightbl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-neightbl.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-neightbl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/neightbl.c' object='lib/route/libnl_route_3_la-neightbl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-neightbl.lo `test -f 'lib/route/neightbl.c' || echo '$(srcdir)/'`lib/route/neightbl.c + +lib/route/libnl_route_3_la-netconf.lo: lib/route/netconf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-netconf.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-netconf.Tpo -c -o lib/route/libnl_route_3_la-netconf.lo `test -f 'lib/route/netconf.c' || echo '$(srcdir)/'`lib/route/netconf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-netconf.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-netconf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/netconf.c' object='lib/route/libnl_route_3_la-netconf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-netconf.lo `test -f 'lib/route/netconf.c' || echo '$(srcdir)/'`lib/route/netconf.c + +lib/route/libnl_route_3_la-nexthop.lo: lib/route/nexthop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-nexthop.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-nexthop.Tpo -c -o lib/route/libnl_route_3_la-nexthop.lo `test -f 'lib/route/nexthop.c' || echo '$(srcdir)/'`lib/route/nexthop.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-nexthop.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-nexthop.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/nexthop.c' object='lib/route/libnl_route_3_la-nexthop.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-nexthop.lo `test -f 'lib/route/nexthop.c' || echo '$(srcdir)/'`lib/route/nexthop.c + +lib/route/libnl_route_3_la-nexthop_encap.lo: lib/route/nexthop_encap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-nexthop_encap.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-nexthop_encap.Tpo -c -o lib/route/libnl_route_3_la-nexthop_encap.lo `test -f 'lib/route/nexthop_encap.c' || echo '$(srcdir)/'`lib/route/nexthop_encap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-nexthop_encap.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-nexthop_encap.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/nexthop_encap.c' object='lib/route/libnl_route_3_la-nexthop_encap.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-nexthop_encap.lo `test -f 'lib/route/nexthop_encap.c' || echo '$(srcdir)/'`lib/route/nexthop_encap.c + +lib/route/libnl_route_3_la-nh.lo: lib/route/nh.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-nh.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-nh.Tpo -c -o lib/route/libnl_route_3_la-nh.lo `test -f 'lib/route/nh.c' || echo '$(srcdir)/'`lib/route/nh.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-nh.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-nh.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/nh.c' object='lib/route/libnl_route_3_la-nh.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-nh.lo `test -f 'lib/route/nh.c' || echo '$(srcdir)/'`lib/route/nh.c + +lib/route/libnl_route_3_la-nh_encap_mpls.lo: lib/route/nh_encap_mpls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-nh_encap_mpls.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-nh_encap_mpls.Tpo -c -o lib/route/libnl_route_3_la-nh_encap_mpls.lo `test -f 'lib/route/nh_encap_mpls.c' || echo '$(srcdir)/'`lib/route/nh_encap_mpls.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-nh_encap_mpls.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-nh_encap_mpls.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/nh_encap_mpls.c' object='lib/route/libnl_route_3_la-nh_encap_mpls.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-nh_encap_mpls.lo `test -f 'lib/route/nh_encap_mpls.c' || echo '$(srcdir)/'`lib/route/nh_encap_mpls.c + +lib/route/libnl_route_3_la-pktloc.lo: lib/route/pktloc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-pktloc.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-pktloc.Tpo -c -o lib/route/libnl_route_3_la-pktloc.lo `test -f 'lib/route/pktloc.c' || echo '$(srcdir)/'`lib/route/pktloc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-pktloc.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-pktloc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/pktloc.c' object='lib/route/libnl_route_3_la-pktloc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-pktloc.lo `test -f 'lib/route/pktloc.c' || echo '$(srcdir)/'`lib/route/pktloc.c + +lib/route/libnl_route_3_la-qdisc.lo: lib/route/qdisc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-qdisc.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-qdisc.Tpo -c -o lib/route/libnl_route_3_la-qdisc.lo `test -f 'lib/route/qdisc.c' || echo '$(srcdir)/'`lib/route/qdisc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-qdisc.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-qdisc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/qdisc.c' object='lib/route/libnl_route_3_la-qdisc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-qdisc.lo `test -f 'lib/route/qdisc.c' || echo '$(srcdir)/'`lib/route/qdisc.c + +lib/route/qdisc/libnl_route_3_la-blackhole.lo: lib/route/qdisc/blackhole.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/qdisc/libnl_route_3_la-blackhole.lo -MD -MP -MF lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-blackhole.Tpo -c -o lib/route/qdisc/libnl_route_3_la-blackhole.lo `test -f 'lib/route/qdisc/blackhole.c' || echo '$(srcdir)/'`lib/route/qdisc/blackhole.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-blackhole.Tpo lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-blackhole.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/qdisc/blackhole.c' object='lib/route/qdisc/libnl_route_3_la-blackhole.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/qdisc/libnl_route_3_la-blackhole.lo `test -f 'lib/route/qdisc/blackhole.c' || echo '$(srcdir)/'`lib/route/qdisc/blackhole.c + +lib/route/qdisc/libnl_route_3_la-cbq.lo: lib/route/qdisc/cbq.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/qdisc/libnl_route_3_la-cbq.lo -MD -MP -MF lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-cbq.Tpo -c -o lib/route/qdisc/libnl_route_3_la-cbq.lo `test -f 'lib/route/qdisc/cbq.c' || echo '$(srcdir)/'`lib/route/qdisc/cbq.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-cbq.Tpo lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-cbq.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/qdisc/cbq.c' object='lib/route/qdisc/libnl_route_3_la-cbq.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/qdisc/libnl_route_3_la-cbq.lo `test -f 'lib/route/qdisc/cbq.c' || echo '$(srcdir)/'`lib/route/qdisc/cbq.c + +lib/route/qdisc/libnl_route_3_la-dsmark.lo: lib/route/qdisc/dsmark.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/qdisc/libnl_route_3_la-dsmark.lo -MD -MP -MF lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-dsmark.Tpo -c -o lib/route/qdisc/libnl_route_3_la-dsmark.lo `test -f 'lib/route/qdisc/dsmark.c' || echo '$(srcdir)/'`lib/route/qdisc/dsmark.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-dsmark.Tpo lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-dsmark.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/qdisc/dsmark.c' object='lib/route/qdisc/libnl_route_3_la-dsmark.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/qdisc/libnl_route_3_la-dsmark.lo `test -f 'lib/route/qdisc/dsmark.c' || echo '$(srcdir)/'`lib/route/qdisc/dsmark.c + +lib/route/qdisc/libnl_route_3_la-fifo.lo: lib/route/qdisc/fifo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/qdisc/libnl_route_3_la-fifo.lo -MD -MP -MF lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-fifo.Tpo -c -o lib/route/qdisc/libnl_route_3_la-fifo.lo `test -f 'lib/route/qdisc/fifo.c' || echo '$(srcdir)/'`lib/route/qdisc/fifo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-fifo.Tpo lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-fifo.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/qdisc/fifo.c' object='lib/route/qdisc/libnl_route_3_la-fifo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/qdisc/libnl_route_3_la-fifo.lo `test -f 'lib/route/qdisc/fifo.c' || echo '$(srcdir)/'`lib/route/qdisc/fifo.c + +lib/route/qdisc/libnl_route_3_la-fq_codel.lo: lib/route/qdisc/fq_codel.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/qdisc/libnl_route_3_la-fq_codel.lo -MD -MP -MF lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-fq_codel.Tpo -c -o lib/route/qdisc/libnl_route_3_la-fq_codel.lo `test -f 'lib/route/qdisc/fq_codel.c' || echo '$(srcdir)/'`lib/route/qdisc/fq_codel.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-fq_codel.Tpo lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-fq_codel.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/qdisc/fq_codel.c' object='lib/route/qdisc/libnl_route_3_la-fq_codel.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/qdisc/libnl_route_3_la-fq_codel.lo `test -f 'lib/route/qdisc/fq_codel.c' || echo '$(srcdir)/'`lib/route/qdisc/fq_codel.c + +lib/route/qdisc/libnl_route_3_la-hfsc.lo: lib/route/qdisc/hfsc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/qdisc/libnl_route_3_la-hfsc.lo -MD -MP -MF lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-hfsc.Tpo -c -o lib/route/qdisc/libnl_route_3_la-hfsc.lo `test -f 'lib/route/qdisc/hfsc.c' || echo '$(srcdir)/'`lib/route/qdisc/hfsc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-hfsc.Tpo lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-hfsc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/qdisc/hfsc.c' object='lib/route/qdisc/libnl_route_3_la-hfsc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/qdisc/libnl_route_3_la-hfsc.lo `test -f 'lib/route/qdisc/hfsc.c' || echo '$(srcdir)/'`lib/route/qdisc/hfsc.c + +lib/route/qdisc/libnl_route_3_la-htb.lo: lib/route/qdisc/htb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/qdisc/libnl_route_3_la-htb.lo -MD -MP -MF lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-htb.Tpo -c -o lib/route/qdisc/libnl_route_3_la-htb.lo `test -f 'lib/route/qdisc/htb.c' || echo '$(srcdir)/'`lib/route/qdisc/htb.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-htb.Tpo lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-htb.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/qdisc/htb.c' object='lib/route/qdisc/libnl_route_3_la-htb.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/qdisc/libnl_route_3_la-htb.lo `test -f 'lib/route/qdisc/htb.c' || echo '$(srcdir)/'`lib/route/qdisc/htb.c + +lib/route/qdisc/libnl_route_3_la-ingress.lo: lib/route/qdisc/ingress.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/qdisc/libnl_route_3_la-ingress.lo -MD -MP -MF lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-ingress.Tpo -c -o lib/route/qdisc/libnl_route_3_la-ingress.lo `test -f 'lib/route/qdisc/ingress.c' || echo '$(srcdir)/'`lib/route/qdisc/ingress.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-ingress.Tpo lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-ingress.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/qdisc/ingress.c' object='lib/route/qdisc/libnl_route_3_la-ingress.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/qdisc/libnl_route_3_la-ingress.lo `test -f 'lib/route/qdisc/ingress.c' || echo '$(srcdir)/'`lib/route/qdisc/ingress.c + +lib/route/qdisc/libnl_route_3_la-mqprio.lo: lib/route/qdisc/mqprio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/qdisc/libnl_route_3_la-mqprio.lo -MD -MP -MF lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-mqprio.Tpo -c -o lib/route/qdisc/libnl_route_3_la-mqprio.lo `test -f 'lib/route/qdisc/mqprio.c' || echo '$(srcdir)/'`lib/route/qdisc/mqprio.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-mqprio.Tpo lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-mqprio.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/qdisc/mqprio.c' object='lib/route/qdisc/libnl_route_3_la-mqprio.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/qdisc/libnl_route_3_la-mqprio.lo `test -f 'lib/route/qdisc/mqprio.c' || echo '$(srcdir)/'`lib/route/qdisc/mqprio.c + +lib/route/qdisc/libnl_route_3_la-netem.lo: lib/route/qdisc/netem.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/qdisc/libnl_route_3_la-netem.lo -MD -MP -MF lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-netem.Tpo -c -o lib/route/qdisc/libnl_route_3_la-netem.lo `test -f 'lib/route/qdisc/netem.c' || echo '$(srcdir)/'`lib/route/qdisc/netem.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-netem.Tpo lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-netem.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/qdisc/netem.c' object='lib/route/qdisc/libnl_route_3_la-netem.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/qdisc/libnl_route_3_la-netem.lo `test -f 'lib/route/qdisc/netem.c' || echo '$(srcdir)/'`lib/route/qdisc/netem.c + +lib/route/qdisc/libnl_route_3_la-plug.lo: lib/route/qdisc/plug.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/qdisc/libnl_route_3_la-plug.lo -MD -MP -MF lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-plug.Tpo -c -o lib/route/qdisc/libnl_route_3_la-plug.lo `test -f 'lib/route/qdisc/plug.c' || echo '$(srcdir)/'`lib/route/qdisc/plug.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-plug.Tpo lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-plug.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/qdisc/plug.c' object='lib/route/qdisc/libnl_route_3_la-plug.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/qdisc/libnl_route_3_la-plug.lo `test -f 'lib/route/qdisc/plug.c' || echo '$(srcdir)/'`lib/route/qdisc/plug.c + +lib/route/qdisc/libnl_route_3_la-prio.lo: lib/route/qdisc/prio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/qdisc/libnl_route_3_la-prio.lo -MD -MP -MF lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-prio.Tpo -c -o lib/route/qdisc/libnl_route_3_la-prio.lo `test -f 'lib/route/qdisc/prio.c' || echo '$(srcdir)/'`lib/route/qdisc/prio.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-prio.Tpo lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-prio.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/qdisc/prio.c' object='lib/route/qdisc/libnl_route_3_la-prio.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/qdisc/libnl_route_3_la-prio.lo `test -f 'lib/route/qdisc/prio.c' || echo '$(srcdir)/'`lib/route/qdisc/prio.c + +lib/route/qdisc/libnl_route_3_la-red.lo: lib/route/qdisc/red.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/qdisc/libnl_route_3_la-red.lo -MD -MP -MF lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-red.Tpo -c -o lib/route/qdisc/libnl_route_3_la-red.lo `test -f 'lib/route/qdisc/red.c' || echo '$(srcdir)/'`lib/route/qdisc/red.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-red.Tpo lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-red.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/qdisc/red.c' object='lib/route/qdisc/libnl_route_3_la-red.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/qdisc/libnl_route_3_la-red.lo `test -f 'lib/route/qdisc/red.c' || echo '$(srcdir)/'`lib/route/qdisc/red.c + +lib/route/qdisc/libnl_route_3_la-sfq.lo: lib/route/qdisc/sfq.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/qdisc/libnl_route_3_la-sfq.lo -MD -MP -MF lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-sfq.Tpo -c -o lib/route/qdisc/libnl_route_3_la-sfq.lo `test -f 'lib/route/qdisc/sfq.c' || echo '$(srcdir)/'`lib/route/qdisc/sfq.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-sfq.Tpo lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-sfq.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/qdisc/sfq.c' object='lib/route/qdisc/libnl_route_3_la-sfq.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/qdisc/libnl_route_3_la-sfq.lo `test -f 'lib/route/qdisc/sfq.c' || echo '$(srcdir)/'`lib/route/qdisc/sfq.c + +lib/route/qdisc/libnl_route_3_la-tbf.lo: lib/route/qdisc/tbf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/qdisc/libnl_route_3_la-tbf.lo -MD -MP -MF lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-tbf.Tpo -c -o lib/route/qdisc/libnl_route_3_la-tbf.lo `test -f 'lib/route/qdisc/tbf.c' || echo '$(srcdir)/'`lib/route/qdisc/tbf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-tbf.Tpo lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-tbf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/qdisc/tbf.c' object='lib/route/qdisc/libnl_route_3_la-tbf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/qdisc/libnl_route_3_la-tbf.lo `test -f 'lib/route/qdisc/tbf.c' || echo '$(srcdir)/'`lib/route/qdisc/tbf.c + +lib/route/libnl_route_3_la-route.lo: lib/route/route.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-route.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-route.Tpo -c -o lib/route/libnl_route_3_la-route.lo `test -f 'lib/route/route.c' || echo '$(srcdir)/'`lib/route/route.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-route.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-route.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/route.c' object='lib/route/libnl_route_3_la-route.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-route.lo `test -f 'lib/route/route.c' || echo '$(srcdir)/'`lib/route/route.c + +lib/route/libnl_route_3_la-route_obj.lo: lib/route/route_obj.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-route_obj.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-route_obj.Tpo -c -o lib/route/libnl_route_3_la-route_obj.lo `test -f 'lib/route/route_obj.c' || echo '$(srcdir)/'`lib/route/route_obj.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-route_obj.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-route_obj.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/route_obj.c' object='lib/route/libnl_route_3_la-route_obj.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-route_obj.lo `test -f 'lib/route/route_obj.c' || echo '$(srcdir)/'`lib/route/route_obj.c + +lib/route/libnl_route_3_la-route_utils.lo: lib/route/route_utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-route_utils.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-route_utils.Tpo -c -o lib/route/libnl_route_3_la-route_utils.lo `test -f 'lib/route/route_utils.c' || echo '$(srcdir)/'`lib/route/route_utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-route_utils.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-route_utils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/route_utils.c' object='lib/route/libnl_route_3_la-route_utils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-route_utils.lo `test -f 'lib/route/route_utils.c' || echo '$(srcdir)/'`lib/route/route_utils.c + +lib/route/libnl_route_3_la-rtnl.lo: lib/route/rtnl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-rtnl.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-rtnl.Tpo -c -o lib/route/libnl_route_3_la-rtnl.lo `test -f 'lib/route/rtnl.c' || echo '$(srcdir)/'`lib/route/rtnl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-rtnl.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-rtnl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/rtnl.c' object='lib/route/libnl_route_3_la-rtnl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-rtnl.lo `test -f 'lib/route/rtnl.c' || echo '$(srcdir)/'`lib/route/rtnl.c + +lib/route/libnl_route_3_la-rule.lo: lib/route/rule.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-rule.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-rule.Tpo -c -o lib/route/libnl_route_3_la-rule.lo `test -f 'lib/route/rule.c' || echo '$(srcdir)/'`lib/route/rule.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-rule.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-rule.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/rule.c' object='lib/route/libnl_route_3_la-rule.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-rule.lo `test -f 'lib/route/rule.c' || echo '$(srcdir)/'`lib/route/rule.c + +lib/route/libnl_route_3_la-tc.lo: lib/route/tc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-tc.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-tc.Tpo -c -o lib/route/libnl_route_3_la-tc.lo `test -f 'lib/route/tc.c' || echo '$(srcdir)/'`lib/route/tc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-tc.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-tc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/tc.c' object='lib/route/libnl_route_3_la-tc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-tc.lo `test -f 'lib/route/tc.c' || echo '$(srcdir)/'`lib/route/tc.c + +lib/route/cls/libnl_route_3_la-ematch_grammar.lo: lib/route/cls/ematch_grammar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/cls/libnl_route_3_la-ematch_grammar.lo -MD -MP -MF lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch_grammar.Tpo -c -o lib/route/cls/libnl_route_3_la-ematch_grammar.lo `test -f 'lib/route/cls/ematch_grammar.c' || echo '$(srcdir)/'`lib/route/cls/ematch_grammar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch_grammar.Tpo lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch_grammar.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/cls/ematch_grammar.c' object='lib/route/cls/libnl_route_3_la-ematch_grammar.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/cls/libnl_route_3_la-ematch_grammar.lo `test -f 'lib/route/cls/ematch_grammar.c' || echo '$(srcdir)/'`lib/route/cls/ematch_grammar.c + +lib/route/cls/libnl_route_3_la-ematch_syntax.lo: lib/route/cls/ematch_syntax.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/cls/libnl_route_3_la-ematch_syntax.lo -MD -MP -MF lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch_syntax.Tpo -c -o lib/route/cls/libnl_route_3_la-ematch_syntax.lo `test -f 'lib/route/cls/ematch_syntax.c' || echo '$(srcdir)/'`lib/route/cls/ematch_syntax.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch_syntax.Tpo lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch_syntax.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/cls/ematch_syntax.c' object='lib/route/cls/libnl_route_3_la-ematch_syntax.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/cls/libnl_route_3_la-ematch_syntax.lo `test -f 'lib/route/cls/ematch_syntax.c' || echo '$(srcdir)/'`lib/route/cls/ematch_syntax.c + +lib/route/libnl_route_3_la-pktloc_grammar.lo: lib/route/pktloc_grammar.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-pktloc_grammar.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-pktloc_grammar.Tpo -c -o lib/route/libnl_route_3_la-pktloc_grammar.lo `test -f 'lib/route/pktloc_grammar.c' || echo '$(srcdir)/'`lib/route/pktloc_grammar.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-pktloc_grammar.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-pktloc_grammar.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/pktloc_grammar.c' object='lib/route/libnl_route_3_la-pktloc_grammar.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-pktloc_grammar.lo `test -f 'lib/route/pktloc_grammar.c' || echo '$(srcdir)/'`lib/route/pktloc_grammar.c + +lib/route/libnl_route_3_la-pktloc_syntax.lo: lib/route/pktloc_syntax.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/route/libnl_route_3_la-pktloc_syntax.lo -MD -MP -MF lib/route/$(DEPDIR)/libnl_route_3_la-pktloc_syntax.Tpo -c -o lib/route/libnl_route_3_la-pktloc_syntax.lo `test -f 'lib/route/pktloc_syntax.c' || echo '$(srcdir)/'`lib/route/pktloc_syntax.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/route/$(DEPDIR)/libnl_route_3_la-pktloc_syntax.Tpo lib/route/$(DEPDIR)/libnl_route_3_la-pktloc_syntax.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/route/pktloc_syntax.c' object='lib/route/libnl_route_3_la-pktloc_syntax.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_route_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/route/libnl_route_3_la-pktloc_syntax.lo `test -f 'lib/route/pktloc_syntax.c' || echo '$(srcdir)/'`lib/route/pktloc_syntax.c + +lib/xfrm/libnl_xfrm_3_la-ae.lo: lib/xfrm/ae.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_xfrm_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/xfrm/libnl_xfrm_3_la-ae.lo -MD -MP -MF lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-ae.Tpo -c -o lib/xfrm/libnl_xfrm_3_la-ae.lo `test -f 'lib/xfrm/ae.c' || echo '$(srcdir)/'`lib/xfrm/ae.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-ae.Tpo lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-ae.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/xfrm/ae.c' object='lib/xfrm/libnl_xfrm_3_la-ae.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_xfrm_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/xfrm/libnl_xfrm_3_la-ae.lo `test -f 'lib/xfrm/ae.c' || echo '$(srcdir)/'`lib/xfrm/ae.c + +lib/xfrm/libnl_xfrm_3_la-lifetime.lo: lib/xfrm/lifetime.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_xfrm_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/xfrm/libnl_xfrm_3_la-lifetime.lo -MD -MP -MF lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-lifetime.Tpo -c -o lib/xfrm/libnl_xfrm_3_la-lifetime.lo `test -f 'lib/xfrm/lifetime.c' || echo '$(srcdir)/'`lib/xfrm/lifetime.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-lifetime.Tpo lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-lifetime.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/xfrm/lifetime.c' object='lib/xfrm/libnl_xfrm_3_la-lifetime.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_xfrm_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/xfrm/libnl_xfrm_3_la-lifetime.lo `test -f 'lib/xfrm/lifetime.c' || echo '$(srcdir)/'`lib/xfrm/lifetime.c + +lib/xfrm/libnl_xfrm_3_la-sa.lo: lib/xfrm/sa.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_xfrm_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/xfrm/libnl_xfrm_3_la-sa.lo -MD -MP -MF lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-sa.Tpo -c -o lib/xfrm/libnl_xfrm_3_la-sa.lo `test -f 'lib/xfrm/sa.c' || echo '$(srcdir)/'`lib/xfrm/sa.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-sa.Tpo lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-sa.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/xfrm/sa.c' object='lib/xfrm/libnl_xfrm_3_la-sa.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_xfrm_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/xfrm/libnl_xfrm_3_la-sa.lo `test -f 'lib/xfrm/sa.c' || echo '$(srcdir)/'`lib/xfrm/sa.c + +lib/xfrm/libnl_xfrm_3_la-selector.lo: lib/xfrm/selector.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_xfrm_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/xfrm/libnl_xfrm_3_la-selector.lo -MD -MP -MF lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-selector.Tpo -c -o lib/xfrm/libnl_xfrm_3_la-selector.lo `test -f 'lib/xfrm/selector.c' || echo '$(srcdir)/'`lib/xfrm/selector.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-selector.Tpo lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-selector.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/xfrm/selector.c' object='lib/xfrm/libnl_xfrm_3_la-selector.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_xfrm_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/xfrm/libnl_xfrm_3_la-selector.lo `test -f 'lib/xfrm/selector.c' || echo '$(srcdir)/'`lib/xfrm/selector.c + +lib/xfrm/libnl_xfrm_3_la-sp.lo: lib/xfrm/sp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_xfrm_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/xfrm/libnl_xfrm_3_la-sp.lo -MD -MP -MF lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-sp.Tpo -c -o lib/xfrm/libnl_xfrm_3_la-sp.lo `test -f 'lib/xfrm/sp.c' || echo '$(srcdir)/'`lib/xfrm/sp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-sp.Tpo lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-sp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/xfrm/sp.c' object='lib/xfrm/libnl_xfrm_3_la-sp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_xfrm_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/xfrm/libnl_xfrm_3_la-sp.lo `test -f 'lib/xfrm/sp.c' || echo '$(srcdir)/'`lib/xfrm/sp.c + +lib/xfrm/libnl_xfrm_3_la-template.lo: lib/xfrm/template.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_xfrm_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/xfrm/libnl_xfrm_3_la-template.lo -MD -MP -MF lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-template.Tpo -c -o lib/xfrm/libnl_xfrm_3_la-template.lo `test -f 'lib/xfrm/template.c' || echo '$(srcdir)/'`lib/xfrm/template.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-template.Tpo lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-template.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/xfrm/template.c' object='lib/xfrm/libnl_xfrm_3_la-template.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libnl_xfrm_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/xfrm/libnl_xfrm_3_la-template.lo `test -f 'lib/xfrm/template.c' || echo '$(srcdir)/'`lib/xfrm/template.c + +src/lib/libnl_cli_3_la-addr.lo: src/lib/addr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/lib/libnl_cli_3_la-addr.lo -MD -MP -MF src/lib/$(DEPDIR)/libnl_cli_3_la-addr.Tpo -c -o src/lib/libnl_cli_3_la-addr.lo `test -f 'src/lib/addr.c' || echo '$(srcdir)/'`src/lib/addr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/lib/$(DEPDIR)/libnl_cli_3_la-addr.Tpo src/lib/$(DEPDIR)/libnl_cli_3_la-addr.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lib/addr.c' object='src/lib/libnl_cli_3_la-addr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/lib/libnl_cli_3_la-addr.lo `test -f 'src/lib/addr.c' || echo '$(srcdir)/'`src/lib/addr.c + +src/lib/libnl_cli_3_la-class.lo: src/lib/class.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/lib/libnl_cli_3_la-class.lo -MD -MP -MF src/lib/$(DEPDIR)/libnl_cli_3_la-class.Tpo -c -o src/lib/libnl_cli_3_la-class.lo `test -f 'src/lib/class.c' || echo '$(srcdir)/'`src/lib/class.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/lib/$(DEPDIR)/libnl_cli_3_la-class.Tpo src/lib/$(DEPDIR)/libnl_cli_3_la-class.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lib/class.c' object='src/lib/libnl_cli_3_la-class.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/lib/libnl_cli_3_la-class.lo `test -f 'src/lib/class.c' || echo '$(srcdir)/'`src/lib/class.c + +src/lib/libnl_cli_3_la-cls.lo: src/lib/cls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/lib/libnl_cli_3_la-cls.lo -MD -MP -MF src/lib/$(DEPDIR)/libnl_cli_3_la-cls.Tpo -c -o src/lib/libnl_cli_3_la-cls.lo `test -f 'src/lib/cls.c' || echo '$(srcdir)/'`src/lib/cls.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/lib/$(DEPDIR)/libnl_cli_3_la-cls.Tpo src/lib/$(DEPDIR)/libnl_cli_3_la-cls.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lib/cls.c' object='src/lib/libnl_cli_3_la-cls.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/lib/libnl_cli_3_la-cls.lo `test -f 'src/lib/cls.c' || echo '$(srcdir)/'`src/lib/cls.c + +src/lib/libnl_cli_3_la-ct.lo: src/lib/ct.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/lib/libnl_cli_3_la-ct.lo -MD -MP -MF src/lib/$(DEPDIR)/libnl_cli_3_la-ct.Tpo -c -o src/lib/libnl_cli_3_la-ct.lo `test -f 'src/lib/ct.c' || echo '$(srcdir)/'`src/lib/ct.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/lib/$(DEPDIR)/libnl_cli_3_la-ct.Tpo src/lib/$(DEPDIR)/libnl_cli_3_la-ct.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lib/ct.c' object='src/lib/libnl_cli_3_la-ct.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/lib/libnl_cli_3_la-ct.lo `test -f 'src/lib/ct.c' || echo '$(srcdir)/'`src/lib/ct.c + +src/lib/libnl_cli_3_la-exp.lo: src/lib/exp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/lib/libnl_cli_3_la-exp.lo -MD -MP -MF src/lib/$(DEPDIR)/libnl_cli_3_la-exp.Tpo -c -o src/lib/libnl_cli_3_la-exp.lo `test -f 'src/lib/exp.c' || echo '$(srcdir)/'`src/lib/exp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/lib/$(DEPDIR)/libnl_cli_3_la-exp.Tpo src/lib/$(DEPDIR)/libnl_cli_3_la-exp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lib/exp.c' object='src/lib/libnl_cli_3_la-exp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/lib/libnl_cli_3_la-exp.lo `test -f 'src/lib/exp.c' || echo '$(srcdir)/'`src/lib/exp.c + +src/lib/libnl_cli_3_la-link.lo: src/lib/link.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/lib/libnl_cli_3_la-link.lo -MD -MP -MF src/lib/$(DEPDIR)/libnl_cli_3_la-link.Tpo -c -o src/lib/libnl_cli_3_la-link.lo `test -f 'src/lib/link.c' || echo '$(srcdir)/'`src/lib/link.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/lib/$(DEPDIR)/libnl_cli_3_la-link.Tpo src/lib/$(DEPDIR)/libnl_cli_3_la-link.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lib/link.c' object='src/lib/libnl_cli_3_la-link.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/lib/libnl_cli_3_la-link.lo `test -f 'src/lib/link.c' || echo '$(srcdir)/'`src/lib/link.c + +src/lib/libnl_cli_3_la-neigh.lo: src/lib/neigh.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/lib/libnl_cli_3_la-neigh.lo -MD -MP -MF src/lib/$(DEPDIR)/libnl_cli_3_la-neigh.Tpo -c -o src/lib/libnl_cli_3_la-neigh.lo `test -f 'src/lib/neigh.c' || echo '$(srcdir)/'`src/lib/neigh.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/lib/$(DEPDIR)/libnl_cli_3_la-neigh.Tpo src/lib/$(DEPDIR)/libnl_cli_3_la-neigh.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lib/neigh.c' object='src/lib/libnl_cli_3_la-neigh.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/lib/libnl_cli_3_la-neigh.lo `test -f 'src/lib/neigh.c' || echo '$(srcdir)/'`src/lib/neigh.c + +src/lib/libnl_cli_3_la-nh.lo: src/lib/nh.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/lib/libnl_cli_3_la-nh.lo -MD -MP -MF src/lib/$(DEPDIR)/libnl_cli_3_la-nh.Tpo -c -o src/lib/libnl_cli_3_la-nh.lo `test -f 'src/lib/nh.c' || echo '$(srcdir)/'`src/lib/nh.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/lib/$(DEPDIR)/libnl_cli_3_la-nh.Tpo src/lib/$(DEPDIR)/libnl_cli_3_la-nh.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lib/nh.c' object='src/lib/libnl_cli_3_la-nh.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/lib/libnl_cli_3_la-nh.lo `test -f 'src/lib/nh.c' || echo '$(srcdir)/'`src/lib/nh.c + +src/lib/libnl_cli_3_la-qdisc.lo: src/lib/qdisc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/lib/libnl_cli_3_la-qdisc.lo -MD -MP -MF src/lib/$(DEPDIR)/libnl_cli_3_la-qdisc.Tpo -c -o src/lib/libnl_cli_3_la-qdisc.lo `test -f 'src/lib/qdisc.c' || echo '$(srcdir)/'`src/lib/qdisc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/lib/$(DEPDIR)/libnl_cli_3_la-qdisc.Tpo src/lib/$(DEPDIR)/libnl_cli_3_la-qdisc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lib/qdisc.c' object='src/lib/libnl_cli_3_la-qdisc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/lib/libnl_cli_3_la-qdisc.lo `test -f 'src/lib/qdisc.c' || echo '$(srcdir)/'`src/lib/qdisc.c + +src/lib/libnl_cli_3_la-route.lo: src/lib/route.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/lib/libnl_cli_3_la-route.lo -MD -MP -MF src/lib/$(DEPDIR)/libnl_cli_3_la-route.Tpo -c -o src/lib/libnl_cli_3_la-route.lo `test -f 'src/lib/route.c' || echo '$(srcdir)/'`src/lib/route.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/lib/$(DEPDIR)/libnl_cli_3_la-route.Tpo src/lib/$(DEPDIR)/libnl_cli_3_la-route.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lib/route.c' object='src/lib/libnl_cli_3_la-route.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/lib/libnl_cli_3_la-route.lo `test -f 'src/lib/route.c' || echo '$(srcdir)/'`src/lib/route.c + +src/lib/libnl_cli_3_la-rule.lo: src/lib/rule.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/lib/libnl_cli_3_la-rule.lo -MD -MP -MF src/lib/$(DEPDIR)/libnl_cli_3_la-rule.Tpo -c -o src/lib/libnl_cli_3_la-rule.lo `test -f 'src/lib/rule.c' || echo '$(srcdir)/'`src/lib/rule.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/lib/$(DEPDIR)/libnl_cli_3_la-rule.Tpo src/lib/$(DEPDIR)/libnl_cli_3_la-rule.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lib/rule.c' object='src/lib/libnl_cli_3_la-rule.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/lib/libnl_cli_3_la-rule.lo `test -f 'src/lib/rule.c' || echo '$(srcdir)/'`src/lib/rule.c + +src/lib/libnl_cli_3_la-tc.lo: src/lib/tc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/lib/libnl_cli_3_la-tc.lo -MD -MP -MF src/lib/$(DEPDIR)/libnl_cli_3_la-tc.Tpo -c -o src/lib/libnl_cli_3_la-tc.lo `test -f 'src/lib/tc.c' || echo '$(srcdir)/'`src/lib/tc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/lib/$(DEPDIR)/libnl_cli_3_la-tc.Tpo src/lib/$(DEPDIR)/libnl_cli_3_la-tc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lib/tc.c' object='src/lib/libnl_cli_3_la-tc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/lib/libnl_cli_3_la-tc.lo `test -f 'src/lib/tc.c' || echo '$(srcdir)/'`src/lib/tc.c + +src/lib/libnl_cli_3_la-utils.lo: src/lib/utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/lib/libnl_cli_3_la-utils.lo -MD -MP -MF src/lib/$(DEPDIR)/libnl_cli_3_la-utils.Tpo -c -o src/lib/libnl_cli_3_la-utils.lo `test -f 'src/lib/utils.c' || echo '$(srcdir)/'`src/lib/utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/lib/$(DEPDIR)/libnl_cli_3_la-utils.Tpo src/lib/$(DEPDIR)/libnl_cli_3_la-utils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lib/utils.c' object='src/lib/libnl_cli_3_la-utils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_lib_libnl_cli_3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/lib/libnl_cli_3_la-utils.lo `test -f 'src/lib/utils.c' || echo '$(srcdir)/'`src/lib/utils.c + +tests/libnl_test_util_la-nl-test-util.lo: tests/nl-test-util.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_libnl_test_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/libnl_test_util_la-nl-test-util.lo -MD -MP -MF tests/$(DEPDIR)/libnl_test_util_la-nl-test-util.Tpo -c -o tests/libnl_test_util_la-nl-test-util.lo `test -f 'tests/nl-test-util.c' || echo '$(srcdir)/'`tests/nl-test-util.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/libnl_test_util_la-nl-test-util.Tpo tests/$(DEPDIR)/libnl_test_util_la-nl-test-util.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/nl-test-util.c' object='tests/libnl_test_util_la-nl-test-util.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_libnl_test_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/libnl_test_util_la-nl-test-util.lo `test -f 'tests/nl-test-util.c' || echo '$(srcdir)/'`tests/nl-test-util.c + +src/genl_ctrl_list-genl-ctrl-list.o: src/genl-ctrl-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_genl_ctrl_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/genl_ctrl_list-genl-ctrl-list.o -MD -MP -MF src/$(DEPDIR)/genl_ctrl_list-genl-ctrl-list.Tpo -c -o src/genl_ctrl_list-genl-ctrl-list.o `test -f 'src/genl-ctrl-list.c' || echo '$(srcdir)/'`src/genl-ctrl-list.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/genl_ctrl_list-genl-ctrl-list.Tpo src/$(DEPDIR)/genl_ctrl_list-genl-ctrl-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/genl-ctrl-list.c' object='src/genl_ctrl_list-genl-ctrl-list.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_genl_ctrl_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/genl_ctrl_list-genl-ctrl-list.o `test -f 'src/genl-ctrl-list.c' || echo '$(srcdir)/'`src/genl-ctrl-list.c + +src/genl_ctrl_list-genl-ctrl-list.obj: src/genl-ctrl-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_genl_ctrl_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/genl_ctrl_list-genl-ctrl-list.obj -MD -MP -MF src/$(DEPDIR)/genl_ctrl_list-genl-ctrl-list.Tpo -c -o src/genl_ctrl_list-genl-ctrl-list.obj `if test -f 'src/genl-ctrl-list.c'; then $(CYGPATH_W) 'src/genl-ctrl-list.c'; else $(CYGPATH_W) '$(srcdir)/src/genl-ctrl-list.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/genl_ctrl_list-genl-ctrl-list.Tpo src/$(DEPDIR)/genl_ctrl_list-genl-ctrl-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/genl-ctrl-list.c' object='src/genl_ctrl_list-genl-ctrl-list.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_genl_ctrl_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/genl_ctrl_list-genl-ctrl-list.obj `if test -f 'src/genl-ctrl-list.c'; then $(CYGPATH_W) 'src/genl-ctrl-list.c'; else $(CYGPATH_W) '$(srcdir)/src/genl-ctrl-list.c'; fi` + +src/idiag_socket_details-idiag-socket-details.o: src/idiag-socket-details.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_idiag_socket_details_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/idiag_socket_details-idiag-socket-details.o -MD -MP -MF src/$(DEPDIR)/idiag_socket_details-idiag-socket-details.Tpo -c -o src/idiag_socket_details-idiag-socket-details.o `test -f 'src/idiag-socket-details.c' || echo '$(srcdir)/'`src/idiag-socket-details.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/idiag_socket_details-idiag-socket-details.Tpo src/$(DEPDIR)/idiag_socket_details-idiag-socket-details.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/idiag-socket-details.c' object='src/idiag_socket_details-idiag-socket-details.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_idiag_socket_details_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/idiag_socket_details-idiag-socket-details.o `test -f 'src/idiag-socket-details.c' || echo '$(srcdir)/'`src/idiag-socket-details.c + +src/idiag_socket_details-idiag-socket-details.obj: src/idiag-socket-details.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_idiag_socket_details_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/idiag_socket_details-idiag-socket-details.obj -MD -MP -MF src/$(DEPDIR)/idiag_socket_details-idiag-socket-details.Tpo -c -o src/idiag_socket_details-idiag-socket-details.obj `if test -f 'src/idiag-socket-details.c'; then $(CYGPATH_W) 'src/idiag-socket-details.c'; else $(CYGPATH_W) '$(srcdir)/src/idiag-socket-details.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/idiag_socket_details-idiag-socket-details.Tpo src/$(DEPDIR)/idiag_socket_details-idiag-socket-details.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/idiag-socket-details.c' object='src/idiag_socket_details-idiag-socket-details.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_idiag_socket_details_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/idiag_socket_details-idiag-socket-details.obj `if test -f 'src/idiag-socket-details.c'; then $(CYGPATH_W) 'src/idiag-socket-details.c'; else $(CYGPATH_W) '$(srcdir)/src/idiag-socket-details.c'; fi` + +src/nf_ct_add-nf-ct-add.o: src/nf-ct-add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_ct_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nf_ct_add-nf-ct-add.o -MD -MP -MF src/$(DEPDIR)/nf_ct_add-nf-ct-add.Tpo -c -o src/nf_ct_add-nf-ct-add.o `test -f 'src/nf-ct-add.c' || echo '$(srcdir)/'`src/nf-ct-add.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nf_ct_add-nf-ct-add.Tpo src/$(DEPDIR)/nf_ct_add-nf-ct-add.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nf-ct-add.c' object='src/nf_ct_add-nf-ct-add.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_ct_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nf_ct_add-nf-ct-add.o `test -f 'src/nf-ct-add.c' || echo '$(srcdir)/'`src/nf-ct-add.c + +src/nf_ct_add-nf-ct-add.obj: src/nf-ct-add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_ct_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nf_ct_add-nf-ct-add.obj -MD -MP -MF src/$(DEPDIR)/nf_ct_add-nf-ct-add.Tpo -c -o src/nf_ct_add-nf-ct-add.obj `if test -f 'src/nf-ct-add.c'; then $(CYGPATH_W) 'src/nf-ct-add.c'; else $(CYGPATH_W) '$(srcdir)/src/nf-ct-add.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nf_ct_add-nf-ct-add.Tpo src/$(DEPDIR)/nf_ct_add-nf-ct-add.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nf-ct-add.c' object='src/nf_ct_add-nf-ct-add.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_ct_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nf_ct_add-nf-ct-add.obj `if test -f 'src/nf-ct-add.c'; then $(CYGPATH_W) 'src/nf-ct-add.c'; else $(CYGPATH_W) '$(srcdir)/src/nf-ct-add.c'; fi` + +src/nf_ct_events-nf-ct-events.o: src/nf-ct-events.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_ct_events_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nf_ct_events-nf-ct-events.o -MD -MP -MF src/$(DEPDIR)/nf_ct_events-nf-ct-events.Tpo -c -o src/nf_ct_events-nf-ct-events.o `test -f 'src/nf-ct-events.c' || echo '$(srcdir)/'`src/nf-ct-events.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nf_ct_events-nf-ct-events.Tpo src/$(DEPDIR)/nf_ct_events-nf-ct-events.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nf-ct-events.c' object='src/nf_ct_events-nf-ct-events.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_ct_events_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nf_ct_events-nf-ct-events.o `test -f 'src/nf-ct-events.c' || echo '$(srcdir)/'`src/nf-ct-events.c + +src/nf_ct_events-nf-ct-events.obj: src/nf-ct-events.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_ct_events_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nf_ct_events-nf-ct-events.obj -MD -MP -MF src/$(DEPDIR)/nf_ct_events-nf-ct-events.Tpo -c -o src/nf_ct_events-nf-ct-events.obj `if test -f 'src/nf-ct-events.c'; then $(CYGPATH_W) 'src/nf-ct-events.c'; else $(CYGPATH_W) '$(srcdir)/src/nf-ct-events.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nf_ct_events-nf-ct-events.Tpo src/$(DEPDIR)/nf_ct_events-nf-ct-events.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nf-ct-events.c' object='src/nf_ct_events-nf-ct-events.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_ct_events_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nf_ct_events-nf-ct-events.obj `if test -f 'src/nf-ct-events.c'; then $(CYGPATH_W) 'src/nf-ct-events.c'; else $(CYGPATH_W) '$(srcdir)/src/nf-ct-events.c'; fi` + +src/nf_ct_list-nf-ct-list.o: src/nf-ct-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_ct_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nf_ct_list-nf-ct-list.o -MD -MP -MF src/$(DEPDIR)/nf_ct_list-nf-ct-list.Tpo -c -o src/nf_ct_list-nf-ct-list.o `test -f 'src/nf-ct-list.c' || echo '$(srcdir)/'`src/nf-ct-list.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nf_ct_list-nf-ct-list.Tpo src/$(DEPDIR)/nf_ct_list-nf-ct-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nf-ct-list.c' object='src/nf_ct_list-nf-ct-list.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_ct_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nf_ct_list-nf-ct-list.o `test -f 'src/nf-ct-list.c' || echo '$(srcdir)/'`src/nf-ct-list.c + +src/nf_ct_list-nf-ct-list.obj: src/nf-ct-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_ct_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nf_ct_list-nf-ct-list.obj -MD -MP -MF src/$(DEPDIR)/nf_ct_list-nf-ct-list.Tpo -c -o src/nf_ct_list-nf-ct-list.obj `if test -f 'src/nf-ct-list.c'; then $(CYGPATH_W) 'src/nf-ct-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nf-ct-list.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nf_ct_list-nf-ct-list.Tpo src/$(DEPDIR)/nf_ct_list-nf-ct-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nf-ct-list.c' object='src/nf_ct_list-nf-ct-list.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_ct_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nf_ct_list-nf-ct-list.obj `if test -f 'src/nf-ct-list.c'; then $(CYGPATH_W) 'src/nf-ct-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nf-ct-list.c'; fi` + +src/nf_exp_add-nf-exp-add.o: src/nf-exp-add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_exp_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nf_exp_add-nf-exp-add.o -MD -MP -MF src/$(DEPDIR)/nf_exp_add-nf-exp-add.Tpo -c -o src/nf_exp_add-nf-exp-add.o `test -f 'src/nf-exp-add.c' || echo '$(srcdir)/'`src/nf-exp-add.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nf_exp_add-nf-exp-add.Tpo src/$(DEPDIR)/nf_exp_add-nf-exp-add.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nf-exp-add.c' object='src/nf_exp_add-nf-exp-add.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_exp_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nf_exp_add-nf-exp-add.o `test -f 'src/nf-exp-add.c' || echo '$(srcdir)/'`src/nf-exp-add.c + +src/nf_exp_add-nf-exp-add.obj: src/nf-exp-add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_exp_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nf_exp_add-nf-exp-add.obj -MD -MP -MF src/$(DEPDIR)/nf_exp_add-nf-exp-add.Tpo -c -o src/nf_exp_add-nf-exp-add.obj `if test -f 'src/nf-exp-add.c'; then $(CYGPATH_W) 'src/nf-exp-add.c'; else $(CYGPATH_W) '$(srcdir)/src/nf-exp-add.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nf_exp_add-nf-exp-add.Tpo src/$(DEPDIR)/nf_exp_add-nf-exp-add.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nf-exp-add.c' object='src/nf_exp_add-nf-exp-add.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_exp_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nf_exp_add-nf-exp-add.obj `if test -f 'src/nf-exp-add.c'; then $(CYGPATH_W) 'src/nf-exp-add.c'; else $(CYGPATH_W) '$(srcdir)/src/nf-exp-add.c'; fi` + +src/nf_exp_delete-nf-exp-delete.o: src/nf-exp-delete.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_exp_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nf_exp_delete-nf-exp-delete.o -MD -MP -MF src/$(DEPDIR)/nf_exp_delete-nf-exp-delete.Tpo -c -o src/nf_exp_delete-nf-exp-delete.o `test -f 'src/nf-exp-delete.c' || echo '$(srcdir)/'`src/nf-exp-delete.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nf_exp_delete-nf-exp-delete.Tpo src/$(DEPDIR)/nf_exp_delete-nf-exp-delete.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nf-exp-delete.c' object='src/nf_exp_delete-nf-exp-delete.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_exp_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nf_exp_delete-nf-exp-delete.o `test -f 'src/nf-exp-delete.c' || echo '$(srcdir)/'`src/nf-exp-delete.c + +src/nf_exp_delete-nf-exp-delete.obj: src/nf-exp-delete.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_exp_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nf_exp_delete-nf-exp-delete.obj -MD -MP -MF src/$(DEPDIR)/nf_exp_delete-nf-exp-delete.Tpo -c -o src/nf_exp_delete-nf-exp-delete.obj `if test -f 'src/nf-exp-delete.c'; then $(CYGPATH_W) 'src/nf-exp-delete.c'; else $(CYGPATH_W) '$(srcdir)/src/nf-exp-delete.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nf_exp_delete-nf-exp-delete.Tpo src/$(DEPDIR)/nf_exp_delete-nf-exp-delete.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nf-exp-delete.c' object='src/nf_exp_delete-nf-exp-delete.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_exp_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nf_exp_delete-nf-exp-delete.obj `if test -f 'src/nf-exp-delete.c'; then $(CYGPATH_W) 'src/nf-exp-delete.c'; else $(CYGPATH_W) '$(srcdir)/src/nf-exp-delete.c'; fi` + +src/nf_exp_list-nf-exp-list.o: src/nf-exp-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_exp_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nf_exp_list-nf-exp-list.o -MD -MP -MF src/$(DEPDIR)/nf_exp_list-nf-exp-list.Tpo -c -o src/nf_exp_list-nf-exp-list.o `test -f 'src/nf-exp-list.c' || echo '$(srcdir)/'`src/nf-exp-list.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nf_exp_list-nf-exp-list.Tpo src/$(DEPDIR)/nf_exp_list-nf-exp-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nf-exp-list.c' object='src/nf_exp_list-nf-exp-list.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_exp_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nf_exp_list-nf-exp-list.o `test -f 'src/nf-exp-list.c' || echo '$(srcdir)/'`src/nf-exp-list.c + +src/nf_exp_list-nf-exp-list.obj: src/nf-exp-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_exp_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nf_exp_list-nf-exp-list.obj -MD -MP -MF src/$(DEPDIR)/nf_exp_list-nf-exp-list.Tpo -c -o src/nf_exp_list-nf-exp-list.obj `if test -f 'src/nf-exp-list.c'; then $(CYGPATH_W) 'src/nf-exp-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nf-exp-list.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nf_exp_list-nf-exp-list.Tpo src/$(DEPDIR)/nf_exp_list-nf-exp-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nf-exp-list.c' object='src/nf_exp_list-nf-exp-list.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_exp_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nf_exp_list-nf-exp-list.obj `if test -f 'src/nf-exp-list.c'; then $(CYGPATH_W) 'src/nf-exp-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nf-exp-list.c'; fi` + +src/nf_log-nf-log.o: src/nf-log.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_log_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nf_log-nf-log.o -MD -MP -MF src/$(DEPDIR)/nf_log-nf-log.Tpo -c -o src/nf_log-nf-log.o `test -f 'src/nf-log.c' || echo '$(srcdir)/'`src/nf-log.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nf_log-nf-log.Tpo src/$(DEPDIR)/nf_log-nf-log.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nf-log.c' object='src/nf_log-nf-log.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_log_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nf_log-nf-log.o `test -f 'src/nf-log.c' || echo '$(srcdir)/'`src/nf-log.c + +src/nf_log-nf-log.obj: src/nf-log.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_log_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nf_log-nf-log.obj -MD -MP -MF src/$(DEPDIR)/nf_log-nf-log.Tpo -c -o src/nf_log-nf-log.obj `if test -f 'src/nf-log.c'; then $(CYGPATH_W) 'src/nf-log.c'; else $(CYGPATH_W) '$(srcdir)/src/nf-log.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nf_log-nf-log.Tpo src/$(DEPDIR)/nf_log-nf-log.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nf-log.c' object='src/nf_log-nf-log.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_log_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nf_log-nf-log.obj `if test -f 'src/nf-log.c'; then $(CYGPATH_W) 'src/nf-log.c'; else $(CYGPATH_W) '$(srcdir)/src/nf-log.c'; fi` + +src/nf_monitor-nf-monitor.o: src/nf-monitor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_monitor_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nf_monitor-nf-monitor.o -MD -MP -MF src/$(DEPDIR)/nf_monitor-nf-monitor.Tpo -c -o src/nf_monitor-nf-monitor.o `test -f 'src/nf-monitor.c' || echo '$(srcdir)/'`src/nf-monitor.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nf_monitor-nf-monitor.Tpo src/$(DEPDIR)/nf_monitor-nf-monitor.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nf-monitor.c' object='src/nf_monitor-nf-monitor.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_monitor_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nf_monitor-nf-monitor.o `test -f 'src/nf-monitor.c' || echo '$(srcdir)/'`src/nf-monitor.c + +src/nf_monitor-nf-monitor.obj: src/nf-monitor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_monitor_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nf_monitor-nf-monitor.obj -MD -MP -MF src/$(DEPDIR)/nf_monitor-nf-monitor.Tpo -c -o src/nf_monitor-nf-monitor.obj `if test -f 'src/nf-monitor.c'; then $(CYGPATH_W) 'src/nf-monitor.c'; else $(CYGPATH_W) '$(srcdir)/src/nf-monitor.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nf_monitor-nf-monitor.Tpo src/$(DEPDIR)/nf_monitor-nf-monitor.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nf-monitor.c' object='src/nf_monitor-nf-monitor.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_monitor_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nf_monitor-nf-monitor.obj `if test -f 'src/nf-monitor.c'; then $(CYGPATH_W) 'src/nf-monitor.c'; else $(CYGPATH_W) '$(srcdir)/src/nf-monitor.c'; fi` + +src/nf_queue-nf-queue.o: src/nf-queue.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_queue_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nf_queue-nf-queue.o -MD -MP -MF src/$(DEPDIR)/nf_queue-nf-queue.Tpo -c -o src/nf_queue-nf-queue.o `test -f 'src/nf-queue.c' || echo '$(srcdir)/'`src/nf-queue.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nf_queue-nf-queue.Tpo src/$(DEPDIR)/nf_queue-nf-queue.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nf-queue.c' object='src/nf_queue-nf-queue.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_queue_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nf_queue-nf-queue.o `test -f 'src/nf-queue.c' || echo '$(srcdir)/'`src/nf-queue.c + +src/nf_queue-nf-queue.obj: src/nf-queue.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_queue_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nf_queue-nf-queue.obj -MD -MP -MF src/$(DEPDIR)/nf_queue-nf-queue.Tpo -c -o src/nf_queue-nf-queue.obj `if test -f 'src/nf-queue.c'; then $(CYGPATH_W) 'src/nf-queue.c'; else $(CYGPATH_W) '$(srcdir)/src/nf-queue.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nf_queue-nf-queue.Tpo src/$(DEPDIR)/nf_queue-nf-queue.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nf-queue.c' object='src/nf_queue-nf-queue.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nf_queue_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nf_queue-nf-queue.obj `if test -f 'src/nf-queue.c'; then $(CYGPATH_W) 'src/nf-queue.c'; else $(CYGPATH_W) '$(srcdir)/src/nf-queue.c'; fi` + +src/nl_addr_add-nl-addr-add.o: src/nl-addr-add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_addr_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_addr_add-nl-addr-add.o -MD -MP -MF src/$(DEPDIR)/nl_addr_add-nl-addr-add.Tpo -c -o src/nl_addr_add-nl-addr-add.o `test -f 'src/nl-addr-add.c' || echo '$(srcdir)/'`src/nl-addr-add.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_addr_add-nl-addr-add.Tpo src/$(DEPDIR)/nl_addr_add-nl-addr-add.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-addr-add.c' object='src/nl_addr_add-nl-addr-add.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_addr_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_addr_add-nl-addr-add.o `test -f 'src/nl-addr-add.c' || echo '$(srcdir)/'`src/nl-addr-add.c + +src/nl_addr_add-nl-addr-add.obj: src/nl-addr-add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_addr_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_addr_add-nl-addr-add.obj -MD -MP -MF src/$(DEPDIR)/nl_addr_add-nl-addr-add.Tpo -c -o src/nl_addr_add-nl-addr-add.obj `if test -f 'src/nl-addr-add.c'; then $(CYGPATH_W) 'src/nl-addr-add.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-addr-add.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_addr_add-nl-addr-add.Tpo src/$(DEPDIR)/nl_addr_add-nl-addr-add.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-addr-add.c' object='src/nl_addr_add-nl-addr-add.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_addr_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_addr_add-nl-addr-add.obj `if test -f 'src/nl-addr-add.c'; then $(CYGPATH_W) 'src/nl-addr-add.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-addr-add.c'; fi` + +src/nl_addr_delete-nl-addr-delete.o: src/nl-addr-delete.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_addr_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_addr_delete-nl-addr-delete.o -MD -MP -MF src/$(DEPDIR)/nl_addr_delete-nl-addr-delete.Tpo -c -o src/nl_addr_delete-nl-addr-delete.o `test -f 'src/nl-addr-delete.c' || echo '$(srcdir)/'`src/nl-addr-delete.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_addr_delete-nl-addr-delete.Tpo src/$(DEPDIR)/nl_addr_delete-nl-addr-delete.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-addr-delete.c' object='src/nl_addr_delete-nl-addr-delete.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_addr_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_addr_delete-nl-addr-delete.o `test -f 'src/nl-addr-delete.c' || echo '$(srcdir)/'`src/nl-addr-delete.c + +src/nl_addr_delete-nl-addr-delete.obj: src/nl-addr-delete.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_addr_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_addr_delete-nl-addr-delete.obj -MD -MP -MF src/$(DEPDIR)/nl_addr_delete-nl-addr-delete.Tpo -c -o src/nl_addr_delete-nl-addr-delete.obj `if test -f 'src/nl-addr-delete.c'; then $(CYGPATH_W) 'src/nl-addr-delete.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-addr-delete.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_addr_delete-nl-addr-delete.Tpo src/$(DEPDIR)/nl_addr_delete-nl-addr-delete.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-addr-delete.c' object='src/nl_addr_delete-nl-addr-delete.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_addr_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_addr_delete-nl-addr-delete.obj `if test -f 'src/nl-addr-delete.c'; then $(CYGPATH_W) 'src/nl-addr-delete.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-addr-delete.c'; fi` + +src/nl_addr_list-nl-addr-list.o: src/nl-addr-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_addr_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_addr_list-nl-addr-list.o -MD -MP -MF src/$(DEPDIR)/nl_addr_list-nl-addr-list.Tpo -c -o src/nl_addr_list-nl-addr-list.o `test -f 'src/nl-addr-list.c' || echo '$(srcdir)/'`src/nl-addr-list.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_addr_list-nl-addr-list.Tpo src/$(DEPDIR)/nl_addr_list-nl-addr-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-addr-list.c' object='src/nl_addr_list-nl-addr-list.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_addr_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_addr_list-nl-addr-list.o `test -f 'src/nl-addr-list.c' || echo '$(srcdir)/'`src/nl-addr-list.c + +src/nl_addr_list-nl-addr-list.obj: src/nl-addr-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_addr_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_addr_list-nl-addr-list.obj -MD -MP -MF src/$(DEPDIR)/nl_addr_list-nl-addr-list.Tpo -c -o src/nl_addr_list-nl-addr-list.obj `if test -f 'src/nl-addr-list.c'; then $(CYGPATH_W) 'src/nl-addr-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-addr-list.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_addr_list-nl-addr-list.Tpo src/$(DEPDIR)/nl_addr_list-nl-addr-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-addr-list.c' object='src/nl_addr_list-nl-addr-list.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_addr_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_addr_list-nl-addr-list.obj `if test -f 'src/nl-addr-list.c'; then $(CYGPATH_W) 'src/nl-addr-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-addr-list.c'; fi` + +src/nl_class_add-nl-class-add.o: src/nl-class-add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_class_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_class_add-nl-class-add.o -MD -MP -MF src/$(DEPDIR)/nl_class_add-nl-class-add.Tpo -c -o src/nl_class_add-nl-class-add.o `test -f 'src/nl-class-add.c' || echo '$(srcdir)/'`src/nl-class-add.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_class_add-nl-class-add.Tpo src/$(DEPDIR)/nl_class_add-nl-class-add.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-class-add.c' object='src/nl_class_add-nl-class-add.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_class_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_class_add-nl-class-add.o `test -f 'src/nl-class-add.c' || echo '$(srcdir)/'`src/nl-class-add.c + +src/nl_class_add-nl-class-add.obj: src/nl-class-add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_class_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_class_add-nl-class-add.obj -MD -MP -MF src/$(DEPDIR)/nl_class_add-nl-class-add.Tpo -c -o src/nl_class_add-nl-class-add.obj `if test -f 'src/nl-class-add.c'; then $(CYGPATH_W) 'src/nl-class-add.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-class-add.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_class_add-nl-class-add.Tpo src/$(DEPDIR)/nl_class_add-nl-class-add.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-class-add.c' object='src/nl_class_add-nl-class-add.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_class_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_class_add-nl-class-add.obj `if test -f 'src/nl-class-add.c'; then $(CYGPATH_W) 'src/nl-class-add.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-class-add.c'; fi` + +src/nl_class_delete-nl-class-delete.o: src/nl-class-delete.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_class_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_class_delete-nl-class-delete.o -MD -MP -MF src/$(DEPDIR)/nl_class_delete-nl-class-delete.Tpo -c -o src/nl_class_delete-nl-class-delete.o `test -f 'src/nl-class-delete.c' || echo '$(srcdir)/'`src/nl-class-delete.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_class_delete-nl-class-delete.Tpo src/$(DEPDIR)/nl_class_delete-nl-class-delete.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-class-delete.c' object='src/nl_class_delete-nl-class-delete.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_class_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_class_delete-nl-class-delete.o `test -f 'src/nl-class-delete.c' || echo '$(srcdir)/'`src/nl-class-delete.c + +src/nl_class_delete-nl-class-delete.obj: src/nl-class-delete.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_class_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_class_delete-nl-class-delete.obj -MD -MP -MF src/$(DEPDIR)/nl_class_delete-nl-class-delete.Tpo -c -o src/nl_class_delete-nl-class-delete.obj `if test -f 'src/nl-class-delete.c'; then $(CYGPATH_W) 'src/nl-class-delete.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-class-delete.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_class_delete-nl-class-delete.Tpo src/$(DEPDIR)/nl_class_delete-nl-class-delete.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-class-delete.c' object='src/nl_class_delete-nl-class-delete.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_class_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_class_delete-nl-class-delete.obj `if test -f 'src/nl-class-delete.c'; then $(CYGPATH_W) 'src/nl-class-delete.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-class-delete.c'; fi` + +src/nl_class_list-nl-class-list.o: src/nl-class-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_class_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_class_list-nl-class-list.o -MD -MP -MF src/$(DEPDIR)/nl_class_list-nl-class-list.Tpo -c -o src/nl_class_list-nl-class-list.o `test -f 'src/nl-class-list.c' || echo '$(srcdir)/'`src/nl-class-list.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_class_list-nl-class-list.Tpo src/$(DEPDIR)/nl_class_list-nl-class-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-class-list.c' object='src/nl_class_list-nl-class-list.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_class_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_class_list-nl-class-list.o `test -f 'src/nl-class-list.c' || echo '$(srcdir)/'`src/nl-class-list.c + +src/nl_class_list-nl-class-list.obj: src/nl-class-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_class_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_class_list-nl-class-list.obj -MD -MP -MF src/$(DEPDIR)/nl_class_list-nl-class-list.Tpo -c -o src/nl_class_list-nl-class-list.obj `if test -f 'src/nl-class-list.c'; then $(CYGPATH_W) 'src/nl-class-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-class-list.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_class_list-nl-class-list.Tpo src/$(DEPDIR)/nl_class_list-nl-class-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-class-list.c' object='src/nl_class_list-nl-class-list.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_class_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_class_list-nl-class-list.obj `if test -f 'src/nl-class-list.c'; then $(CYGPATH_W) 'src/nl-class-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-class-list.c'; fi` + +src/nl_classid_lookup-nl-classid-lookup.o: src/nl-classid-lookup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_classid_lookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_classid_lookup-nl-classid-lookup.o -MD -MP -MF src/$(DEPDIR)/nl_classid_lookup-nl-classid-lookup.Tpo -c -o src/nl_classid_lookup-nl-classid-lookup.o `test -f 'src/nl-classid-lookup.c' || echo '$(srcdir)/'`src/nl-classid-lookup.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_classid_lookup-nl-classid-lookup.Tpo src/$(DEPDIR)/nl_classid_lookup-nl-classid-lookup.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-classid-lookup.c' object='src/nl_classid_lookup-nl-classid-lookup.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_classid_lookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_classid_lookup-nl-classid-lookup.o `test -f 'src/nl-classid-lookup.c' || echo '$(srcdir)/'`src/nl-classid-lookup.c + +src/nl_classid_lookup-nl-classid-lookup.obj: src/nl-classid-lookup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_classid_lookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_classid_lookup-nl-classid-lookup.obj -MD -MP -MF src/$(DEPDIR)/nl_classid_lookup-nl-classid-lookup.Tpo -c -o src/nl_classid_lookup-nl-classid-lookup.obj `if test -f 'src/nl-classid-lookup.c'; then $(CYGPATH_W) 'src/nl-classid-lookup.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-classid-lookup.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_classid_lookup-nl-classid-lookup.Tpo src/$(DEPDIR)/nl_classid_lookup-nl-classid-lookup.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-classid-lookup.c' object='src/nl_classid_lookup-nl-classid-lookup.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_classid_lookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_classid_lookup-nl-classid-lookup.obj `if test -f 'src/nl-classid-lookup.c'; then $(CYGPATH_W) 'src/nl-classid-lookup.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-classid-lookup.c'; fi` + +src/nl_cls_add-nl-cls-add.o: src/nl-cls-add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_cls_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_cls_add-nl-cls-add.o -MD -MP -MF src/$(DEPDIR)/nl_cls_add-nl-cls-add.Tpo -c -o src/nl_cls_add-nl-cls-add.o `test -f 'src/nl-cls-add.c' || echo '$(srcdir)/'`src/nl-cls-add.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_cls_add-nl-cls-add.Tpo src/$(DEPDIR)/nl_cls_add-nl-cls-add.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-cls-add.c' object='src/nl_cls_add-nl-cls-add.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_cls_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_cls_add-nl-cls-add.o `test -f 'src/nl-cls-add.c' || echo '$(srcdir)/'`src/nl-cls-add.c + +src/nl_cls_add-nl-cls-add.obj: src/nl-cls-add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_cls_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_cls_add-nl-cls-add.obj -MD -MP -MF src/$(DEPDIR)/nl_cls_add-nl-cls-add.Tpo -c -o src/nl_cls_add-nl-cls-add.obj `if test -f 'src/nl-cls-add.c'; then $(CYGPATH_W) 'src/nl-cls-add.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-cls-add.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_cls_add-nl-cls-add.Tpo src/$(DEPDIR)/nl_cls_add-nl-cls-add.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-cls-add.c' object='src/nl_cls_add-nl-cls-add.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_cls_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_cls_add-nl-cls-add.obj `if test -f 'src/nl-cls-add.c'; then $(CYGPATH_W) 'src/nl-cls-add.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-cls-add.c'; fi` + +src/nl_cls_delete-nl-cls-delete.o: src/nl-cls-delete.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_cls_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_cls_delete-nl-cls-delete.o -MD -MP -MF src/$(DEPDIR)/nl_cls_delete-nl-cls-delete.Tpo -c -o src/nl_cls_delete-nl-cls-delete.o `test -f 'src/nl-cls-delete.c' || echo '$(srcdir)/'`src/nl-cls-delete.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_cls_delete-nl-cls-delete.Tpo src/$(DEPDIR)/nl_cls_delete-nl-cls-delete.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-cls-delete.c' object='src/nl_cls_delete-nl-cls-delete.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_cls_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_cls_delete-nl-cls-delete.o `test -f 'src/nl-cls-delete.c' || echo '$(srcdir)/'`src/nl-cls-delete.c + +src/nl_cls_delete-nl-cls-delete.obj: src/nl-cls-delete.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_cls_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_cls_delete-nl-cls-delete.obj -MD -MP -MF src/$(DEPDIR)/nl_cls_delete-nl-cls-delete.Tpo -c -o src/nl_cls_delete-nl-cls-delete.obj `if test -f 'src/nl-cls-delete.c'; then $(CYGPATH_W) 'src/nl-cls-delete.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-cls-delete.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_cls_delete-nl-cls-delete.Tpo src/$(DEPDIR)/nl_cls_delete-nl-cls-delete.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-cls-delete.c' object='src/nl_cls_delete-nl-cls-delete.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_cls_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_cls_delete-nl-cls-delete.obj `if test -f 'src/nl-cls-delete.c'; then $(CYGPATH_W) 'src/nl-cls-delete.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-cls-delete.c'; fi` + +src/nl_cls_list-nl-cls-list.o: src/nl-cls-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_cls_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_cls_list-nl-cls-list.o -MD -MP -MF src/$(DEPDIR)/nl_cls_list-nl-cls-list.Tpo -c -o src/nl_cls_list-nl-cls-list.o `test -f 'src/nl-cls-list.c' || echo '$(srcdir)/'`src/nl-cls-list.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_cls_list-nl-cls-list.Tpo src/$(DEPDIR)/nl_cls_list-nl-cls-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-cls-list.c' object='src/nl_cls_list-nl-cls-list.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_cls_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_cls_list-nl-cls-list.o `test -f 'src/nl-cls-list.c' || echo '$(srcdir)/'`src/nl-cls-list.c + +src/nl_cls_list-nl-cls-list.obj: src/nl-cls-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_cls_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_cls_list-nl-cls-list.obj -MD -MP -MF src/$(DEPDIR)/nl_cls_list-nl-cls-list.Tpo -c -o src/nl_cls_list-nl-cls-list.obj `if test -f 'src/nl-cls-list.c'; then $(CYGPATH_W) 'src/nl-cls-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-cls-list.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_cls_list-nl-cls-list.Tpo src/$(DEPDIR)/nl_cls_list-nl-cls-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-cls-list.c' object='src/nl_cls_list-nl-cls-list.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_cls_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_cls_list-nl-cls-list.obj `if test -f 'src/nl-cls-list.c'; then $(CYGPATH_W) 'src/nl-cls-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-cls-list.c'; fi` + +src/nl_fib_lookup-nl-fib-lookup.o: src/nl-fib-lookup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_fib_lookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_fib_lookup-nl-fib-lookup.o -MD -MP -MF src/$(DEPDIR)/nl_fib_lookup-nl-fib-lookup.Tpo -c -o src/nl_fib_lookup-nl-fib-lookup.o `test -f 'src/nl-fib-lookup.c' || echo '$(srcdir)/'`src/nl-fib-lookup.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_fib_lookup-nl-fib-lookup.Tpo src/$(DEPDIR)/nl_fib_lookup-nl-fib-lookup.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-fib-lookup.c' object='src/nl_fib_lookup-nl-fib-lookup.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_fib_lookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_fib_lookup-nl-fib-lookup.o `test -f 'src/nl-fib-lookup.c' || echo '$(srcdir)/'`src/nl-fib-lookup.c + +src/nl_fib_lookup-nl-fib-lookup.obj: src/nl-fib-lookup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_fib_lookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_fib_lookup-nl-fib-lookup.obj -MD -MP -MF src/$(DEPDIR)/nl_fib_lookup-nl-fib-lookup.Tpo -c -o src/nl_fib_lookup-nl-fib-lookup.obj `if test -f 'src/nl-fib-lookup.c'; then $(CYGPATH_W) 'src/nl-fib-lookup.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-fib-lookup.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_fib_lookup-nl-fib-lookup.Tpo src/$(DEPDIR)/nl_fib_lookup-nl-fib-lookup.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-fib-lookup.c' object='src/nl_fib_lookup-nl-fib-lookup.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_fib_lookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_fib_lookup-nl-fib-lookup.obj `if test -f 'src/nl-fib-lookup.c'; then $(CYGPATH_W) 'src/nl-fib-lookup.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-fib-lookup.c'; fi` + +src/nl_link_enslave-nl-link-enslave.o: src/nl-link-enslave.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_enslave_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_link_enslave-nl-link-enslave.o -MD -MP -MF src/$(DEPDIR)/nl_link_enslave-nl-link-enslave.Tpo -c -o src/nl_link_enslave-nl-link-enslave.o `test -f 'src/nl-link-enslave.c' || echo '$(srcdir)/'`src/nl-link-enslave.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_link_enslave-nl-link-enslave.Tpo src/$(DEPDIR)/nl_link_enslave-nl-link-enslave.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-link-enslave.c' object='src/nl_link_enslave-nl-link-enslave.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_enslave_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_link_enslave-nl-link-enslave.o `test -f 'src/nl-link-enslave.c' || echo '$(srcdir)/'`src/nl-link-enslave.c + +src/nl_link_enslave-nl-link-enslave.obj: src/nl-link-enslave.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_enslave_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_link_enslave-nl-link-enslave.obj -MD -MP -MF src/$(DEPDIR)/nl_link_enslave-nl-link-enslave.Tpo -c -o src/nl_link_enslave-nl-link-enslave.obj `if test -f 'src/nl-link-enslave.c'; then $(CYGPATH_W) 'src/nl-link-enslave.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-link-enslave.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_link_enslave-nl-link-enslave.Tpo src/$(DEPDIR)/nl_link_enslave-nl-link-enslave.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-link-enslave.c' object='src/nl_link_enslave-nl-link-enslave.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_enslave_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_link_enslave-nl-link-enslave.obj `if test -f 'src/nl-link-enslave.c'; then $(CYGPATH_W) 'src/nl-link-enslave.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-link-enslave.c'; fi` + +src/nl_link_ifindex2name-nl-link-ifindex2name.o: src/nl-link-ifindex2name.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_ifindex2name_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_link_ifindex2name-nl-link-ifindex2name.o -MD -MP -MF src/$(DEPDIR)/nl_link_ifindex2name-nl-link-ifindex2name.Tpo -c -o src/nl_link_ifindex2name-nl-link-ifindex2name.o `test -f 'src/nl-link-ifindex2name.c' || echo '$(srcdir)/'`src/nl-link-ifindex2name.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_link_ifindex2name-nl-link-ifindex2name.Tpo src/$(DEPDIR)/nl_link_ifindex2name-nl-link-ifindex2name.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-link-ifindex2name.c' object='src/nl_link_ifindex2name-nl-link-ifindex2name.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_ifindex2name_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_link_ifindex2name-nl-link-ifindex2name.o `test -f 'src/nl-link-ifindex2name.c' || echo '$(srcdir)/'`src/nl-link-ifindex2name.c + +src/nl_link_ifindex2name-nl-link-ifindex2name.obj: src/nl-link-ifindex2name.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_ifindex2name_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_link_ifindex2name-nl-link-ifindex2name.obj -MD -MP -MF src/$(DEPDIR)/nl_link_ifindex2name-nl-link-ifindex2name.Tpo -c -o src/nl_link_ifindex2name-nl-link-ifindex2name.obj `if test -f 'src/nl-link-ifindex2name.c'; then $(CYGPATH_W) 'src/nl-link-ifindex2name.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-link-ifindex2name.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_link_ifindex2name-nl-link-ifindex2name.Tpo src/$(DEPDIR)/nl_link_ifindex2name-nl-link-ifindex2name.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-link-ifindex2name.c' object='src/nl_link_ifindex2name-nl-link-ifindex2name.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_ifindex2name_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_link_ifindex2name-nl-link-ifindex2name.obj `if test -f 'src/nl-link-ifindex2name.c'; then $(CYGPATH_W) 'src/nl-link-ifindex2name.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-link-ifindex2name.c'; fi` + +src/nl_link_list-nl-link-list.o: src/nl-link-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_link_list-nl-link-list.o -MD -MP -MF src/$(DEPDIR)/nl_link_list-nl-link-list.Tpo -c -o src/nl_link_list-nl-link-list.o `test -f 'src/nl-link-list.c' || echo '$(srcdir)/'`src/nl-link-list.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_link_list-nl-link-list.Tpo src/$(DEPDIR)/nl_link_list-nl-link-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-link-list.c' object='src/nl_link_list-nl-link-list.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_link_list-nl-link-list.o `test -f 'src/nl-link-list.c' || echo '$(srcdir)/'`src/nl-link-list.c + +src/nl_link_list-nl-link-list.obj: src/nl-link-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_link_list-nl-link-list.obj -MD -MP -MF src/$(DEPDIR)/nl_link_list-nl-link-list.Tpo -c -o src/nl_link_list-nl-link-list.obj `if test -f 'src/nl-link-list.c'; then $(CYGPATH_W) 'src/nl-link-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-link-list.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_link_list-nl-link-list.Tpo src/$(DEPDIR)/nl_link_list-nl-link-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-link-list.c' object='src/nl_link_list-nl-link-list.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_link_list-nl-link-list.obj `if test -f 'src/nl-link-list.c'; then $(CYGPATH_W) 'src/nl-link-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-link-list.c'; fi` + +src/nl_link_name2ifindex-nl-link-name2ifindex.o: src/nl-link-name2ifindex.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_name2ifindex_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_link_name2ifindex-nl-link-name2ifindex.o -MD -MP -MF src/$(DEPDIR)/nl_link_name2ifindex-nl-link-name2ifindex.Tpo -c -o src/nl_link_name2ifindex-nl-link-name2ifindex.o `test -f 'src/nl-link-name2ifindex.c' || echo '$(srcdir)/'`src/nl-link-name2ifindex.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_link_name2ifindex-nl-link-name2ifindex.Tpo src/$(DEPDIR)/nl_link_name2ifindex-nl-link-name2ifindex.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-link-name2ifindex.c' object='src/nl_link_name2ifindex-nl-link-name2ifindex.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_name2ifindex_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_link_name2ifindex-nl-link-name2ifindex.o `test -f 'src/nl-link-name2ifindex.c' || echo '$(srcdir)/'`src/nl-link-name2ifindex.c + +src/nl_link_name2ifindex-nl-link-name2ifindex.obj: src/nl-link-name2ifindex.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_name2ifindex_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_link_name2ifindex-nl-link-name2ifindex.obj -MD -MP -MF src/$(DEPDIR)/nl_link_name2ifindex-nl-link-name2ifindex.Tpo -c -o src/nl_link_name2ifindex-nl-link-name2ifindex.obj `if test -f 'src/nl-link-name2ifindex.c'; then $(CYGPATH_W) 'src/nl-link-name2ifindex.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-link-name2ifindex.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_link_name2ifindex-nl-link-name2ifindex.Tpo src/$(DEPDIR)/nl_link_name2ifindex-nl-link-name2ifindex.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-link-name2ifindex.c' object='src/nl_link_name2ifindex-nl-link-name2ifindex.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_name2ifindex_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_link_name2ifindex-nl-link-name2ifindex.obj `if test -f 'src/nl-link-name2ifindex.c'; then $(CYGPATH_W) 'src/nl-link-name2ifindex.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-link-name2ifindex.c'; fi` + +src/nl_link_release-nl-link-release.o: src/nl-link-release.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_release_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_link_release-nl-link-release.o -MD -MP -MF src/$(DEPDIR)/nl_link_release-nl-link-release.Tpo -c -o src/nl_link_release-nl-link-release.o `test -f 'src/nl-link-release.c' || echo '$(srcdir)/'`src/nl-link-release.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_link_release-nl-link-release.Tpo src/$(DEPDIR)/nl_link_release-nl-link-release.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-link-release.c' object='src/nl_link_release-nl-link-release.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_release_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_link_release-nl-link-release.o `test -f 'src/nl-link-release.c' || echo '$(srcdir)/'`src/nl-link-release.c + +src/nl_link_release-nl-link-release.obj: src/nl-link-release.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_release_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_link_release-nl-link-release.obj -MD -MP -MF src/$(DEPDIR)/nl_link_release-nl-link-release.Tpo -c -o src/nl_link_release-nl-link-release.obj `if test -f 'src/nl-link-release.c'; then $(CYGPATH_W) 'src/nl-link-release.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-link-release.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_link_release-nl-link-release.Tpo src/$(DEPDIR)/nl_link_release-nl-link-release.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-link-release.c' object='src/nl_link_release-nl-link-release.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_release_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_link_release-nl-link-release.obj `if test -f 'src/nl-link-release.c'; then $(CYGPATH_W) 'src/nl-link-release.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-link-release.c'; fi` + +src/nl_link_set-nl-link-set.o: src/nl-link-set.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_set_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_link_set-nl-link-set.o -MD -MP -MF src/$(DEPDIR)/nl_link_set-nl-link-set.Tpo -c -o src/nl_link_set-nl-link-set.o `test -f 'src/nl-link-set.c' || echo '$(srcdir)/'`src/nl-link-set.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_link_set-nl-link-set.Tpo src/$(DEPDIR)/nl_link_set-nl-link-set.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-link-set.c' object='src/nl_link_set-nl-link-set.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_set_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_link_set-nl-link-set.o `test -f 'src/nl-link-set.c' || echo '$(srcdir)/'`src/nl-link-set.c + +src/nl_link_set-nl-link-set.obj: src/nl-link-set.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_set_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_link_set-nl-link-set.obj -MD -MP -MF src/$(DEPDIR)/nl_link_set-nl-link-set.Tpo -c -o src/nl_link_set-nl-link-set.obj `if test -f 'src/nl-link-set.c'; then $(CYGPATH_W) 'src/nl-link-set.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-link-set.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_link_set-nl-link-set.Tpo src/$(DEPDIR)/nl_link_set-nl-link-set.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-link-set.c' object='src/nl_link_set-nl-link-set.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_set_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_link_set-nl-link-set.obj `if test -f 'src/nl-link-set.c'; then $(CYGPATH_W) 'src/nl-link-set.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-link-set.c'; fi` + +src/nl_link_stats-nl-link-stats.o: src/nl-link-stats.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_stats_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_link_stats-nl-link-stats.o -MD -MP -MF src/$(DEPDIR)/nl_link_stats-nl-link-stats.Tpo -c -o src/nl_link_stats-nl-link-stats.o `test -f 'src/nl-link-stats.c' || echo '$(srcdir)/'`src/nl-link-stats.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_link_stats-nl-link-stats.Tpo src/$(DEPDIR)/nl_link_stats-nl-link-stats.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-link-stats.c' object='src/nl_link_stats-nl-link-stats.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_stats_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_link_stats-nl-link-stats.o `test -f 'src/nl-link-stats.c' || echo '$(srcdir)/'`src/nl-link-stats.c + +src/nl_link_stats-nl-link-stats.obj: src/nl-link-stats.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_stats_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_link_stats-nl-link-stats.obj -MD -MP -MF src/$(DEPDIR)/nl_link_stats-nl-link-stats.Tpo -c -o src/nl_link_stats-nl-link-stats.obj `if test -f 'src/nl-link-stats.c'; then $(CYGPATH_W) 'src/nl-link-stats.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-link-stats.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_link_stats-nl-link-stats.Tpo src/$(DEPDIR)/nl_link_stats-nl-link-stats.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-link-stats.c' object='src/nl_link_stats-nl-link-stats.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_link_stats_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_link_stats-nl-link-stats.obj `if test -f 'src/nl-link-stats.c'; then $(CYGPATH_W) 'src/nl-link-stats.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-link-stats.c'; fi` + +src/nl_list_caches-nl-list-caches.o: src/nl-list-caches.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_list_caches_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_list_caches-nl-list-caches.o -MD -MP -MF src/$(DEPDIR)/nl_list_caches-nl-list-caches.Tpo -c -o src/nl_list_caches-nl-list-caches.o `test -f 'src/nl-list-caches.c' || echo '$(srcdir)/'`src/nl-list-caches.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_list_caches-nl-list-caches.Tpo src/$(DEPDIR)/nl_list_caches-nl-list-caches.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-list-caches.c' object='src/nl_list_caches-nl-list-caches.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_list_caches_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_list_caches-nl-list-caches.o `test -f 'src/nl-list-caches.c' || echo '$(srcdir)/'`src/nl-list-caches.c + +src/nl_list_caches-nl-list-caches.obj: src/nl-list-caches.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_list_caches_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_list_caches-nl-list-caches.obj -MD -MP -MF src/$(DEPDIR)/nl_list_caches-nl-list-caches.Tpo -c -o src/nl_list_caches-nl-list-caches.obj `if test -f 'src/nl-list-caches.c'; then $(CYGPATH_W) 'src/nl-list-caches.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-list-caches.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_list_caches-nl-list-caches.Tpo src/$(DEPDIR)/nl_list_caches-nl-list-caches.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-list-caches.c' object='src/nl_list_caches-nl-list-caches.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_list_caches_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_list_caches-nl-list-caches.obj `if test -f 'src/nl-list-caches.c'; then $(CYGPATH_W) 'src/nl-list-caches.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-list-caches.c'; fi` + +src/nl_list_sockets-nl-list-sockets.o: src/nl-list-sockets.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_list_sockets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_list_sockets-nl-list-sockets.o -MD -MP -MF src/$(DEPDIR)/nl_list_sockets-nl-list-sockets.Tpo -c -o src/nl_list_sockets-nl-list-sockets.o `test -f 'src/nl-list-sockets.c' || echo '$(srcdir)/'`src/nl-list-sockets.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_list_sockets-nl-list-sockets.Tpo src/$(DEPDIR)/nl_list_sockets-nl-list-sockets.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-list-sockets.c' object='src/nl_list_sockets-nl-list-sockets.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_list_sockets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_list_sockets-nl-list-sockets.o `test -f 'src/nl-list-sockets.c' || echo '$(srcdir)/'`src/nl-list-sockets.c + +src/nl_list_sockets-nl-list-sockets.obj: src/nl-list-sockets.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_list_sockets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_list_sockets-nl-list-sockets.obj -MD -MP -MF src/$(DEPDIR)/nl_list_sockets-nl-list-sockets.Tpo -c -o src/nl_list_sockets-nl-list-sockets.obj `if test -f 'src/nl-list-sockets.c'; then $(CYGPATH_W) 'src/nl-list-sockets.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-list-sockets.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_list_sockets-nl-list-sockets.Tpo src/$(DEPDIR)/nl_list_sockets-nl-list-sockets.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-list-sockets.c' object='src/nl_list_sockets-nl-list-sockets.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_list_sockets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_list_sockets-nl-list-sockets.obj `if test -f 'src/nl-list-sockets.c'; then $(CYGPATH_W) 'src/nl-list-sockets.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-list-sockets.c'; fi` + +src/nl_monitor-nl-monitor.o: src/nl-monitor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_monitor_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_monitor-nl-monitor.o -MD -MP -MF src/$(DEPDIR)/nl_monitor-nl-monitor.Tpo -c -o src/nl_monitor-nl-monitor.o `test -f 'src/nl-monitor.c' || echo '$(srcdir)/'`src/nl-monitor.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_monitor-nl-monitor.Tpo src/$(DEPDIR)/nl_monitor-nl-monitor.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-monitor.c' object='src/nl_monitor-nl-monitor.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_monitor_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_monitor-nl-monitor.o `test -f 'src/nl-monitor.c' || echo '$(srcdir)/'`src/nl-monitor.c + +src/nl_monitor-nl-monitor.obj: src/nl-monitor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_monitor_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_monitor-nl-monitor.obj -MD -MP -MF src/$(DEPDIR)/nl_monitor-nl-monitor.Tpo -c -o src/nl_monitor-nl-monitor.obj `if test -f 'src/nl-monitor.c'; then $(CYGPATH_W) 'src/nl-monitor.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-monitor.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_monitor-nl-monitor.Tpo src/$(DEPDIR)/nl_monitor-nl-monitor.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-monitor.c' object='src/nl_monitor-nl-monitor.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_monitor_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_monitor-nl-monitor.obj `if test -f 'src/nl-monitor.c'; then $(CYGPATH_W) 'src/nl-monitor.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-monitor.c'; fi` + +src/nl_neigh_add-nl-neigh-add.o: src/nl-neigh-add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_neigh_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_neigh_add-nl-neigh-add.o -MD -MP -MF src/$(DEPDIR)/nl_neigh_add-nl-neigh-add.Tpo -c -o src/nl_neigh_add-nl-neigh-add.o `test -f 'src/nl-neigh-add.c' || echo '$(srcdir)/'`src/nl-neigh-add.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_neigh_add-nl-neigh-add.Tpo src/$(DEPDIR)/nl_neigh_add-nl-neigh-add.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-neigh-add.c' object='src/nl_neigh_add-nl-neigh-add.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_neigh_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_neigh_add-nl-neigh-add.o `test -f 'src/nl-neigh-add.c' || echo '$(srcdir)/'`src/nl-neigh-add.c + +src/nl_neigh_add-nl-neigh-add.obj: src/nl-neigh-add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_neigh_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_neigh_add-nl-neigh-add.obj -MD -MP -MF src/$(DEPDIR)/nl_neigh_add-nl-neigh-add.Tpo -c -o src/nl_neigh_add-nl-neigh-add.obj `if test -f 'src/nl-neigh-add.c'; then $(CYGPATH_W) 'src/nl-neigh-add.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-neigh-add.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_neigh_add-nl-neigh-add.Tpo src/$(DEPDIR)/nl_neigh_add-nl-neigh-add.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-neigh-add.c' object='src/nl_neigh_add-nl-neigh-add.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_neigh_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_neigh_add-nl-neigh-add.obj `if test -f 'src/nl-neigh-add.c'; then $(CYGPATH_W) 'src/nl-neigh-add.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-neigh-add.c'; fi` + +src/nl_neigh_delete-nl-neigh-delete.o: src/nl-neigh-delete.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_neigh_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_neigh_delete-nl-neigh-delete.o -MD -MP -MF src/$(DEPDIR)/nl_neigh_delete-nl-neigh-delete.Tpo -c -o src/nl_neigh_delete-nl-neigh-delete.o `test -f 'src/nl-neigh-delete.c' || echo '$(srcdir)/'`src/nl-neigh-delete.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_neigh_delete-nl-neigh-delete.Tpo src/$(DEPDIR)/nl_neigh_delete-nl-neigh-delete.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-neigh-delete.c' object='src/nl_neigh_delete-nl-neigh-delete.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_neigh_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_neigh_delete-nl-neigh-delete.o `test -f 'src/nl-neigh-delete.c' || echo '$(srcdir)/'`src/nl-neigh-delete.c + +src/nl_neigh_delete-nl-neigh-delete.obj: src/nl-neigh-delete.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_neigh_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_neigh_delete-nl-neigh-delete.obj -MD -MP -MF src/$(DEPDIR)/nl_neigh_delete-nl-neigh-delete.Tpo -c -o src/nl_neigh_delete-nl-neigh-delete.obj `if test -f 'src/nl-neigh-delete.c'; then $(CYGPATH_W) 'src/nl-neigh-delete.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-neigh-delete.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_neigh_delete-nl-neigh-delete.Tpo src/$(DEPDIR)/nl_neigh_delete-nl-neigh-delete.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-neigh-delete.c' object='src/nl_neigh_delete-nl-neigh-delete.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_neigh_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_neigh_delete-nl-neigh-delete.obj `if test -f 'src/nl-neigh-delete.c'; then $(CYGPATH_W) 'src/nl-neigh-delete.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-neigh-delete.c'; fi` + +src/nl_neigh_list-nl-neigh-list.o: src/nl-neigh-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_neigh_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_neigh_list-nl-neigh-list.o -MD -MP -MF src/$(DEPDIR)/nl_neigh_list-nl-neigh-list.Tpo -c -o src/nl_neigh_list-nl-neigh-list.o `test -f 'src/nl-neigh-list.c' || echo '$(srcdir)/'`src/nl-neigh-list.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_neigh_list-nl-neigh-list.Tpo src/$(DEPDIR)/nl_neigh_list-nl-neigh-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-neigh-list.c' object='src/nl_neigh_list-nl-neigh-list.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_neigh_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_neigh_list-nl-neigh-list.o `test -f 'src/nl-neigh-list.c' || echo '$(srcdir)/'`src/nl-neigh-list.c + +src/nl_neigh_list-nl-neigh-list.obj: src/nl-neigh-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_neigh_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_neigh_list-nl-neigh-list.obj -MD -MP -MF src/$(DEPDIR)/nl_neigh_list-nl-neigh-list.Tpo -c -o src/nl_neigh_list-nl-neigh-list.obj `if test -f 'src/nl-neigh-list.c'; then $(CYGPATH_W) 'src/nl-neigh-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-neigh-list.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_neigh_list-nl-neigh-list.Tpo src/$(DEPDIR)/nl_neigh_list-nl-neigh-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-neigh-list.c' object='src/nl_neigh_list-nl-neigh-list.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_neigh_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_neigh_list-nl-neigh-list.obj `if test -f 'src/nl-neigh-list.c'; then $(CYGPATH_W) 'src/nl-neigh-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-neigh-list.c'; fi` + +src/nl_neightbl_list-nl-neightbl-list.o: src/nl-neightbl-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_neightbl_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_neightbl_list-nl-neightbl-list.o -MD -MP -MF src/$(DEPDIR)/nl_neightbl_list-nl-neightbl-list.Tpo -c -o src/nl_neightbl_list-nl-neightbl-list.o `test -f 'src/nl-neightbl-list.c' || echo '$(srcdir)/'`src/nl-neightbl-list.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_neightbl_list-nl-neightbl-list.Tpo src/$(DEPDIR)/nl_neightbl_list-nl-neightbl-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-neightbl-list.c' object='src/nl_neightbl_list-nl-neightbl-list.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_neightbl_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_neightbl_list-nl-neightbl-list.o `test -f 'src/nl-neightbl-list.c' || echo '$(srcdir)/'`src/nl-neightbl-list.c + +src/nl_neightbl_list-nl-neightbl-list.obj: src/nl-neightbl-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_neightbl_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_neightbl_list-nl-neightbl-list.obj -MD -MP -MF src/$(DEPDIR)/nl_neightbl_list-nl-neightbl-list.Tpo -c -o src/nl_neightbl_list-nl-neightbl-list.obj `if test -f 'src/nl-neightbl-list.c'; then $(CYGPATH_W) 'src/nl-neightbl-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-neightbl-list.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_neightbl_list-nl-neightbl-list.Tpo src/$(DEPDIR)/nl_neightbl_list-nl-neightbl-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-neightbl-list.c' object='src/nl_neightbl_list-nl-neightbl-list.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_neightbl_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_neightbl_list-nl-neightbl-list.obj `if test -f 'src/nl-neightbl-list.c'; then $(CYGPATH_W) 'src/nl-neightbl-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-neightbl-list.c'; fi` + +src/nl_nh_list-nl-nh-list.o: src/nl-nh-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_nh_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_nh_list-nl-nh-list.o -MD -MP -MF src/$(DEPDIR)/nl_nh_list-nl-nh-list.Tpo -c -o src/nl_nh_list-nl-nh-list.o `test -f 'src/nl-nh-list.c' || echo '$(srcdir)/'`src/nl-nh-list.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_nh_list-nl-nh-list.Tpo src/$(DEPDIR)/nl_nh_list-nl-nh-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-nh-list.c' object='src/nl_nh_list-nl-nh-list.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_nh_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_nh_list-nl-nh-list.o `test -f 'src/nl-nh-list.c' || echo '$(srcdir)/'`src/nl-nh-list.c + +src/nl_nh_list-nl-nh-list.obj: src/nl-nh-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_nh_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_nh_list-nl-nh-list.obj -MD -MP -MF src/$(DEPDIR)/nl_nh_list-nl-nh-list.Tpo -c -o src/nl_nh_list-nl-nh-list.obj `if test -f 'src/nl-nh-list.c'; then $(CYGPATH_W) 'src/nl-nh-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-nh-list.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_nh_list-nl-nh-list.Tpo src/$(DEPDIR)/nl_nh_list-nl-nh-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-nh-list.c' object='src/nl_nh_list-nl-nh-list.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_nh_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_nh_list-nl-nh-list.obj `if test -f 'src/nl-nh-list.c'; then $(CYGPATH_W) 'src/nl-nh-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-nh-list.c'; fi` + +src/nl_pktloc_lookup-nl-pktloc-lookup.o: src/nl-pktloc-lookup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_pktloc_lookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_pktloc_lookup-nl-pktloc-lookup.o -MD -MP -MF src/$(DEPDIR)/nl_pktloc_lookup-nl-pktloc-lookup.Tpo -c -o src/nl_pktloc_lookup-nl-pktloc-lookup.o `test -f 'src/nl-pktloc-lookup.c' || echo '$(srcdir)/'`src/nl-pktloc-lookup.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_pktloc_lookup-nl-pktloc-lookup.Tpo src/$(DEPDIR)/nl_pktloc_lookup-nl-pktloc-lookup.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-pktloc-lookup.c' object='src/nl_pktloc_lookup-nl-pktloc-lookup.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_pktloc_lookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_pktloc_lookup-nl-pktloc-lookup.o `test -f 'src/nl-pktloc-lookup.c' || echo '$(srcdir)/'`src/nl-pktloc-lookup.c + +src/nl_pktloc_lookup-nl-pktloc-lookup.obj: src/nl-pktloc-lookup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_pktloc_lookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_pktloc_lookup-nl-pktloc-lookup.obj -MD -MP -MF src/$(DEPDIR)/nl_pktloc_lookup-nl-pktloc-lookup.Tpo -c -o src/nl_pktloc_lookup-nl-pktloc-lookup.obj `if test -f 'src/nl-pktloc-lookup.c'; then $(CYGPATH_W) 'src/nl-pktloc-lookup.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-pktloc-lookup.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_pktloc_lookup-nl-pktloc-lookup.Tpo src/$(DEPDIR)/nl_pktloc_lookup-nl-pktloc-lookup.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-pktloc-lookup.c' object='src/nl_pktloc_lookup-nl-pktloc-lookup.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_pktloc_lookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_pktloc_lookup-nl-pktloc-lookup.obj `if test -f 'src/nl-pktloc-lookup.c'; then $(CYGPATH_W) 'src/nl-pktloc-lookup.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-pktloc-lookup.c'; fi` + +src/nl_qdisc_add-nl-qdisc-add.o: src/nl-qdisc-add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_qdisc_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_qdisc_add-nl-qdisc-add.o -MD -MP -MF src/$(DEPDIR)/nl_qdisc_add-nl-qdisc-add.Tpo -c -o src/nl_qdisc_add-nl-qdisc-add.o `test -f 'src/nl-qdisc-add.c' || echo '$(srcdir)/'`src/nl-qdisc-add.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_qdisc_add-nl-qdisc-add.Tpo src/$(DEPDIR)/nl_qdisc_add-nl-qdisc-add.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-qdisc-add.c' object='src/nl_qdisc_add-nl-qdisc-add.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_qdisc_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_qdisc_add-nl-qdisc-add.o `test -f 'src/nl-qdisc-add.c' || echo '$(srcdir)/'`src/nl-qdisc-add.c + +src/nl_qdisc_add-nl-qdisc-add.obj: src/nl-qdisc-add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_qdisc_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_qdisc_add-nl-qdisc-add.obj -MD -MP -MF src/$(DEPDIR)/nl_qdisc_add-nl-qdisc-add.Tpo -c -o src/nl_qdisc_add-nl-qdisc-add.obj `if test -f 'src/nl-qdisc-add.c'; then $(CYGPATH_W) 'src/nl-qdisc-add.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-qdisc-add.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_qdisc_add-nl-qdisc-add.Tpo src/$(DEPDIR)/nl_qdisc_add-nl-qdisc-add.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-qdisc-add.c' object='src/nl_qdisc_add-nl-qdisc-add.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_qdisc_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_qdisc_add-nl-qdisc-add.obj `if test -f 'src/nl-qdisc-add.c'; then $(CYGPATH_W) 'src/nl-qdisc-add.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-qdisc-add.c'; fi` + +src/nl_qdisc_delete-nl-qdisc-delete.o: src/nl-qdisc-delete.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_qdisc_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_qdisc_delete-nl-qdisc-delete.o -MD -MP -MF src/$(DEPDIR)/nl_qdisc_delete-nl-qdisc-delete.Tpo -c -o src/nl_qdisc_delete-nl-qdisc-delete.o `test -f 'src/nl-qdisc-delete.c' || echo '$(srcdir)/'`src/nl-qdisc-delete.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_qdisc_delete-nl-qdisc-delete.Tpo src/$(DEPDIR)/nl_qdisc_delete-nl-qdisc-delete.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-qdisc-delete.c' object='src/nl_qdisc_delete-nl-qdisc-delete.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_qdisc_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_qdisc_delete-nl-qdisc-delete.o `test -f 'src/nl-qdisc-delete.c' || echo '$(srcdir)/'`src/nl-qdisc-delete.c + +src/nl_qdisc_delete-nl-qdisc-delete.obj: src/nl-qdisc-delete.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_qdisc_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_qdisc_delete-nl-qdisc-delete.obj -MD -MP -MF src/$(DEPDIR)/nl_qdisc_delete-nl-qdisc-delete.Tpo -c -o src/nl_qdisc_delete-nl-qdisc-delete.obj `if test -f 'src/nl-qdisc-delete.c'; then $(CYGPATH_W) 'src/nl-qdisc-delete.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-qdisc-delete.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_qdisc_delete-nl-qdisc-delete.Tpo src/$(DEPDIR)/nl_qdisc_delete-nl-qdisc-delete.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-qdisc-delete.c' object='src/nl_qdisc_delete-nl-qdisc-delete.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_qdisc_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_qdisc_delete-nl-qdisc-delete.obj `if test -f 'src/nl-qdisc-delete.c'; then $(CYGPATH_W) 'src/nl-qdisc-delete.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-qdisc-delete.c'; fi` + +src/nl_qdisc_list-nl-qdisc-list.o: src/nl-qdisc-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_qdisc_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_qdisc_list-nl-qdisc-list.o -MD -MP -MF src/$(DEPDIR)/nl_qdisc_list-nl-qdisc-list.Tpo -c -o src/nl_qdisc_list-nl-qdisc-list.o `test -f 'src/nl-qdisc-list.c' || echo '$(srcdir)/'`src/nl-qdisc-list.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_qdisc_list-nl-qdisc-list.Tpo src/$(DEPDIR)/nl_qdisc_list-nl-qdisc-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-qdisc-list.c' object='src/nl_qdisc_list-nl-qdisc-list.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_qdisc_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_qdisc_list-nl-qdisc-list.o `test -f 'src/nl-qdisc-list.c' || echo '$(srcdir)/'`src/nl-qdisc-list.c + +src/nl_qdisc_list-nl-qdisc-list.obj: src/nl-qdisc-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_qdisc_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_qdisc_list-nl-qdisc-list.obj -MD -MP -MF src/$(DEPDIR)/nl_qdisc_list-nl-qdisc-list.Tpo -c -o src/nl_qdisc_list-nl-qdisc-list.obj `if test -f 'src/nl-qdisc-list.c'; then $(CYGPATH_W) 'src/nl-qdisc-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-qdisc-list.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_qdisc_list-nl-qdisc-list.Tpo src/$(DEPDIR)/nl_qdisc_list-nl-qdisc-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-qdisc-list.c' object='src/nl_qdisc_list-nl-qdisc-list.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_qdisc_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_qdisc_list-nl-qdisc-list.obj `if test -f 'src/nl-qdisc-list.c'; then $(CYGPATH_W) 'src/nl-qdisc-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-qdisc-list.c'; fi` + +src/nl_route_add-nl-route-add.o: src/nl-route-add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_route_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_route_add-nl-route-add.o -MD -MP -MF src/$(DEPDIR)/nl_route_add-nl-route-add.Tpo -c -o src/nl_route_add-nl-route-add.o `test -f 'src/nl-route-add.c' || echo '$(srcdir)/'`src/nl-route-add.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_route_add-nl-route-add.Tpo src/$(DEPDIR)/nl_route_add-nl-route-add.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-route-add.c' object='src/nl_route_add-nl-route-add.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_route_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_route_add-nl-route-add.o `test -f 'src/nl-route-add.c' || echo '$(srcdir)/'`src/nl-route-add.c + +src/nl_route_add-nl-route-add.obj: src/nl-route-add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_route_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_route_add-nl-route-add.obj -MD -MP -MF src/$(DEPDIR)/nl_route_add-nl-route-add.Tpo -c -o src/nl_route_add-nl-route-add.obj `if test -f 'src/nl-route-add.c'; then $(CYGPATH_W) 'src/nl-route-add.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-route-add.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_route_add-nl-route-add.Tpo src/$(DEPDIR)/nl_route_add-nl-route-add.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-route-add.c' object='src/nl_route_add-nl-route-add.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_route_add_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_route_add-nl-route-add.obj `if test -f 'src/nl-route-add.c'; then $(CYGPATH_W) 'src/nl-route-add.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-route-add.c'; fi` + +src/nl_route_delete-nl-route-delete.o: src/nl-route-delete.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_route_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_route_delete-nl-route-delete.o -MD -MP -MF src/$(DEPDIR)/nl_route_delete-nl-route-delete.Tpo -c -o src/nl_route_delete-nl-route-delete.o `test -f 'src/nl-route-delete.c' || echo '$(srcdir)/'`src/nl-route-delete.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_route_delete-nl-route-delete.Tpo src/$(DEPDIR)/nl_route_delete-nl-route-delete.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-route-delete.c' object='src/nl_route_delete-nl-route-delete.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_route_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_route_delete-nl-route-delete.o `test -f 'src/nl-route-delete.c' || echo '$(srcdir)/'`src/nl-route-delete.c + +src/nl_route_delete-nl-route-delete.obj: src/nl-route-delete.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_route_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_route_delete-nl-route-delete.obj -MD -MP -MF src/$(DEPDIR)/nl_route_delete-nl-route-delete.Tpo -c -o src/nl_route_delete-nl-route-delete.obj `if test -f 'src/nl-route-delete.c'; then $(CYGPATH_W) 'src/nl-route-delete.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-route-delete.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_route_delete-nl-route-delete.Tpo src/$(DEPDIR)/nl_route_delete-nl-route-delete.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-route-delete.c' object='src/nl_route_delete-nl-route-delete.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_route_delete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_route_delete-nl-route-delete.obj `if test -f 'src/nl-route-delete.c'; then $(CYGPATH_W) 'src/nl-route-delete.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-route-delete.c'; fi` + +src/nl_route_get-nl-route-get.o: src/nl-route-get.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_route_get_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_route_get-nl-route-get.o -MD -MP -MF src/$(DEPDIR)/nl_route_get-nl-route-get.Tpo -c -o src/nl_route_get-nl-route-get.o `test -f 'src/nl-route-get.c' || echo '$(srcdir)/'`src/nl-route-get.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_route_get-nl-route-get.Tpo src/$(DEPDIR)/nl_route_get-nl-route-get.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-route-get.c' object='src/nl_route_get-nl-route-get.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_route_get_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_route_get-nl-route-get.o `test -f 'src/nl-route-get.c' || echo '$(srcdir)/'`src/nl-route-get.c + +src/nl_route_get-nl-route-get.obj: src/nl-route-get.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_route_get_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_route_get-nl-route-get.obj -MD -MP -MF src/$(DEPDIR)/nl_route_get-nl-route-get.Tpo -c -o src/nl_route_get-nl-route-get.obj `if test -f 'src/nl-route-get.c'; then $(CYGPATH_W) 'src/nl-route-get.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-route-get.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_route_get-nl-route-get.Tpo src/$(DEPDIR)/nl_route_get-nl-route-get.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-route-get.c' object='src/nl_route_get-nl-route-get.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_route_get_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_route_get-nl-route-get.obj `if test -f 'src/nl-route-get.c'; then $(CYGPATH_W) 'src/nl-route-get.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-route-get.c'; fi` + +src/nl_route_list-nl-route-list.o: src/nl-route-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_route_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_route_list-nl-route-list.o -MD -MP -MF src/$(DEPDIR)/nl_route_list-nl-route-list.Tpo -c -o src/nl_route_list-nl-route-list.o `test -f 'src/nl-route-list.c' || echo '$(srcdir)/'`src/nl-route-list.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_route_list-nl-route-list.Tpo src/$(DEPDIR)/nl_route_list-nl-route-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-route-list.c' object='src/nl_route_list-nl-route-list.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_route_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_route_list-nl-route-list.o `test -f 'src/nl-route-list.c' || echo '$(srcdir)/'`src/nl-route-list.c + +src/nl_route_list-nl-route-list.obj: src/nl-route-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_route_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_route_list-nl-route-list.obj -MD -MP -MF src/$(DEPDIR)/nl_route_list-nl-route-list.Tpo -c -o src/nl_route_list-nl-route-list.obj `if test -f 'src/nl-route-list.c'; then $(CYGPATH_W) 'src/nl-route-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-route-list.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_route_list-nl-route-list.Tpo src/$(DEPDIR)/nl_route_list-nl-route-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-route-list.c' object='src/nl_route_list-nl-route-list.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_route_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_route_list-nl-route-list.obj `if test -f 'src/nl-route-list.c'; then $(CYGPATH_W) 'src/nl-route-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-route-list.c'; fi` + +src/nl_rule_list-nl-rule-list.o: src/nl-rule-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_rule_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_rule_list-nl-rule-list.o -MD -MP -MF src/$(DEPDIR)/nl_rule_list-nl-rule-list.Tpo -c -o src/nl_rule_list-nl-rule-list.o `test -f 'src/nl-rule-list.c' || echo '$(srcdir)/'`src/nl-rule-list.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_rule_list-nl-rule-list.Tpo src/$(DEPDIR)/nl_rule_list-nl-rule-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-rule-list.c' object='src/nl_rule_list-nl-rule-list.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_rule_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_rule_list-nl-rule-list.o `test -f 'src/nl-rule-list.c' || echo '$(srcdir)/'`src/nl-rule-list.c + +src/nl_rule_list-nl-rule-list.obj: src/nl-rule-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_rule_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_rule_list-nl-rule-list.obj -MD -MP -MF src/$(DEPDIR)/nl_rule_list-nl-rule-list.Tpo -c -o src/nl_rule_list-nl-rule-list.obj `if test -f 'src/nl-rule-list.c'; then $(CYGPATH_W) 'src/nl-rule-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-rule-list.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_rule_list-nl-rule-list.Tpo src/$(DEPDIR)/nl_rule_list-nl-rule-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-rule-list.c' object='src/nl_rule_list-nl-rule-list.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_rule_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_rule_list-nl-rule-list.obj `if test -f 'src/nl-rule-list.c'; then $(CYGPATH_W) 'src/nl-rule-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-rule-list.c'; fi` + +src/nl_tctree_list-nl-tctree-list.o: src/nl-tctree-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_tctree_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_tctree_list-nl-tctree-list.o -MD -MP -MF src/$(DEPDIR)/nl_tctree_list-nl-tctree-list.Tpo -c -o src/nl_tctree_list-nl-tctree-list.o `test -f 'src/nl-tctree-list.c' || echo '$(srcdir)/'`src/nl-tctree-list.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_tctree_list-nl-tctree-list.Tpo src/$(DEPDIR)/nl_tctree_list-nl-tctree-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-tctree-list.c' object='src/nl_tctree_list-nl-tctree-list.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_tctree_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_tctree_list-nl-tctree-list.o `test -f 'src/nl-tctree-list.c' || echo '$(srcdir)/'`src/nl-tctree-list.c + +src/nl_tctree_list-nl-tctree-list.obj: src/nl-tctree-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_tctree_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_tctree_list-nl-tctree-list.obj -MD -MP -MF src/$(DEPDIR)/nl_tctree_list-nl-tctree-list.Tpo -c -o src/nl_tctree_list-nl-tctree-list.obj `if test -f 'src/nl-tctree-list.c'; then $(CYGPATH_W) 'src/nl-tctree-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-tctree-list.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_tctree_list-nl-tctree-list.Tpo src/$(DEPDIR)/nl_tctree_list-nl-tctree-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-tctree-list.c' object='src/nl_tctree_list-nl-tctree-list.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_tctree_list_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_tctree_list-nl-tctree-list.obj `if test -f 'src/nl-tctree-list.c'; then $(CYGPATH_W) 'src/nl-tctree-list.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-tctree-list.c'; fi` + +src/nl_util_addr-nl-util-addr.o: src/nl-util-addr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_util_addr_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_util_addr-nl-util-addr.o -MD -MP -MF src/$(DEPDIR)/nl_util_addr-nl-util-addr.Tpo -c -o src/nl_util_addr-nl-util-addr.o `test -f 'src/nl-util-addr.c' || echo '$(srcdir)/'`src/nl-util-addr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_util_addr-nl-util-addr.Tpo src/$(DEPDIR)/nl_util_addr-nl-util-addr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-util-addr.c' object='src/nl_util_addr-nl-util-addr.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_util_addr_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_util_addr-nl-util-addr.o `test -f 'src/nl-util-addr.c' || echo '$(srcdir)/'`src/nl-util-addr.c + +src/nl_util_addr-nl-util-addr.obj: src/nl-util-addr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_util_addr_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/nl_util_addr-nl-util-addr.obj -MD -MP -MF src/$(DEPDIR)/nl_util_addr-nl-util-addr.Tpo -c -o src/nl_util_addr-nl-util-addr.obj `if test -f 'src/nl-util-addr.c'; then $(CYGPATH_W) 'src/nl-util-addr.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-util-addr.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/nl_util_addr-nl-util-addr.Tpo src/$(DEPDIR)/nl_util_addr-nl-util-addr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/nl-util-addr.c' object='src/nl_util_addr-nl-util-addr.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_nl_util_addr_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/nl_util_addr-nl-util-addr.obj `if test -f 'src/nl-util-addr.c'; then $(CYGPATH_W) 'src/nl-util-addr.c'; else $(CYGPATH_W) '$(srcdir)/src/nl-util-addr.c'; fi` + +tests/check_all-check-all.o: tests/check-all.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/check_all-check-all.o -MD -MP -MF tests/$(DEPDIR)/check_all-check-all.Tpo -c -o tests/check_all-check-all.o `test -f 'tests/check-all.c' || echo '$(srcdir)/'`tests/check-all.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/check_all-check-all.Tpo tests/$(DEPDIR)/check_all-check-all.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/check-all.c' object='tests/check_all-check-all.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/check_all-check-all.o `test -f 'tests/check-all.c' || echo '$(srcdir)/'`tests/check-all.c + +tests/check_all-check-all.obj: tests/check-all.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/check_all-check-all.obj -MD -MP -MF tests/$(DEPDIR)/check_all-check-all.Tpo -c -o tests/check_all-check-all.obj `if test -f 'tests/check-all.c'; then $(CYGPATH_W) 'tests/check-all.c'; else $(CYGPATH_W) '$(srcdir)/tests/check-all.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/check_all-check-all.Tpo tests/$(DEPDIR)/check_all-check-all.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/check-all.c' object='tests/check_all-check-all.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/check_all-check-all.obj `if test -f 'tests/check-all.c'; then $(CYGPATH_W) 'tests/check-all.c'; else $(CYGPATH_W) '$(srcdir)/tests/check-all.c'; fi` + +tests/check_all-cksuite-all-addr.o: tests/cksuite-all-addr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/check_all-cksuite-all-addr.o -MD -MP -MF tests/$(DEPDIR)/check_all-cksuite-all-addr.Tpo -c -o tests/check_all-cksuite-all-addr.o `test -f 'tests/cksuite-all-addr.c' || echo '$(srcdir)/'`tests/cksuite-all-addr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/check_all-cksuite-all-addr.Tpo tests/$(DEPDIR)/check_all-cksuite-all-addr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/cksuite-all-addr.c' object='tests/check_all-cksuite-all-addr.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/check_all-cksuite-all-addr.o `test -f 'tests/cksuite-all-addr.c' || echo '$(srcdir)/'`tests/cksuite-all-addr.c + +tests/check_all-cksuite-all-addr.obj: tests/cksuite-all-addr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/check_all-cksuite-all-addr.obj -MD -MP -MF tests/$(DEPDIR)/check_all-cksuite-all-addr.Tpo -c -o tests/check_all-cksuite-all-addr.obj `if test -f 'tests/cksuite-all-addr.c'; then $(CYGPATH_W) 'tests/cksuite-all-addr.c'; else $(CYGPATH_W) '$(srcdir)/tests/cksuite-all-addr.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/check_all-cksuite-all-addr.Tpo tests/$(DEPDIR)/check_all-cksuite-all-addr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/cksuite-all-addr.c' object='tests/check_all-cksuite-all-addr.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/check_all-cksuite-all-addr.obj `if test -f 'tests/cksuite-all-addr.c'; then $(CYGPATH_W) 'tests/cksuite-all-addr.c'; else $(CYGPATH_W) '$(srcdir)/tests/cksuite-all-addr.c'; fi` + +tests/check_all-cksuite-all-attr.o: tests/cksuite-all-attr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/check_all-cksuite-all-attr.o -MD -MP -MF tests/$(DEPDIR)/check_all-cksuite-all-attr.Tpo -c -o tests/check_all-cksuite-all-attr.o `test -f 'tests/cksuite-all-attr.c' || echo '$(srcdir)/'`tests/cksuite-all-attr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/check_all-cksuite-all-attr.Tpo tests/$(DEPDIR)/check_all-cksuite-all-attr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/cksuite-all-attr.c' object='tests/check_all-cksuite-all-attr.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/check_all-cksuite-all-attr.o `test -f 'tests/cksuite-all-attr.c' || echo '$(srcdir)/'`tests/cksuite-all-attr.c + +tests/check_all-cksuite-all-attr.obj: tests/cksuite-all-attr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/check_all-cksuite-all-attr.obj -MD -MP -MF tests/$(DEPDIR)/check_all-cksuite-all-attr.Tpo -c -o tests/check_all-cksuite-all-attr.obj `if test -f 'tests/cksuite-all-attr.c'; then $(CYGPATH_W) 'tests/cksuite-all-attr.c'; else $(CYGPATH_W) '$(srcdir)/tests/cksuite-all-attr.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/check_all-cksuite-all-attr.Tpo tests/$(DEPDIR)/check_all-cksuite-all-attr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/cksuite-all-attr.c' object='tests/check_all-cksuite-all-attr.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/check_all-cksuite-all-attr.obj `if test -f 'tests/cksuite-all-attr.c'; then $(CYGPATH_W) 'tests/cksuite-all-attr.c'; else $(CYGPATH_W) '$(srcdir)/tests/cksuite-all-attr.c'; fi` + +tests/check_all-cksuite-all-ematch-tree-clone.o: tests/cksuite-all-ematch-tree-clone.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/check_all-cksuite-all-ematch-tree-clone.o -MD -MP -MF tests/$(DEPDIR)/check_all-cksuite-all-ematch-tree-clone.Tpo -c -o tests/check_all-cksuite-all-ematch-tree-clone.o `test -f 'tests/cksuite-all-ematch-tree-clone.c' || echo '$(srcdir)/'`tests/cksuite-all-ematch-tree-clone.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/check_all-cksuite-all-ematch-tree-clone.Tpo tests/$(DEPDIR)/check_all-cksuite-all-ematch-tree-clone.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/cksuite-all-ematch-tree-clone.c' object='tests/check_all-cksuite-all-ematch-tree-clone.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/check_all-cksuite-all-ematch-tree-clone.o `test -f 'tests/cksuite-all-ematch-tree-clone.c' || echo '$(srcdir)/'`tests/cksuite-all-ematch-tree-clone.c + +tests/check_all-cksuite-all-ematch-tree-clone.obj: tests/cksuite-all-ematch-tree-clone.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/check_all-cksuite-all-ematch-tree-clone.obj -MD -MP -MF tests/$(DEPDIR)/check_all-cksuite-all-ematch-tree-clone.Tpo -c -o tests/check_all-cksuite-all-ematch-tree-clone.obj `if test -f 'tests/cksuite-all-ematch-tree-clone.c'; then $(CYGPATH_W) 'tests/cksuite-all-ematch-tree-clone.c'; else $(CYGPATH_W) '$(srcdir)/tests/cksuite-all-ematch-tree-clone.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/check_all-cksuite-all-ematch-tree-clone.Tpo tests/$(DEPDIR)/check_all-cksuite-all-ematch-tree-clone.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/cksuite-all-ematch-tree-clone.c' object='tests/check_all-cksuite-all-ematch-tree-clone.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/check_all-cksuite-all-ematch-tree-clone.obj `if test -f 'tests/cksuite-all-ematch-tree-clone.c'; then $(CYGPATH_W) 'tests/cksuite-all-ematch-tree-clone.c'; else $(CYGPATH_W) '$(srcdir)/tests/cksuite-all-ematch-tree-clone.c'; fi` + +tests/check_all-cksuite-all-netns.o: tests/cksuite-all-netns.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/check_all-cksuite-all-netns.o -MD -MP -MF tests/$(DEPDIR)/check_all-cksuite-all-netns.Tpo -c -o tests/check_all-cksuite-all-netns.o `test -f 'tests/cksuite-all-netns.c' || echo '$(srcdir)/'`tests/cksuite-all-netns.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/check_all-cksuite-all-netns.Tpo tests/$(DEPDIR)/check_all-cksuite-all-netns.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/cksuite-all-netns.c' object='tests/check_all-cksuite-all-netns.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/check_all-cksuite-all-netns.o `test -f 'tests/cksuite-all-netns.c' || echo '$(srcdir)/'`tests/cksuite-all-netns.c + +tests/check_all-cksuite-all-netns.obj: tests/cksuite-all-netns.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/check_all-cksuite-all-netns.obj -MD -MP -MF tests/$(DEPDIR)/check_all-cksuite-all-netns.Tpo -c -o tests/check_all-cksuite-all-netns.obj `if test -f 'tests/cksuite-all-netns.c'; then $(CYGPATH_W) 'tests/cksuite-all-netns.c'; else $(CYGPATH_W) '$(srcdir)/tests/cksuite-all-netns.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/check_all-cksuite-all-netns.Tpo tests/$(DEPDIR)/check_all-cksuite-all-netns.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/cksuite-all-netns.c' object='tests/check_all-cksuite-all-netns.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_all_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/check_all-cksuite-all-netns.obj `if test -f 'tests/cksuite-all-netns.c'; then $(CYGPATH_W) 'tests/cksuite-all-netns.c'; else $(CYGPATH_W) '$(srcdir)/tests/cksuite-all-netns.c'; fi` + +tests/check_direct-check-direct.o: tests/check-direct.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_direct_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/check_direct-check-direct.o -MD -MP -MF tests/$(DEPDIR)/check_direct-check-direct.Tpo -c -o tests/check_direct-check-direct.o `test -f 'tests/check-direct.c' || echo '$(srcdir)/'`tests/check-direct.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/check_direct-check-direct.Tpo tests/$(DEPDIR)/check_direct-check-direct.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/check-direct.c' object='tests/check_direct-check-direct.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_direct_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/check_direct-check-direct.o `test -f 'tests/check-direct.c' || echo '$(srcdir)/'`tests/check-direct.c + +tests/check_direct-check-direct.obj: tests/check-direct.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_direct_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/check_direct-check-direct.obj -MD -MP -MF tests/$(DEPDIR)/check_direct-check-direct.Tpo -c -o tests/check_direct-check-direct.obj `if test -f 'tests/check-direct.c'; then $(CYGPATH_W) 'tests/check-direct.c'; else $(CYGPATH_W) '$(srcdir)/tests/check-direct.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/check_direct-check-direct.Tpo tests/$(DEPDIR)/check_direct-check-direct.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/check-direct.c' object='tests/check_direct-check-direct.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_check_direct_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/check_direct-check-direct.obj `if test -f 'tests/check-direct.c'; then $(CYGPATH_W) 'tests/check-direct.c'; else $(CYGPATH_W) '$(srcdir)/tests/check-direct.c'; fi` + +tests/test_cache_mngr-test-cache-mngr.o: tests/test-cache-mngr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_cache_mngr_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_cache_mngr-test-cache-mngr.o -MD -MP -MF tests/$(DEPDIR)/test_cache_mngr-test-cache-mngr.Tpo -c -o tests/test_cache_mngr-test-cache-mngr.o `test -f 'tests/test-cache-mngr.c' || echo '$(srcdir)/'`tests/test-cache-mngr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_cache_mngr-test-cache-mngr.Tpo tests/$(DEPDIR)/test_cache_mngr-test-cache-mngr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-cache-mngr.c' object='tests/test_cache_mngr-test-cache-mngr.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_cache_mngr_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_cache_mngr-test-cache-mngr.o `test -f 'tests/test-cache-mngr.c' || echo '$(srcdir)/'`tests/test-cache-mngr.c + +tests/test_cache_mngr-test-cache-mngr.obj: tests/test-cache-mngr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_cache_mngr_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_cache_mngr-test-cache-mngr.obj -MD -MP -MF tests/$(DEPDIR)/test_cache_mngr-test-cache-mngr.Tpo -c -o tests/test_cache_mngr-test-cache-mngr.obj `if test -f 'tests/test-cache-mngr.c'; then $(CYGPATH_W) 'tests/test-cache-mngr.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-cache-mngr.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_cache_mngr-test-cache-mngr.Tpo tests/$(DEPDIR)/test_cache_mngr-test-cache-mngr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-cache-mngr.c' object='tests/test_cache_mngr-test-cache-mngr.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_cache_mngr_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_cache_mngr-test-cache-mngr.obj `if test -f 'tests/test-cache-mngr.c'; then $(CYGPATH_W) 'tests/test-cache-mngr.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-cache-mngr.c'; fi` + +tests/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.o: tests/test-complex-HTB-with-hash-filters.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_complex_HTB_with_hash_filters_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.o -MD -MP -MF tests/$(DEPDIR)/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.Tpo -c -o tests/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.o `test -f 'tests/test-complex-HTB-with-hash-filters.c' || echo '$(srcdir)/'`tests/test-complex-HTB-with-hash-filters.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.Tpo tests/$(DEPDIR)/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-complex-HTB-with-hash-filters.c' object='tests/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_complex_HTB_with_hash_filters_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.o `test -f 'tests/test-complex-HTB-with-hash-filters.c' || echo '$(srcdir)/'`tests/test-complex-HTB-with-hash-filters.c + +tests/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.obj: tests/test-complex-HTB-with-hash-filters.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_complex_HTB_with_hash_filters_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.obj -MD -MP -MF tests/$(DEPDIR)/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.Tpo -c -o tests/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.obj `if test -f 'tests/test-complex-HTB-with-hash-filters.c'; then $(CYGPATH_W) 'tests/test-complex-HTB-with-hash-filters.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-complex-HTB-with-hash-filters.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.Tpo tests/$(DEPDIR)/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-complex-HTB-with-hash-filters.c' object='tests/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_complex_HTB_with_hash_filters_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.obj `if test -f 'tests/test-complex-HTB-with-hash-filters.c'; then $(CYGPATH_W) 'tests/test-complex-HTB-with-hash-filters.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-complex-HTB-with-hash-filters.c'; fi` + +tests/test_create_bond-test-create-bond.o: tests/test-create-bond.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_bond_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_bond-test-create-bond.o -MD -MP -MF tests/$(DEPDIR)/test_create_bond-test-create-bond.Tpo -c -o tests/test_create_bond-test-create-bond.o `test -f 'tests/test-create-bond.c' || echo '$(srcdir)/'`tests/test-create-bond.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_bond-test-create-bond.Tpo tests/$(DEPDIR)/test_create_bond-test-create-bond.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-bond.c' object='tests/test_create_bond-test-create-bond.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_bond_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_bond-test-create-bond.o `test -f 'tests/test-create-bond.c' || echo '$(srcdir)/'`tests/test-create-bond.c + +tests/test_create_bond-test-create-bond.obj: tests/test-create-bond.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_bond_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_bond-test-create-bond.obj -MD -MP -MF tests/$(DEPDIR)/test_create_bond-test-create-bond.Tpo -c -o tests/test_create_bond-test-create-bond.obj `if test -f 'tests/test-create-bond.c'; then $(CYGPATH_W) 'tests/test-create-bond.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-bond.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_bond-test-create-bond.Tpo tests/$(DEPDIR)/test_create_bond-test-create-bond.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-bond.c' object='tests/test_create_bond-test-create-bond.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_bond_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_bond-test-create-bond.obj `if test -f 'tests/test-create-bond.c'; then $(CYGPATH_W) 'tests/test-create-bond.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-bond.c'; fi` + +tests/test_create_bridge-test-create-bridge.o: tests/test-create-bridge.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_bridge_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_bridge-test-create-bridge.o -MD -MP -MF tests/$(DEPDIR)/test_create_bridge-test-create-bridge.Tpo -c -o tests/test_create_bridge-test-create-bridge.o `test -f 'tests/test-create-bridge.c' || echo '$(srcdir)/'`tests/test-create-bridge.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_bridge-test-create-bridge.Tpo tests/$(DEPDIR)/test_create_bridge-test-create-bridge.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-bridge.c' object='tests/test_create_bridge-test-create-bridge.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_bridge_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_bridge-test-create-bridge.o `test -f 'tests/test-create-bridge.c' || echo '$(srcdir)/'`tests/test-create-bridge.c + +tests/test_create_bridge-test-create-bridge.obj: tests/test-create-bridge.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_bridge_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_bridge-test-create-bridge.obj -MD -MP -MF tests/$(DEPDIR)/test_create_bridge-test-create-bridge.Tpo -c -o tests/test_create_bridge-test-create-bridge.obj `if test -f 'tests/test-create-bridge.c'; then $(CYGPATH_W) 'tests/test-create-bridge.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-bridge.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_bridge-test-create-bridge.Tpo tests/$(DEPDIR)/test_create_bridge-test-create-bridge.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-bridge.c' object='tests/test_create_bridge-test-create-bridge.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_bridge_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_bridge-test-create-bridge.obj `if test -f 'tests/test-create-bridge.c'; then $(CYGPATH_W) 'tests/test-create-bridge.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-bridge.c'; fi` + +tests/test_create_geneve-test-create-geneve.o: tests/test-create-geneve.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_geneve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_geneve-test-create-geneve.o -MD -MP -MF tests/$(DEPDIR)/test_create_geneve-test-create-geneve.Tpo -c -o tests/test_create_geneve-test-create-geneve.o `test -f 'tests/test-create-geneve.c' || echo '$(srcdir)/'`tests/test-create-geneve.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_geneve-test-create-geneve.Tpo tests/$(DEPDIR)/test_create_geneve-test-create-geneve.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-geneve.c' object='tests/test_create_geneve-test-create-geneve.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_geneve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_geneve-test-create-geneve.o `test -f 'tests/test-create-geneve.c' || echo '$(srcdir)/'`tests/test-create-geneve.c + +tests/test_create_geneve-test-create-geneve.obj: tests/test-create-geneve.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_geneve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_geneve-test-create-geneve.obj -MD -MP -MF tests/$(DEPDIR)/test_create_geneve-test-create-geneve.Tpo -c -o tests/test_create_geneve-test-create-geneve.obj `if test -f 'tests/test-create-geneve.c'; then $(CYGPATH_W) 'tests/test-create-geneve.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-geneve.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_geneve-test-create-geneve.Tpo tests/$(DEPDIR)/test_create_geneve-test-create-geneve.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-geneve.c' object='tests/test_create_geneve-test-create-geneve.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_geneve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_geneve-test-create-geneve.obj `if test -f 'tests/test-create-geneve.c'; then $(CYGPATH_W) 'tests/test-create-geneve.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-geneve.c'; fi` + +tests/test_create_ifb-test-create-ifb.o: tests/test-create-ifb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ifb_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_ifb-test-create-ifb.o -MD -MP -MF tests/$(DEPDIR)/test_create_ifb-test-create-ifb.Tpo -c -o tests/test_create_ifb-test-create-ifb.o `test -f 'tests/test-create-ifb.c' || echo '$(srcdir)/'`tests/test-create-ifb.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_ifb-test-create-ifb.Tpo tests/$(DEPDIR)/test_create_ifb-test-create-ifb.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-ifb.c' object='tests/test_create_ifb-test-create-ifb.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ifb_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_ifb-test-create-ifb.o `test -f 'tests/test-create-ifb.c' || echo '$(srcdir)/'`tests/test-create-ifb.c + +tests/test_create_ifb-test-create-ifb.obj: tests/test-create-ifb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ifb_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_ifb-test-create-ifb.obj -MD -MP -MF tests/$(DEPDIR)/test_create_ifb-test-create-ifb.Tpo -c -o tests/test_create_ifb-test-create-ifb.obj `if test -f 'tests/test-create-ifb.c'; then $(CYGPATH_W) 'tests/test-create-ifb.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-ifb.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_ifb-test-create-ifb.Tpo tests/$(DEPDIR)/test_create_ifb-test-create-ifb.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-ifb.c' object='tests/test_create_ifb-test-create-ifb.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ifb_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_ifb-test-create-ifb.obj `if test -f 'tests/test-create-ifb.c'; then $(CYGPATH_W) 'tests/test-create-ifb.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-ifb.c'; fi` + +tests/test_create_ip6tnl-test-create-ip6tnl.o: tests/test-create-ip6tnl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ip6tnl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_ip6tnl-test-create-ip6tnl.o -MD -MP -MF tests/$(DEPDIR)/test_create_ip6tnl-test-create-ip6tnl.Tpo -c -o tests/test_create_ip6tnl-test-create-ip6tnl.o `test -f 'tests/test-create-ip6tnl.c' || echo '$(srcdir)/'`tests/test-create-ip6tnl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_ip6tnl-test-create-ip6tnl.Tpo tests/$(DEPDIR)/test_create_ip6tnl-test-create-ip6tnl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-ip6tnl.c' object='tests/test_create_ip6tnl-test-create-ip6tnl.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ip6tnl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_ip6tnl-test-create-ip6tnl.o `test -f 'tests/test-create-ip6tnl.c' || echo '$(srcdir)/'`tests/test-create-ip6tnl.c + +tests/test_create_ip6tnl-test-create-ip6tnl.obj: tests/test-create-ip6tnl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ip6tnl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_ip6tnl-test-create-ip6tnl.obj -MD -MP -MF tests/$(DEPDIR)/test_create_ip6tnl-test-create-ip6tnl.Tpo -c -o tests/test_create_ip6tnl-test-create-ip6tnl.obj `if test -f 'tests/test-create-ip6tnl.c'; then $(CYGPATH_W) 'tests/test-create-ip6tnl.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-ip6tnl.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_ip6tnl-test-create-ip6tnl.Tpo tests/$(DEPDIR)/test_create_ip6tnl-test-create-ip6tnl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-ip6tnl.c' object='tests/test_create_ip6tnl-test-create-ip6tnl.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ip6tnl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_ip6tnl-test-create-ip6tnl.obj `if test -f 'tests/test-create-ip6tnl.c'; then $(CYGPATH_W) 'tests/test-create-ip6tnl.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-ip6tnl.c'; fi` + +tests/test_create_ipgre-test-create-ipgre.o: tests/test-create-ipgre.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipgre_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_ipgre-test-create-ipgre.o -MD -MP -MF tests/$(DEPDIR)/test_create_ipgre-test-create-ipgre.Tpo -c -o tests/test_create_ipgre-test-create-ipgre.o `test -f 'tests/test-create-ipgre.c' || echo '$(srcdir)/'`tests/test-create-ipgre.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_ipgre-test-create-ipgre.Tpo tests/$(DEPDIR)/test_create_ipgre-test-create-ipgre.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-ipgre.c' object='tests/test_create_ipgre-test-create-ipgre.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipgre_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_ipgre-test-create-ipgre.o `test -f 'tests/test-create-ipgre.c' || echo '$(srcdir)/'`tests/test-create-ipgre.c + +tests/test_create_ipgre-test-create-ipgre.obj: tests/test-create-ipgre.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipgre_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_ipgre-test-create-ipgre.obj -MD -MP -MF tests/$(DEPDIR)/test_create_ipgre-test-create-ipgre.Tpo -c -o tests/test_create_ipgre-test-create-ipgre.obj `if test -f 'tests/test-create-ipgre.c'; then $(CYGPATH_W) 'tests/test-create-ipgre.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-ipgre.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_ipgre-test-create-ipgre.Tpo tests/$(DEPDIR)/test_create_ipgre-test-create-ipgre.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-ipgre.c' object='tests/test_create_ipgre-test-create-ipgre.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipgre_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_ipgre-test-create-ipgre.obj `if test -f 'tests/test-create-ipgre.c'; then $(CYGPATH_W) 'tests/test-create-ipgre.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-ipgre.c'; fi` + +tests/test_create_ipgretap-test-create-ipgretap.o: tests/test-create-ipgretap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipgretap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_ipgretap-test-create-ipgretap.o -MD -MP -MF tests/$(DEPDIR)/test_create_ipgretap-test-create-ipgretap.Tpo -c -o tests/test_create_ipgretap-test-create-ipgretap.o `test -f 'tests/test-create-ipgretap.c' || echo '$(srcdir)/'`tests/test-create-ipgretap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_ipgretap-test-create-ipgretap.Tpo tests/$(DEPDIR)/test_create_ipgretap-test-create-ipgretap.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-ipgretap.c' object='tests/test_create_ipgretap-test-create-ipgretap.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipgretap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_ipgretap-test-create-ipgretap.o `test -f 'tests/test-create-ipgretap.c' || echo '$(srcdir)/'`tests/test-create-ipgretap.c + +tests/test_create_ipgretap-test-create-ipgretap.obj: tests/test-create-ipgretap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipgretap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_ipgretap-test-create-ipgretap.obj -MD -MP -MF tests/$(DEPDIR)/test_create_ipgretap-test-create-ipgretap.Tpo -c -o tests/test_create_ipgretap-test-create-ipgretap.obj `if test -f 'tests/test-create-ipgretap.c'; then $(CYGPATH_W) 'tests/test-create-ipgretap.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-ipgretap.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_ipgretap-test-create-ipgretap.Tpo tests/$(DEPDIR)/test_create_ipgretap-test-create-ipgretap.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-ipgretap.c' object='tests/test_create_ipgretap-test-create-ipgretap.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipgretap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_ipgretap-test-create-ipgretap.obj `if test -f 'tests/test-create-ipgretap.c'; then $(CYGPATH_W) 'tests/test-create-ipgretap.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-ipgretap.c'; fi` + +tests/test_create_ipip-test-create-ipip.o: tests/test-create-ipip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipip_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_ipip-test-create-ipip.o -MD -MP -MF tests/$(DEPDIR)/test_create_ipip-test-create-ipip.Tpo -c -o tests/test_create_ipip-test-create-ipip.o `test -f 'tests/test-create-ipip.c' || echo '$(srcdir)/'`tests/test-create-ipip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_ipip-test-create-ipip.Tpo tests/$(DEPDIR)/test_create_ipip-test-create-ipip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-ipip.c' object='tests/test_create_ipip-test-create-ipip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipip_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_ipip-test-create-ipip.o `test -f 'tests/test-create-ipip.c' || echo '$(srcdir)/'`tests/test-create-ipip.c + +tests/test_create_ipip-test-create-ipip.obj: tests/test-create-ipip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipip_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_ipip-test-create-ipip.obj -MD -MP -MF tests/$(DEPDIR)/test_create_ipip-test-create-ipip.Tpo -c -o tests/test_create_ipip-test-create-ipip.obj `if test -f 'tests/test-create-ipip.c'; then $(CYGPATH_W) 'tests/test-create-ipip.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-ipip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_ipip-test-create-ipip.Tpo tests/$(DEPDIR)/test_create_ipip-test-create-ipip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-ipip.c' object='tests/test_create_ipip-test-create-ipip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipip_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_ipip-test-create-ipip.obj `if test -f 'tests/test-create-ipip.c'; then $(CYGPATH_W) 'tests/test-create-ipip.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-ipip.c'; fi` + +tests/test_create_ipvlan-test-create-ipvlan.o: tests/test-create-ipvlan.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipvlan_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_ipvlan-test-create-ipvlan.o -MD -MP -MF tests/$(DEPDIR)/test_create_ipvlan-test-create-ipvlan.Tpo -c -o tests/test_create_ipvlan-test-create-ipvlan.o `test -f 'tests/test-create-ipvlan.c' || echo '$(srcdir)/'`tests/test-create-ipvlan.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_ipvlan-test-create-ipvlan.Tpo tests/$(DEPDIR)/test_create_ipvlan-test-create-ipvlan.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-ipvlan.c' object='tests/test_create_ipvlan-test-create-ipvlan.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipvlan_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_ipvlan-test-create-ipvlan.o `test -f 'tests/test-create-ipvlan.c' || echo '$(srcdir)/'`tests/test-create-ipvlan.c + +tests/test_create_ipvlan-test-create-ipvlan.obj: tests/test-create-ipvlan.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipvlan_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_ipvlan-test-create-ipvlan.obj -MD -MP -MF tests/$(DEPDIR)/test_create_ipvlan-test-create-ipvlan.Tpo -c -o tests/test_create_ipvlan-test-create-ipvlan.obj `if test -f 'tests/test-create-ipvlan.c'; then $(CYGPATH_W) 'tests/test-create-ipvlan.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-ipvlan.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_ipvlan-test-create-ipvlan.Tpo tests/$(DEPDIR)/test_create_ipvlan-test-create-ipvlan.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-ipvlan.c' object='tests/test_create_ipvlan-test-create-ipvlan.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipvlan_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_ipvlan-test-create-ipvlan.obj `if test -f 'tests/test-create-ipvlan.c'; then $(CYGPATH_W) 'tests/test-create-ipvlan.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-ipvlan.c'; fi` + +tests/test_create_ipvti-test-create-ipvti.o: tests/test-create-ipvti.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipvti_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_ipvti-test-create-ipvti.o -MD -MP -MF tests/$(DEPDIR)/test_create_ipvti-test-create-ipvti.Tpo -c -o tests/test_create_ipvti-test-create-ipvti.o `test -f 'tests/test-create-ipvti.c' || echo '$(srcdir)/'`tests/test-create-ipvti.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_ipvti-test-create-ipvti.Tpo tests/$(DEPDIR)/test_create_ipvti-test-create-ipvti.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-ipvti.c' object='tests/test_create_ipvti-test-create-ipvti.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipvti_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_ipvti-test-create-ipvti.o `test -f 'tests/test-create-ipvti.c' || echo '$(srcdir)/'`tests/test-create-ipvti.c + +tests/test_create_ipvti-test-create-ipvti.obj: tests/test-create-ipvti.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipvti_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_ipvti-test-create-ipvti.obj -MD -MP -MF tests/$(DEPDIR)/test_create_ipvti-test-create-ipvti.Tpo -c -o tests/test_create_ipvti-test-create-ipvti.obj `if test -f 'tests/test-create-ipvti.c'; then $(CYGPATH_W) 'tests/test-create-ipvti.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-ipvti.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_ipvti-test-create-ipvti.Tpo tests/$(DEPDIR)/test_create_ipvti-test-create-ipvti.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-ipvti.c' object='tests/test_create_ipvti-test-create-ipvti.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_ipvti_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_ipvti-test-create-ipvti.obj `if test -f 'tests/test-create-ipvti.c'; then $(CYGPATH_W) 'tests/test-create-ipvti.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-ipvti.c'; fi` + +tests/test_create_macsec-test-create-macsec.o: tests/test-create-macsec.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_macsec_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_macsec-test-create-macsec.o -MD -MP -MF tests/$(DEPDIR)/test_create_macsec-test-create-macsec.Tpo -c -o tests/test_create_macsec-test-create-macsec.o `test -f 'tests/test-create-macsec.c' || echo '$(srcdir)/'`tests/test-create-macsec.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_macsec-test-create-macsec.Tpo tests/$(DEPDIR)/test_create_macsec-test-create-macsec.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-macsec.c' object='tests/test_create_macsec-test-create-macsec.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_macsec_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_macsec-test-create-macsec.o `test -f 'tests/test-create-macsec.c' || echo '$(srcdir)/'`tests/test-create-macsec.c + +tests/test_create_macsec-test-create-macsec.obj: tests/test-create-macsec.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_macsec_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_macsec-test-create-macsec.obj -MD -MP -MF tests/$(DEPDIR)/test_create_macsec-test-create-macsec.Tpo -c -o tests/test_create_macsec-test-create-macsec.obj `if test -f 'tests/test-create-macsec.c'; then $(CYGPATH_W) 'tests/test-create-macsec.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-macsec.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_macsec-test-create-macsec.Tpo tests/$(DEPDIR)/test_create_macsec-test-create-macsec.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-macsec.c' object='tests/test_create_macsec-test-create-macsec.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_macsec_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_macsec-test-create-macsec.obj `if test -f 'tests/test-create-macsec.c'; then $(CYGPATH_W) 'tests/test-create-macsec.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-macsec.c'; fi` + +tests/test_create_macvlan-test-create-macvlan.o: tests/test-create-macvlan.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_macvlan_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_macvlan-test-create-macvlan.o -MD -MP -MF tests/$(DEPDIR)/test_create_macvlan-test-create-macvlan.Tpo -c -o tests/test_create_macvlan-test-create-macvlan.o `test -f 'tests/test-create-macvlan.c' || echo '$(srcdir)/'`tests/test-create-macvlan.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_macvlan-test-create-macvlan.Tpo tests/$(DEPDIR)/test_create_macvlan-test-create-macvlan.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-macvlan.c' object='tests/test_create_macvlan-test-create-macvlan.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_macvlan_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_macvlan-test-create-macvlan.o `test -f 'tests/test-create-macvlan.c' || echo '$(srcdir)/'`tests/test-create-macvlan.c + +tests/test_create_macvlan-test-create-macvlan.obj: tests/test-create-macvlan.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_macvlan_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_macvlan-test-create-macvlan.obj -MD -MP -MF tests/$(DEPDIR)/test_create_macvlan-test-create-macvlan.Tpo -c -o tests/test_create_macvlan-test-create-macvlan.obj `if test -f 'tests/test-create-macvlan.c'; then $(CYGPATH_W) 'tests/test-create-macvlan.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-macvlan.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_macvlan-test-create-macvlan.Tpo tests/$(DEPDIR)/test_create_macvlan-test-create-macvlan.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-macvlan.c' object='tests/test_create_macvlan-test-create-macvlan.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_macvlan_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_macvlan-test-create-macvlan.obj `if test -f 'tests/test-create-macvlan.c'; then $(CYGPATH_W) 'tests/test-create-macvlan.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-macvlan.c'; fi` + +tests/test_create_macvtap-test-create-macvtap.o: tests/test-create-macvtap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_macvtap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_macvtap-test-create-macvtap.o -MD -MP -MF tests/$(DEPDIR)/test_create_macvtap-test-create-macvtap.Tpo -c -o tests/test_create_macvtap-test-create-macvtap.o `test -f 'tests/test-create-macvtap.c' || echo '$(srcdir)/'`tests/test-create-macvtap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_macvtap-test-create-macvtap.Tpo tests/$(DEPDIR)/test_create_macvtap-test-create-macvtap.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-macvtap.c' object='tests/test_create_macvtap-test-create-macvtap.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_macvtap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_macvtap-test-create-macvtap.o `test -f 'tests/test-create-macvtap.c' || echo '$(srcdir)/'`tests/test-create-macvtap.c + +tests/test_create_macvtap-test-create-macvtap.obj: tests/test-create-macvtap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_macvtap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_macvtap-test-create-macvtap.obj -MD -MP -MF tests/$(DEPDIR)/test_create_macvtap-test-create-macvtap.Tpo -c -o tests/test_create_macvtap-test-create-macvtap.obj `if test -f 'tests/test-create-macvtap.c'; then $(CYGPATH_W) 'tests/test-create-macvtap.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-macvtap.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_macvtap-test-create-macvtap.Tpo tests/$(DEPDIR)/test_create_macvtap-test-create-macvtap.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-macvtap.c' object='tests/test_create_macvtap-test-create-macvtap.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_macvtap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_macvtap-test-create-macvtap.obj `if test -f 'tests/test-create-macvtap.c'; then $(CYGPATH_W) 'tests/test-create-macvtap.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-macvtap.c'; fi` + +tests/test_create_sit-test-create-sit.o: tests/test-create-sit.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_sit_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_sit-test-create-sit.o -MD -MP -MF tests/$(DEPDIR)/test_create_sit-test-create-sit.Tpo -c -o tests/test_create_sit-test-create-sit.o `test -f 'tests/test-create-sit.c' || echo '$(srcdir)/'`tests/test-create-sit.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_sit-test-create-sit.Tpo tests/$(DEPDIR)/test_create_sit-test-create-sit.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-sit.c' object='tests/test_create_sit-test-create-sit.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_sit_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_sit-test-create-sit.o `test -f 'tests/test-create-sit.c' || echo '$(srcdir)/'`tests/test-create-sit.c + +tests/test_create_sit-test-create-sit.obj: tests/test-create-sit.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_sit_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_sit-test-create-sit.obj -MD -MP -MF tests/$(DEPDIR)/test_create_sit-test-create-sit.Tpo -c -o tests/test_create_sit-test-create-sit.obj `if test -f 'tests/test-create-sit.c'; then $(CYGPATH_W) 'tests/test-create-sit.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-sit.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_sit-test-create-sit.Tpo tests/$(DEPDIR)/test_create_sit-test-create-sit.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-sit.c' object='tests/test_create_sit-test-create-sit.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_sit_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_sit-test-create-sit.obj `if test -f 'tests/test-create-sit.c'; then $(CYGPATH_W) 'tests/test-create-sit.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-sit.c'; fi` + +tests/test_create_veth-test-create-veth.o: tests/test-create-veth.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_veth_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_veth-test-create-veth.o -MD -MP -MF tests/$(DEPDIR)/test_create_veth-test-create-veth.Tpo -c -o tests/test_create_veth-test-create-veth.o `test -f 'tests/test-create-veth.c' || echo '$(srcdir)/'`tests/test-create-veth.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_veth-test-create-veth.Tpo tests/$(DEPDIR)/test_create_veth-test-create-veth.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-veth.c' object='tests/test_create_veth-test-create-veth.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_veth_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_veth-test-create-veth.o `test -f 'tests/test-create-veth.c' || echo '$(srcdir)/'`tests/test-create-veth.c + +tests/test_create_veth-test-create-veth.obj: tests/test-create-veth.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_veth_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_veth-test-create-veth.obj -MD -MP -MF tests/$(DEPDIR)/test_create_veth-test-create-veth.Tpo -c -o tests/test_create_veth-test-create-veth.obj `if test -f 'tests/test-create-veth.c'; then $(CYGPATH_W) 'tests/test-create-veth.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-veth.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_veth-test-create-veth.Tpo tests/$(DEPDIR)/test_create_veth-test-create-veth.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-veth.c' object='tests/test_create_veth-test-create-veth.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_veth_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_veth-test-create-veth.obj `if test -f 'tests/test-create-veth.c'; then $(CYGPATH_W) 'tests/test-create-veth.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-veth.c'; fi` + +tests/test_create_vlan-test-create-vlan.o: tests/test-create-vlan.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_vlan_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_vlan-test-create-vlan.o -MD -MP -MF tests/$(DEPDIR)/test_create_vlan-test-create-vlan.Tpo -c -o tests/test_create_vlan-test-create-vlan.o `test -f 'tests/test-create-vlan.c' || echo '$(srcdir)/'`tests/test-create-vlan.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_vlan-test-create-vlan.Tpo tests/$(DEPDIR)/test_create_vlan-test-create-vlan.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-vlan.c' object='tests/test_create_vlan-test-create-vlan.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_vlan_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_vlan-test-create-vlan.o `test -f 'tests/test-create-vlan.c' || echo '$(srcdir)/'`tests/test-create-vlan.c + +tests/test_create_vlan-test-create-vlan.obj: tests/test-create-vlan.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_vlan_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_vlan-test-create-vlan.obj -MD -MP -MF tests/$(DEPDIR)/test_create_vlan-test-create-vlan.Tpo -c -o tests/test_create_vlan-test-create-vlan.obj `if test -f 'tests/test-create-vlan.c'; then $(CYGPATH_W) 'tests/test-create-vlan.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-vlan.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_vlan-test-create-vlan.Tpo tests/$(DEPDIR)/test_create_vlan-test-create-vlan.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-vlan.c' object='tests/test_create_vlan-test-create-vlan.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_vlan_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_vlan-test-create-vlan.obj `if test -f 'tests/test-create-vlan.c'; then $(CYGPATH_W) 'tests/test-create-vlan.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-vlan.c'; fi` + +tests/test_create_vrf-test-create-vrf.o: tests/test-create-vrf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_vrf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_vrf-test-create-vrf.o -MD -MP -MF tests/$(DEPDIR)/test_create_vrf-test-create-vrf.Tpo -c -o tests/test_create_vrf-test-create-vrf.o `test -f 'tests/test-create-vrf.c' || echo '$(srcdir)/'`tests/test-create-vrf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_vrf-test-create-vrf.Tpo tests/$(DEPDIR)/test_create_vrf-test-create-vrf.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-vrf.c' object='tests/test_create_vrf-test-create-vrf.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_vrf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_vrf-test-create-vrf.o `test -f 'tests/test-create-vrf.c' || echo '$(srcdir)/'`tests/test-create-vrf.c + +tests/test_create_vrf-test-create-vrf.obj: tests/test-create-vrf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_vrf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_vrf-test-create-vrf.obj -MD -MP -MF tests/$(DEPDIR)/test_create_vrf-test-create-vrf.Tpo -c -o tests/test_create_vrf-test-create-vrf.obj `if test -f 'tests/test-create-vrf.c'; then $(CYGPATH_W) 'tests/test-create-vrf.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-vrf.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_vrf-test-create-vrf.Tpo tests/$(DEPDIR)/test_create_vrf-test-create-vrf.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-vrf.c' object='tests/test_create_vrf-test-create-vrf.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_vrf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_vrf-test-create-vrf.obj `if test -f 'tests/test-create-vrf.c'; then $(CYGPATH_W) 'tests/test-create-vrf.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-vrf.c'; fi` + +tests/test_create_vxlan-test-create-vxlan.o: tests/test-create-vxlan.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_vxlan_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_vxlan-test-create-vxlan.o -MD -MP -MF tests/$(DEPDIR)/test_create_vxlan-test-create-vxlan.Tpo -c -o tests/test_create_vxlan-test-create-vxlan.o `test -f 'tests/test-create-vxlan.c' || echo '$(srcdir)/'`tests/test-create-vxlan.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_vxlan-test-create-vxlan.Tpo tests/$(DEPDIR)/test_create_vxlan-test-create-vxlan.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-vxlan.c' object='tests/test_create_vxlan-test-create-vxlan.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_vxlan_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_vxlan-test-create-vxlan.o `test -f 'tests/test-create-vxlan.c' || echo '$(srcdir)/'`tests/test-create-vxlan.c + +tests/test_create_vxlan-test-create-vxlan.obj: tests/test-create-vxlan.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_vxlan_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_vxlan-test-create-vxlan.obj -MD -MP -MF tests/$(DEPDIR)/test_create_vxlan-test-create-vxlan.Tpo -c -o tests/test_create_vxlan-test-create-vxlan.obj `if test -f 'tests/test-create-vxlan.c'; then $(CYGPATH_W) 'tests/test-create-vxlan.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-vxlan.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_vxlan-test-create-vxlan.Tpo tests/$(DEPDIR)/test_create_vxlan-test-create-vxlan.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-vxlan.c' object='tests/test_create_vxlan-test-create-vxlan.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_vxlan_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_vxlan-test-create-vxlan.obj `if test -f 'tests/test-create-vxlan.c'; then $(CYGPATH_W) 'tests/test-create-vxlan.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-vxlan.c'; fi` + +tests/test_create_xfrmi-test-create-xfrmi.o: tests/test-create-xfrmi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_xfrmi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_xfrmi-test-create-xfrmi.o -MD -MP -MF tests/$(DEPDIR)/test_create_xfrmi-test-create-xfrmi.Tpo -c -o tests/test_create_xfrmi-test-create-xfrmi.o `test -f 'tests/test-create-xfrmi.c' || echo '$(srcdir)/'`tests/test-create-xfrmi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_xfrmi-test-create-xfrmi.Tpo tests/$(DEPDIR)/test_create_xfrmi-test-create-xfrmi.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-xfrmi.c' object='tests/test_create_xfrmi-test-create-xfrmi.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_xfrmi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_xfrmi-test-create-xfrmi.o `test -f 'tests/test-create-xfrmi.c' || echo '$(srcdir)/'`tests/test-create-xfrmi.c + +tests/test_create_xfrmi-test-create-xfrmi.obj: tests/test-create-xfrmi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_xfrmi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_create_xfrmi-test-create-xfrmi.obj -MD -MP -MF tests/$(DEPDIR)/test_create_xfrmi-test-create-xfrmi.Tpo -c -o tests/test_create_xfrmi-test-create-xfrmi.obj `if test -f 'tests/test-create-xfrmi.c'; then $(CYGPATH_W) 'tests/test-create-xfrmi.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-xfrmi.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_create_xfrmi-test-create-xfrmi.Tpo tests/$(DEPDIR)/test_create_xfrmi-test-create-xfrmi.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-create-xfrmi.c' object='tests/test_create_xfrmi-test-create-xfrmi.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_create_xfrmi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_create_xfrmi-test-create-xfrmi.obj `if test -f 'tests/test-create-xfrmi.c'; then $(CYGPATH_W) 'tests/test-create-xfrmi.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-create-xfrmi.c'; fi` + +tests/test_delete_link-test-delete-link.o: tests/test-delete-link.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_delete_link_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_delete_link-test-delete-link.o -MD -MP -MF tests/$(DEPDIR)/test_delete_link-test-delete-link.Tpo -c -o tests/test_delete_link-test-delete-link.o `test -f 'tests/test-delete-link.c' || echo '$(srcdir)/'`tests/test-delete-link.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_delete_link-test-delete-link.Tpo tests/$(DEPDIR)/test_delete_link-test-delete-link.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-delete-link.c' object='tests/test_delete_link-test-delete-link.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_delete_link_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_delete_link-test-delete-link.o `test -f 'tests/test-delete-link.c' || echo '$(srcdir)/'`tests/test-delete-link.c + +tests/test_delete_link-test-delete-link.obj: tests/test-delete-link.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_delete_link_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_delete_link-test-delete-link.obj -MD -MP -MF tests/$(DEPDIR)/test_delete_link-test-delete-link.Tpo -c -o tests/test_delete_link-test-delete-link.obj `if test -f 'tests/test-delete-link.c'; then $(CYGPATH_W) 'tests/test-delete-link.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-delete-link.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_delete_link-test-delete-link.Tpo tests/$(DEPDIR)/test_delete_link-test-delete-link.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-delete-link.c' object='tests/test_delete_link-test-delete-link.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_delete_link_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_delete_link-test-delete-link.obj `if test -f 'tests/test-delete-link.c'; then $(CYGPATH_W) 'tests/test-delete-link.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-delete-link.c'; fi` + +tests/test_genl-test-genl.o: tests/test-genl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_genl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_genl-test-genl.o -MD -MP -MF tests/$(DEPDIR)/test_genl-test-genl.Tpo -c -o tests/test_genl-test-genl.o `test -f 'tests/test-genl.c' || echo '$(srcdir)/'`tests/test-genl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_genl-test-genl.Tpo tests/$(DEPDIR)/test_genl-test-genl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-genl.c' object='tests/test_genl-test-genl.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_genl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_genl-test-genl.o `test -f 'tests/test-genl.c' || echo '$(srcdir)/'`tests/test-genl.c + +tests/test_genl-test-genl.obj: tests/test-genl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_genl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_genl-test-genl.obj -MD -MP -MF tests/$(DEPDIR)/test_genl-test-genl.Tpo -c -o tests/test_genl-test-genl.obj `if test -f 'tests/test-genl.c'; then $(CYGPATH_W) 'tests/test-genl.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-genl.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_genl-test-genl.Tpo tests/$(DEPDIR)/test_genl-test-genl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-genl.c' object='tests/test_genl-test-genl.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_genl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_genl-test-genl.obj `if test -f 'tests/test-genl.c'; then $(CYGPATH_W) 'tests/test-genl.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-genl.c'; fi` + +tests/test_loopback_up_down-test-loopback-up-down.o: tests/test-loopback-up-down.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_loopback_up_down_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_loopback_up_down-test-loopback-up-down.o -MD -MP -MF tests/$(DEPDIR)/test_loopback_up_down-test-loopback-up-down.Tpo -c -o tests/test_loopback_up_down-test-loopback-up-down.o `test -f 'tests/test-loopback-up-down.c' || echo '$(srcdir)/'`tests/test-loopback-up-down.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_loopback_up_down-test-loopback-up-down.Tpo tests/$(DEPDIR)/test_loopback_up_down-test-loopback-up-down.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-loopback-up-down.c' object='tests/test_loopback_up_down-test-loopback-up-down.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_loopback_up_down_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_loopback_up_down-test-loopback-up-down.o `test -f 'tests/test-loopback-up-down.c' || echo '$(srcdir)/'`tests/test-loopback-up-down.c + +tests/test_loopback_up_down-test-loopback-up-down.obj: tests/test-loopback-up-down.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_loopback_up_down_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_loopback_up_down-test-loopback-up-down.obj -MD -MP -MF tests/$(DEPDIR)/test_loopback_up_down-test-loopback-up-down.Tpo -c -o tests/test_loopback_up_down-test-loopback-up-down.obj `if test -f 'tests/test-loopback-up-down.c'; then $(CYGPATH_W) 'tests/test-loopback-up-down.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-loopback-up-down.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_loopback_up_down-test-loopback-up-down.Tpo tests/$(DEPDIR)/test_loopback_up_down-test-loopback-up-down.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-loopback-up-down.c' object='tests/test_loopback_up_down-test-loopback-up-down.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_loopback_up_down_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_loopback_up_down-test-loopback-up-down.obj `if test -f 'tests/test-loopback-up-down.c'; then $(CYGPATH_W) 'tests/test-loopback-up-down.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-loopback-up-down.c'; fi` + +tests/test_nf_cache_mngr-test-nf-cache-mngr.o: tests/test-nf-cache-mngr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_nf_cache_mngr_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_nf_cache_mngr-test-nf-cache-mngr.o -MD -MP -MF tests/$(DEPDIR)/test_nf_cache_mngr-test-nf-cache-mngr.Tpo -c -o tests/test_nf_cache_mngr-test-nf-cache-mngr.o `test -f 'tests/test-nf-cache-mngr.c' || echo '$(srcdir)/'`tests/test-nf-cache-mngr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_nf_cache_mngr-test-nf-cache-mngr.Tpo tests/$(DEPDIR)/test_nf_cache_mngr-test-nf-cache-mngr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-nf-cache-mngr.c' object='tests/test_nf_cache_mngr-test-nf-cache-mngr.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_nf_cache_mngr_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_nf_cache_mngr-test-nf-cache-mngr.o `test -f 'tests/test-nf-cache-mngr.c' || echo '$(srcdir)/'`tests/test-nf-cache-mngr.c + +tests/test_nf_cache_mngr-test-nf-cache-mngr.obj: tests/test-nf-cache-mngr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_nf_cache_mngr_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_nf_cache_mngr-test-nf-cache-mngr.obj -MD -MP -MF tests/$(DEPDIR)/test_nf_cache_mngr-test-nf-cache-mngr.Tpo -c -o tests/test_nf_cache_mngr-test-nf-cache-mngr.obj `if test -f 'tests/test-nf-cache-mngr.c'; then $(CYGPATH_W) 'tests/test-nf-cache-mngr.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-nf-cache-mngr.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_nf_cache_mngr-test-nf-cache-mngr.Tpo tests/$(DEPDIR)/test_nf_cache_mngr-test-nf-cache-mngr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-nf-cache-mngr.c' object='tests/test_nf_cache_mngr-test-nf-cache-mngr.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_nf_cache_mngr_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_nf_cache_mngr-test-nf-cache-mngr.obj `if test -f 'tests/test-nf-cache-mngr.c'; then $(CYGPATH_W) 'tests/test-nf-cache-mngr.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-nf-cache-mngr.c'; fi` + +tests/test_socket_creation-test-socket-creation.o: tests/test-socket-creation.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_socket_creation_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_socket_creation-test-socket-creation.o -MD -MP -MF tests/$(DEPDIR)/test_socket_creation-test-socket-creation.Tpo -c -o tests/test_socket_creation-test-socket-creation.o `test -f 'tests/test-socket-creation.c' || echo '$(srcdir)/'`tests/test-socket-creation.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_socket_creation-test-socket-creation.Tpo tests/$(DEPDIR)/test_socket_creation-test-socket-creation.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-socket-creation.c' object='tests/test_socket_creation-test-socket-creation.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_socket_creation_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_socket_creation-test-socket-creation.o `test -f 'tests/test-socket-creation.c' || echo '$(srcdir)/'`tests/test-socket-creation.c + +tests/test_socket_creation-test-socket-creation.obj: tests/test-socket-creation.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_socket_creation_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_socket_creation-test-socket-creation.obj -MD -MP -MF tests/$(DEPDIR)/test_socket_creation-test-socket-creation.Tpo -c -o tests/test_socket_creation-test-socket-creation.obj `if test -f 'tests/test-socket-creation.c'; then $(CYGPATH_W) 'tests/test-socket-creation.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-socket-creation.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_socket_creation-test-socket-creation.Tpo tests/$(DEPDIR)/test_socket_creation-test-socket-creation.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-socket-creation.c' object='tests/test_socket_creation-test-socket-creation.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_socket_creation_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_socket_creation-test-socket-creation.obj `if test -f 'tests/test-socket-creation.c'; then $(CYGPATH_W) 'tests/test-socket-creation.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-socket-creation.c'; fi` + +tests/test_u32_filter_with_actions-test-u32-filter-with-actions.o: tests/test-u32-filter-with-actions.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_u32_filter_with_actions_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_u32_filter_with_actions-test-u32-filter-with-actions.o -MD -MP -MF tests/$(DEPDIR)/test_u32_filter_with_actions-test-u32-filter-with-actions.Tpo -c -o tests/test_u32_filter_with_actions-test-u32-filter-with-actions.o `test -f 'tests/test-u32-filter-with-actions.c' || echo '$(srcdir)/'`tests/test-u32-filter-with-actions.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_u32_filter_with_actions-test-u32-filter-with-actions.Tpo tests/$(DEPDIR)/test_u32_filter_with_actions-test-u32-filter-with-actions.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-u32-filter-with-actions.c' object='tests/test_u32_filter_with_actions-test-u32-filter-with-actions.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_u32_filter_with_actions_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_u32_filter_with_actions-test-u32-filter-with-actions.o `test -f 'tests/test-u32-filter-with-actions.c' || echo '$(srcdir)/'`tests/test-u32-filter-with-actions.c + +tests/test_u32_filter_with_actions-test-u32-filter-with-actions.obj: tests/test-u32-filter-with-actions.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_u32_filter_with_actions_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tests/test_u32_filter_with_actions-test-u32-filter-with-actions.obj -MD -MP -MF tests/$(DEPDIR)/test_u32_filter_with_actions-test-u32-filter-with-actions.Tpo -c -o tests/test_u32_filter_with_actions-test-u32-filter-with-actions.obj `if test -f 'tests/test-u32-filter-with-actions.c'; then $(CYGPATH_W) 'tests/test-u32-filter-with-actions.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-u32-filter-with-actions.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/test_u32_filter_with_actions-test-u32-filter-with-actions.Tpo tests/$(DEPDIR)/test_u32_filter_with_actions-test-u32-filter-with-actions.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-u32-filter-with-actions.c' object='tests/test_u32_filter_with_actions-test-u32-filter-with-actions.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tests_test_u32_filter_with_actions_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test_u32_filter_with_actions-test-u32-filter-with-actions.obj `if test -f 'tests/test-u32-filter-with-actions.c'; then $(CYGPATH_W) 'tests/test-u32-filter-with-actions.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-u32-filter-with-actions.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs + -rm -rf lib/.libs lib/_libs + -rm -rf lib/cli/cls/.libs lib/cli/cls/_libs + -rm -rf lib/cli/qdisc/.libs lib/cli/qdisc/_libs + -rm -rf lib/fib_lookup/.libs lib/fib_lookup/_libs + -rm -rf lib/genl/.libs lib/genl/_libs + -rm -rf lib/idiag/.libs lib/idiag/_libs + -rm -rf lib/netfilter/.libs lib/netfilter/_libs + -rm -rf lib/route/.libs lib/route/_libs + -rm -rf lib/route/act/.libs lib/route/act/_libs + -rm -rf lib/route/cls/.libs lib/route/cls/_libs + -rm -rf lib/route/cls/ematch/.libs lib/route/cls/ematch/_libs + -rm -rf lib/route/link/.libs lib/route/link/_libs + -rm -rf lib/route/qdisc/.libs lib/route/qdisc/_libs + -rm -rf lib/xfrm/.libs lib/xfrm/_libs + -rm -rf src/.libs src/_libs + -rm -rf src/lib/.libs src/lib/_libs + -rm -rf tests/.libs tests/_libs distclean-libtool: -rm -f libtool config.lt +install-man8: $(dist_man8_MANS) + @$(NORMAL_INSTALL) + @list1='$(dist_man8_MANS)'; \ + list2=''; \ + test -n "$(man8dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.8[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ + done; } + +uninstall-man8: + @$(NORMAL_UNINSTALL) + @list='$(dist_man8_MANS)'; test -n "$(man8dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ @@ -416,110 +6587,289 @@ uninstall-pkgsysconfDATA: @list='$(pkgsysconf_DATA)'; test -n "$(pkgsysconfdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgsysconfdir)'; $(am__uninstall_files_from_dir) +install-libnlinclude_netlinkHEADERS: $(libnlinclude_netlink_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libnlinclude_netlink_HEADERS)'; test -n "$(libnlinclude_netlinkdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libnlinclude_netlinkdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libnlinclude_netlinkdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libnlinclude_netlinkdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libnlinclude_netlinkdir)" || exit $$?; \ + done -# This directory's subdirectories are mostly independent; you can cd -# into them and run `make' without going through this Makefile. -# To change the values of `make' variables: instead of editing Makefiles, -# (1) if the variable is set in `config.status', edit `config.status' -# (which will cause the Makefiles to be regenerated when you run `make'); -# (2) otherwise, pass the desired values on the `make' command line. -$(RECURSIVE_TARGETS): - @fail= failcom='exit 1'; \ - for f in x $$MAKEFLAGS; do \ - case $$f in \ - *=* | --[!k]*);; \ - *k*) failcom='fail=yes';; \ - esac; \ - done; \ - dot_seen=no; \ - target=`echo $@ | sed s/-recursive//`; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - dot_seen=yes; \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || eval $$failcom; \ - done; \ - if test "$$dot_seen" = "no"; then \ - $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ - fi; test -z "$$fail" - -$(RECURSIVE_CLEAN_TARGETS): - @fail= failcom='exit 1'; \ - for f in x $$MAKEFLAGS; do \ - case $$f in \ - *=* | --[!k]*);; \ - *k*) failcom='fail=yes';; \ - esac; \ - done; \ - dot_seen=no; \ - case "$@" in \ - distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ - *) list='$(SUBDIRS)' ;; \ - esac; \ - rev=''; for subdir in $$list; do \ - if test "$$subdir" = "."; then :; else \ - rev="$$subdir $$rev"; \ - fi; \ - done; \ - rev="$$rev ."; \ - target=`echo $@ | sed s/-recursive//`; \ - for subdir in $$rev; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || eval $$failcom; \ - done && test -z "$$fail" -tags-recursive: - list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ +uninstall-libnlinclude_netlinkHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libnlinclude_netlink_HEADERS)'; test -n "$(libnlinclude_netlinkdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libnlinclude_netlinkdir)'; $(am__uninstall_files_from_dir) +install-libnlinclude_netlink_cliHEADERS: $(libnlinclude_netlink_cli_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libnlinclude_netlink_cli_HEADERS)'; test -n "$(libnlinclude_netlink_clidir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libnlinclude_netlink_clidir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libnlinclude_netlink_clidir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libnlinclude_netlink_clidir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libnlinclude_netlink_clidir)" || exit $$?; \ + done + +uninstall-libnlinclude_netlink_cliHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libnlinclude_netlink_cli_HEADERS)'; test -n "$(libnlinclude_netlink_clidir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libnlinclude_netlink_clidir)'; $(am__uninstall_files_from_dir) +install-libnlinclude_netlink_fib_lookupHEADERS: $(libnlinclude_netlink_fib_lookup_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libnlinclude_netlink_fib_lookup_HEADERS)'; test -n "$(libnlinclude_netlink_fib_lookupdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libnlinclude_netlink_fib_lookupdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libnlinclude_netlink_fib_lookupdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libnlinclude_netlink_fib_lookupdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libnlinclude_netlink_fib_lookupdir)" || exit $$?; \ + done + +uninstall-libnlinclude_netlink_fib_lookupHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libnlinclude_netlink_fib_lookup_HEADERS)'; test -n "$(libnlinclude_netlink_fib_lookupdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libnlinclude_netlink_fib_lookupdir)'; $(am__uninstall_files_from_dir) +install-libnlinclude_netlink_genlHEADERS: $(libnlinclude_netlink_genl_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libnlinclude_netlink_genl_HEADERS)'; test -n "$(libnlinclude_netlink_genldir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libnlinclude_netlink_genldir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libnlinclude_netlink_genldir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libnlinclude_netlink_genldir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libnlinclude_netlink_genldir)" || exit $$?; \ + done + +uninstall-libnlinclude_netlink_genlHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libnlinclude_netlink_genl_HEADERS)'; test -n "$(libnlinclude_netlink_genldir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libnlinclude_netlink_genldir)'; $(am__uninstall_files_from_dir) +install-libnlinclude_netlink_idiagHEADERS: $(libnlinclude_netlink_idiag_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libnlinclude_netlink_idiag_HEADERS)'; test -n "$(libnlinclude_netlink_idiagdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libnlinclude_netlink_idiagdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libnlinclude_netlink_idiagdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libnlinclude_netlink_idiagdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libnlinclude_netlink_idiagdir)" || exit $$?; \ + done + +uninstall-libnlinclude_netlink_idiagHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libnlinclude_netlink_idiag_HEADERS)'; test -n "$(libnlinclude_netlink_idiagdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libnlinclude_netlink_idiagdir)'; $(am__uninstall_files_from_dir) +install-libnlinclude_netlink_netfilterHEADERS: $(libnlinclude_netlink_netfilter_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libnlinclude_netlink_netfilter_HEADERS)'; test -n "$(libnlinclude_netlink_netfilterdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libnlinclude_netlink_netfilterdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libnlinclude_netlink_netfilterdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libnlinclude_netlink_netfilterdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libnlinclude_netlink_netfilterdir)" || exit $$?; \ + done + +uninstall-libnlinclude_netlink_netfilterHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libnlinclude_netlink_netfilter_HEADERS)'; test -n "$(libnlinclude_netlink_netfilterdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libnlinclude_netlink_netfilterdir)'; $(am__uninstall_files_from_dir) +install-libnlinclude_netlink_routeHEADERS: $(libnlinclude_netlink_route_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libnlinclude_netlink_route_HEADERS)'; test -n "$(libnlinclude_netlink_routedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libnlinclude_netlink_routedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libnlinclude_netlink_routedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libnlinclude_netlink_routedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libnlinclude_netlink_routedir)" || exit $$?; \ + done + +uninstall-libnlinclude_netlink_routeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libnlinclude_netlink_route_HEADERS)'; test -n "$(libnlinclude_netlink_routedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libnlinclude_netlink_routedir)'; $(am__uninstall_files_from_dir) +install-libnlinclude_netlink_route_actHEADERS: $(libnlinclude_netlink_route_act_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libnlinclude_netlink_route_act_HEADERS)'; test -n "$(libnlinclude_netlink_route_actdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libnlinclude_netlink_route_actdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libnlinclude_netlink_route_actdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libnlinclude_netlink_route_actdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libnlinclude_netlink_route_actdir)" || exit $$?; \ + done + +uninstall-libnlinclude_netlink_route_actHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libnlinclude_netlink_route_act_HEADERS)'; test -n "$(libnlinclude_netlink_route_actdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libnlinclude_netlink_route_actdir)'; $(am__uninstall_files_from_dir) +install-libnlinclude_netlink_route_clsHEADERS: $(libnlinclude_netlink_route_cls_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libnlinclude_netlink_route_cls_HEADERS)'; test -n "$(libnlinclude_netlink_route_clsdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libnlinclude_netlink_route_clsdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libnlinclude_netlink_route_clsdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libnlinclude_netlink_route_clsdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libnlinclude_netlink_route_clsdir)" || exit $$?; \ + done + +uninstall-libnlinclude_netlink_route_clsHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libnlinclude_netlink_route_cls_HEADERS)'; test -n "$(libnlinclude_netlink_route_clsdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libnlinclude_netlink_route_clsdir)'; $(am__uninstall_files_from_dir) +install-libnlinclude_netlink_route_cls_ematchHEADERS: $(libnlinclude_netlink_route_cls_ematch_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libnlinclude_netlink_route_cls_ematch_HEADERS)'; test -n "$(libnlinclude_netlink_route_cls_ematchdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libnlinclude_netlink_route_cls_ematchdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libnlinclude_netlink_route_cls_ematchdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libnlinclude_netlink_route_cls_ematchdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libnlinclude_netlink_route_cls_ematchdir)" || exit $$?; \ + done + +uninstall-libnlinclude_netlink_route_cls_ematchHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libnlinclude_netlink_route_cls_ematch_HEADERS)'; test -n "$(libnlinclude_netlink_route_cls_ematchdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libnlinclude_netlink_route_cls_ematchdir)'; $(am__uninstall_files_from_dir) +install-libnlinclude_netlink_route_linkHEADERS: $(libnlinclude_netlink_route_link_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libnlinclude_netlink_route_link_HEADERS)'; test -n "$(libnlinclude_netlink_route_linkdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libnlinclude_netlink_route_linkdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libnlinclude_netlink_route_linkdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libnlinclude_netlink_route_linkdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libnlinclude_netlink_route_linkdir)" || exit $$?; \ + done + +uninstall-libnlinclude_netlink_route_linkHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libnlinclude_netlink_route_link_HEADERS)'; test -n "$(libnlinclude_netlink_route_linkdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libnlinclude_netlink_route_linkdir)'; $(am__uninstall_files_from_dir) +install-libnlinclude_netlink_route_qdiscHEADERS: $(libnlinclude_netlink_route_qdisc_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libnlinclude_netlink_route_qdisc_HEADERS)'; test -n "$(libnlinclude_netlink_route_qdiscdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libnlinclude_netlink_route_qdiscdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libnlinclude_netlink_route_qdiscdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libnlinclude_netlink_route_qdiscdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libnlinclude_netlink_route_qdiscdir)" || exit $$?; \ done -ctags-recursive: - list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + +uninstall-libnlinclude_netlink_route_qdiscHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libnlinclude_netlink_route_qdisc_HEADERS)'; test -n "$(libnlinclude_netlink_route_qdiscdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libnlinclude_netlink_route_qdiscdir)'; $(am__uninstall_files_from_dir) +install-libnlinclude_netlink_xfrmHEADERS: $(libnlinclude_netlink_xfrm_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libnlinclude_netlink_xfrm_HEADERS)'; test -n "$(libnlinclude_netlink_xfrmdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libnlinclude_netlink_xfrmdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libnlinclude_netlink_xfrmdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libnlinclude_netlink_xfrmdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libnlinclude_netlink_xfrmdir)" || exit $$?; \ done -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) +uninstall-libnlinclude_netlink_xfrmHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libnlinclude_netlink_xfrm_HEADERS)'; test -n "$(libnlinclude_netlink_xfrmdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libnlinclude_netlink_xfrmdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ - if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ - include_option=--etags-include; \ - empty_fix=.; \ - else \ - include_option=--include; \ - empty_fix=; \ - fi; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - test ! -f $$subdir/TAGS || \ - set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ - fi; \ - done; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ + $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ @@ -531,15 +6881,11 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $$unique; \ fi; \ fi -ctags: CTAGS -CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique @@ -548,11 +6894,205 @@ GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: $(check_PROGRAMS) $(check_LTLIBRARIES) + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_PROGRAMS) $(check_LTLIBRARIES) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +tests/check-all.log: tests/check-all$(EXEEXT) + @p='tests/check-all$(EXEEXT)'; \ + b='tests/check-all'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/check-direct.log: tests/check-direct$(EXEEXT) + @p='tests/check-direct$(EXEEXT)'; \ + b='tests/check-direct'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am -distdir: $(DISTFILES) +distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @@ -584,31 +7124,6 @@ distdir: $(DISTFILES) || exit 1; \ fi; \ done - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - $(am__make_dryrun) \ - || test -d "$(distdir)/$$subdir" \ - || $(MKDIR_P) "$(distdir)/$$subdir" \ - || exit 1; \ - dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ - $(am__relativize); \ - new_distdir=$$reldir; \ - dir1=$$subdir; dir2="$(top_distdir)"; \ - $(am__relativize); \ - new_top_distdir=$$reldir; \ - echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ - echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ - ($(am__cd) $$subdir && \ - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$$new_top_distdir" \ - distdir="$$new_distdir" \ - am__remove_distdir=: \ - am__skip_length_check=: \ - am__skip_mode_fix=: \ - distdir) \ - || exit 1; \ - fi; \ - done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ @@ -617,41 +7132,47 @@ distdir: $(DISTFILES) ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz - $(am__remove_distdir) + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 - $(am__remove_distdir) + $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz - $(am__remove_distdir) - -dist-lzma: distdir - tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma - $(am__remove_distdir) + $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz - $(am__remove_distdir) + $(am__post_remove_distdir) + +dist-zstd: distdir + tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst + $(am__post_remove_distdir) dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z - $(am__remove_distdir) + $(am__post_remove_distdir) dist-shar: distdir - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz - $(am__remove_distdir) + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) - $(am__remove_distdir) + $(am__post_remove_distdir) -dist dist-all: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz - $(am__remove_distdir) +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another @@ -659,11 +7180,9 @@ dist dist-all: distdir distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ - *.tar.lzma*) \ - lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ @@ -671,24 +7190,27 @@ distcheck: dist *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ + *.tar.zst*) \ + zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ esac - chmod -R a-w $(distdir); chmod u+w $(distdir) - mkdir $(distdir)/_build - mkdir $(distdir)/_inst + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ - && $(am__cd) $(distdir)/_build \ - && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ - && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ @@ -709,7 +7231,7 @@ distcheck: dist && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 - $(am__remove_distdir) + $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' @@ -740,22 +7262,35 @@ distcleancheck: distclean $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am -check: check-recursive -all-am: Makefile $(DATA) -installdirs: installdirs-recursive -installdirs-am: - for dir in "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(pkgsysconfdir)"; do \ + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(check_LTLIBRARIES) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS check-local +check: check-am +all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(MANS) $(DATA) $(HEADERS) +install-binPROGRAMS: install-libLTLIBRARIES + +install-checkPROGRAMS: install-libLTLIBRARIES + +install-sbinPROGRAMS: install-libLTLIBRARIES + +install-checkLTLIBRARIES: install-libLTLIBRARIES + +install-pkglibclsLTLIBRARIES: install-libLTLIBRARIES + +install-pkglibqdiscLTLIBRARIES: install-libLTLIBRARIES + +installdirs: + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkglib_clsdir)" "$(DESTDIR)$(pkglib_qdiscdir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(pkgsysconfdir)" "$(DESTDIR)$(libnlinclude_netlinkdir)" "$(DESTDIR)$(libnlinclude_netlink_clidir)" "$(DESTDIR)$(libnlinclude_netlink_fib_lookupdir)" "$(DESTDIR)$(libnlinclude_netlink_genldir)" "$(DESTDIR)$(libnlinclude_netlink_idiagdir)" "$(DESTDIR)$(libnlinclude_netlink_netfilterdir)" "$(DESTDIR)$(libnlinclude_netlink_routedir)" "$(DESTDIR)$(libnlinclude_netlink_route_actdir)" "$(DESTDIR)$(libnlinclude_netlink_route_clsdir)" "$(DESTDIR)$(libnlinclude_netlink_route_cls_ematchdir)" "$(DESTDIR)$(libnlinclude_netlink_route_linkdir)" "$(DESTDIR)$(libnlinclude_netlink_route_qdiscdir)" "$(DESTDIR)$(libnlinclude_netlink_xfrmdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done -install: install-recursive -install-exec: install-exec-recursive -install-data: install-data-recursive -uninstall: uninstall-recursive +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am -installcheck: installcheck-recursive +installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ @@ -767,107 +7302,768 @@ install-strip: "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f lib/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/$(am__dirstamp) + -rm -f lib/cli/cls/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/cli/cls/$(am__dirstamp) + -rm -f lib/cli/qdisc/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/cli/qdisc/$(am__dirstamp) + -rm -f lib/fib_lookup/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/fib_lookup/$(am__dirstamp) + -rm -f lib/genl/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/genl/$(am__dirstamp) + -rm -f lib/idiag/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/idiag/$(am__dirstamp) + -rm -f lib/netfilter/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/netfilter/$(am__dirstamp) + -rm -f lib/route/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/route/$(am__dirstamp) + -rm -f lib/route/act/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/route/act/$(am__dirstamp) + -rm -f lib/route/cls/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/route/cls/$(am__dirstamp) + -rm -f lib/route/cls/ematch/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/route/cls/ematch/$(am__dirstamp) + -rm -f lib/route/link/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/route/link/$(am__dirstamp) + -rm -f lib/route/qdisc/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/route/qdisc/$(am__dirstamp) + -rm -f lib/xfrm/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/xfrm/$(am__dirstamp) + -rm -f src/$(DEPDIR)/$(am__dirstamp) + -rm -f src/$(am__dirstamp) + -rm -f src/lib/$(DEPDIR)/$(am__dirstamp) + -rm -f src/lib/$(am__dirstamp) + -rm -f tests/$(DEPDIR)/$(am__dirstamp) + -rm -f tests/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -clean: clean-recursive +clean: clean-am -clean-am: clean-generic clean-libtool mostlyclean-am +clean-am: clean-binPROGRAMS clean-checkLTLIBRARIES clean-checkPROGRAMS \ + clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ + clean-pkglib_clsLTLIBRARIES clean-pkglib_qdiscLTLIBRARIES \ + clean-sbinPROGRAMS mostlyclean-am -distclean: distclean-recursive +distclean: distclean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f lib/$(DEPDIR)/libnl_3_la-addr.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-attr.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-cache.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-cache_mngr.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-cache_mngt.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-data.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-error.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-handlers.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-hash.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-hashtable.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-mpls.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-msg.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-nl.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-object.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-socket.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-utils.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-version.Plo + -rm -f lib/cli/cls/$(DEPDIR)/basic_la-basic.Plo + -rm -f lib/cli/cls/$(DEPDIR)/cgroup_la-cgroup.Plo + -rm -f lib/cli/qdisc/$(DEPDIR)/bfifo_la-bfifo.Plo + -rm -f lib/cli/qdisc/$(DEPDIR)/blackhole_la-blackhole.Plo + -rm -f lib/cli/qdisc/$(DEPDIR)/fq_codel_la-fq_codel.Plo + -rm -f lib/cli/qdisc/$(DEPDIR)/hfsc_la-hfsc.Plo + -rm -f lib/cli/qdisc/$(DEPDIR)/htb_la-htb.Plo + -rm -f lib/cli/qdisc/$(DEPDIR)/ingress_la-ingress.Plo + -rm -f lib/cli/qdisc/$(DEPDIR)/pfifo_la-pfifo.Plo + -rm -f lib/cli/qdisc/$(DEPDIR)/plug_la-plug.Plo + -rm -f lib/fib_lookup/$(DEPDIR)/libnl_route_3_la-lookup.Plo + -rm -f lib/fib_lookup/$(DEPDIR)/libnl_route_3_la-request.Plo + -rm -f lib/genl/$(DEPDIR)/libnl_genl_3_la-ctrl.Plo + -rm -f lib/genl/$(DEPDIR)/libnl_genl_3_la-family.Plo + -rm -f lib/genl/$(DEPDIR)/libnl_genl_3_la-genl.Plo + -rm -f lib/genl/$(DEPDIR)/libnl_genl_3_la-mngt.Plo + -rm -f lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag.Plo + -rm -f lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_meminfo_obj.Plo + -rm -f lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_msg_obj.Plo + -rm -f lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_req_obj.Plo + -rm -f lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_vegasinfo_obj.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-ct.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-ct_obj.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-exp.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-exp_obj.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_msg.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_msg_obj.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_obj.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-netfilter.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-nfnl.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_msg.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_msg_obj.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_obj.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-act.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-addr.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-class.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-classid.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-cls.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-link.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-mdb.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-neigh.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-neightbl.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-netconf.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-nexthop.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-nexthop_encap.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-nh.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-nh_encap_mpls.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-pktloc.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-pktloc_grammar.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-pktloc_syntax.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-qdisc.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-route.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-route_obj.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-route_utils.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-rtnl.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-rule.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-tc.Plo + -rm -f lib/route/act/$(DEPDIR)/libnl_route_3_la-gact.Plo + -rm -f lib/route/act/$(DEPDIR)/libnl_route_3_la-mirred.Plo + -rm -f lib/route/act/$(DEPDIR)/libnl_route_3_la-nat.Plo + -rm -f lib/route/act/$(DEPDIR)/libnl_route_3_la-skbedit.Plo + -rm -f lib/route/act/$(DEPDIR)/libnl_route_3_la-vlan.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-basic.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-cgroup.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch_grammar.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch_syntax.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-flower.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-fw.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-mall.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-police.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-u32.Plo + -rm -f lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-cmp.Plo + -rm -f lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-container.Plo + -rm -f lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-meta.Plo + -rm -f lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-nbyte.Plo + -rm -f lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-text.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-api.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-bonding.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-bridge.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-bridge_info.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-can.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-dummy.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-geneve.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-ifb.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-inet.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-inet6.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6gre.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6tnl.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6vti.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-ipgre.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-ipip.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-ipvlan.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-ipvti.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-macsec.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-macvlan.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-ppp.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-sit.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-sriov.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-team.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-veth.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-vlan.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-vrf.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-vxlan.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-xfrmi.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-blackhole.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-cbq.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-dsmark.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-fifo.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-fq_codel.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-hfsc.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-htb.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-ingress.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-mqprio.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-netem.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-plug.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-prio.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-red.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-sfq.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-tbf.Plo + -rm -f lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-ae.Plo + -rm -f lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-lifetime.Plo + -rm -f lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-sa.Plo + -rm -f lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-selector.Plo + -rm -f lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-sp.Plo + -rm -f lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-template.Plo + -rm -f src/$(DEPDIR)/genl_ctrl_list-genl-ctrl-list.Po + -rm -f src/$(DEPDIR)/idiag_socket_details-idiag-socket-details.Po + -rm -f src/$(DEPDIR)/nf_ct_add-nf-ct-add.Po + -rm -f src/$(DEPDIR)/nf_ct_events-nf-ct-events.Po + -rm -f src/$(DEPDIR)/nf_ct_list-nf-ct-list.Po + -rm -f src/$(DEPDIR)/nf_exp_add-nf-exp-add.Po + -rm -f src/$(DEPDIR)/nf_exp_delete-nf-exp-delete.Po + -rm -f src/$(DEPDIR)/nf_exp_list-nf-exp-list.Po + -rm -f src/$(DEPDIR)/nf_log-nf-log.Po + -rm -f src/$(DEPDIR)/nf_monitor-nf-monitor.Po + -rm -f src/$(DEPDIR)/nf_queue-nf-queue.Po + -rm -f src/$(DEPDIR)/nl_addr_add-nl-addr-add.Po + -rm -f src/$(DEPDIR)/nl_addr_delete-nl-addr-delete.Po + -rm -f src/$(DEPDIR)/nl_addr_list-nl-addr-list.Po + -rm -f src/$(DEPDIR)/nl_class_add-nl-class-add.Po + -rm -f src/$(DEPDIR)/nl_class_delete-nl-class-delete.Po + -rm -f src/$(DEPDIR)/nl_class_list-nl-class-list.Po + -rm -f src/$(DEPDIR)/nl_classid_lookup-nl-classid-lookup.Po + -rm -f src/$(DEPDIR)/nl_cls_add-nl-cls-add.Po + -rm -f src/$(DEPDIR)/nl_cls_delete-nl-cls-delete.Po + -rm -f src/$(DEPDIR)/nl_cls_list-nl-cls-list.Po + -rm -f src/$(DEPDIR)/nl_fib_lookup-nl-fib-lookup.Po + -rm -f src/$(DEPDIR)/nl_link_enslave-nl-link-enslave.Po + -rm -f src/$(DEPDIR)/nl_link_ifindex2name-nl-link-ifindex2name.Po + -rm -f src/$(DEPDIR)/nl_link_list-nl-link-list.Po + -rm -f src/$(DEPDIR)/nl_link_name2ifindex-nl-link-name2ifindex.Po + -rm -f src/$(DEPDIR)/nl_link_release-nl-link-release.Po + -rm -f src/$(DEPDIR)/nl_link_set-nl-link-set.Po + -rm -f src/$(DEPDIR)/nl_link_stats-nl-link-stats.Po + -rm -f src/$(DEPDIR)/nl_list_caches-nl-list-caches.Po + -rm -f src/$(DEPDIR)/nl_list_sockets-nl-list-sockets.Po + -rm -f src/$(DEPDIR)/nl_monitor-nl-monitor.Po + -rm -f src/$(DEPDIR)/nl_neigh_add-nl-neigh-add.Po + -rm -f src/$(DEPDIR)/nl_neigh_delete-nl-neigh-delete.Po + -rm -f src/$(DEPDIR)/nl_neigh_list-nl-neigh-list.Po + -rm -f src/$(DEPDIR)/nl_neightbl_list-nl-neightbl-list.Po + -rm -f src/$(DEPDIR)/nl_nh_list-nl-nh-list.Po + -rm -f src/$(DEPDIR)/nl_pktloc_lookup-nl-pktloc-lookup.Po + -rm -f src/$(DEPDIR)/nl_qdisc_add-nl-qdisc-add.Po + -rm -f src/$(DEPDIR)/nl_qdisc_delete-nl-qdisc-delete.Po + -rm -f src/$(DEPDIR)/nl_qdisc_list-nl-qdisc-list.Po + -rm -f src/$(DEPDIR)/nl_route_add-nl-route-add.Po + -rm -f src/$(DEPDIR)/nl_route_delete-nl-route-delete.Po + -rm -f src/$(DEPDIR)/nl_route_get-nl-route-get.Po + -rm -f src/$(DEPDIR)/nl_route_list-nl-route-list.Po + -rm -f src/$(DEPDIR)/nl_rule_list-nl-rule-list.Po + -rm -f src/$(DEPDIR)/nl_tctree_list-nl-tctree-list.Po + -rm -f src/$(DEPDIR)/nl_util_addr-nl-util-addr.Po + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-addr.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-class.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-cls.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-ct.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-exp.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-link.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-neigh.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-nh.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-qdisc.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-route.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-rule.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-tc.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-utils.Plo + -rm -f tests/$(DEPDIR)/check_all-check-all.Po + -rm -f tests/$(DEPDIR)/check_all-cksuite-all-addr.Po + -rm -f tests/$(DEPDIR)/check_all-cksuite-all-attr.Po + -rm -f tests/$(DEPDIR)/check_all-cksuite-all-ematch-tree-clone.Po + -rm -f tests/$(DEPDIR)/check_all-cksuite-all-netns.Po + -rm -f tests/$(DEPDIR)/check_direct-check-direct.Po + -rm -f tests/$(DEPDIR)/libnl_test_util_la-nl-test-util.Plo + -rm -f tests/$(DEPDIR)/test_cache_mngr-test-cache-mngr.Po + -rm -f tests/$(DEPDIR)/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.Po + -rm -f tests/$(DEPDIR)/test_create_bond-test-create-bond.Po + -rm -f tests/$(DEPDIR)/test_create_bridge-test-create-bridge.Po + -rm -f tests/$(DEPDIR)/test_create_geneve-test-create-geneve.Po + -rm -f tests/$(DEPDIR)/test_create_ifb-test-create-ifb.Po + -rm -f tests/$(DEPDIR)/test_create_ip6tnl-test-create-ip6tnl.Po + -rm -f tests/$(DEPDIR)/test_create_ipgre-test-create-ipgre.Po + -rm -f tests/$(DEPDIR)/test_create_ipgretap-test-create-ipgretap.Po + -rm -f tests/$(DEPDIR)/test_create_ipip-test-create-ipip.Po + -rm -f tests/$(DEPDIR)/test_create_ipvlan-test-create-ipvlan.Po + -rm -f tests/$(DEPDIR)/test_create_ipvti-test-create-ipvti.Po + -rm -f tests/$(DEPDIR)/test_create_macsec-test-create-macsec.Po + -rm -f tests/$(DEPDIR)/test_create_macvlan-test-create-macvlan.Po + -rm -f tests/$(DEPDIR)/test_create_macvtap-test-create-macvtap.Po + -rm -f tests/$(DEPDIR)/test_create_sit-test-create-sit.Po + -rm -f tests/$(DEPDIR)/test_create_veth-test-create-veth.Po + -rm -f tests/$(DEPDIR)/test_create_vlan-test-create-vlan.Po + -rm -f tests/$(DEPDIR)/test_create_vrf-test-create-vrf.Po + -rm -f tests/$(DEPDIR)/test_create_vxlan-test-create-vxlan.Po + -rm -f tests/$(DEPDIR)/test_create_xfrmi-test-create-xfrmi.Po + -rm -f tests/$(DEPDIR)/test_delete_link-test-delete-link.Po + -rm -f tests/$(DEPDIR)/test_genl-test-genl.Po + -rm -f tests/$(DEPDIR)/test_loopback_up_down-test-loopback-up-down.Po + -rm -f tests/$(DEPDIR)/test_nf_cache_mngr-test-nf-cache-mngr.Po + -rm -f tests/$(DEPDIR)/test_socket_creation-test-socket-creation.Po + -rm -f tests/$(DEPDIR)/test_u32_filter_with_actions-test-u32-filter-with-actions.Po -rm -f Makefile -distclean-am: clean-am distclean-generic distclean-libtool \ - distclean-tags +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-tags -dvi: dvi-recursive +dvi: dvi-am dvi-am: -html: html-recursive +html: html-am html-am: -info: info-recursive +info: info-am info-am: -install-data-am: install-pkgconfigDATA install-pkgsysconfDATA +install-data-am: install-libnlinclude_netlinkHEADERS \ + install-libnlinclude_netlink_cliHEADERS \ + install-libnlinclude_netlink_fib_lookupHEADERS \ + install-libnlinclude_netlink_genlHEADERS \ + install-libnlinclude_netlink_idiagHEADERS \ + install-libnlinclude_netlink_netfilterHEADERS \ + install-libnlinclude_netlink_routeHEADERS \ + install-libnlinclude_netlink_route_actHEADERS \ + install-libnlinclude_netlink_route_clsHEADERS \ + install-libnlinclude_netlink_route_cls_ematchHEADERS \ + install-libnlinclude_netlink_route_linkHEADERS \ + install-libnlinclude_netlink_route_qdiscHEADERS \ + install-libnlinclude_netlink_xfrmHEADERS install-man \ + install-pkgconfigDATA install-pkglib_clsLTLIBRARIES \ + install-pkglib_qdiscLTLIBRARIES install-pkgsysconfDATA -install-dvi: install-dvi-recursive +install-dvi: install-dvi-am install-dvi-am: -install-exec-am: +install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ + install-sbinPROGRAMS -install-html: install-html-recursive +install-html: install-html-am install-html-am: -install-info: install-info-recursive +install-info: install-info-am install-info-am: -install-man: +install-man: install-man8 -install-pdf: install-pdf-recursive +install-pdf: install-pdf-am install-pdf-am: -install-ps: install-ps-recursive +install-ps: install-ps-am install-ps-am: installcheck-am: -maintainer-clean: maintainer-clean-recursive +maintainer-clean: maintainer-clean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache + -rm -f lib/$(DEPDIR)/libnl_3_la-addr.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-attr.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-cache.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-cache_mngr.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-cache_mngt.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-data.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-error.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-handlers.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-hash.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-hashtable.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-mpls.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-msg.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-nl.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-object.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-socket.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-utils.Plo + -rm -f lib/$(DEPDIR)/libnl_3_la-version.Plo + -rm -f lib/cli/cls/$(DEPDIR)/basic_la-basic.Plo + -rm -f lib/cli/cls/$(DEPDIR)/cgroup_la-cgroup.Plo + -rm -f lib/cli/qdisc/$(DEPDIR)/bfifo_la-bfifo.Plo + -rm -f lib/cli/qdisc/$(DEPDIR)/blackhole_la-blackhole.Plo + -rm -f lib/cli/qdisc/$(DEPDIR)/fq_codel_la-fq_codel.Plo + -rm -f lib/cli/qdisc/$(DEPDIR)/hfsc_la-hfsc.Plo + -rm -f lib/cli/qdisc/$(DEPDIR)/htb_la-htb.Plo + -rm -f lib/cli/qdisc/$(DEPDIR)/ingress_la-ingress.Plo + -rm -f lib/cli/qdisc/$(DEPDIR)/pfifo_la-pfifo.Plo + -rm -f lib/cli/qdisc/$(DEPDIR)/plug_la-plug.Plo + -rm -f lib/fib_lookup/$(DEPDIR)/libnl_route_3_la-lookup.Plo + -rm -f lib/fib_lookup/$(DEPDIR)/libnl_route_3_la-request.Plo + -rm -f lib/genl/$(DEPDIR)/libnl_genl_3_la-ctrl.Plo + -rm -f lib/genl/$(DEPDIR)/libnl_genl_3_la-family.Plo + -rm -f lib/genl/$(DEPDIR)/libnl_genl_3_la-genl.Plo + -rm -f lib/genl/$(DEPDIR)/libnl_genl_3_la-mngt.Plo + -rm -f lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag.Plo + -rm -f lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_meminfo_obj.Plo + -rm -f lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_msg_obj.Plo + -rm -f lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_req_obj.Plo + -rm -f lib/idiag/$(DEPDIR)/libnl_idiag_3_la-idiag_vegasinfo_obj.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-ct.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-ct_obj.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-exp.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-exp_obj.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_msg.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_msg_obj.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-log_obj.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-netfilter.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-nfnl.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_msg.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_msg_obj.Plo + -rm -f lib/netfilter/$(DEPDIR)/libnl_nf_3_la-queue_obj.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-act.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-addr.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-class.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-classid.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-cls.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-link.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-mdb.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-neigh.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-neightbl.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-netconf.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-nexthop.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-nexthop_encap.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-nh.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-nh_encap_mpls.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-pktloc.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-pktloc_grammar.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-pktloc_syntax.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-qdisc.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-route.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-route_obj.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-route_utils.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-rtnl.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-rule.Plo + -rm -f lib/route/$(DEPDIR)/libnl_route_3_la-tc.Plo + -rm -f lib/route/act/$(DEPDIR)/libnl_route_3_la-gact.Plo + -rm -f lib/route/act/$(DEPDIR)/libnl_route_3_la-mirred.Plo + -rm -f lib/route/act/$(DEPDIR)/libnl_route_3_la-nat.Plo + -rm -f lib/route/act/$(DEPDIR)/libnl_route_3_la-skbedit.Plo + -rm -f lib/route/act/$(DEPDIR)/libnl_route_3_la-vlan.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-basic.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-cgroup.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch_grammar.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-ematch_syntax.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-flower.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-fw.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-mall.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-police.Plo + -rm -f lib/route/cls/$(DEPDIR)/libnl_route_3_la-u32.Plo + -rm -f lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-cmp.Plo + -rm -f lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-container.Plo + -rm -f lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-meta.Plo + -rm -f lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-nbyte.Plo + -rm -f lib/route/cls/ematch/$(DEPDIR)/libnl_route_3_la-text.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-api.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-bonding.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-bridge.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-bridge_info.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-can.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-dummy.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-geneve.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-ifb.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-inet.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-inet6.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6gre.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6tnl.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-ip6vti.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-ipgre.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-ipip.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-ipvlan.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-ipvti.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-macsec.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-macvlan.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-ppp.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-sit.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-sriov.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-team.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-veth.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-vlan.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-vrf.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-vxlan.Plo + -rm -f lib/route/link/$(DEPDIR)/libnl_route_3_la-xfrmi.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-blackhole.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-cbq.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-dsmark.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-fifo.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-fq_codel.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-hfsc.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-htb.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-ingress.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-mqprio.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-netem.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-plug.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-prio.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-red.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-sfq.Plo + -rm -f lib/route/qdisc/$(DEPDIR)/libnl_route_3_la-tbf.Plo + -rm -f lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-ae.Plo + -rm -f lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-lifetime.Plo + -rm -f lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-sa.Plo + -rm -f lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-selector.Plo + -rm -f lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-sp.Plo + -rm -f lib/xfrm/$(DEPDIR)/libnl_xfrm_3_la-template.Plo + -rm -f src/$(DEPDIR)/genl_ctrl_list-genl-ctrl-list.Po + -rm -f src/$(DEPDIR)/idiag_socket_details-idiag-socket-details.Po + -rm -f src/$(DEPDIR)/nf_ct_add-nf-ct-add.Po + -rm -f src/$(DEPDIR)/nf_ct_events-nf-ct-events.Po + -rm -f src/$(DEPDIR)/nf_ct_list-nf-ct-list.Po + -rm -f src/$(DEPDIR)/nf_exp_add-nf-exp-add.Po + -rm -f src/$(DEPDIR)/nf_exp_delete-nf-exp-delete.Po + -rm -f src/$(DEPDIR)/nf_exp_list-nf-exp-list.Po + -rm -f src/$(DEPDIR)/nf_log-nf-log.Po + -rm -f src/$(DEPDIR)/nf_monitor-nf-monitor.Po + -rm -f src/$(DEPDIR)/nf_queue-nf-queue.Po + -rm -f src/$(DEPDIR)/nl_addr_add-nl-addr-add.Po + -rm -f src/$(DEPDIR)/nl_addr_delete-nl-addr-delete.Po + -rm -f src/$(DEPDIR)/nl_addr_list-nl-addr-list.Po + -rm -f src/$(DEPDIR)/nl_class_add-nl-class-add.Po + -rm -f src/$(DEPDIR)/nl_class_delete-nl-class-delete.Po + -rm -f src/$(DEPDIR)/nl_class_list-nl-class-list.Po + -rm -f src/$(DEPDIR)/nl_classid_lookup-nl-classid-lookup.Po + -rm -f src/$(DEPDIR)/nl_cls_add-nl-cls-add.Po + -rm -f src/$(DEPDIR)/nl_cls_delete-nl-cls-delete.Po + -rm -f src/$(DEPDIR)/nl_cls_list-nl-cls-list.Po + -rm -f src/$(DEPDIR)/nl_fib_lookup-nl-fib-lookup.Po + -rm -f src/$(DEPDIR)/nl_link_enslave-nl-link-enslave.Po + -rm -f src/$(DEPDIR)/nl_link_ifindex2name-nl-link-ifindex2name.Po + -rm -f src/$(DEPDIR)/nl_link_list-nl-link-list.Po + -rm -f src/$(DEPDIR)/nl_link_name2ifindex-nl-link-name2ifindex.Po + -rm -f src/$(DEPDIR)/nl_link_release-nl-link-release.Po + -rm -f src/$(DEPDIR)/nl_link_set-nl-link-set.Po + -rm -f src/$(DEPDIR)/nl_link_stats-nl-link-stats.Po + -rm -f src/$(DEPDIR)/nl_list_caches-nl-list-caches.Po + -rm -f src/$(DEPDIR)/nl_list_sockets-nl-list-sockets.Po + -rm -f src/$(DEPDIR)/nl_monitor-nl-monitor.Po + -rm -f src/$(DEPDIR)/nl_neigh_add-nl-neigh-add.Po + -rm -f src/$(DEPDIR)/nl_neigh_delete-nl-neigh-delete.Po + -rm -f src/$(DEPDIR)/nl_neigh_list-nl-neigh-list.Po + -rm -f src/$(DEPDIR)/nl_neightbl_list-nl-neightbl-list.Po + -rm -f src/$(DEPDIR)/nl_nh_list-nl-nh-list.Po + -rm -f src/$(DEPDIR)/nl_pktloc_lookup-nl-pktloc-lookup.Po + -rm -f src/$(DEPDIR)/nl_qdisc_add-nl-qdisc-add.Po + -rm -f src/$(DEPDIR)/nl_qdisc_delete-nl-qdisc-delete.Po + -rm -f src/$(DEPDIR)/nl_qdisc_list-nl-qdisc-list.Po + -rm -f src/$(DEPDIR)/nl_route_add-nl-route-add.Po + -rm -f src/$(DEPDIR)/nl_route_delete-nl-route-delete.Po + -rm -f src/$(DEPDIR)/nl_route_get-nl-route-get.Po + -rm -f src/$(DEPDIR)/nl_route_list-nl-route-list.Po + -rm -f src/$(DEPDIR)/nl_rule_list-nl-rule-list.Po + -rm -f src/$(DEPDIR)/nl_tctree_list-nl-tctree-list.Po + -rm -f src/$(DEPDIR)/nl_util_addr-nl-util-addr.Po + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-addr.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-class.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-cls.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-ct.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-exp.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-link.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-neigh.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-nh.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-qdisc.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-route.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-rule.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-tc.Plo + -rm -f src/lib/$(DEPDIR)/libnl_cli_3_la-utils.Plo + -rm -f tests/$(DEPDIR)/check_all-check-all.Po + -rm -f tests/$(DEPDIR)/check_all-cksuite-all-addr.Po + -rm -f tests/$(DEPDIR)/check_all-cksuite-all-attr.Po + -rm -f tests/$(DEPDIR)/check_all-cksuite-all-ematch-tree-clone.Po + -rm -f tests/$(DEPDIR)/check_all-cksuite-all-netns.Po + -rm -f tests/$(DEPDIR)/check_direct-check-direct.Po + -rm -f tests/$(DEPDIR)/libnl_test_util_la-nl-test-util.Plo + -rm -f tests/$(DEPDIR)/test_cache_mngr-test-cache-mngr.Po + -rm -f tests/$(DEPDIR)/test_complex_HTB_with_hash_filters-test-complex-HTB-with-hash-filters.Po + -rm -f tests/$(DEPDIR)/test_create_bond-test-create-bond.Po + -rm -f tests/$(DEPDIR)/test_create_bridge-test-create-bridge.Po + -rm -f tests/$(DEPDIR)/test_create_geneve-test-create-geneve.Po + -rm -f tests/$(DEPDIR)/test_create_ifb-test-create-ifb.Po + -rm -f tests/$(DEPDIR)/test_create_ip6tnl-test-create-ip6tnl.Po + -rm -f tests/$(DEPDIR)/test_create_ipgre-test-create-ipgre.Po + -rm -f tests/$(DEPDIR)/test_create_ipgretap-test-create-ipgretap.Po + -rm -f tests/$(DEPDIR)/test_create_ipip-test-create-ipip.Po + -rm -f tests/$(DEPDIR)/test_create_ipvlan-test-create-ipvlan.Po + -rm -f tests/$(DEPDIR)/test_create_ipvti-test-create-ipvti.Po + -rm -f tests/$(DEPDIR)/test_create_macsec-test-create-macsec.Po + -rm -f tests/$(DEPDIR)/test_create_macvlan-test-create-macvlan.Po + -rm -f tests/$(DEPDIR)/test_create_macvtap-test-create-macvtap.Po + -rm -f tests/$(DEPDIR)/test_create_sit-test-create-sit.Po + -rm -f tests/$(DEPDIR)/test_create_veth-test-create-veth.Po + -rm -f tests/$(DEPDIR)/test_create_vlan-test-create-vlan.Po + -rm -f tests/$(DEPDIR)/test_create_vrf-test-create-vrf.Po + -rm -f tests/$(DEPDIR)/test_create_vxlan-test-create-vxlan.Po + -rm -f tests/$(DEPDIR)/test_create_xfrmi-test-create-xfrmi.Po + -rm -f tests/$(DEPDIR)/test_delete_link-test-delete-link.Po + -rm -f tests/$(DEPDIR)/test_genl-test-genl.Po + -rm -f tests/$(DEPDIR)/test_loopback_up_down-test-loopback-up-down.Po + -rm -f tests/$(DEPDIR)/test_nf_cache_mngr-test-nf-cache-mngr.Po + -rm -f tests/$(DEPDIR)/test_socket_creation-test-socket-creation.Po + -rm -f tests/$(DEPDIR)/test_u32_filter_with_actions-test-u32-filter-with-actions.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic -mostlyclean: mostlyclean-recursive +mostlyclean: mostlyclean-am -mostlyclean-am: mostlyclean-generic mostlyclean-libtool +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool -pdf: pdf-recursive +pdf: pdf-am pdf-am: -ps: ps-recursive +ps: ps-am ps-am: -uninstall-am: uninstall-pkgconfigDATA uninstall-pkgsysconfDATA +uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ + uninstall-libnlinclude_netlinkHEADERS \ + uninstall-libnlinclude_netlink_cliHEADERS \ + uninstall-libnlinclude_netlink_fib_lookupHEADERS \ + uninstall-libnlinclude_netlink_genlHEADERS \ + uninstall-libnlinclude_netlink_idiagHEADERS \ + uninstall-libnlinclude_netlink_netfilterHEADERS \ + uninstall-libnlinclude_netlink_routeHEADERS \ + uninstall-libnlinclude_netlink_route_actHEADERS \ + uninstall-libnlinclude_netlink_route_clsHEADERS \ + uninstall-libnlinclude_netlink_route_cls_ematchHEADERS \ + uninstall-libnlinclude_netlink_route_linkHEADERS \ + uninstall-libnlinclude_netlink_route_qdiscHEADERS \ + uninstall-libnlinclude_netlink_xfrmHEADERS uninstall-man \ + uninstall-pkgconfigDATA uninstall-pkglib_clsLTLIBRARIES \ + uninstall-pkglib_qdiscLTLIBRARIES uninstall-pkgsysconfDATA \ + uninstall-sbinPROGRAMS -.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ - install-am install-strip tags-recursive +uninstall-man: uninstall-man8 -.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ - all all-am am--refresh check check-am clean clean-generic \ - clean-libtool ctags ctags-recursive dist dist-all dist-bzip2 \ - dist-gzip dist-lzip dist-lzma dist-shar dist-tarZ dist-xz \ - dist-zip distcheck distclean distclean-generic \ +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles am--refresh check \ + check-TESTS check-am check-local clean clean-binPROGRAMS \ + clean-checkLTLIBRARIES clean-checkPROGRAMS clean-cscope \ + clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ + clean-pkglib_clsLTLIBRARIES clean-pkglib_qdiscLTLIBRARIES \ + clean-sbinPROGRAMS cscope cscopelist-am ctags ctags-am dist \ + dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ + dist-xz dist-zip dist-zstd distcheck distclean \ + distclean-compile distclean-generic distclean-hdr \ distclean-libtool distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-pkgconfigDATA \ - install-pkgsysconfDATA install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs installdirs-am \ - maintainer-clean maintainer-clean-generic mostlyclean \ + install install-am install-binPROGRAMS install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-libLTLIBRARIES \ + install-libnlinclude_netlinkHEADERS \ + install-libnlinclude_netlink_cliHEADERS \ + install-libnlinclude_netlink_fib_lookupHEADERS \ + install-libnlinclude_netlink_genlHEADERS \ + install-libnlinclude_netlink_idiagHEADERS \ + install-libnlinclude_netlink_netfilterHEADERS \ + install-libnlinclude_netlink_routeHEADERS \ + install-libnlinclude_netlink_route_actHEADERS \ + install-libnlinclude_netlink_route_clsHEADERS \ + install-libnlinclude_netlink_route_cls_ematchHEADERS \ + install-libnlinclude_netlink_route_linkHEADERS \ + install-libnlinclude_netlink_route_qdiscHEADERS \ + install-libnlinclude_netlink_xfrmHEADERS install-man \ + install-man8 install-pdf install-pdf-am install-pkgconfigDATA \ + install-pkglib_clsLTLIBRARIES install-pkglib_qdiscLTLIBRARIES \ + install-pkgsysconfDATA install-ps install-ps-am \ + install-sbinPROGRAMS install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-recursive uninstall uninstall-am \ - uninstall-pkgconfigDATA uninstall-pkgsysconfDATA + recheck tags tags-am uninstall uninstall-am \ + uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ + uninstall-libnlinclude_netlinkHEADERS \ + uninstall-libnlinclude_netlink_cliHEADERS \ + uninstall-libnlinclude_netlink_fib_lookupHEADERS \ + uninstall-libnlinclude_netlink_genlHEADERS \ + uninstall-libnlinclude_netlink_idiagHEADERS \ + uninstall-libnlinclude_netlink_netfilterHEADERS \ + uninstall-libnlinclude_netlink_routeHEADERS \ + uninstall-libnlinclude_netlink_route_actHEADERS \ + uninstall-libnlinclude_netlink_route_clsHEADERS \ + uninstall-libnlinclude_netlink_route_cls_ematchHEADERS \ + uninstall-libnlinclude_netlink_route_linkHEADERS \ + uninstall-libnlinclude_netlink_route_qdiscHEADERS \ + uninstall-libnlinclude_netlink_xfrmHEADERS uninstall-man \ + uninstall-man8 uninstall-pkgconfigDATA \ + uninstall-pkglib_clsLTLIBRARIES \ + uninstall-pkglib_qdiscLTLIBRARIES uninstall-pkgsysconfDATA \ + uninstall-sbinPROGRAMS + +.PRECIOUS: Makefile + + +############################################################################### + +# Hack to avoid using ylwrap. It does not function correctly in combination +# with --header-file= + +lib/route/pktloc_grammar.h: lib/route/pktloc_grammar.c + @true + +lib/route/pktloc_grammar.c: lib/route/pktloc_grammar.l lib/route/.dirstamp + $(AM_V_GEN) $(FLEX) --header-file=lib/route/pktloc_grammar.h $(LFLAGS) -o $@ $< + +lib/route/pktloc_syntax.h: lib/route/pktloc_syntax.c + @true + +lib/route/pktloc_syntax.c: lib/route/pktloc_syntax.y lib/route/.dirstamp + $(AM_V_GEN) $(YACC) -d $(YFLAGS) -o $@ $< + +lib/route/cls/ematch_grammar.h: lib/route/cls/ematch_grammar.c + @true + +lib/route/cls/ematch_grammar.c: lib/route/cls/ematch_grammar.l lib/route/cls/.dirstamp + $(AM_V_GEN) $(FLEX) --header-file=lib/route/cls/ematch_grammar.h $(LFLAGS) -o $@ $< + +lib/route/cls/ematch_syntax.h: lib/route/cls/ematch_syntax.c + @true + +lib/route/cls/ematch_syntax.c: lib/route/cls/ematch_syntax.y lib/route/cls/.dirstamp + $(AM_V_GEN) $(YACC) -d $(YFLAGS) -o $@ $< + +$(lib_libnl_route_3_la_OBJECTS): $(grammar_files_headers) + +############################################################################### + +python-build: + cd "$(srcdir)/python"; \ + python setup.py build + +.PHONY: python-build + +############################################################################### + +%.build-headers-test.c: % + mkdir -p "$(dir $@)" + printf "#include <$$(echo "$<" | sed 's|.*\\nint main(int argc, char **argv) { return 0; }" > $@ + +%.build-headers-test.o: %.build-headers-test.c + $(COMPILE) -Wall -Werror -Wno-error=cpp -I$(srcdir)/include -I$(builddir)/include -c -o $@ $< + +# Test whether the public headers are all self-contained and can be build. +# This test is not hooked up as `make check`. +check-local-build-headers: $(BUILD_HEADERS_OBJS) + +############################################################################### + +check-local: $(check_local) + +.PHONY: $(check_local) + +############################################################################### + +check-progs: all $(check_PROGRAMS) $(check_LTLIBRARIES) + +.PHONY: check-progs +############################################################################### # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/aclocal.m4 b/aclocal.m4 index af98b20..10e5e0a 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,8 +1,7 @@ -# generated automatically by aclocal 1.11.6 -*- Autoconf -*- +# generated automatically by aclocal 1.16.5 -*- Autoconf -*- + +# Copyright (C) 1996-2021 Free Software Foundation, Inc. -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, -# Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -12,43 +11,76 @@ # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl -m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],, -[m4_warning([this file was generated for autoconf 2.68. +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],, +[m4_warning([this file was generated for autoconf 2.71. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. -To do so, use the procedure documented by the package, typically `autoreconf'.])]) +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) -# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- -# serial 1 (pkg-config-0.24) -# -# Copyright © 2004 Scott James Remnant . -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. +# pkg.m4 - Macros to locate and use pkg-config. -*- Autoconf -*- +# serial 12 (pkg-config-0.29.2) -# PKG_PROG_PKG_CONFIG([MIN-VERSION]) -# ---------------------------------- +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.2]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) -m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) @@ -66,18 +98,19 @@ if test -n "$PKG_CONFIG"; then PKG_CONFIG="" fi fi[]dnl -])# PKG_PROG_PKG_CONFIG +])dnl PKG_PROG_PKG_CONFIG -# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -# -# Check to see whether a particular set of modules exists. Similar -# to PKG_CHECK_MODULES(), but does not set variables or print errors. -# -# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) -# only at the first occurence in configure.ac, so if the first place -# it's called might be skipped (such as if it is within an "if", you -# have to call PKG_CHECK_EXISTS manually -# -------------------------------------------------------------- +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurrence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ @@ -87,22 +120,26 @@ m4_ifvaln([$3], [else $3])dnl fi]) -# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) -# --------------------------------------------- +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], - [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl -])# _PKG_CONFIG +])dnl _PKG_CONFIG -# _PKG_SHORT_ERRORS_SUPPORTED -# ----------------------------- +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -110,26 +147,24 @@ if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then else _pkg_short_errors_supported=no fi[]dnl -])# _PKG_SHORT_ERRORS_SUPPORTED +])dnl _PKG_SHORT_ERRORS_SUPPORTED -# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], -# [ACTION-IF-NOT-FOUND]) -# -# -# Note that if there is a possibility the first call to -# PKG_CHECK_MODULES might not happen, you should be sure to include an -# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac -# -# -# -------------------------------------------------------------- +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no -AC_MSG_CHECKING([for $1]) +AC_MSG_CHECKING([for $2]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) @@ -139,17 +174,17 @@ and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then - AC_MSG_RESULT([no]) + AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then - $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1` - else - $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1` + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD - m4_default([$4], [AC_MSG_ERROR( + m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS @@ -157,46 +192,194 @@ $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. -_PKG_TEXT]) +_PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then - AC_MSG_RESULT([no]) - m4_default([$4], [AC_MSG_FAILURE( + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT -To get pkg-config, see .]) +To get pkg-config, see .])[]dnl ]) else - $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS - $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) - $3 + $3 fi[]dnl -])# PKG_CHECK_MODULES +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR -# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008, 2011 Free Software -# Foundation, Inc. +dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND], +dnl [DESCRIPTION], [DEFAULT]) +dnl ------------------------------------------ +dnl +dnl Prepare a "--with-" configure option using the lowercase +dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and +dnl PKG_CHECK_MODULES in a single macro. +AC_DEFUN([PKG_WITH_MODULES], +[ +m4_pushdef([with_arg], m4_tolower([$1])) + +m4_pushdef([description], + [m4_default([$5], [build with ]with_arg[ support])]) + +m4_pushdef([def_arg], [m4_default([$6], [auto])]) +m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes]) +m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no]) + +m4_case(def_arg, + [yes],[m4_pushdef([with_without], [--without-]with_arg)], + [m4_pushdef([with_without],[--with-]with_arg)]) + +AC_ARG_WITH(with_arg, + AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),, + [AS_TR_SH([with_]with_arg)=def_arg]) + +AS_CASE([$AS_TR_SH([with_]with_arg)], + [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)], + [auto],[PKG_CHECK_MODULES([$1],[$2], + [m4_n([def_action_if_found]) $3], + [m4_n([def_action_if_not_found]) $4])]) + +m4_popdef([with_arg]) +m4_popdef([description]) +m4_popdef([def_arg]) + +])dnl PKG_WITH_MODULES + +dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [DESCRIPTION], [DEFAULT]) +dnl ----------------------------------------------- +dnl +dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES +dnl check._[VARIABLE-PREFIX] is exported as make variable. +AC_DEFUN([PKG_HAVE_WITH_MODULES], +[ +PKG_WITH_MODULES([$1],[$2],,,[$3],[$4]) + +AM_CONDITIONAL([HAVE_][$1], + [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"]) +])dnl PKG_HAVE_WITH_MODULES + +dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [DESCRIPTION], [DEFAULT]) +dnl ------------------------------------------------------ +dnl +dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after +dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make +dnl and preprocessor variable. +AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES], +[ +PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4]) + +AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"], + [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])]) +])dnl PKG_HAVE_DEFINE_WITH_MODULES + +# Copyright (C) 2002-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 1 - # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], -[am__api_version='1.11' +[am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.11.6], [], +m4_if([$1], [1.16.5], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -212,19 +395,17 @@ m4_define([_AM_AUTOCONF_VERSION], []) # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.11.6])dnl +[AM_AUTOMAKE_VERSION([1.16.5])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) -# Copyright (C) 2011 Free Software Foundation, Inc. +# Copyright (C) 2011-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 1 - # AM_PROG_AR([ACT-IF-FAIL]) # ------------------------- # Try to determine the archiver interface, and trigger the ar-lib wrapper @@ -239,7 +420,8 @@ AC_CHECK_TOOLS([AR], [ar lib "link -lib"], [false]) : ${AR=ar} AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface], - [am_cv_ar_interface=ar + [AC_LANG_PUSH([C]) + am_cv_ar_interface=ar AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int some_variable = 0;]])], [am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([am_ar_try]) @@ -256,7 +438,7 @@ AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface], fi rm -f conftest.lib libconftest.a ]) - ]) + AC_LANG_POP([C])]) case $am_cv_ar_interface in ar) @@ -280,17 +462,15 @@ AC_SUBST([AR])dnl # AM_AUX_DIR_EXPAND -*- Autoconf -*- -# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc. +# Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 1 - # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets -# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to -# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and @@ -309,7 +489,7 @@ AC_SUBST([AR])dnl # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually -# harmless because $srcdir is `.', but things will broke when you +# harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, @@ -327,30 +507,26 @@ AC_SUBST([AR])dnl # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], -[dnl Rely on autoconf to set up CDPATH properly. -AC_PREREQ([2.50])dnl -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 -# Free Software Foundation, Inc. +# Copyright (C) 1997-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 9 - # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], -[AC_PREREQ(2.52)dnl - ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], - [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl @@ -369,16 +545,14 @@ AC_CONFIG_COMMANDS_PRE( Usually this means the macro was only invoked conditionally.]]) fi])]) -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009, -# 2010, 2011 Free Software Foundation, Inc. +# Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 12 -# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing @@ -388,7 +562,7 @@ fi])]) # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. -# NAME is "CC", "CXX", "GCJ", or "OBJC". +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was @@ -401,12 +575,13 @@ AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl -ifelse([$1], CC, [depcc="$CC" am_compiler_list=], - [$1], CXX, [depcc="$CXX" am_compiler_list=], - [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], - [$1], UPC, [depcc="$UPC" am_compiler_list=], - [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], - [depcc="$$1" am_compiler_list=]) +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], @@ -414,8 +589,8 @@ AC_CACHE_CHECK([dependency style of $depcc], # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're @@ -455,16 +630,16 @@ AC_CACHE_CHECK([dependency style of $depcc], : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with - # Solaris 8's {/usr,}/bin/sh. - touch sub/conftst$i.h + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - # We check with `-c' and `-o' for the sake of the "dashmstdout" + # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in @@ -473,8 +648,8 @@ AC_CACHE_CHECK([dependency style of $depcc], test "$am__universal" = false || continue ;; nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else @@ -482,7 +657,7 @@ AC_CACHE_CHECK([dependency style of $depcc], fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok `-c -o', but also, the minuso test has + # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} @@ -530,7 +705,7 @@ AM_CONDITIONAL([am__fastdep$1], [ # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. -# This macro is AC_REQUIREd in _AM_DEPENDENCIES +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl @@ -540,9 +715,13 @@ AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], -[AC_ARG_ENABLE(dependency-tracking, -[ --disable-dependency-tracking speeds up one-time build - --enable-dependency-tracking do not reject slow dependency extractors]) +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' @@ -557,67 +736,56 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl # Generate code to set up dependency tracking. -*- Autoconf -*- -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 -# Free Software Foundation, Inc. +# Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -#serial 5 - # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ - # Autoconf 2.62 quotes --file arguments for eval, but not when files + # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + AS_CASE([$CONFIG_FILES], + [*\'*], [eval set x "$CONFIG_FILES"], + [*], [set x $CONFIG_FILES]) shift - for mf + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf do # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named `Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line + am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`AS_DIRNAME("$mf")` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running `make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # When using ansi2knr, U may be empty or an underscore; expand it - U=`sed -n 's/^U = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`AS_DIRNAME(["$file"])` - AS_MKDIR_P([$dirpart/$fdir]) - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`AS_DIRNAME(["$am_mf"])` + am_filepart=`AS_BASENAME(["$am_mf"])` + AM_RUN_LOG([cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles]) || am_rc=$? done + if test $am_rc -ne 0; then + AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE="gmake" (or whatever is + necessary). You can also try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking).]) + fi + AS_UNSET([am_dirpart]) + AS_UNSET([am_filepart]) + AS_UNSET([am_mf]) + AS_UNSET([am_rc]) + rm -f conftest-deps.mk } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS @@ -626,29 +794,31 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # -# This code is only required when automatic dependency tracking -# is enabled. FIXME. This creates each `.P' file that we will -# need in order to bootstrap the dependency handling code. +# This code is only required when automatic dependency tracking is enabled. +# This creates each '.Po' and '.Plo' makefile fragment that we'll need in +# order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], - [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) -]) + [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) # Do all the work for Automake. -*- Autoconf -*- -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005, 2006, 2008, 2009 Free Software Foundation, Inc. +# Copyright (C) 1996-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 16 - # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- @@ -661,7 +831,11 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], -[AC_PREREQ([2.62])dnl +[AC_PREREQ([2.65])dnl +m4_ifdef([_$0_ALREADY_INIT], + [m4_fatal([$0 expanded multiple times +]m4_defn([_$0_ALREADY_INIT]))], + [m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl @@ -690,33 +864,42 @@ AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], -[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. -m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, +m4_if( + m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, -[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) - AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl -AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) -AM_MISSING_PROG(AUTOCONF, autoconf) -AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) -AM_MISSING_PROG(AUTOHEADER, autoheader) -AM_MISSING_PROG(MAKEINFO, makeinfo) +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl -AC_REQUIRE([AM_PROG_MKDIR_P])dnl -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl @@ -725,34 +908,96 @@ _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], - [_AM_DEPENDENCIES(CC)], - [define([AC_PROG_CC], - defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], - [_AM_DEPENDENCIES(CXX)], - [define([AC_PROG_CXX], - defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], - [_AM_DEPENDENCIES(OBJC)], - [define([AC_PROG_OBJC], - defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) -_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl -dnl The `parallel-tests' driver may need to know about EXEEXT, so add the -dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro -dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +# Variables for tags utilities; see am/tags.am +if test -z "$CTAGS"; then + CTAGS=ctags +fi +AC_SUBST([CTAGS]) +if test -z "$ETAGS"; then + ETAGS=etags +fi +AC_SUBST([ETAGS]) +if test -z "$CSCOPE"; then + CSCOPE=cscope +fi +AC_SUBST([CSCOPE]) + +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) -dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) - # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. @@ -774,21 +1019,18 @@ for _am_header in $config_headers :; do done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# Copyright (C) 2001, 2003, 2005, 2008, 2011 Free Software Foundation, -# Inc. +# Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 1 - # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -if test x"${install_sh}" != xset; then +if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; @@ -796,16 +1038,14 @@ if test x"${install_sh}" != xset; then install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi -AC_SUBST(install_sh)]) +AC_SUBST([install_sh])]) -# Copyright (C) 2003, 2005 Free Software Foundation, Inc. +# Copyright (C) 2003-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 2 - # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], @@ -821,102 +1061,55 @@ AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- -# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. +# Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 4 - # AM_MAKE_INCLUDE() # ----------------- -# Check to see how make treats includes. +# Check whether make has an 'include' directive that can support all +# the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], -[am_make=${MAKE-make} -cat > confinc << 'END' +[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) +cat > confinc.mk << 'END' am__doit: - @echo this is the am__doit target + @echo this is the am__doit target >confinc.out .PHONY: am__doit END -# If we don't find an include directive, just comment out the code. -AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from `make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD - ;; - esac -fi -AC_SUBST([am__include]) -AC_SUBST([am__quote]) -AC_MSG_RESULT([$_am_result]) -rm -f confinc confmf -]) - -# Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2008 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 6 - -# AM_PROG_CC_C_O -# -------------- -# Like AC_PROG_CC_C_O, but changed for automake. -AC_DEFUN([AM_PROG_CC_C_O], -[AC_REQUIRE([AC_PROG_CC_C_O])dnl -AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -AC_REQUIRE_AUX_FILE([compile])dnl -# FIXME: we rely on the cache variable name because -# there is no other way. -set dummy $CC -am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` -eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o -if test "$am_t" != yes; then - # Losing compiler, so override with the script. - # FIXME: It is wrong to rewrite CC. - # But if we don't then we get into trouble of one sort or another. - # A longer-term fix would be to have automake use am__CC in this case, - # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" - CC="$am_aux_dir/compile $CC" -fi -dnl Make sure AC_PROG_CC is never called again, or it will override our -dnl setting of CC. -m4_define([AC_PROG_CC], - [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) -]) +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) + AS_CASE([$?:`cat confinc.out 2>/dev/null`], + ['0:this is the am__doit target'], + [AS_CASE([$s], + [BSD], [am__include='.include' am__quote='"'], + [am__include='include' am__quote=''])]) + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +AC_MSG_RESULT([${_am_result}]) +AC_SUBST([am__include])]) +AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 -# Free Software Foundation, Inc. +# Copyright (C) 1997-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 6 - # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], @@ -924,71 +1117,33 @@ AC_DEFUN([AM_MISSING_PROG], $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) - # AM_MISSING_HAS_RUN # ------------------ -# Define MISSING if not defined so far and test if it supports --run. -# If it does, set am_missing_run to use it, otherwise, to nothing. +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; - *) - MISSING="\${SHELL} $am_aux_dir/missing" ;; - esac + MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL -if eval "$MISSING --run true"; then - am_missing_run="$MISSING --run " +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " else am_missing_run= - AC_MSG_WARN([`missing' script is too old or missing]) + AC_MSG_WARN(['missing' script is too old or missing]) fi ]) -# Copyright (C) 2003, 2004, 2005, 2006, 2011 Free Software Foundation, -# Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 1 - -# AM_PROG_MKDIR_P -# --------------- -# Check for `mkdir -p'. -AC_DEFUN([AM_PROG_MKDIR_P], -[AC_PREREQ([2.60])dnl -AC_REQUIRE([AC_PROG_MKDIR_P])dnl -dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, -dnl while keeping a definition of mkdir_p for backward compatibility. -dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. -dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of -dnl Makefile.ins that do not define MKDIR_P, so we do our own -dnl adjustment using top_builddir (which is defined more often than -dnl MKDIR_P). -AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl -case $mkdir_p in - [[\\/$]]* | ?:[[\\/]]*) ;; - */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; -esac -]) - # Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001, 2002, 2003, 2005, 2008, 2010 Free Software -# Foundation, Inc. +# Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 5 - # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], @@ -998,7 +1153,7 @@ AC_DEFUN([_AM_MANGLE_OPTION], # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], -[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ @@ -1012,24 +1167,82 @@ AC_DEFUN([_AM_SET_OPTIONS], AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) -# Check to make sure that the build environment is sane. -*- Autoconf -*- +# Copyright (C) 1999-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) -# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 -# Free Software Foundation, Inc. +# Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 5 +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) -# Just in case -sleep 1 -echo timestamp > conftest.file # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' @@ -1040,32 +1253,40 @@ case `pwd` in esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) - AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac -# Do `set' in a subshell so we don't clobber the current shell's +# Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( - set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` - if test "$[*]" = "X"; then - # -L didn't work. - set X `ls -t "$srcdir/configure" conftest.file` - fi - rm -f conftest.file - if test "$[*]" != "X $srcdir/configure conftest.file" \ - && test "$[*]" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken -alias in your environment]) - fi - + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done test "$[2]" = conftest.file ) then @@ -1075,31 +1296,50 @@ else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi -AC_MSG_RESULT(yes)]) +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) -# Copyright (C) 2009, 2011 Free Software Foundation, Inc. +# Copyright (C) 2009-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 2 - # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT -# (`yes' being less verbose, `no' or empty being verbose). +# ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], -[AC_ARG_ENABLE([silent-rules], -[ --enable-silent-rules less verbose build output (undo: `make V=1') - --disable-silent-rules verbose build output (undo: `make V=0')]) -case $enable_silent_rules in -yes) AM_DEFAULT_VERBOSITY=0;; -no) AM_DEFAULT_VERBOSITY=1;; -*) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl -dnl A few `make' implementations (e.g., NonStop OS and NextStep) +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} @@ -1117,7 +1357,7 @@ else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then - dnl Using `$V' instead of `$(V)' breaks IRIX make. + dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else @@ -1134,44 +1374,40 @@ AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) -# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc. +# Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 1 - # AM_PROG_INSTALL_STRIP # --------------------- -# One issue with vendor `install' (even GNU) is that you can't +# One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we -# always use install-sh in `make install-strip', and initialize +# always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl -# Installed binaries are usually stripped using `strip' when the user -# run `make install-strip'. However `strip' might not be the right +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake -# will honor the `STRIP' environment variable to overrule this program. -dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) -# Copyright (C) 2006, 2008, 2010 Free Software Foundation, Inc. +# Copyright (C) 2006-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 3 - # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. @@ -1185,18 +1421,16 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- -# Copyright (C) 2004, 2005, 2012 Free Software Foundation, Inc. +# Copyright (C) 2004-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 2 - # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. -# FORMAT should be one of `v7', `ustar', or `pax'. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory @@ -1206,76 +1440,114 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar +# AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) -m4_if([$1], [v7], - [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], - [m4_case([$1], [ustar],, [pax],, - [m4_fatal([Unknown tar format])]) -AC_MSG_CHECKING([how to create a $1 tar archive]) -# Loop over all known methods to create a tar archive until one works. + +# We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' -_am_tools=${am_cv_prog_tar_$1-$_am_tools} -# Do not fold the above two line into one, because Tru64 sh and -# Solaris sh will not grok spaces in the rhs of `-'. -for _am_tool in $_am_tools -do - case $_am_tool in - gnutar) - for _am_tar in tar gnutar gtar; - do - AM_RUN_LOG([$_am_tar --version]) && break - done - am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' - am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' - am__untar="$_am_tar -xf -" - ;; - plaintar) - # Must skip GNU tar: if it does not support --format= it doesn't create - # ustar tarball either. - (tar --version) >/dev/null 2>&1 && continue - am__tar='tar chf - "$$tardir"' - am__tar_='tar chf - "$tardir"' - am__untar='tar xf -' - ;; - pax) - am__tar='pax -L -x $1 -w "$$tardir"' - am__tar_='pax -L -x $1 -w "$tardir"' - am__untar='pax -r' - ;; - cpio) - am__tar='find "$$tardir" -print | cpio -o -H $1 -L' - am__tar_='find "$tardir" -print | cpio -o -H $1 -L' - am__untar='cpio -i -H $1 -d' - ;; - none) - am__tar=false - am__tar_=false - am__untar=false - ;; - esac - # If the value was cached, stop now. We just wanted to have am__tar - # and am__untar set. - test -n "${am_cv_prog_tar_$1}" && break +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac - # tar/untar a dummy directory, and stop if the command works - rm -rf conftest.dir - mkdir conftest.dir - echo GrepMe > conftest.dir/file - AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi + done rm -rf conftest.dir - if test -s conftest.tar; then - AM_RUN_LOG([$am__untar /dev/null 2>&1 && break - fi -done -rm -rf conftest.dir -AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) -AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR diff --git a/build-aux/ar-lib b/build-aux/ar-lib index 0f62c6f..c349042 100755 --- a/build-aux/ar-lib +++ b/build-aux/ar-lib @@ -2,9 +2,9 @@ # Wrapper for Microsoft lib.exe me=ar-lib -scriptversion=2012-03-01.08; # UTC +scriptversion=2019-07-04.01; # UTC -# Copyright (C) 2010, 2012 Free Software Foundation, Inc. +# Copyright (C) 2010-2021 Free Software Foundation, Inc. # Written by Peter Rosin . # # This program is free software; you can redistribute it and/or modify @@ -18,7 +18,7 @@ scriptversion=2012-03-01.08; # UTC # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -53,7 +53,7 @@ func_file_conv () MINGW*) file_conv=mingw ;; - CYGWIN*) + CYGWIN* | MSYS*) file_conv=cygwin ;; *) @@ -65,7 +65,7 @@ func_file_conv () mingw) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; - cygwin) + cygwin | msys) file=`cygpath -m "$file" || echo "$file"` ;; wine) @@ -224,10 +224,11 @@ elif test -n "$extract"; then esac done else - $AR -NOLOGO -LIST "$archive" | sed -e 's/\\/\\\\/g' | while read member - do - $AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $? - done + $AR -NOLOGO -LIST "$archive" | tr -d '\r' | sed -e 's/\\/\\\\/g' \ + | while read member + do + $AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $? + done fi elif test -n "$quick$replace"; then diff --git a/build-aux/compile b/build-aux/compile index 862a14e..df363c8 100755 --- a/build-aux/compile +++ b/build-aux/compile @@ -1,10 +1,9 @@ #! /bin/sh # Wrapper for compilers which do not understand '-c -o'. -scriptversion=2012-03-05.13; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009, 2010, 2012 Free -# Software Foundation, Inc. +# Copyright (C) 1999-2021 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify @@ -18,7 +17,7 @@ scriptversion=2012-03-05.13; # UTC # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -54,7 +53,7 @@ func_file_conv () MINGW*) file_conv=mingw ;; - CYGWIN*) + CYGWIN* | MSYS*) file_conv=cygwin ;; *) @@ -68,7 +67,7 @@ func_file_conv () mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; - cygwin/*) + cygwin/* | msys/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) @@ -113,6 +112,11 @@ func_cl_dashl () lib=$dir/$lib.lib break fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi done IFS=$save_IFS @@ -251,7 +255,8 @@ EOF echo "compile $scriptversion" exit $? ;; - cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ + icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac @@ -335,9 +340,9 @@ exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/build-aux/config.guess b/build-aux/config.guess index d622a44..e7a6fe3 100755 --- a/build-aux/config.guess +++ b/build-aux/config.guess @@ -1,14 +1,14 @@ -#! /bin/sh +#!/usr/bin/sh # Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011, 2012 Free Software Foundation, Inc. +# Copyright 1992-2023 Free Software Foundation, Inc. -timestamp='2012-02-10' +# shellcheck disable=SC2006,SC2268 # see below for rationale + +timestamp='2023-06-23' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but @@ -17,33 +17,39 @@ timestamp='2012-02-10' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see . +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Originally written by Per Bothner. Please send patches (context -# diff format) to and include a ChangeLog -# entry. +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). # -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess +# +# Please send patches to . + + +# The "shellcheck disable" line above the timestamp inhibits complaints +# about features and limitations of the classic Bourne shell that were +# superseded or lifted in POSIX. However, this script identifies a wide +# variety of pre-POSIX systems that do not have POSIX shells at all, and +# even some reasonably current systems (Solaris 10 as case-in-point) still +# have a pre-POSIX /bin/sh. + me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] -Output the configuration name of the system \`$me' is run on. +Output the configuration name of the system '$me' is run on. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -54,15 +60,13 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 -Free Software Foundation, Inc. +Copyright 1992-2023 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" -Try \`$me --help' for more information." +Try '$me --help' for more information." # Parse command line while test $# -gt 0 ; do @@ -90,57 +94,103 @@ if test $# != 0; then exit 1 fi -trap 'exit 1' 1 2 15 +# Just in case it came from the environment. +GUESS= # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. +# Historically, 'CC_FOR_BUILD' used to be named 'HOST_CC'. We still +# use 'HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' +tmp= +# shellcheck disable=SC2172 +trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 + +set_cc_for_build() { + # prevent multiple calls if $tmp is already set + test "$tmp" && return 0 + : "${TMPDIR=/tmp}" + # shellcheck disable=SC2039,SC3028 + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } + dummy=$tmp/dummy + case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in + ,,) echo "int x;" > "$dummy.c" + for driver in cc gcc c89 c99 ; do + if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD=$driver + break + fi + done + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; + esac +} # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then +if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown +case $UNAME_SYSTEM in +Linux|GNU|GNU/*) + LIBC=unknown + + set_cc_for_build + cat <<-EOF > "$dummy.c" + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #elif defined(__GLIBC__) + LIBC=gnu + #else + #include + /* First heuristic to detect musl libc. */ + #ifdef __DEFINED_va_list + LIBC=musl + #endif + #endif + EOF + cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + eval "$cc_set_libc" + + # Second heuristic to detect musl libc. + if [ "$LIBC" = unknown ] && + command -v ldd >/dev/null && + ldd --version 2>&1 | grep -q ^musl; then + LIBC=musl + fi + + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + if [ "$LIBC" = unknown ]; then + LIBC=gnu + fi + ;; +esac + # Note: order is significant - the case branches are not exclusive. -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in +case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, @@ -152,22 +202,32 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + /sbin/sysctl -n hw.machine_arch 2>/dev/null || \ + /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \ + echo unknown)` + case $UNAME_MACHINE_ARCH in + aarch64eb) machine=aarch64_be-unknown ;; armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + earmv*) + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine=${arch}${endian}-unknown + ;; + *) machine=$UNAME_MACHINE_ARCH-unknown ;; esac # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in + # to ELF recently (or will in the future) and ABI. + case $UNAME_MACHINE_ARCH in + earm*) + os=netbsdelf + ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build + set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then @@ -182,41 +242,80 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in os=netbsd ;; esac + # Determine ABI tags. + case $UNAME_MACHINE_ARCH in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` + ;; + esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in + case $UNAME_VERSION in Debian*) release='-gnu' ;; *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit ;; + GUESS=$machine-${os}${release}${abi-} + ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE + ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} - exit ;; + GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE + ;; + *:SecBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'` + GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE + ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE + ;; + *:MidnightBSD:*:*) + GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE + ;; *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} - exit ;; + GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE + ;; *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} - exit ;; + GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE + ;; + *:OS108:*:*) + GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE + ;; macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} - exit ;; + GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE + ;; *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} - exit ;; + GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE + ;; + *:Sortix:*:*) + GUESS=$UNAME_MACHINE-unknown-sortix + ;; + *:Twizzler:*:*) + GUESS=$UNAME_MACHINE-unknown-twizzler + ;; + *:Redox:*:*) + GUESS=$UNAME_MACHINE-unknown-redox + ;; + mips:OSF1:*.*) + GUESS=mips-dec-osf1 + ;; alpha:OSF1:*:*) + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + trap '' 0 case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` @@ -230,163 +329,158 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in + case $ALPHA_CPU_TYPE in "EV4 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; + UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; + UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; + UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; + UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; + UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; + UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; + UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; + UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; + UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; + OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + GUESS=$UNAME_MACHINE-dec-osf$OSF_REL + ;; Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; + GUESS=m68k-unknown-sysv4 + ;; *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit ;; + GUESS=$UNAME_MACHINE-unknown-amigaos + ;; *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - exit ;; + GUESS=$UNAME_MACHINE-unknown-morphos + ;; *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; + GUESS=i370-ibm-openedition + ;; *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; + GUESS=s390-ibm-zvmoe + ;; *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; + GUESS=powerpc-ibm-os400 + ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit ;; - arm:riscos:*:*|arm:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; + GUESS=arm-acorn-riscix$UNAME_RELEASE + ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + GUESS=arm-unknown-riscos + ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; + GUESS=hppa1.1-hitachi-hiuxmpp + ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; + case `(/bin/universe) 2>/dev/null` in + att) GUESS=pyramid-pyramid-sysv3 ;; + *) GUESS=pyramid-pyramid-bsd ;; + esac + ;; NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; + GUESS=pyramid-pyramid-svr4 + ;; DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; + GUESS=sparc-icl-nx6 + ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; + sparc) GUESS=sparc-icl-nx7 ;; + esac + ;; s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL + ;; sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=sparc-hal-solaris2$SUN_REL + ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=sparc-sun-solaris2$SUN_REL + ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} - exit ;; + GUESS=i386-pc-auroraux$UNAME_RELEASE + ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" + set_cc_for_build + SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then - SUN_ARCH="x86_64" + SUN_ARCH=x86_64 fi fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=$SUN_ARCH-pc-solaris2$SUN_REL + ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=sparc-sun-solaris3$SUN_REL + ;; sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in + case `/usr/bin/arch -k` in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit ;; + # Japanese Language versions have a version number like '4.1.3-JL'. + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` + GUESS=sparc-sun-sunos$SUN_REL + ;; sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit ;; + GUESS=m68k-sun-sunos$UNAME_RELEASE + ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 + case `/bin/arch` in sun3) - echo m68k-sun-sunos${UNAME_RELEASE} + GUESS=m68k-sun-sunos$UNAME_RELEASE ;; sun4) - echo sparc-sun-sunos${UNAME_RELEASE} + GUESS=sparc-sun-sunos$UNAME_RELEASE ;; esac - exit ;; + ;; aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit ;; + GUESS=sparc-auspex-sunos$UNAME_RELEASE + ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor @@ -396,44 +490,44 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; + GUESS=m68k-atari-mint$UNAME_RELEASE + ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; + GUESS=m68k-atari-mint$UNAME_RELEASE + ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; + GUESS=m68k-atari-mint$UNAME_RELEASE + ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; + GUESS=m68k-milan-mint$UNAME_RELEASE + ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; + GUESS=m68k-hades-mint$UNAME_RELEASE + ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; + GUESS=m68k-unknown-mint$UNAME_RELEASE + ;; m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} - exit ;; + GUESS=m68k-apple-machten$UNAME_RELEASE + ;; powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit ;; + GUESS=powerpc-apple-machten$UNAME_RELEASE + ;; RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; + GUESS=mips-dec-mach_bsd4.3 + ;; RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit ;; + GUESS=mips-dec-ultrix$UNAME_RELEASE + ;; VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit ;; + GUESS=vax-dec-ultrix$UNAME_RELEASE + ;; 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit ;; + GUESS=clipper-intergraph-clix$UNAME_RELEASE + ;; mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { @@ -442,95 +536,96 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} - exit ;; + GUESS=mips-mips-riscos$UNAME_RELEASE + ;; Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; + GUESS=powerpc-motorola-powermax + ;; Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; + GUESS=powerpc-harris-powermax + ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; + GUESS=powerpc-harris-powermax + ;; Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; + GUESS=powerpc-harris-powerunix + ;; m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; + GUESS=m88k-harris-cxux7 + ;; m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; + GUESS=m88k-motorola-sysv4 + ;; m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; + GUESS=m88k-motorola-sysv3 + ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] + if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ + test "$TARGET_BINARY_INTERFACE"x = x then - echo m88k-dg-dgux${UNAME_RELEASE} + GUESS=m88k-dg-dgux$UNAME_RELEASE else - echo m88k-dg-dguxbcs${UNAME_RELEASE} + GUESS=m88k-dg-dguxbcs$UNAME_RELEASE fi else - echo i586-dg-dgux${UNAME_RELEASE} + GUESS=i586-dg-dgux$UNAME_RELEASE fi - exit ;; + ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; + GUESS=m88k-dolphin-sysv3 + ;; M88*:*:R3*:*) # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; + GUESS=m88k-motorola-sysv3 + ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; + GUESS=m88k-tektronix-sysv3 + ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; + GUESS=m68k-tektronix-bsd + ;; *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit ;; + IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'` + GUESS=mips-sgi-irix$IRIX_REL + ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id + ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; + GUESS=i386-ibm-aix + ;; ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then + if test -x /usr/bin/oslevel ; then IBM_REV=`/usr/bin/oslevel` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit ;; + GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV + ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" #include main() @@ -541,76 +636,77 @@ EOF exit(0); } EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then - echo "$SYSTEM_NAME" + GUESS=$SYSTEM_NAME else - echo rs6000-ibm-aix3.2.5 + GUESS=rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 + GUESS=rs6000-ibm-aix3.2.4 else - echo rs6000-ibm-aix3.2 + GUESS=rs6000-ibm-aix3.2 fi - exit ;; + ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` + if test -x /usr/bin/lslpp ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \ + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit ;; + GUESS=$IBM_ARCH-ibm-aix$IBM_REV + ;; *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit ;; + GUESS=rs6000-ibm-aix + ;; + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) + GUESS=romp-ibm-bsd4.4 + ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 + GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to + ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; + GUESS=rs6000-bull-bosx + ;; DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; + GUESS=m68k-bull-sysv3 + ;; 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; + GUESS=m68k-hp-bsd + ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; + GUESS=m68k-hp-bsd4.4 + ;; 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; + HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` + case $UNAME_MACHINE in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then + if test -x /usr/bin/getconf; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + case $sc_cpu_version in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + case $sc_kernel_bits in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + if test "$HP_ARCH" = ""; then + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include @@ -643,13 +739,13 @@ EOF exit (0); } EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ ${HP_ARCH} = "hppa2.0w" ] + if test "$HP_ARCH" = hppa2.0w then - eval $set_cc_for_build + set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler @@ -660,23 +756,23 @@ EOF # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then - HP_ARCH="hppa2.0w" + HP_ARCH=hppa2.0w else - HP_ARCH="hppa64" + HP_ARCH=hppa64 fi fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit ;; + GUESS=$HP_ARCH-hp-hpux$HPUX_REV + ;; ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit ;; + HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` + GUESS=ia64-hp-hpux$HPUX_REV + ;; 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" #include int main () @@ -701,38 +797,38 @@ EOF exit (0); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit ;; + GUESS=unknown-hitachi-hiuxwe2 + ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) + GUESS=hppa1.1-hp-bsd + ;; 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; + GUESS=hppa1.0-hp-bsd + ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit ;; + GUESS=hppa1.0-hp-mpeix + ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) + GUESS=hppa1.1-hp-osf + ;; hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; + GUESS=hppa1.0-hp-osf + ;; i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk + if test -x /usr/sbin/sysversion ; then + GUESS=$UNAME_MACHINE-unknown-osf1mk else - echo ${UNAME_MACHINE}-unknown-osf1 + GUESS=$UNAME_MACHINE-unknown-osf1 fi - exit ;; + ;; parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; + GUESS=hppa1.1-hp-lites + ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; + GUESS=c1-convex-bsd + ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd @@ -740,136 +836,154 @@ EOF fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; + GUESS=c34-convex-bsd + ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; + GUESS=c38-convex-bsd + ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; + GUESS=c4-convex-bsd + ;; CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=ymp-cray-unicos$CRAY_REL + ;; CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=t90-cray-unicos$CRAY_REL + ;; CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=alphaev5-cray-unicosmk$CRAY_REL + ;; CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=sv1-cray-unicos$CRAY_REL + ;; *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=craynv-cray-unicosmp$CRAY_REL + ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` + GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} + ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} + ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit ;; + GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE + ;; sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit ;; + GUESS=sparc-unknown-bsdi$UNAME_RELEASE + ;; *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit ;; + GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE + ;; + arm:FreeBSD:*:*) + UNAME_PROCESSOR=`uname -p` + set_cc_for_build + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi + else + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf + fi + ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in + case $UNAME_PROCESSOR in amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; esac - exit ;; + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL + ;; i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit ;; + GUESS=$UNAME_MACHINE-pc-cygwin + ;; + *:MINGW64*:*) + GUESS=$UNAME_MACHINE-pc-mingw64 + ;; *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; - i*:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; + GUESS=$UNAME_MACHINE-pc-mingw32 + ;; + *:MSYS*:*) + GUESS=$UNAME_MACHINE-pc-msys + ;; i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit ;; + GUESS=$UNAME_MACHINE-pc-pw32 + ;; + *:SerenityOS:*:*) + GUESS=$UNAME_MACHINE-pc-serenity + ;; *:Interix*:*) - case ${UNAME_MACHINE} in + case $UNAME_MACHINE in x86) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; + GUESS=i586-pc-interix$UNAME_RELEASE + ;; authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} - exit ;; + GUESS=x86_64-unknown-interix$UNAME_RELEASE + ;; IA64) - echo ia64-unknown-interix${UNAME_RELEASE} - exit ;; + GUESS=ia64-unknown-interix$UNAME_RELEASE + ;; esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit ;; + GUESS=$UNAME_MACHINE-pc-uwin + ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; + GUESS=x86_64-pc-cygwin + ;; prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=powerpcle-unknown-solaris2$SUN_REL + ;; *:GNU:*:*) # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit ;; + GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'` + GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'` + GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL + ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu - exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit ;; + GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"` + GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC + ;; + x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*) + GUESS="$UNAME_MACHINE-pc-managarm-mlibc" + ;; + *:[Mm]anagarm:*:*) + GUESS="$UNAME_MACHINE-unknown-managarm-mlibc" + ;; + *:Minix:*:*) + GUESS=$UNAME_MACHINE-unknown-minix + ;; aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; @@ -879,168 +993,237 @@ EOF EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit ;; + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; arm*:Linux:*:*) - eval $set_cc_for_build + set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then - echo ${UNAME_MACHINE}-unknown-linux-gnu + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then - echo ${UNAME_MACHINE}-unknown-linux-gnueabi + GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi else - echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf fi fi - exit ;; + ;; avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-gnu - exit ;; + GUESS=$UNAME_MACHINE-axis-linux-$LIBC + ;; crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-gnu - exit ;; + GUESS=$UNAME_MACHINE-axis-linux-$LIBC + ;; + e2k:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; i*86:Linux:*:*) - LIBC=gnu - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" - exit ;; + GUESS=$UNAME_MACHINE-pc-linux-$LIBC + ;; ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + k1om:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + loongarch32:Linux:*:* | loongarch64:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + set_cc_for_build + IS_GLIBC=0 + test x"${LIBC}" = xgnu && IS_GLIBC=1 + sed 's/^ //' << EOF > "$dummy.c" #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el + #undef mips + #undef mipsel + #undef mips64 + #undef mips64el + #if ${IS_GLIBC} && defined(_ABI64) + LIBCABI=gnuabi64 + #else + #if ${IS_GLIBC} && defined(_ABIN32) + LIBCABI=gnuabin32 + #else + LIBCABI=${LIBC} + #endif + #endif + + #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa64r6 + #else + #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa32r6 + #else + #if defined(__mips64) + CPU=mips64 + #else + CPU=mips + #endif + #endif + #endif + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el + MIPS_ENDIAN=el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} + MIPS_ENDIAN= #else - CPU= + MIPS_ENDIAN= #endif #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'` + eval "$cc_set_vars" + test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } + ;; + mips64el:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + openrisc*:Linux:*:*) + GUESS=or1k-unknown-linux-$LIBC + ;; + or32:Linux:*:* | or1k*:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; - or32:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; padre:Linux:*:*) - echo sparc-unknown-linux-gnu - exit ;; + GUESS=sparc-unknown-linux-$LIBC + ;; parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit ;; + GUESS=hppa64-unknown-linux-$LIBC + ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; + PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;; + PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;; + *) GUESS=hppa-unknown-linux-$LIBC ;; esac - exit ;; + ;; ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu - exit ;; + GUESS=powerpc64-unknown-linux-$LIBC + ;; ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit ;; + GUESS=powerpc-unknown-linux-$LIBC + ;; + ppc64le:Linux:*:*) + GUESS=powerpc64le-unknown-linux-$LIBC + ;; + ppcle:Linux:*:*) + GUESS=powerpcle-unknown-linux-$LIBC + ;; + riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux - exit ;; + GUESS=$UNAME_MACHINE-ibm-linux-$LIBC + ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-gnu - exit ;; + GUESS=$UNAME_MACHINE-dec-linux-$LIBC + ;; x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; + set_cc_for_build + CPU=$UNAME_MACHINE + LIBCABI=$LIBC + if test "$CC_FOR_BUILD" != no_compiler_found; then + ABI=64 + sed 's/^ //' << EOF > "$dummy.c" + #ifdef __i386__ + ABI=x86 + #else + #ifdef __ILP32__ + ABI=x32 + #endif + #endif +EOF + cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'` + eval "$cc_set_abi" + case $ABI in + x86) CPU=i686 ;; + x32) LIBCABI=${LIBC}x32 ;; + esac + fi + GUESS=$CPU-pc-linux-$LIBCABI + ;; xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; + GUESS=i386-sequent-sysv4 + ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit ;; + GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION + ;; i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility + # If we were able to find 'uname', then EMX Unix compatibility # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit ;; + GUESS=$UNAME_MACHINE-pc-os2-emx + ;; i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit ;; + GUESS=$UNAME_MACHINE-unknown-stop + ;; i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit ;; + GUESS=$UNAME_MACHINE-unknown-atheos + ;; i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable - exit ;; + GUESS=$UNAME_MACHINE-pc-syllable + ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit ;; + GUESS=i386-unknown-lynxos$UNAME_RELEASE + ;; i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + GUESS=$UNAME_MACHINE-pc-msdosdjgpp + ;; + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL fi - exit ;; + ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in @@ -1048,12 +1231,12 @@ EOF *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit ;; + GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 @@ -1063,43 +1246,43 @@ EOF && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL else - echo ${UNAME_MACHINE}-pc-sysv32 + GUESS=$UNAME_MACHINE-pc-sysv32 fi - exit ;; + ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that + # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; + GUESS=i586-pc-msdosdjgpp + ;; Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; + GUESS=i386-pc-mach3 + ;; paragon:*:*:*) - echo i860-intel-osf1 - exit ;; + GUESS=i860-intel-osf1 + ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4 fi - exit ;; + ;; mini*:CTIX:SYS*5:*) # "miniframe" - echo m68010-convergent-sysv - exit ;; + GUESS=m68010-convergent-sysv + ;; mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; + GUESS=m68k-convergent-sysv + ;; M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; + GUESS=m68k-diab-dnix + ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) @@ -1107,9 +1290,9 @@ EOF test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; @@ -1118,226 +1301,287 @@ EOF test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit ;; + GUESS=m68k-unknown-lynxos$UNAME_RELEASE + ;; mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; + GUESS=m68k-atari-sysv4 + ;; TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit ;; + GUESS=sparc-unknown-lynxos$UNAME_RELEASE + ;; rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit ;; + GUESS=rs6000-unknown-lynxos$UNAME_RELEASE + ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit ;; + GUESS=powerpc-unknown-lynxos$UNAME_RELEASE + ;; SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit ;; + GUESS=mips-dde-sysv$UNAME_RELEASE + ;; RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; + GUESS=mips-sni-sysv4 + ;; RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; + GUESS=mips-sni-sysv4 + ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 + GUESS=$UNAME_MACHINE-sni-sysv4 else - echo ns32k-sni-sysv + GUESS=ns32k-sni-sysv fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + ;; + PENTIUM:*:4.0*:*) # Unisys 'ClearPath HMP IX 4000' SVR4/MP effort # says - echo i586-unisys-sysv4 - exit ;; + GUESS=i586-unisys-sysv4 + ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; + GUESS=hppa1.1-stratus-sysv4 + ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; + GUESS=i860-stratus-sysv4 + ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos - exit ;; + GUESS=$UNAME_MACHINE-stratus-vos + ;; *:VOS:*:*) # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; + GUESS=hppa1.1-stratus-vos + ;; mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit ;; + GUESS=m68k-apple-aux$UNAME_RELEASE + ;; news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; + GUESS=mips-sony-newsos6 + ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + if test -d /usr/nec; then + GUESS=mips-nec-sysv$UNAME_RELEASE else - echo mips-unknown-sysv${UNAME_RELEASE} + GUESS=mips-unknown-sysv$UNAME_RELEASE fi - exit ;; + ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; + GUESS=powerpc-be-beos + ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; + GUESS=powerpc-apple-beos + ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; + GUESS=i586-pc-beos + ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; + GUESS=i586-pc-haiku + ;; + ppc:Haiku:*:*) # Haiku running on Apple PowerPC + GUESS=powerpc-apple-haiku + ;; + *:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat) + GUESS=$UNAME_MACHINE-unknown-haiku + ;; SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit ;; + GUESS=sx4-nec-superux$UNAME_RELEASE + ;; SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit ;; + GUESS=sx5-nec-superux$UNAME_RELEASE + ;; SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit ;; + GUESS=sx6-nec-superux$UNAME_RELEASE + ;; SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} - exit ;; + GUESS=sx7-nec-superux$UNAME_RELEASE + ;; SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} - exit ;; + GUESS=sx8-nec-superux$UNAME_RELEASE + ;; SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} - exit ;; + GUESS=sx8r-nec-superux$UNAME_RELEASE + ;; + SX-ACE:SUPER-UX:*:*) + GUESS=sxace-nec-superux$UNAME_RELEASE + ;; Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit ;; + GUESS=powerpc-apple-rhapsody$UNAME_RELEASE + ;; *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit ;; + GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE + ;; + arm64:Darwin:*:*) + GUESS=aarch64-apple-darwin$UNAME_RELEASE + ;; *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + UNAME_PROCESSOR=`uname -p` case $UNAME_PROCESSOR in - i386) - eval $set_cc_for_build - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - UNAME_PROCESSOR="x86_64" - fi - fi ;; unknown) UNAME_PROCESSOR=powerpc ;; esac - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit ;; + if command -v xcode-select > /dev/null 2> /dev/null && \ + ! xcode-select --print-path > /dev/null 2> /dev/null ; then + # Avoid executing cc if there is no toolchain installed as + # cc will be a stub that puts up a graphical alert + # prompting the user to install developer tools. + CC_FOR_BUILD=no_compiler_found + else + set_cc_for_build + fi + if test "$CC_FOR_BUILD" != no_compiler_found; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # uname -m returns i386 or x86_64 + UNAME_PROCESSOR=$UNAME_MACHINE + fi + GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE + ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then + if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit ;; + GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE + ;; *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} - exit ;; - NSE-?:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} - exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit ;; + GUESS=i386-pc-qnx + ;; + NEO-*:NONSTOP_KERNEL:*:*) + GUESS=neo-tandem-nsk$UNAME_RELEASE + ;; + NSE-*:NONSTOP_KERNEL:*:*) + GUESS=nse-tandem-nsk$UNAME_RELEASE + ;; + NSR-*:NONSTOP_KERNEL:*:*) + GUESS=nsr-tandem-nsk$UNAME_RELEASE + ;; + NSV-*:NONSTOP_KERNEL:*:*) + GUESS=nsv-tandem-nsk$UNAME_RELEASE + ;; + NSX-*:NONSTOP_KERNEL:*:*) + GUESS=nsx-tandem-nsk$UNAME_RELEASE + ;; *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; + GUESS=mips-compaq-nonstopux + ;; BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; + GUESS=bs2000-siemens-sysv + ;; DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit ;; + GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE + ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - if test "$cputype" = "386"; then + if test "${cputype-}" = 386; then UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" + elif test "x${cputype-}" != x; then + UNAME_MACHINE=$cputype fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit ;; + GUESS=$UNAME_MACHINE-unknown-plan9 + ;; *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; + GUESS=pdp10-unknown-tops10 + ;; *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; + GUESS=pdp10-unknown-tenex + ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; + GUESS=pdp10-dec-tops20 + ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; + GUESS=pdp10-xkl-tops20 + ;; *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; + GUESS=pdp10-unknown-tops20 + ;; *:ITS:*:*) - echo pdp10-unknown-its - exit ;; + GUESS=pdp10-unknown-its + ;; SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} - exit ;; + GUESS=mips-sei-seiux$UNAME_RELEASE + ;; *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit ;; + DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL + ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; + case $UNAME_MACHINE in + A*) GUESS=alpha-dec-vms ;; + I*) GUESS=ia64-dec-vms ;; + V*) GUESS=vax-dec-vms ;; esac ;; *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; + GUESS=i386-pc-xenix + ;; i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' - exit ;; + SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'` + GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL + ;; i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos - exit ;; - i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros - exit ;; + GUESS=$UNAME_MACHINE-pc-rdos + ;; + i*86:Fiwix:*:*) + GUESS=$UNAME_MACHINE-pc-fiwix + ;; + *:AROS:*:*) + GUESS=$UNAME_MACHINE-unknown-aros + ;; x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-unknown-esx - exit ;; + GUESS=$UNAME_MACHINE-unknown-esx + ;; + amd64:Isilon\ OneFS:*:*) + GUESS=x86_64-unknown-onefs + ;; + *:Unleashed:*:*) + GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE + ;; esac -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 +# Do we have a guess based on uname results? +if test "x$GUESS" != x; then + echo "$GUESS" + exit +fi -eval $set_cc_for_build -cat >$dummy.c < "$dummy.c" < -# include +#include +#include +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#include +#if defined(_SIZE_T_) || defined(SIGLOST) +#include +#endif +#endif #endif main () { @@ -1350,20 +1594,12 @@ main () #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 - "4" + "4" #else - "" -#endif - ); exit (0); + "" #endif + ); exit (0); #endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) @@ -1405,39 +1641,54 @@ main () #endif #if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); + struct utsname un; + uname(&un); + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif +#if !defined (ultrix) +#include +#if defined (BSD) +#if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +#else +#if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#endif +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#else +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname un; + uname (&un); + printf ("vax-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname *un; + uname (&un); + printf ("mips-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("mips-dec-ultrix\n"); exit (0); +#endif +#endif #endif #if defined (alliant) && defined (i860) @@ -1448,54 +1699,46 @@ main () } EOF -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && +$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. +test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } +echo "$0: unable to guess system type" >&2 -# Convex versions that predate uname can use getsysinfo(1) +case $UNAME_MACHINE:$UNAME_SYSTEM in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <&2 < in order to provide the needed -information to handle your system. +our_year=`echo $timestamp | sed 's,-.*,,'` +thisyear=`date +%Y` +# shellcheck disable=SC2003 +script_age=`expr "$thisyear" - "$our_year"` +if test "$script_age" -lt 3 ; then + cat >&2 </dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" EOF +fi exit 1 # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/build-aux/config.sub b/build-aux/config.sub index c894da4..a6d99a0 100755 --- a/build-aux/config.sub +++ b/build-aux/config.sub @@ -1,36 +1,33 @@ -#! /bin/sh +#!/usr/bin/sh # Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011, 2012 Free Software Foundation, Inc. +# Copyright 1992-2023 Free Software Foundation, Inc. -timestamp='2012-02-10' +# shellcheck disable=SC2006,SC2268 # see below for rationale -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +timestamp='2023-06-23' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see . +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). -# Please send patches to . Submit a context -# diff and a properly formatted GNU ChangeLog entry. +# Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. @@ -38,7 +35,7 @@ timestamp='2012-02-10' # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD +# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases @@ -55,15 +52,21 @@ timestamp='2012-02-10' # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. +# The "shellcheck disable" line above the timestamp inhibits complaints +# about features and limitations of the classic Bourne shell that were +# superseded or lifted in POSIX. However, this script identifies a wide +# variety of pre-POSIX systems that do not have POSIX shells at all, and +# even some reasonably current systems (Solaris 10 as case-in-point) still +# have a pre-POSIX /bin/sh. + me=`echo "$0" | sed -e 's,.*/,,'` usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -73,15 +76,13 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 -Free Software Foundation, Inc. +Copyright 1992-2023 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" -Try \`$me --help' for more information." +Try '$me --help' for more information." # Parse command line while test $# -gt 0 ; do @@ -97,12 +98,12 @@ while test $# -gt 0 ; do - ) # Use stdin as input. break ;; -* ) - echo "$me: invalid option $1$help" + echo "$me: invalid option $1$help" >&2 exit 1 ;; *local*) # First pass through any local machine types. - echo $1 + echo "$1" exit ;; * ) @@ -118,1190 +119,1186 @@ case $# in exit 1;; esac -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - android-linux) - os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac +# Split fields of configuration type +# shellcheck disable=SC2162 +saved_IFS=$IFS +IFS="-" read field1 field2 field3 field4 <&2 + exit 1 ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + *-*-*-*) + basic_machine=$field1-$field2 + basic_os=$field3-$field4 ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` + *-*-*) + # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two + # parts + maybe_os=$field2-$field3 + case $maybe_os in + nto-qnx* | linux-* | uclinux-uclibc* \ + | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ + | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ + | storm-chaos* | os2-emx* | rtmk-nova* | managarm-*) + basic_machine=$field1 + basic_os=$maybe_os + ;; + android-linux) + basic_machine=$field1-unknown + basic_os=linux-android + ;; + *) + basic_machine=$field1-$field2 + basic_os=$field3 + ;; + esac ;; - -psos*) - os=-psos + *-*) + # A lone config we happen to match not fitting any pattern + case $field1-$field2 in + decstation-3100) + basic_machine=mips-dec + basic_os= + ;; + *-*) + # Second component is usually, but not always the OS + case $field2 in + # Prevent following clause from handling this valid os + sun*os*) + basic_machine=$field1 + basic_os=$field2 + ;; + zephyr*) + basic_machine=$field1-unknown + basic_os=$field2 + ;; + # Manufacturers + dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ + | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ + | unicom* | ibm* | next | hp | isi* | apollo | altos* \ + | convergent* | ncr* | news | 32* | 3600* | 3100* \ + | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ + | ultra | tti* | harris | dolphin | highlevel | gould \ + | cbm | ns | masscomp | apple | axis | knuth | cray \ + | microblaze* | sim | cisco \ + | oki | wec | wrs | winbond) + basic_machine=$field1-$field2 + basic_os= + ;; + *) + basic_machine=$field1 + basic_os=$field2 + ;; + esac + ;; + esac ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint + *) + # Convert single-component short-hands not valid as part of + # multi-component configurations. + case $field1 in + 386bsd) + basic_machine=i386-pc + basic_os=bsd + ;; + a29khif) + basic_machine=a29k-amd + basic_os=udi + ;; + adobe68k) + basic_machine=m68010-adobe + basic_os=scout + ;; + alliant) + basic_machine=fx80-alliant + basic_os= + ;; + altos | altos3068) + basic_machine=m68k-altos + basic_os= + ;; + am29k) + basic_machine=a29k-none + basic_os=bsd + ;; + amdahl) + basic_machine=580-amdahl + basic_os=sysv + ;; + amiga) + basic_machine=m68k-unknown + basic_os= + ;; + amigaos | amigados) + basic_machine=m68k-unknown + basic_os=amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + basic_os=sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + basic_os=sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + basic_os=bsd + ;; + aros) + basic_machine=i386-pc + basic_os=aros + ;; + aux) + basic_machine=m68k-apple + basic_os=aux + ;; + balance) + basic_machine=ns32k-sequent + basic_os=dynix + ;; + blackfin) + basic_machine=bfin-unknown + basic_os=linux + ;; + cegcc) + basic_machine=arm-unknown + basic_os=cegcc + ;; + convex-c1) + basic_machine=c1-convex + basic_os=bsd + ;; + convex-c2) + basic_machine=c2-convex + basic_os=bsd + ;; + convex-c32) + basic_machine=c32-convex + basic_os=bsd + ;; + convex-c34) + basic_machine=c34-convex + basic_os=bsd + ;; + convex-c38) + basic_machine=c38-convex + basic_os=bsd + ;; + cray) + basic_machine=j90-cray + basic_os=unicos + ;; + crds | unos) + basic_machine=m68k-crds + basic_os= + ;; + da30) + basic_machine=m68k-da30 + basic_os= + ;; + decstation | pmax | pmin | dec3100 | decstatn) + basic_machine=mips-dec + basic_os= + ;; + delta88) + basic_machine=m88k-motorola + basic_os=sysv3 + ;; + dicos) + basic_machine=i686-pc + basic_os=dicos + ;; + djgpp) + basic_machine=i586-pc + basic_os=msdosdjgpp + ;; + ebmon29k) + basic_machine=a29k-amd + basic_os=ebmon + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + basic_os=ose + ;; + gmicro) + basic_machine=tron-gmicro + basic_os=sysv + ;; + go32) + basic_machine=i386-pc + basic_os=go32 + ;; + h8300hms) + basic_machine=h8300-hitachi + basic_os=hms + ;; + h8300xray) + basic_machine=h8300-hitachi + basic_os=xray + ;; + h8500hms) + basic_machine=h8500-hitachi + basic_os=hms + ;; + harris) + basic_machine=m88k-harris + basic_os=sysv3 + ;; + hp300 | hp300hpux) + basic_machine=m68k-hp + basic_os=hpux + ;; + hp300bsd) + basic_machine=m68k-hp + basic_os=bsd + ;; + hppaosf) + basic_machine=hppa1.1-hp + basic_os=osf + ;; + hppro) + basic_machine=hppa1.1-hp + basic_os=proelf + ;; + i386mach) + basic_machine=i386-mach + basic_os=mach + ;; + isi68 | isi) + basic_machine=m68k-isi + basic_os=sysv + ;; + m68knommu) + basic_machine=m68k-unknown + basic_os=linux + ;; + magnum | m3230) + basic_machine=mips-mips + basic_os=sysv + ;; + merlin) + basic_machine=ns32k-utek + basic_os=sysv + ;; + mingw64) + basic_machine=x86_64-pc + basic_os=mingw64 + ;; + mingw32) + basic_machine=i686-pc + basic_os=mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + basic_os=mingw32ce + ;; + monitor) + basic_machine=m68k-rom68k + basic_os=coff + ;; + morphos) + basic_machine=powerpc-unknown + basic_os=morphos + ;; + moxiebox) + basic_machine=moxie-unknown + basic_os=moxiebox + ;; + msdos) + basic_machine=i386-pc + basic_os=msdos + ;; + msys) + basic_machine=i686-pc + basic_os=msys + ;; + mvs) + basic_machine=i370-ibm + basic_os=mvs + ;; + nacl) + basic_machine=le32-unknown + basic_os=nacl + ;; + ncr3000) + basic_machine=i486-ncr + basic_os=sysv4 + ;; + netbsd386) + basic_machine=i386-pc + basic_os=netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + basic_os=linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + basic_os=newsos + ;; + news1000) + basic_machine=m68030-sony + basic_os=newsos + ;; + necv70) + basic_machine=v70-nec + basic_os=sysv + ;; + nh3000) + basic_machine=m68k-harris + basic_os=cxux + ;; + nh[45]000) + basic_machine=m88k-harris + basic_os=cxux + ;; + nindy960) + basic_machine=i960-intel + basic_os=nindy + ;; + mon960) + basic_machine=i960-intel + basic_os=mon960 + ;; + nonstopux) + basic_machine=mips-compaq + basic_os=nonstopux + ;; + os400) + basic_machine=powerpc-ibm + basic_os=os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + basic_os=ose + ;; + os68k) + basic_machine=m68k-none + basic_os=os68k + ;; + paragon) + basic_machine=i860-intel + basic_os=osf + ;; + parisc) + basic_machine=hppa-unknown + basic_os=linux + ;; + psp) + basic_machine=mipsallegrexel-sony + basic_os=psp + ;; + pw32) + basic_machine=i586-unknown + basic_os=pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + basic_os=rdos + ;; + rdos32) + basic_machine=i386-pc + basic_os=rdos + ;; + rom68k) + basic_machine=m68k-rom68k + basic_os=coff + ;; + sa29200) + basic_machine=a29k-amd + basic_os=udi + ;; + sei) + basic_machine=mips-sei + basic_os=seiux + ;; + sequent) + basic_machine=i386-sequent + basic_os= + ;; + sps7) + basic_machine=m68k-bull + basic_os=sysv2 + ;; + st2000) + basic_machine=m68k-tandem + basic_os= + ;; + stratus) + basic_machine=i860-stratus + basic_os=sysv4 + ;; + sun2) + basic_machine=m68000-sun + basic_os= + ;; + sun2os3) + basic_machine=m68000-sun + basic_os=sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + basic_os=sunos4 + ;; + sun3) + basic_machine=m68k-sun + basic_os= + ;; + sun3os3) + basic_machine=m68k-sun + basic_os=sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + basic_os=sunos4 + ;; + sun4) + basic_machine=sparc-sun + basic_os= + ;; + sun4os3) + basic_machine=sparc-sun + basic_os=sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + basic_os=sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + basic_os=solaris2 + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + basic_os= + ;; + sv1) + basic_machine=sv1-cray + basic_os=unicos + ;; + symmetry) + basic_machine=i386-sequent + basic_os=dynix + ;; + t3e) + basic_machine=alphaev5-cray + basic_os=unicos + ;; + t90) + basic_machine=t90-cray + basic_os=unicos + ;; + toad1) + basic_machine=pdp10-xkl + basic_os=tops20 + ;; + tpf) + basic_machine=s390x-ibm + basic_os=tpf + ;; + udi29k) + basic_machine=a29k-amd + basic_os=udi + ;; + ultra3) + basic_machine=a29k-nyu + basic_os=sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + basic_os=none + ;; + vaxv) + basic_machine=vax-dec + basic_os=sysv + ;; + vms) + basic_machine=vax-dec + basic_os=vms + ;; + vsta) + basic_machine=i386-pc + basic_os=vsta + ;; + vxworks960) + basic_machine=i960-wrs + basic_os=vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + basic_os=vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + basic_os=vxworks + ;; + xbox) + basic_machine=i686-pc + basic_os=mingw32 + ;; + ymp) + basic_machine=ymp-cray + basic_os=unicos + ;; + *) + basic_machine=$1 + basic_os= + ;; + esac ;; esac -# Decode aliases for certain CPU-COMPANY combinations. +# Decode 1-component or ad-hoc basic machines case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ - | be32 | be64 \ - | bfin \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | epiphany \ - | fido | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 \ - | ns16k | ns32k \ - | open8 \ - | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pyramid \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown + # Here we handle the default manufacturer of certain CPU types. It is in + # some cases the only manufacturer, in others, it is the most popular. + w89k) + cpu=hppa1.1 + vendor=winbond ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown + op50n) + cpu=hppa1.1 + vendor=oki ;; - xgate) - basic_machine=$basic_machine-unknown - os=-none + op60c) + cpu=hppa1.1 + vendor=oki ;; - xscaleeb) - basic_machine=armeb-unknown + ibm*) + cpu=i370 + vendor=ibm ;; - - xscaleel) - basic_machine=armel-unknown + orion105) + cpu=clipper + vendor=highlevel ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 + mac | mpw | mac-mpw) + cpu=m68k + vendor=apple ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pyramid-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown + pmac | pmac-mpw) + cpu=powerpc + vendor=apple ;; + # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att + cpu=m68000 + vendor=att ;; 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux + cpu=we32k + vendor=att ;; bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec + cpu=powerpc + vendor=ibm + basic_os=cnk ;; decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 + cpu=pdp10 + vendor=dec + basic_os=tops10 ;; decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 + cpu=pdp10 + vendor=dec + basic_os=tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 + cpu=m68k + vendor=motorola ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd + dpx2*) + cpu=m68k + vendor=bull + basic_os=sysv3 ;; encore | umax | mmax) - basic_machine=ns32k-encore + cpu=ns32k + vendor=encore ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose + elxsi) + cpu=elxsi + vendor=elxsi + basic_os=${basic_os:-bsd} ;; fx2800) - basic_machine=i860-alliant + cpu=i860 + vendor=alliant ;; genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 + cpu=ns32k + vendor=ns ;; h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux + cpu=hppa1.1 + vendor=hitachi + basic_os=hiuxwe2 ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp + cpu=hppa1.0 + vendor=hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp + cpu=m68000 + vendor=hp ;; hp9k3[2-9][0-9]) - basic_machine=m68k-hp + cpu=m68k + vendor=hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp + cpu=hppa1.0 + vendor=hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm + cpu=hppa1.0 + vendor=hp ;; i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv32 ;; i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv4 ;; i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv ;; i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=solaris2 ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta + j90 | j90-cray) + cpu=j90 + vendor=cray + basic_os=${basic_os:-unicos} ;; iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) + cpu=mips + vendor=sgi + case $basic_os in + irix*) ;; *) - os=-irix4 + basic_os=irix4 ;; esac ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze) - basic_machine=microblaze-xilinx - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos + cpu=m68000 + vendor=convergent ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - msys) - basic_machine=i386-pc - os=-msys - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos + *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) + cpu=m68k + vendor=atari + basic_os=mint ;; news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) + cpu=mips + vendor=sony + basic_os=newsos + ;; + next | m*-next) + cpu=m68k + vendor=next + case $basic_os in + openstep*) + ;; + nextstep*) ;; - -ns2*) - os=-nextstep2 + ns2*) + basic_os=nextstep2 ;; *) - os=-nextstep3 + basic_os=nextstep3 ;; esac ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem + cpu=np1 + vendor=gould ;; op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k + cpu=hppa1.1 + vendor=oki + basic_os=proelf ;; pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux + cpu=hppa1.1 + vendor=hitachi + basic_os=hiuxwe2 ;; pbd) - basic_machine=sparc-tti + cpu=sparc + vendor=tti ;; pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + cpu=m68k + vendor=tti ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + pc532) + cpu=ns32k + vendor=pc532 ;; pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + cpu=pn + vendor=gould ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + power) + cpu=power + vendor=ibm ;; ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff + cpu=i386 + vendor=ibm ;; rm[46]00) - basic_machine=mips-siemens + cpu=mips + vendor=siemens ;; rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi + cpu=romp + vendor=ibm ;; - sb1) - basic_machine=mipsisa64sb1-unknown + sde) + cpu=mipsisa32 + vendor=sde + basic_os=${basic_os:-elf} ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown + simso-wrs) + cpu=sparclite + vendor=wrs + basic_os=vxworks ;; - sde) - basic_machine=mipsisa32-sde - os=-elf + tower | tower-32) + cpu=m68k + vendor=ncr ;; - sei) - basic_machine=mips-sei - os=-seiux + vpp*|vx|vx-*) + cpu=f301 + vendor=fujitsu ;; - sequent) - basic_machine=i386-sequent + w65) + cpu=w65 + vendor=wdc ;; - sh) - basic_machine=sh-hitachi - os=-hms + w89k-*) + cpu=hppa1.1 + vendor=winbond + basic_os=proelf ;; - sh5el) - basic_machine=sh5le-unknown + none) + cpu=none + vendor=none ;; - sh64) - basic_machine=sh64-unknown + leon|leon[3-9]) + cpu=sparc + vendor=$basic_machine ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks + leon-*|leon[3-9]-*) + cpu=sparc + vendor=`echo "$basic_machine" | sed 's/-.*//'` ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 + + *-*) + # shellcheck disable=SC2162 + saved_IFS=$IFS + IFS="-" read cpu vendor <&2 - exit 1 + # Recognize the canonical CPU types that are allowed with any + # company name. + case $cpu in + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | abacus \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \ + | alphapca5[67] | alpha64pca5[67] \ + | am33_2.0 \ + | amdgcn \ + | arc | arceb | arc32 | arc64 \ + | arm | arm[lb]e | arme[lb] | armv* \ + | avr | avr32 \ + | asmjs \ + | ba \ + | be32 | be64 \ + | bfin | bpf | bs2000 \ + | c[123]* | c30 | [cjt]90 | c4x \ + | c8051 | clipper | craynv | csky | cydra \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | elxsi | epiphany \ + | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \ + | h8300 | h8500 \ + | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i*86 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | loongarch32 | loongarch64 \ + | m32c | m32r | m32rle \ + | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \ + | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \ + | m88110 | m88k | maxq | mb | mcore | mep | metag \ + | microblaze | microblazeel \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64eb | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r3 | mipsisa32r3el \ + | mipsisa32r5 | mipsisa32r5el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r3 | mipsisa64r3el \ + | mipsisa64r5 | mipsisa64r5el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mmix \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nfp \ + | nios | nios2 | nios2eb | nios2el \ + | none | np1 | ns16k | ns32k | nvptx \ + | open8 \ + | or1k* \ + | or32 \ + | orion \ + | picochip \ + | pdp10 | pdp11 | pj | pjl | pn | power \ + | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \ + | pru \ + | pyramid \ + | riscv | riscv32 | riscv32be | riscv64 | riscv64be \ + | rl78 | romp | rs6000 | rx \ + | s390 | s390x \ + | score \ + | sh | shl \ + | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \ + | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \ + | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \ + | spu \ + | tahoe \ + | thumbv7* \ + | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \ + | tron \ + | ubicom32 \ + | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \ + | vax \ + | visium \ + | w65 \ + | wasm32 | wasm64 \ + | we32k \ + | x86 | x86_64 | xc16x | xgate | xps100 \ + | xstormy16 | xtensa* \ + | ymp \ + | z8k | z80) + ;; + + *) + echo "Invalid configuration '$1': machine '$cpu-$vendor' not recognized" 1>&2 + exit 1 + ;; + esac ;; esac # Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` +case $vendor in + digital*) + vendor=dec ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + commodore*) + vendor=cbm ;; *) ;; @@ -1309,203 +1306,219 @@ esac # Decode manufacturer-specific aliases for certain operating systems. -if [ x"$os" != x"" ] +if test x$basic_os != x then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux + +# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just +# set os. +case $basic_os in + gnu/linux*) + kernel=linux + os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'` + ;; + os2-emx) + kernel=os2 + os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'` + ;; + nto-qnx*) + kernel=nto + os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'` + ;; + *-*) + # shellcheck disable=SC2162 + saved_IFS=$IFS + IFS="-" read kernel os <&2 - exit 1 + # No normalization, but not necessarily accepted, that comes below. ;; esac + else # Here we handle the default operating systems that come with various machines. @@ -1518,255 +1531,376 @@ else # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. -case $basic_machine in +kernel= +case $cpu-$vendor in score-*) - os=-elf + os=elf ;; spu-*) - os=-elf + os=elf ;; *-acorn) - os=-riscix1.2 + os=riscix1.2 ;; arm*-rebel) - os=-linux + kernel=linux + os=gnu ;; arm*-semi) - os=-aout + os=aout ;; c4x-* | tic4x-*) - os=-coff + os=coff + ;; + c8051-*) + os=elf + ;; + clipper-intergraph) + os=clix + ;; + hexagon-*) + os=elf ;; tic54x-*) - os=-coff + os=coff ;; tic55x-*) - os=-coff + os=coff ;; tic6x-*) - os=-coff + os=coff ;; # This must come before the *-dec entry. pdp10-*) - os=-tops20 + os=tops20 ;; pdp11-*) - os=-none + os=none ;; *-dec | vax-*) - os=-ultrix4.2 + os=ultrix4.2 ;; m68*-apollo) - os=-domain + os=domain ;; i386-sun) - os=-sunos4.0.2 + os=sunos4.0.2 ;; m68000-sun) - os=-sunos3 + os=sunos3 ;; m68*-cisco) - os=-aout + os=aout ;; mep-*) - os=-elf + os=elf ;; mips*-cisco) - os=-elf + os=elf ;; mips*-*) - os=-elf + os=elf ;; or32-*) - os=-coff + os=coff ;; *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 + os=sysv3 ;; sparc-* | *-sun) - os=-sunos4.1.1 + os=sunos4.1.1 ;; - *-be) - os=-beos + pru-*) + os=elf ;; - *-haiku) - os=-haiku + *-be) + os=beos ;; *-ibm) - os=-aix + os=aix ;; *-knuth) - os=-mmixware + os=mmixware ;; *-wec) - os=-proelf + os=proelf ;; *-winbond) - os=-proelf + os=proelf ;; *-oki) - os=-proelf + os=proelf ;; *-hp) - os=-hpux + os=hpux ;; *-hitachi) - os=-hiux + os=hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv + os=sysv ;; *-cbm) - os=-amigaos + os=amigaos ;; *-dg) - os=-dgux + os=dgux ;; *-dolphin) - os=-sysv3 + os=sysv3 ;; m68k-ccur) - os=-rtu + os=rtu ;; m88k-omron*) - os=-luna + os=luna ;; - *-next ) - os=-nextstep + *-next) + os=nextstep ;; *-sequent) - os=-ptx + os=ptx ;; *-crds) - os=-unos + os=unos ;; *-ns) - os=-genix + os=genix ;; i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 + os=mvs ;; *-gould) - os=-sysv + os=sysv ;; *-highlevel) - os=-bsd + os=bsd ;; *-encore) - os=-bsd + os=bsd ;; *-sgi) - os=-irix + os=irix ;; *-siemens) - os=-sysv4 + os=sysv4 ;; *-masscomp) - os=-rtu + os=rtu ;; f30[01]-fujitsu | f700-fujitsu) - os=-uxpv + os=uxpv ;; *-rom68k) - os=-coff + os=coff ;; *-*bug) - os=-coff + os=coff ;; *-apple) - os=-macos + os=macos ;; *-atari*) - os=-mint + os=mint + ;; + *-wrs) + os=vxworks ;; *) - os=-none + os=none ;; esac + fi +# Now, validate our (potentially fixed-up) OS. +case $os in + # Sometimes we do "kernel-libc", so those need to count as OSes. + musl* | newlib* | relibc* | uclibc*) + ;; + # Likewise for "kernel-abi" + eabi* | gnueabi*) + ;; + # VxWorks passes extra cpu info in the 4th filed. + simlinux | simwindows | spe) + ;; + # Now accept the basic system types. + # The portable systems comes first. + # Each alternative MUST end in a * to match a version number. + gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \ + | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \ + | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ + | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \ + | hiux* | abug | nacl* | netware* | windows* \ + | os9* | macos* | osx* | ios* \ + | mpw* | magic* | mmixware* | mon960* | lnews* \ + | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ + | aos* | aros* | cloudabi* | sortix* | twizzler* \ + | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ + | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ + | mirbsd* | netbsd* | dicos* | openedition* | ose* \ + | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \ + | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \ + | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ + | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ + | udi* | lites* | ieee* | go32* | aux* | hcos* \ + | chorusrdb* | cegcc* | glidix* | serenity* \ + | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ + | midipix* | mingw32* | mingw64* | mint* \ + | uxpv* | beos* | mpeix* | udk* | moxiebox* \ + | interix* | uwin* | mks* | rhapsody* | darwin* \ + | openstep* | oskit* | conix* | pw32* | nonstopux* \ + | storm-chaos* | tops10* | tenex* | tops20* | its* \ + | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \ + | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \ + | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ + | skyos* | haiku* | rdos* | toppers* | drops* | es* \ + | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ + | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ + | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \ + | fiwix* | mlibc* ) + ;; + # This one is extra strict with allowed versions + sco3.2v2 | sco3.2v[4-9]* | sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + ;; + none) + ;; + kernel* ) + # Restricted further below + ;; + *) + echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2 + exit 1 + ;; +esac + +# As a final step for OS-related things, validate the OS-kernel combination +# (given a valid OS), if there is a kernel. +case $kernel-$os in + linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ + | linux-musl* | linux-relibc* | linux-uclibc* | linux-mlibc* ) + ;; + uclinux-uclibc* ) + ;; + managarm-mlibc* | managarm-kernel* ) + ;; + -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* | -mlibc* ) + # These are just libc implementations, not actual OSes, and thus + # require a kernel. + echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2 + exit 1 + ;; + -kernel* ) + echo "Invalid configuration '$1': '$os' needs explicit kernel." 1>&2 + exit 1 + ;; + *-kernel* ) + echo "Invalid configuration '$1': '$kernel' does not support '$os'." 1>&2 + exit 1 + ;; + kfreebsd*-gnu* | kopensolaris*-gnu*) + ;; + vxworks-simlinux | vxworks-simwindows | vxworks-spe) + ;; + nto-qnx*) + ;; + os2-emx) + ;; + *-eabi* | *-gnueabi*) + ;; + -*) + # Blank kernel with real OS is always fine. + ;; + *-*) + echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2 + exit 1 + ;; +esac + # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) +case $vendor in + unknown) + case $cpu-$os in + *-riscix*) vendor=acorn ;; - -sunos*) + *-sunos*) vendor=sun ;; - -cnk*|-aix*) + *-cnk* | *-aix*) vendor=ibm ;; - -beos*) + *-beos*) vendor=be ;; - -hpux*) + *-hpux*) vendor=hp ;; - -mpeix*) + *-mpeix*) vendor=hp ;; - -hiux*) + *-hiux*) vendor=hitachi ;; - -unos*) + *-unos*) vendor=crds ;; - -dgux*) + *-dgux*) vendor=dg ;; - -luna*) + *-luna*) vendor=omron ;; - -genix*) + *-genix*) vendor=ns ;; - -mvs* | -opened*) + *-clix*) + vendor=intergraph + ;; + *-mvs* | *-opened*) + vendor=ibm + ;; + *-os400*) vendor=ibm ;; - -os400*) + s390-* | s390x-*) vendor=ibm ;; - -ptx*) + *-ptx*) vendor=sequent ;; - -tpf*) + *-tpf*) vendor=ibm ;; - -vxsim* | -vxworks* | -windiss*) + *-vxsim* | *-vxworks* | *-windiss*) vendor=wrs ;; - -aux*) + *-aux*) vendor=apple ;; - -hms*) + *-hms*) vendor=hitachi ;; - -mpw* | -macos*) + *-mpw* | *-macos*) vendor=apple ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) vendor=atari ;; - -vos*) + *-vos*) vendor=stratus ;; esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac -echo $basic_machine$os +echo "$cpu-$vendor-${kernel:+$kernel-}$os" exit # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/build-aux/depcomp b/build-aux/depcomp index 25a39e6..715e343 100755 --- a/build-aux/depcomp +++ b/build-aux/depcomp @@ -1,10 +1,9 @@ #! /bin/sh # depcomp - compile a program generating dependencies as side-effects -scriptversion=2012-03-27.16; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010, -# 2011, 2012 Free Software Foundation, Inc. +# Copyright (C) 1999-2021 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -17,7 +16,7 @@ scriptversion=2012-03-27.16; # UTC # GNU General Public License for more details. # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -28,9 +27,9 @@ scriptversion=2012-03-27.16; # UTC case $1 in '') - echo "$0: No command. Try '$0 --help' for more information." 1>&2 - exit 1; - ;; + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] @@ -57,11 +56,65 @@ EOF ;; esac +# Get the directory component of the given path, and save it in the +# global variables '$dir'. Note that this directory component will +# be either empty or ending with a '/' character. This is deliberate. +set_dir_from () +{ + case $1 in + */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; + *) dir=;; + esac +} + +# Get the suffix-stripped basename of the given path, and save it the +# global variable '$base'. +set_base_from () +{ + base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` +} + +# If no dependency file was actually created by the compiler invocation, +# we still have to create a dummy depfile, to avoid errors with the +# Makefile "include basename.Plo" scheme. +make_dummy_depfile () +{ + echo "#dummy" > "$depfile" +} + +# Factor out some common post-processing of the generated depfile. +# Requires the auxiliary global variable '$tmpdepfile' to be set. +aix_post_process_depfile () +{ + # If the compiler actually managed to produce a dependency file, + # post-process it. + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependency.h'. + # Do two passes, one to just change these to + # $object: dependency.h + # and one to simply output + # dependency.h: + # which is needed to avoid the deleted-header problem. + { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" + sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" + } > "$depfile" + rm -f "$tmpdepfile" + else + make_dummy_depfile + fi +} + # A tabulation character. tab=' ' # A newline character. nl=' ' +# Character ranges might be problematic outside the C locale. +# These definitions help. +upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ +lower=abcdefghijklmnopqrstuvwxyz +digits=0123456789 +alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 @@ -75,6 +128,9 @@ tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" +# Avoid interferences from the environment. +gccflag= dashmflag= + # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case @@ -86,32 +142,32 @@ if test "$depmode" = hp; then fi if test "$depmode" = dashXmstdout; then - # This is just like dashmstdout with a different argument. - dashmflag=-xM - depmode=dashmstdout + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then - # This is just like msvisualcpp but w/o cygpath translation. - # Just convert the backslash-escaped backslashes to single forward - # slashes to satisfy depend.m4 - cygpath_u='sed s,\\\\,/,g' - depmode=msvisualcpp + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then - # This is just like msvc7 but w/o cygpath translation. - # Just convert the backslash-escaped backslashes to single forward - # slashes to satisfy depend.m4 - cygpath_u='sed s,\\\\,/,g' - depmode=msvc7 + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 fi if test "$depmode" = xlc; then - # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations. - gccflag=-qmakedep=gcc,-MF - depmode=gcc + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc fi case "$depmode" in @@ -134,8 +190,7 @@ gcc3) done "$@" stat=$? - if test $stat -eq 0; then : - else + if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi @@ -143,13 +198,17 @@ gcc3) ;; gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like -## -MM, not -M (despite what the docs say). +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then @@ -157,15 +216,14 @@ gcc) fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? - if test $stat -eq 0; then : - else + if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" - alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz -## The second -e expression handles DOS-style file names with drive letters. + # The second -e expression handles DOS-style file names with drive + # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. @@ -174,15 +232,15 @@ gcc) ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. - tr ' ' "$nl" < "$tmpdepfile" | ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ - | sed -e 's/$/ :/' >> "$depfile" + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; @@ -200,8 +258,7 @@ sgi) "$@" -MDupdate "$tmpdepfile" fi stat=$? - if test $stat -eq 0; then : - else + if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi @@ -209,7 +266,6 @@ sgi) if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" - # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in @@ -217,19 +273,15 @@ sgi) # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ - tr "$nl" ' ' >> "$depfile" + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ + | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" - # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ - >> "$depfile" + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" + make_dummy_depfile fi rm -f "$tmpdepfile" ;; @@ -247,9 +299,8 @@ aix) # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + set_dir_from "$object" + set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u @@ -262,9 +313,7 @@ aix) "$@" -M fi stat=$? - - if test $stat -eq 0; then : - else + if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi @@ -273,65 +322,113 @@ aix) do test -f "$tmpdepfile" && break done - if test -f "$tmpdepfile"; then - # Each line is of the form 'foo.o: dependent.h'. - # Do two passes, one to just change these to - # '$object: dependent.h' and one to simply 'dependent.h:'. - sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" + aix_post_process_depfile + ;; + +tcc) + # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 + # FIXME: That version still under development at the moment of writing. + # Make that this statement remains true also for stable, released + # versions. + # It will wrap lines (doesn't matter whether long or short) with a + # trailing '\', as in: + # + # foo.o : \ + # foo.c \ + # foo.h \ + # + # It will put a trailing '\' even on the last line, and will use leading + # spaces rather than leading tabs (at least since its commit 0394caf7 + # "Emit spaces for -MD"). + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat fi + rm -f "$depfile" + # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. + # We have to change lines of the first kind to '$object: \'. + sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" + # And for each line of the second kind, we have to emit a 'dep.h:' + # dummy dependency, to avoid the deleted-header problem. + sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; -icc) - # Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'. - # However on - # $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c - # ICC 7.0 will fill foo.d with something like - # foo.o: sub/foo.c - # foo.o: sub/foo.h - # which is wrong. We want - # sub/foo.o: sub/foo.c - # sub/foo.o: sub/foo.h - # sub/foo.c: - # sub/foo.h: - # ICC 7.1 will output +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h - # and will wrap long lines using '\': + # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... - # tcc 0.9.26 (FIXME still under development at the moment of writing) - # will emit a similar output, but also prepend the continuation lines - # with horizontal tabulation characters. - "$@" -MD -MF "$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else + set_dir_from "$object" + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + set_base_from "$source" + tmpdepfile=$base.d + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir=$base.d-lock + trap " + echo '$0: caught signal, cleaning up...' >&2 + rmdir '$lockdir' + exit 1 + " 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0; do + # mkdir is a portable test-and-set. + if mkdir "$lockdir" 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rmdir "$lockdir" + break + else + # If the lock is being held by a different process, wait + # until the winning process is done or we timeout. + while test -d "$lockdir" && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" - # Each line is of the form 'foo.o: dependent.h', - # or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'. + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to - # '$object: dependent.h' and one to simply 'dependent.h:'. - sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \ - < "$tmpdepfile" > "$depfile" - sed ' - s/[ '"$tab"'][ '"$tab"']*/ /g - s/^ *// - s/ *\\*$// - s/^[^:]*: *// - /^$/d - /:$/d - s/$/ :/ - ' < "$tmpdepfile" >> "$depfile" + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ + | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; @@ -342,9 +439,8 @@ hp2) # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + set_dir_from "$object" + set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d @@ -355,8 +451,7 @@ hp2) "$@" +Maked fi stat=$? - if test $stat -eq 0; then : - else + if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi @@ -366,76 +461,61 @@ hp2) test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" + sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ - s/^ *// - s/ \\*$// - s/$/:/ - p - }' "$tmpdepfile" >> "$depfile" + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" else - echo "#dummy" > "$depfile" + make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) - # The Tru64 compiler uses -MD to generate dependencies as a side - # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. - # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put - # dependencies in 'foo.d' instead, so we check for that too. - # Subdirectories are respected. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - - if test "$libtool" = yes; then - # With Tru64 cc, shared objects can also be used to make a - # static library. This mechanism is used in libtool 1.4 series to - # handle both shared and static libraries in a single compilation. - # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. - # - # With libtool 1.5 this exception was removed, and libtool now - # generates 2 separate objects for the 2 libraries. These two - # compilations output dependencies in $dir.libs/$base.o.d and - # in $dir$base.o.d. We have to check for both files, because - # one of the two compilations can be disabled. We should prefer - # $dir$base.o.d over $dir.libs/$base.o.d because the latter is - # automatically cleaned when .libs/ is deleted, while ignoring - # the former would cause a distcleancheck panic. - tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 - tmpdepfile2=$dir$base.o.d # libtool 1.5 - tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 - tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 - "$@" -Wc,-MD - else - tmpdepfile1=$dir$base.o.d - tmpdepfile2=$dir$base.d - tmpdepfile3=$dir$base.d - tmpdepfile4=$dir$base.d - "$@" -MD - fi - - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" - do - test -f "$tmpdepfile" && break - done - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" - else - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + set_dir_from "$object" + set_base_from "$object" + + if test "$libtool" = yes; then + # Libtool generates 2 separate objects for the 2 libraries. These + # two compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir$base.o.d # libtool 1.5 + tmpdepfile2=$dir.libs/$base.o.d # Likewise. + tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + # Same post-processing that is required for AIX mode. + aix_post_process_depfile + ;; msvc7) if test "$libtool" = yes; then @@ -446,8 +526,7 @@ msvc7) "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" - if test "$stat" = 0; then : - else + if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi @@ -473,6 +552,7 @@ $ { G p }' >> "$depfile" + echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; @@ -524,13 +604,14 @@ dashmstdout) # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | - sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile" + sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" - tr ' ' "$nl" < "$tmpdepfile" | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + # Some versions of the HPUX 10.20 sed can't process this sed invocation + # correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; @@ -583,10 +664,12 @@ makedepend) # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" - sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + # Some versions of the HPUX 10.20 sed can't process the last invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed '1,2d' "$tmpdepfile" \ + | tr ' ' "$nl" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; @@ -622,10 +705,10 @@ cpp) esac done - "$@" -E | - sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ - -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | - sed '$ s: \\$::' > "$tmpdepfile" + "$@" -E \ + | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" @@ -657,15 +740,15 @@ msvisualcpp) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") - set fnord "$@" - shift - shift - ;; + set fnord "$@" + shift + shift + ;; *) - set fnord "$@" "$arg" - shift - shift - ;; + set fnord "$@" "$arg" + shift + shift + ;; esac done "$@" -E 2>/dev/null | @@ -700,9 +783,9 @@ exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/build-aux/install-sh b/build-aux/install-sh index a9244eb..ec298b5 100755 --- a/build-aux/install-sh +++ b/build-aux/install-sh @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2011-01-19.21; # UTC +scriptversion=2020-11-14.01; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -35,25 +35,21 @@ scriptversion=2011-01-19.21; # UTC # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it +# 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. +tab=' ' nl=' ' -IFS=" "" $nl" +IFS=" $tab$nl" -# set DOITPROG to echo to test this script +# Set DOITPROG to "echo" to test this script. -# Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} -if test -z "$doit"; then - doit_exec=exec -else - doit_exec=$doit -fi +doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. @@ -68,22 +64,16 @@ mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} -posix_glob='?' -initialize_posix_glob=' - test "$posix_glob" != "?" || { - if (set -f) 2>/dev/null; then - posix_glob= - else - posix_glob=: - fi - } -' - posix_mkdir= # Desired mode of installed file. mode=0755 +# Create dirs (including intermediate dirs) using mode 755. +# This is like GNU 'install' as of coreutils 8.32 (2020). +mkdir_umask=22 + +backupsuffix= chgrpcmd= chmodcmd=$chmodprog chowncmd= @@ -97,7 +87,7 @@ dir_arg= dst_arg= copy_on_change=false -no_target_directory= +is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE @@ -114,18 +104,28 @@ Options: --version display version info and exit. -c (ignored) - -C install only if different (preserve the last data modification time) + -C install only if different (preserve data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. + -p pass -p to $cpprog. -s $stripprog installed files. + -S SUFFIX attempt to back up existing files, with suffix SUFFIX. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG + +By default, rm is invoked with -f; when overridden with RMPROG, +it's up to you to specify -f if you want it. + +If -S is not specified, no backups are attempted. + +Email bug reports to bug-automake@gnu.org. +Automake home page: https://www.gnu.org/software/automake/ " while test $# -ne 0; do @@ -137,46 +137,62 @@ while test $# -ne 0; do -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" - shift;; + shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 - case $mode in - *' '* | *' '* | *' -'* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; -o) chowncmd="$chownprog $2" - shift;; + shift;; + + -p) cpprog="$cpprog -p";; -s) stripcmd=$stripprog;; - -t) dst_arg=$2 - # Protect names problematic for `test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - shift;; + -S) backupsuffix="$2" + shift;; - -T) no_target_directory=true;; + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; - --) shift - break;; + --) shift + break;; - -*) echo "$0: invalid option: $1" >&2 - exit 1;; + -*) echo "$0: invalid option: $1" >&2 + exit 1;; *) break;; esac shift done +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. @@ -190,7 +206,7 @@ if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then fi shift # arg dst_arg=$arg - # Protect names problematic for `test' and other utilities. + # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac @@ -202,12 +218,21 @@ if test $# -eq 0; then echo "$0: no input file specified." >&2 exit 1 fi - # It's OK to call `install-sh -d' without argument. + # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 @@ -223,16 +248,16 @@ if test -z "$dir_arg"; then *[0-7]) if test -z "$stripcmd"; then - u_plus_rw= + u_plus_rw= else - u_plus_rw='% 200' + u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then - u_plus_rw= + u_plus_rw= else - u_plus_rw=,u+rw + u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac @@ -240,7 +265,7 @@ fi for src do - # Protect names problematic for `test' and other utilities. + # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac @@ -250,6 +275,10 @@ do dstdir=$dst test -d "$dstdir" dstdir_status=$? + # Don't chown directories that already exist. + if test $dstdir_status = 0; then + chowncmd="" + fi else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command @@ -266,178 +295,148 @@ do fi dst=$dst_arg - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. + # If destination is a directory, append the input filename. if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 fi dstdir=$dst - dst=$dstdir/`basename "$src"` + dstbase=`basename "$src"` + case $dst in + */) dst=$dst$dstbase;; + *) dst=$dst/$dstbase;; + esac dstdir_status=0 else - # Prefer dirname, but fall back on a substitute if dirname fails. - dstdir=` - (dirname "$dst") 2>/dev/null || - expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$dst" : 'X\(//\)[^/]' \| \ - X"$dst" : 'X\(//\)$' \| \ - X"$dst" : 'X\(/\)' \| . 2>/dev/null || - echo X"$dst" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q' - ` - + dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi + case $dstdir in + */) dstdirslash=$dstdir;; + *) dstdirslash=$dstdir/;; + esac + obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac - - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + # The $RANDOM variable is not portable (e.g., dash). Use it + # here however when possible just to lower collision chance. + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + + trap ' + ret=$? + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null + exit $ret + ' 0 + + # Because "mkdir -p" follows existing symlinks and we likely work + # directly in world-writeable /tmp, make sure that the '$tmpdir' + # directory is successfully created first before we actually test + # 'mkdir -p'. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else - mkdir_mode= + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi - - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 - - if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writeable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/d" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null - fi - trap '' 0;; - esac;; + trap '' 0;; esac if $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else - # The umask is ridiculous, or mkdir does not conform to POSIX, + # mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in - /*) prefix='/';; - [-=\(\)!]*) prefix='./';; - *) prefix='';; + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; esac - eval "$initialize_posix_glob" - oIFS=$IFS IFS=/ - $posix_glob set -f + set -f set fnord $dstdir shift - $posix_glob set +f + set +f IFS=$oIFS prefixes= for d do - test X"$d" = X && continue - - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ done if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true fi fi fi @@ -450,14 +449,25 @@ do else # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ + dsttmp=${dstdirslash}_inst.$$_ + rmtmp=${dstdirslash}_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. - (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + (umask $cp_umask && + { test -z "$stripcmd" || { + # Create $dsttmp read-write so that cp doesn't create it read-only, + # which would cause strip to fail. + if test -z "$doit"; then + : >"$dsttmp" # No need to fork-exec 'touch'. + else + $doit touch "$dsttmp" + fi + } + } && + $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # @@ -472,20 +482,24 @@ do # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - - eval "$initialize_posix_glob" && - $posix_glob set -f && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && - $posix_glob set +f && - + set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else + # If $backupsuffix is set, and the file being installed + # already exists, attempt a backup. Don't worry if it fails, + # e.g., if mv doesn't support -f. + if test -n "$backupsuffix" && test -f "$dst"; then + $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null + fi + # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || @@ -493,24 +507,24 @@ do # to itself, or perhaps because mv is so ancient that it does not # support -f. { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 @@ -519,9 +533,9 @@ do done # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/build-aux/ltmain.sh b/build-aux/ltmain.sh index 63ae69d..49fcad1 100644 --- a/build-aux/ltmain.sh +++ b/build-aux/ltmain.sh @@ -1,9 +1,12 @@ +#! /usr/bin/env sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2019-02-19.15 -# libtool (GNU libtool) 2.4.2 +# libtool (GNU libtool) 2.4.7 +# Provide generalized library-building support services. # Written by Gordon Matzigkeit , 1996 -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, -# 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. +# Copyright (C) 1996-2019, 2021-2022 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. @@ -23,881 +26,2350 @@ # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, -# or obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# along with this program. If not, see . -# Usage: $progname [OPTION]... [MODE-ARG]... -# -# Provide generalized library-building support services. -# -# --config show all configuration variables -# --debug enable verbose shell tracing -# -n, --dry-run display commands without modifying any files -# --features display basic configuration information and exit -# --mode=MODE use operation mode MODE -# --preserve-dup-deps don't remove duplicate dependency libraries -# --quiet, --silent don't print informational messages -# --no-quiet, --no-silent -# print informational messages (default) -# --no-warn don't display warning messages -# --tag=TAG use configuration variables from tag TAG -# -v, --verbose print more informational messages than default -# --no-verbose don't print the extra informational messages -# --version print version information -# -h, --help, --help-all print short, long, or detailed help message -# -# MODE must be one of the following: -# -# clean remove files from the build directory -# compile compile a source file into a libtool object -# execute automatically set library path, then run a program -# finish complete the installation of libtool libraries -# install install libraries or executables -# link create a library or an executable -# uninstall remove libraries from an installed directory + +PROGRAM=libtool +PACKAGE=libtool +VERSION=2.4.7 +package_revision=2.4.7 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2019-02-19.15; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# This is free software. There is NO warranty; not even for +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # -# MODE-ARGS vary depending on the MODE. When passed as first option, -# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. -# Try `$progname --help --mode=MODE' for a more detailed description of MODE. +# Copyright (C) 2004-2019, 2021 Bootstrap Authors # -# When reporting a bug, please describe a test case to reproduce it and -# include the following information: +# This file is dual licensed under the terms of the MIT license +# , and GPL version 2 or later +# . You must apply one of +# these licenses when using or redistributing this software or any of +# the files within it. See the URLs above, or the file `LICENSE` +# included in the Bootstrap distribution for the full license texts. + +# Please report bugs or propose patches to: +# + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: # -# host-triplet: $host -# shell: $SHELL -# compiler: $LTCC -# compiler flags: $LTCFLAGS -# linker: $LD (gnu? $with_gnu_ld) -# $progname: (GNU libtool) 2.4.2 -# automake: $automake_version -# autoconf: $autoconf_version +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh # -# Report bugs to . -# GNU libtool home page: . -# General help using GNU software: . +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. -PROGRAM=libtool -PACKAGE=libtool -VERSION=2.4.2 -TIMESTAMP="" -package_revision=1.3337 -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' -} -# NLS nuisances: We save the old values to restore during execute mode. -lt_user_locale= -lt_safe_locale= -for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do - eval "if test \"\${$lt_var+set}\" = set; then - save_$lt_var=\$$lt_var - $lt_var=C - export $lt_var - lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" - lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" fi" done +# These NLS vars are set unconditionally (bootstrap issue #24). Unset those +# in case the environment reset is needed later and the $save_* variant is not +# defined (see the code above). LC_ALL=C LANGUAGE=C export LANGUAGE LC_ALL -$lt_unset CDPATH - +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi -# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh -# is ksh but when the shell is invoked as "sh" and the current value of -# the _XPG environment variable is not equal to 1 (one), the special -# positional parameter $0, within a function call, is the name of the -# function. -progpath="$0" +# func_unset VAR +# -------------- +# Portably unset VAR. +# In some shells, an 'unset VAR' statement leaves a non-zero return +# status if VAR is already unset, which might be problematic if the +# statement is used at the end of a function (thus poisoning its return +# value) or when 'set -e' is active (causing even a spurious abort of +# the script in this case). +func_unset () +{ + { eval $1=; (eval unset $1) >/dev/null 2>&1 && eval unset $1 || : ; } +} -: ${CP="cp -f"} -test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} -: ${MAKE="make"} -: ${MKDIR="mkdir"} -: ${MV="mv -f"} -: ${RM="rm -f"} -: ${SHELL="${CONFIG_SHELL-/bin/sh}"} -: ${Xsed="$SED -e 1s/^X//"} +# Make sure CDPATH doesn't cause `cd` commands to output the target dir. +func_unset CDPATH -# Global variables: -EXIT_SUCCESS=0 -EXIT_FAILURE=1 -EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. -EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. +# Make sure ${,E,F}GREP behave sanely. +func_unset GREP_OPTIONS -exit_status=$EXIT_SUCCESS -# Make sure IFS has a sensible default -lt_nl=' -' -IFS=" $lt_nl" +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## -dirname="s,/[^/]*$,," -basename="s,^.*/,," -# func_dirname file append nondir_replacement -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -func_dirname () +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () { - func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi -} # func_dirname may be replaced by extended shell implementation + test -f "$1" && test -x "$1" +} -# func_basename file -func_basename () +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () { - func_basename_result=`$ECHO "${1}" | $SED "$basename"` -} # func_basename may be replaced by extended shell implementation + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} -# func_dirname_and_basename file append nondir_replacement -# perform func_basename and func_dirname in a single function -# call: -# dirname: Compute the dirname of FILE. If nonempty, -# add APPEND to the result, otherwise set result -# to NONDIR_REPLACEMENT. -# value returned in "$func_dirname_result" -# basename: Compute filename of FILE. -# value retuned in "$func_basename_result" -# Implementation must be kept synchronized with func_dirname -# and func_basename. For efficiency, we do not delegate to -# those functions but instead duplicate the functionality here. -func_dirname_and_basename () -{ - # Extract subdirectory from the argument. - func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi - func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` -} # func_dirname_and_basename may be replaced by extended shell implementation +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -# func_strip_suffix prefix name -func_stripname () -{ - case ${2} in - .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; - esac -} # func_stripname may be replaced by extended shell implementation + func_check_prog_sed () + { + _G_path_prog=$1 + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } -# These SED scripts presuppose an absolute path with a trailing slash. -pathcar='s,^/\([^/]*\).*$,\1,' -pathcdr='s,^/[^/]*,,' -removedotparts=':dotsl - s@/\./@/@g - t dotsl - s,/\.$,/,' -collapseslashes='s@/\{1,\}@/@g' -finalslash='s,/*$,/,' + func_path_progs "sed gsed" func_check_prog_sed "$PATH:/usr/xpg4/bin" + rm -f conftest.sed + SED=$func_path_progs_result +} -# func_normal_abspath PATH -# Remove doubled-up and trailing slashes, "." path components, -# and cancel out any ".." path components in PATH after making -# it an absolute path. -# value returned in "$func_normal_abspath_result" -func_normal_abspath () + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep "$PATH:/usr/xpg4/bin" + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + +# require_check_ifs_backslash +# --------------------------- +# Check if we can use backslash as IFS='\' separator, and set +# $check_ifs_backshlash_broken to ':' or 'false'. +require_check_ifs_backslash=func_require_check_ifs_backslash +func_require_check_ifs_backslash () { - # Start from root dir and reassemble the path. - func_normal_abspath_result= - func_normal_abspath_tpath=$1 - func_normal_abspath_altnamespace= - case $func_normal_abspath_tpath in - "") - # Empty path, that just means $cwd. - func_stripname '' '/' "`pwd`" - func_normal_abspath_result=$func_stripname_result - return - ;; - # The next three entries are used to spot a run of precisely - # two leading slashes without using negated character classes; - # we take advantage of case's first-match behaviour. - ///*) - # Unusual form of absolute path, do nothing. - ;; - //*) - # Not necessarily an ordinary path; POSIX reserves leading '//' - # and for example Cygwin uses it to access remote file shares - # over CIFS/SMB, so we conserve a leading double slash if found. - func_normal_abspath_altnamespace=/ + _G_save_IFS=$IFS + IFS='\' + _G_check_ifs_backshlash='a\\b' + for _G_i in $_G_check_ifs_backshlash + do + case $_G_i in + a) + check_ifs_backshlash_broken=false ;; - /*) - # Absolute path, do nothing. + '') + break ;; - *) - # Relative path, prepend $cwd. - func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + *) + check_ifs_backshlash_broken=: + break ;; esac - # Cancel out all the simple stuff to save iterations. We also want - # the path to end with a slash for ease of parsing, so make sure - # there is one (and only one) here. - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` - while :; do - # Processed it all yet? - if test "$func_normal_abspath_tpath" = / ; then - # If we ascended to the root using ".." the result may be empty now. - if test -z "$func_normal_abspath_result" ; then - func_normal_abspath_result=/ - fi - break - fi - func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$pathcar"` - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$pathcdr"` - # Figure out what to do with it - case $func_normal_abspath_tcomponent in - "") - # Trailing empty path component, ignore it. - ;; - ..) - # Parent dir; strip last assembled component from result. - func_dirname "$func_normal_abspath_result" - func_normal_abspath_result=$func_dirname_result - ;; - *) - # Actual path component, append it. - func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent - ;; - esac done - # Restore leading double-slash if one was found on entry. - func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result + IFS=$_G_save_IFS + require_check_ifs_backslash=: } -# func_relative_path SRCDIR DSTDIR -# generates a relative path from SRCDIR to DSTDIR, with a trailing -# slash if non-empty, suitable for immediately appending a filename -# without needing to append a separator. -# value returned in "$func_relative_path_result" -func_relative_path () -{ - func_relative_path_result= - func_normal_abspath "$1" - func_relative_path_tlibdir=$func_normal_abspath_result - func_normal_abspath "$2" - func_relative_path_tbindir=$func_normal_abspath_result - - # Ascend the tree starting from libdir - while :; do - # check if we have found a prefix of bindir - case $func_relative_path_tbindir in - $func_relative_path_tlibdir) - # found an exact match - func_relative_path_tcancelled= - break - ;; - $func_relative_path_tlibdir*) - # found a matching prefix - func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" - func_relative_path_tcancelled=$func_stripname_result - if test -z "$func_relative_path_result"; then - func_relative_path_result=. - fi - break - ;; - *) - func_dirname $func_relative_path_tlibdir - func_relative_path_tlibdir=${func_dirname_result} - if test "x$func_relative_path_tlibdir" = x ; then - # Have to descend all the way to the root! - func_relative_path_result=../$func_relative_path_result - func_relative_path_tcancelled=$func_relative_path_tbindir - break - fi - func_relative_path_result=../$func_relative_path_result - ;; - esac - done - # Now calculate path; take care to avoid doubling-up slashes. - func_stripname '' '/' "$func_relative_path_result" - func_relative_path_result=$func_stripname_result - func_stripname '/' '/' "$func_relative_path_tcancelled" - if test "x$func_stripname_result" != x ; then - func_relative_path_result=${func_relative_path_result}/${func_stripname_result} - fi +## ----------------- ## +## Global variables. ## +## ----------------- ## - # Normalisation. If bindir is libdir, return empty string, - # else relative path ending with a slash; either way, target - # file name can be directly appended. - if test ! -z "$func_relative_path_result"; then - func_stripname './' '' "$func_relative_path_result/" - func_relative_path_result=$func_stripname_result - fi -} +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS -# The name of this program: -func_dirname_and_basename "$progpath" -progname=$func_basename_result +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` -# Make sure we have an absolute path for reexecution: +# Make sure we have an absolute progpath for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) - progdir=$func_dirname_result + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` progdir=`cd "$progdir" && pwd` - progpath="$progdir/$progname" + progpath=$progdir/$progname ;; *) - save_IFS="$IFS" + _G_IFS=$IFS IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do - IFS="$save_IFS" + IFS=$_G_IFS test -x "$progdir/$progname" && break done - IFS="$save_IFS" + IFS=$_G_IFS test -n "$progdir" || progdir=`pwd` - progpath="$progdir/$progname" + progpath=$progdir/$progname ;; esac -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed="${SED}"' -e 1s/^X//' -sed_quote_subst='s/\([`"$\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\(["`\\]\)/\\\1/g' -# Sed substitution that turns a string into a regex matching for the -# string literally. -sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' +## ----------------- ## +## Standard options. ## +## ----------------- ## -# Sed substitution that converts a w32 file name or path -# which contains forward slashes, into one that contains -# (escaped) backslashes. A very naive implementation. -lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' - -# Re-`\' parameter expansions in output of double_quote_subst that were -# `\'-ed in input to the same. If an odd number of `\' preceded a '$' -# in input to double_quote_subst, that '$' was protected from expansion. -# Since each input `\' is now two `\'s, look for any number of runs of -# four `\'s followed by two `\'s and then a '$'. `\' that '$'. -bs='\\' -bs2='\\\\' -bs4='\\\\\\\\' -dollar='\$' -sed_double_backslash="\ - s/$bs4/&\\ -/g - s/^$bs2$dollar/$bs&/ - s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g - s/\n//g" +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. -# Standard options: opt_dry_run=false -opt_help=false opt_quiet=false opt_verbose=false -opt_warning=: -# func_echo arg... -# Echo program name prefixed message, along with the current mode -# name if it has been set yet. -func_echo () -{ - $ECHO "$progname: ${opt_mode+$opt_mode: }$*" -} +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= -# func_verbose arg... -# Echo program name prefixed message in verbose mode only. -func_verbose () -{ - $opt_verbose && func_echo ${1+"$@"} +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue - # A bug in bash halts the script if the last line of a function - # fails when set -e is in force, so we need another command to - # work around that: - : -} +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all -# func_echo_all arg... -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "$*" -} -# func_error arg... -# Echo program name prefixed message to standard error. -func_error () -{ - $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 -} +## -------------------- ## +## Resource management. ## +## -------------------- ## -# func_warning arg... -# Echo program name prefixed warning message to standard error. -func_warning () -{ - $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. - # bash bug again: - : -} -# func_fatal_error arg... -# Echo program name prefixed message to standard error, and exit. -func_fatal_error () +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () { - func_error ${1+"$@"} - exit $EXIT_FAILURE -} + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } -# func_fatal_help arg... -# Echo program name prefixed message to standard error, followed by -# a help hint, and exit. -func_fatal_help () -{ - func_error ${1+"$@"} - func_fatal_error "$help" + require_term_colors=: } -help="Try \`$progname --help' for more information." ## default -# func_grep expression filename -# Check whether EXPRESSION matches any line of FILENAME, without output. -func_grep () -{ - $GREP "$1" "$2" >/dev/null 2>&1 -} +## ----------------- ## +## Function library. ## +## ----------------- ## +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. -# func_mkdir_p directory-path -# Make sure the entire path to DIRECTORY-PATH is available. -func_mkdir_p () + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_arg pretty "$2" + eval "$1+=\\ \$func_quote_arg_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_arg pretty "$2" + eval "$1=\$$1\\ \$func_quote_arg_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () { - my_directory_path="$1" - my_dir_list= + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} - if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then - # Protect directory names starting with `-' - case $my_directory_path in - -*) my_directory_path="./$my_directory_path" ;; +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; esac # While some portion of DIR does not yet exist... - while test ! -d "$my_directory_path"; do + while test ! -d "$_G_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. - my_dir_list="$my_directory_path:$my_dir_list" + _G_dir_list=$_G_directory_path:$_G_dir_list # If the last portion added has no slash in it, the list is done - case $my_directory_path in */*) ;; *) break ;; esac + case $_G_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop - my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` done - my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` - save_mkdir_p_IFS="$IFS"; IFS=':' - for my_dir in $my_dir_list; do - IFS="$save_mkdir_p_IFS" - # mkdir can fail with a `File exist' error if two processes + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! - $MKDIR "$my_dir" 2>/dev/null || : + $MKDIR "$_G_dir" 2>/dev/null || : done - IFS="$save_mkdir_p_IFS" + IFS=$func_mkdir_p_IFS # Bail out if we (or some other process) failed to create a directory. - test -d "$my_directory_path" || \ - func_fatal_error "Failed to create \`$1'" + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" fi } -# func_mktempdir [string] +# func_mktempdir [BASENAME] +# ------------------------- # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If -# given, STRING is the basename for that directory. +# given, BASENAME is the basename for that directory. func_mktempdir () { - my_template="${TMPDIR-/tmp}/${1-$progname}" + $debug_cmd - if test "$opt_dry_run" = ":"; then + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then # Return a directory name, but don't create it in dry-run mode - my_tmpdir="${my_template}-$$" + _G_tmpdir=$_G_template-$$ else # If mktemp works, use that first and foremost - my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` - if test ! -d "$my_tmpdir"; then + if test ! -d "$_G_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race - my_tmpdir="${my_template}-${RANDOM-0}$$" + _G_tmpdir=$_G_template-${RANDOM-0}$$ - save_mktempdir_umask=`umask` + func_mktempdir_umask=`umask` umask 0077 - $MKDIR "$my_tmpdir" - umask $save_mktempdir_umask + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure - test -d "$my_tmpdir" || \ - func_fatal_error "cannot create temporary directory \`$my_tmpdir'" + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" fi - $ECHO "$my_tmpdir" + $ECHO "$_G_tmpdir" } -# func_quote_for_eval arg -# Aesthetically quote ARG to be evaled later. -# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT -# is double-quoted, suitable for a subsequent eval, whereas -# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters -# which are still active within double quotes backslashified. -func_quote_for_eval () +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () { - case $1 in - *[\\\`\"\$]*) - func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; *) - func_quote_for_eval_unquoted_result="$1" ;; + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; esac - case $func_quote_for_eval_unquoted_result in - # Double-quote args containing shell metacharacters to delay - # word splitting, command substitution and and variable - # expansion for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_portable EVAL ARG +# ---------------------------- +# Internal function to portably implement func_quote_arg. Note that we still +# keep attention to performance here so we as much as possible try to avoid +# calling sed binary (so far O(N) complexity as long as func_append is O(1)). +func_quote_portable () +{ + $debug_cmd + + $require_check_ifs_backslash + + func_quote_portable_result=$2 + + # one-time-loop (easy break) + while true + do + if $1; then + func_quote_portable_result=`$ECHO "$2" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` + break + fi + + # Quote for eval. + case $func_quote_portable_result in + *[\\\`\"\$]*) + # Fallback to sed for $func_check_bs_ifs_broken=:, or when the string + # contains the shell wildcard characters. + case $check_ifs_backshlash_broken$func_quote_portable_result in + :*|*[\[\*\?]*) + func_quote_portable_result=`$ECHO "$func_quote_portable_result" \ + | $SED "$sed_quote_subst"` + break + ;; + esac + + func_quote_portable_old_IFS=$IFS + for _G_char in '\' '`' '"' '$' + do + # STATE($1) PREV($2) SEPARATOR($3) + set start "" "" + func_quote_portable_result=dummy"$_G_char$func_quote_portable_result$_G_char"dummy + IFS=$_G_char + for _G_part in $func_quote_portable_result + do + case $1 in + quote) + func_append func_quote_portable_result "$3$2" + set quote "$_G_part" "\\$_G_char" + ;; + start) + set first "" "" + func_quote_portable_result= + ;; + first) + set quote "$_G_part" "" + ;; + esac + done + done + IFS=$func_quote_portable_old_IFS + ;; + *) ;; + esac + break + done + + func_quote_portable_unquoted_result=$func_quote_portable_result + case $func_quote_portable_result in + # double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # many bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" + func_quote_portable_result=\"$func_quote_portable_result\" + ;; + esac +} + + +# func_quotefast_eval ARG +# ----------------------- +# Quote one ARG (internal). This is equivalent to 'func_quote_arg eval ARG', +# but optimized for speed. Result is stored in $func_quotefast_eval. +if test xyes = `(x=; printf -v x %q yes; echo x"$x") 2>/dev/null`; then + printf -v _GL_test_printf_tilde %q '~' + if test '\~' = "$_GL_test_printf_tilde"; then + func_quotefast_eval () + { + printf -v func_quotefast_eval_result %q "$1" + } + else + # Broken older Bash implementations. Make those faster too if possible. + func_quotefast_eval () + { + case $1 in + '~'*) + func_quote_portable false "$1" + func_quotefast_eval_result=$func_quote_portable_result + ;; + *) + printf -v func_quotefast_eval_result %q "$1" + ;; + esac + } + fi +else + func_quotefast_eval () + { + func_quote_portable false "$1" + func_quotefast_eval_result=$func_quote_portable_result + } +fi + + +# func_quote_arg MODEs ARG +# ------------------------ +# Quote one ARG to be evaled later. MODEs argument may contain zero or more +# specifiers listed below separated by ',' character. This function returns two +# values: +# i) func_quote_arg_result +# double-quoted (when needed), suitable for a subsequent eval +# ii) func_quote_arg_unquoted_result +# has all characters that are still active within double +# quotes backslashified. Available only if 'unquoted' is specified. +# +# Available modes: +# ---------------- +# 'eval' (default) +# - escape shell special characters +# 'expand' +# - the same as 'eval'; but do not quote variable references +# 'pretty' +# - request aesthetic output, i.e. '"a b"' instead of 'a\ b'. This might +# be used later in func_quote to get output like: 'echo "a b"' instead +# of 'echo a\ b'. This is slower than default on some shells. +# 'unquoted' +# - produce also $func_quote_arg_unquoted_result which does not contain +# wrapping double-quotes. +# +# Examples for 'func_quote_arg pretty,unquoted string': +# +# string | *_result | *_unquoted_result +# ------------+-----------------------+------------------- +# " | \" | \" +# a b | "a b" | a b +# "a b" | "\"a b\"" | \"a b\" +# * | "*" | * +# z="${x-$y}" | "z=\"\${x-\$y}\"" | z=\"\${x-\$y}\" +# +# Examples for 'func_quote_arg pretty,unquoted,expand string': +# +# string | *_result | *_unquoted_result +# --------------+---------------------+-------------------- +# z="${x-$y}" | "z=\"${x-$y}\"" | z=\"${x-$y}\" +func_quote_arg () +{ + _G_quote_expand=false + case ,$1, in + *,expand,*) + _G_quote_expand=: + ;; + esac + + case ,$1, in + *,pretty,*|*,expand,*|*,unquoted,*) + func_quote_portable $_G_quote_expand "$2" + func_quote_arg_result=$func_quote_portable_result + func_quote_arg_unquoted_result=$func_quote_portable_unquoted_result ;; *) - func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" + # Faster quote-for-eval for some shells. + func_quotefast_eval "$2" + func_quote_arg_result=$func_quotefast_eval_result + ;; + esac +} + + +# func_quote MODEs ARGs... +# ------------------------ +# Quote all ARGs to be evaled later and join them into single command. See +# func_quote_arg's description for more info. +func_quote () +{ + $debug_cmd + _G_func_quote_mode=$1 ; shift + func_quote_result= + while test 0 -lt $#; do + func_quote_arg "$_G_func_quote_mode" "$1" + if test -n "$func_quote_result"; then + func_append func_quote_result " $func_quote_arg_result" + else + func_append func_quote_result "$func_quote_arg_result" + fi + shift + done +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_arg pretty,expand "$_G_cmd" + eval "func_notquiet $func_quote_arg_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_arg expand,pretty "$_G_cmd" + eval "func_echo $func_quote_arg_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# This is free software. There is NO warranty; not even for +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# Copyright (C) 2010-2019, 2021 Bootstrap Authors +# +# This file is dual licensed under the terms of the MIT license +# , and GPL version 2 or later +# . You must apply one of +# these licenses when using or redistributing this software or any of +# the files within it. See the URLs above, or the file `LICENSE` +# included in the Bootstrap distribution for the full license texts. + +# Please report bugs or propose patches to: +# + +# Set a version string for this script. +scriptversion=2019-02-19.15; # UTC + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# Copyright'. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug in processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# in the main code. A hook is just a list of function names that can be +# run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of hook functions to be called by +# FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_propagate_result FUNC_NAME_A FUNC_NAME_B +# --------------------------------------------- +# If the *_result variable of FUNC_NAME_A _is set_, assign its value to +# *_result variable of FUNC_NAME_B. +func_propagate_result () +{ + $debug_cmd + + func_propagate_result_result=: + if eval "test \"\${${1}_result+set}\" = set" + then + eval "${2}_result=\$${1}_result" + else + func_propagate_result_result=false + fi +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It's assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook functions." ;; esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + func_unset "${_G_hook}_result" + eval $_G_hook '${1+"$@"}' + func_propagate_result $_G_hook func_run_hooks + if $func_propagate_result_result; then + eval set dummy "$func_run_hooks_result"; shift + fi + done +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list from your hook function. You may remove +# or edit any options that you action, and then pass back the remaining +# unprocessed options in '_result', escaped +# suitably for 'eval'. +# +# The '_result' variable is automatically unset +# before your hook gets called; for best performance, only set the +# *_result variable when necessary (i.e. don't call the 'func_quote' +# function unnecessarily because it can be an expensive operation on some +# machines). +# +# Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# # No change in '$@' (ignored completely by this hook). Leave +# # my_options_prep_result variable intact. +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# args_changed=false +# +# # Note that, for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: +# args_changed=: +# ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# args_changed=: +# ;; +# *) # Make sure the first unrecognised option "$_G_opt" +# # is added back to "$@" in case we need it later, +# # if $args_changed was set to 'true'. +# set dummy "$_G_opt" ${1+"$@"}; shift; break ;; +# esac +# done +# +# # Only call 'func_quote' here if we processed at least one argument. +# if $args_changed; then +# func_quote eval ${1+"$@"} +# my_silent_option_result=$func_quote_result +# fi +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll also need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options_finish [ARG]... +# ---------------------------- +# Finishing the option parse loop (call 'func_options' hooks ATM). +func_options_finish () +{ + $debug_cmd + + func_run_hooks func_options ${1+"$@"} + func_propagate_result func_run_hooks func_options_finish } -# func_quote_for_expand arg -# Aesthetically quote ARG to be evaled later; same as above, -# but do not quote variable references. -func_quote_for_expand () +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () { - case $1 in - *[\\\`\"]*) - my_arg=`$ECHO "$1" | $SED \ - -e "$double_quote_subst" -e "$sed_double_backslash"` ;; - *) - my_arg="$1" ;; - esac + $debug_cmd - case $my_arg in - # Double-quote args containing shell metacharacters to delay - # word splitting and command substitution for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - my_arg="\"$my_arg\"" - ;; - esac + _G_options_quoted=false - func_quote_for_expand_result="$my_arg" + for my_func in options_prep parse_options validate_options options_finish + do + func_unset func_${my_func}_result + func_unset func_run_hooks_result + eval func_$my_func '${1+"$@"}' + func_propagate_result func_$my_func func_options + if $func_propagate_result_result; then + eval set dummy "$func_options_result"; shift + _G_options_quoted=: + fi + done + + $_G_options_quoted || { + # As we (func_options) are top-level options-parser function and + # nobody quoted "$@" for us yet, we need to do it explicitly for + # caller. + func_quote eval ${1+"$@"} + func_options_result=$func_quote_result + } } -# func_show_eval cmd [fail_exp] -# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. -func_show_eval () +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propagate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before returning. +func_hookable func_options_prep +func_options_prep () { - my_cmd="$1" - my_fail_exp="${2-:}" + $debug_cmd - ${opt_silent-false} || { - func_quote_for_expand "$my_cmd" - eval "func_echo $func_quote_for_expand_result" - } + # Option defaults: + opt_verbose=false + opt_warning_types= - if ${opt_dry_run-false}; then :; else - eval "$my_cmd" - my_status=$? - if test "$my_status" -eq 0; then :; else - eval "(exit $my_status); $my_fail_exp" - fi - fi + func_run_hooks func_options_prep ${1+"$@"} + func_propagate_result func_run_hooks func_options_prep } -# func_show_eval_locale cmd [fail_exp] -# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. Use the saved locale for evaluation. -func_show_eval_locale () +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () { - my_cmd="$1" - my_fail_exp="${2-:}" + $debug_cmd + + _G_parse_options_requote=false + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + func_run_hooks func_parse_options ${1+"$@"} + func_propagate_result func_run_hooks func_parse_options + if $func_propagate_result_result; then + eval set dummy "$func_parse_options_result"; shift + # Even though we may have changed "$@", we passed the "$@" array + # down into the hook and it quoted it for us (because we are in + # this if-branch). No need to quote it again. + _G_parse_options_requote=false + fi - ${opt_silent-false} || { - func_quote_for_expand "$my_cmd" - eval "func_echo $func_quote_for_expand_result" - } + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break - if ${opt_dry_run-false}; then :; else - eval "$lt_user_locale - $my_cmd" - my_status=$? - eval "$lt_safe_locale" - if test "$my_status" -eq 0; then :; else - eval "(exit $my_status); $my_fail_exp" + # We expect that one of the options parsed in this function matches + # and thus we remove _G_opt from "$@" and need to re-quote. + _G_match_parse_options=: + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" >&2 + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + if test $# = 0 && func_missing_arg $_G_opt; then + _G_parse_options_requote=: + break + fi + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) _G_parse_options_requote=: ; break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift + _G_match_parse_options=false + break + ;; + esac + + if $_G_match_parse_options; then + _G_parse_options_requote=: fi + done + + if $_G_parse_options_requote; then + # save modified positional parameters for caller + func_quote eval ${1+"$@"} + func_parse_options_result=$func_quote_result fi } -# func_tr_sh -# Turn $1 into a string suitable for a shell variable name. -# Result is stored in $func_tr_sh_result. All characters -# not in the set a-zA-Z0-9_ are replaced with '_'. Further, -# if $1 begins with a digit, a '_' is prepended as well. -func_tr_sh () + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () { - case $1 in - [0-9]* | *[!a-zA-Z0-9_]*) - func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` - ;; - * ) - func_tr_sh_result=$1 - ;; - esac -} + $debug_cmd + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" -# func_version -# Echo version message to standard output and exit. -func_version () -{ - $opt_debug + func_run_hooks func_validate_options ${1+"$@"} + func_propagate_result func_run_hooks func_validate_options - $SED -n '/(C)/!b go - :more - /\./!{ - N - s/\n# / / - b more - } - :go - /^# '$PROGRAM' (GNU /,/# warranty; / { - s/^# // - s/^# *$// - s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ - p - }' < "$progpath" - exit $? + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE } -# func_usage -# Echo short help message to standard output and exit. -func_usage () + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () { - $opt_debug + $debug_cmd - $SED -n '/^# Usage:/,/^# *.*--help/ { - s/^# // - s/^# *$// - s/\$progname/'$progname'/ - p - }' < "$progpath" - echo - $ECHO "run \`$progname --help | more' for full usage" - exit $? + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE } -# func_help [NOEXIT] -# Echo long help message to standard output and exit, -# unless 'noexit' is passed as argument. + +# func_help +# --------- +# Echo long help message to standard output and exit. func_help () { - $opt_debug - - $SED -n '/^# Usage:/,/# Report bugs to/ { - :print - s/^# // - s/^# *$// - s*\$progname*'$progname'* - s*\$host*'"$host"'* - s*\$SHELL*'"$SHELL"'* - s*\$LTCC*'"$LTCC"'* - s*\$LTCFLAGS*'"$LTCFLAGS"'* - s*\$LD*'"$LD"'* - s/\$with_gnu_ld/'"$with_gnu_ld"'/ - s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ - s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ - p - d - } - /^# .* home page:/b print - /^# General help using/b print - ' < "$progpath" - ret=$? - if test -z "$1"; then - exit $ret - fi + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 } -# func_missing_arg argname + +# func_missing_arg ARGNAME +# ------------------------ # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { - $opt_debug + $debug_cmd - func_error "missing argument for $1." + func_error "Missing argument for '$1'." exit_cmd=exit } -# func_split_short_opt shortopt +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables +# after splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + if test "x$func_split_equals_lhs" = "x$1"; then + func_split_equals_rhs= + fi + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs=" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. -func_split_short_opt () +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x\(-.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () { - my_sed_short_opt='1s/^\(..\).*$/\1/;q' - my_sed_short_rest='1s/^..\(.*\)$/\1/;q' + $debug_cmd - func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` - func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` -} # func_split_short_opt may be replaced by extended shell implementation + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} -# func_split_long_opt longopt -# Set func_split_long_opt_name and func_split_long_opt_arg shell -# variables after splitting LONGOPT at the `=' sign. -func_split_long_opt () +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () { - my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' - my_sed_long_arg='1s/^--[^=]*=//' + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} - func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` - func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` -} # func_split_long_opt may be replaced by extended shell implementation -exit_cmd=: +# func_version +# ------------ +# Echo version message to standard output and exit. +# The version message is extracted from the calling file's header +# comments, with leading '# ' stripped: +# 1. First display the progname and version +# 2. Followed by the header comment line matching /^# Written by / +# 3. Then a blank line followed by the first following line matching +# /^# Copyright / +# 4. Immediately followed by any lines between the previous matches, +# except lines preceding the intervening completely blank line. +# For example, see the header comments of this file. +func_version () +{ + $debug_cmd + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /^# Written by /!b + s|^# ||; p; n + :fwd2blnk + /./ { + n + b fwd2blnk + } + p; n + + :holdwrnt + s|^# || + s|^# *$|| + /^Copyright /!{ + /./H + n + b holdwrnt + } + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + G + s|\(\n\)\n*|\1|g + p; q' < "$progpath" + exit $? +} -magic="%%%MAGIC variable%%%" -magic_exe="%%%MAGIC EXE variable%%%" -# Global variables. -nonopt= -preserve_args= -lo2o="s/\\.lo\$/.${objext}/" -o2lo="s/\\.${objext}\$/.lo/" -extracted_archives= -extracted_serial=0 +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "30/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: -# If this variable is set in any of the actions, the command in it -# will be execed at the end. This prevents here-documents from being -# left over by shells. -exec_cmd= +# Set a version string. +scriptversion='(GNU libtool) 2.4.7' -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () -{ - eval "${1}=\$${1}\${2}" -} # func_append may be replaced by extended shell implementation -# func_append_quoted var value -# Quote VALUE and append to the end of shell variable VAR, separated -# by a space. -func_append_quoted () +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () { - func_quote_for_eval "${2}" - eval "${1}=\$${1}\\ \$func_quote_for_eval_result" -} # func_append_quoted may be replaced by extended shell implementation + $debug_cmd + _G_message=$* -# func_arith arithmetic-term... -func_arith () -{ - func_arith_result=`expr "${@}"` -} # func_arith may be replaced by extended shell implementation + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} -# func_len string -# STRING may not start with a hyphen. -func_len () +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () { - func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` -} # func_len may be replaced by extended shell implementation + $debug_cmd + $warning_func ${1+"$@"} +} -# func_lo2o object -func_lo2o () -{ - func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` -} # func_lo2o may be replaced by extended shell implementation +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" -# func_xform libobj-or-source -func_xform () +# Additional text appended to 'usage_message' in response to '--help'. +func_help () { - func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` -} # func_xform may be replaced by extended shell implementation + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname (GNU libtool) 2.4.7 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ -# func_fatal_configuration arg... +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { - func_error ${1+"$@"} - func_error "See the $PACKAGE documentation for more information." - func_fatal_error "Fatal configuration error." + func_fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." } # func_config +# ----------- # Display the configuration for all the tags in this script. func_config () { @@ -915,17 +2387,19 @@ func_config () exit $? } + # func_features +# ------------- # Display the features supported by this script. func_features () { echo "host: $host" - if test "$build_libtool_libs" = yes; then + if test yes = "$build_libtool_libs"; then echo "enable shared libraries" else echo "disable shared libraries" fi - if test "$build_old_libs" = yes; then + if test yes = "$build_old_libs"; then echo "enable static libraries" else echo "disable static libraries" @@ -934,314 +2408,358 @@ func_features () exit $? } -# func_enable_tag tagname + +# func_enable_tag TAGNAME +# ----------------------- # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { - # Global variable: - tagname="$1" + # Global variable: + tagname=$1 - re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" - re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" - sed_extractcf="/$re_begincf/,/$re_endcf/p" + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p - # Validate tagname. - case $tagname in - *[!-_A-Za-z0-9,/]*) - func_fatal_error "invalid tag name: $tagname" - ;; - esac + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac - # Don't test for the "default" C tag, as we know it's - # there but not specially marked. - case $tagname in - CC) ;; + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; *) - if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then - taglist="$taglist $tagname" - - # Evaluate the configuration. Be careful to quote the path - # and the sed script, to avoid splitting on whitespace, but - # also don't use non-portable quotes within backquotes within - # quotes we have to do it in 2 steps: - extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` - eval "$extractedcf" - else - func_error "ignoring unknown tag $tagname" - fi - ;; - esac + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac } + # func_check_version_match +# ------------------------ # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { - if test "$package_revision" != "$macro_revision"; then - if test "$VERSION" != "$macro_version"; then - if test -z "$macro_version"; then - cat >&2 <<_LT_EOF + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF - else - cat >&2 <<_LT_EOF + else + cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF - fi - else - cat >&2 <<_LT_EOF + fi + else + cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF - fi + fi - exit $EXIT_MISMATCH - fi + exit $EXIT_MISMATCH + fi } -# Shorthand for --mode=foo, only valid as the first argument -case $1 in -clean|clea|cle|cl) - shift; set dummy --mode clean ${1+"$@"}; shift - ;; -compile|compil|compi|comp|com|co|c) - shift; set dummy --mode compile ${1+"$@"}; shift - ;; -execute|execut|execu|exec|exe|ex|e) - shift; set dummy --mode execute ${1+"$@"}; shift - ;; -finish|finis|fini|fin|fi|f) - shift; set dummy --mode finish ${1+"$@"}; shift - ;; -install|instal|insta|inst|ins|in|i) - shift; set dummy --mode install ${1+"$@"}; shift - ;; -link|lin|li|l) - shift; set dummy --mode link ${1+"$@"}; shift - ;; -uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) - shift; set dummy --mode uninstall ${1+"$@"}; shift - ;; -esac - +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false -# Option defaults: -opt_debug=: -opt_dry_run=false -opt_config=false -opt_preserve_dup_deps=false -opt_features=false -opt_finish=false -opt_help=false -opt_help_all=false -opt_silent=: -opt_warning=: -opt_verbose=: -opt_silent=false -opt_verbose=false + nonopt= + preserve_args= + _G_rc_lt_options_prep=: -# Parse options once, thoroughly. This comes as soon as possible in the -# script to make things like `--version' happen as quickly as we can. -{ - # this just eases exit handling - while test $# -gt 0; do - opt="$1" - shift - case $opt in - --debug|-x) opt_debug='set -x' - func_echo "enabling shell trace mode" - $opt_debug - ;; - --dry-run|--dryrun|-n) - opt_dry_run=: - ;; - --config) - opt_config=: -func_config - ;; - --dlopen|-dlopen) - optarg="$1" - opt_dlopen="${opt_dlopen+$opt_dlopen -}$optarg" - shift - ;; - --preserve-dup-deps) - opt_preserve_dup_deps=: - ;; - --features) - opt_features=: -func_features - ;; - --finish) - opt_finish=: -set dummy --mode finish ${1+"$@"}; shift - ;; - --help) - opt_help=: - ;; - --help-all) - opt_help_all=: -opt_help=': help-all' - ;; - --mode) - test $# = 0 && func_missing_arg $opt && break - optarg="$1" - opt_mode="$optarg" -case $optarg in - # Valid mode arguments: - clean|compile|execute|finish|install|link|relink|uninstall) ;; - - # Catch anything else as an error - *) func_error "invalid argument for $opt" - exit_cmd=exit - break - ;; -esac - shift - ;; - --no-silent|--no-quiet) - opt_silent=false -func_append preserve_args " $opt" - ;; - --no-warning|--no-warn) - opt_warning=false -func_append preserve_args " $opt" - ;; - --no-verbose) - opt_verbose=false -func_append preserve_args " $opt" - ;; - --silent|--quiet) - opt_silent=: -func_append preserve_args " $opt" - opt_verbose=false - ;; - --verbose|-v) - opt_verbose=: -func_append preserve_args " $opt" -opt_silent=false - ;; - --tag) - test $# = 0 && func_missing_arg $opt && break - optarg="$1" - opt_tag="$optarg" -func_append preserve_args " $opt $optarg" -func_enable_tag "$optarg" - shift - ;; - - -\?|-h) func_usage ;; - --help) func_help ;; - --version) func_version ;; - - # Separate optargs to long options: - --*=*) - func_split_long_opt "$opt" - set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} - shift - ;; - - # Separate non-argument short options: - -\?*|-h*|-n*|-v*) - func_split_short_opt "$opt" - set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - --) break ;; - -*) func_fatal_help "unrecognized option \`$opt'" ;; - *) set dummy "$opt" ${1+"$@"}; shift; break ;; + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + *) + _G_rc_lt_options_prep=false + ;; esac - done - # Validate options: + if $_G_rc_lt_options_prep; then + # Pass back the list of options. + func_quote eval ${1+"$@"} + libtool_options_prep_result=$func_quote_result + fi +} +func_add_hook func_options_prep libtool_options_prep - # save first non-option argument - if test "$#" -gt 0; then - nonopt="$opt" - shift - fi - # preserve --debug - test "$opt_debug" = : || func_append preserve_args " --debug" +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd - case $host in - *cygwin* | *mingw* | *pw32* | *cegcc*) - # don't eliminate duplications in $postdeps and $predeps - opt_duplicate_compiler_generated_deps=: - ;; - *) - opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps - ;; - esac + _G_rc_lt_parse_options=false - $opt_help || { - # Sanity checks first: - func_check_version_match + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_match_lt_parse_options=: + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"} ; shift + _G_match_lt_parse_options=false + break + ;; + esac + $_G_match_lt_parse_options && _G_rc_lt_parse_options=: + done - if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then - func_fatal_configuration "not configured to build any kind of library" + if $_G_rc_lt_parse_options; then + # save modified positional parameters for caller + func_quote eval ${1+"$@"} + libtool_parse_options_result=$func_quote_result fi +} +func_add_hook func_parse_options libtool_parse_options + - # Darwin sucks - eval std_shrext=\"$shrext_cmds\" - # Only execute mode is allowed to have -dlopen flags. - if test -n "$opt_dlopen" && test "$opt_mode" != execute; then - func_error "unrecognized option \`-dlopen'" - $ECHO "$help" 1>&2 - exit $EXIT_FAILURE +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift fi - # Change the help message to a mode-specific one. - generic_help="$help" - help="Try \`$progname --help --mode=$opt_mode' for more information." - } + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + # Keeping compiler generated duplicates in $postdeps and $predeps is not + # harmful, and is necessary in a majority of systems that use it to satisfy + # symbol dependencies. + opt_duplicate_compiler_generated_deps=: + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } - # Bail if the options were screwed - $exit_cmd $EXIT_FAILURE + # Pass back the unparsed argument list + func_quote eval ${1+"$@"} + libtool_validate_options_result=$func_quote_result } +func_add_hook func_validate_options libtool_validate_options +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + ## ----------- ## ## Main. ## ## ----------- ## +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + # func_lalib_p file -# True iff FILE is a libtool `.la' library or `.lo' object file. +# True iff FILE is a libtool '.la' library or '.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && - $SED -e 4q "$1" 2>/dev/null \ - | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p } # func_lalib_unsafe_p file -# True iff FILE is a libtool `.la' library or `.lo' object file. +# True iff FILE is a libtool '.la' library or '.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be -# fatal anyway. Works if `file' does not exist. +# fatal anyway. Works if 'file' does not exist. func_lalib_unsafe_p () { lalib_p=no @@ -1249,13 +2767,13 @@ func_lalib_unsafe_p () for lalib_p_l in 1 2 3 4 do read lalib_p_line - case "$lalib_p_line" in + case $lalib_p_line in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi - test "$lalib_p" = yes + test yes = "$lalib_p" } # func_ltwrapper_script_p file @@ -1264,7 +2782,8 @@ func_lalib_unsafe_p () # determined imposters. func_ltwrapper_script_p () { - func_lalib_p "$1" + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p } # func_ltwrapper_executable_p file @@ -1289,7 +2808,7 @@ func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" - func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper } # func_ltwrapper_p file @@ -1308,11 +2827,13 @@ func_ltwrapper_p () # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { - $opt_debug + $debug_cmd + save_ifs=$IFS; IFS='~' for cmd in $1; do - IFS=$save_ifs + IFS=$sp$nl eval cmd=\"$cmd\" + IFS=$save_ifs func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs @@ -1324,10 +2845,11 @@ func_execute_cmds () # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing -# `FILE.' does not work on cygwin managed mounts. +# 'FILE.' does not work on cygwin managed mounts. func_source () { - $opt_debug + $debug_cmd + case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; @@ -1354,10 +2876,10 @@ func_resolve_sysroot () # store the result into func_replace_sysroot_result. func_replace_sysroot () { - case "$lt_sysroot:$1" in + case $lt_sysroot:$1 in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" - func_replace_sysroot_result="=$func_stripname_result" + func_replace_sysroot_result='='$func_stripname_result ;; *) # Including no sysroot. @@ -1374,7 +2896,8 @@ func_replace_sysroot () # arg is usually of the form 'gcc ...' func_infer_tag () { - $opt_debug + $debug_cmd + if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do @@ -1393,7 +2916,7 @@ func_infer_tag () for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. - eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. @@ -1418,7 +2941,7 @@ func_infer_tag () # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" - func_fatal_error "specify a tag with \`--tag'" + func_fatal_error "specify a tag with '--tag'" # else # func_verbose "using $tagname tagged configuration" fi @@ -1434,15 +2957,15 @@ func_infer_tag () # but don't create it if we're doing a dry run. func_write_libtool_object () { - write_libobj=${1} - if test "$build_libtool_libs" = yes; then - write_lobj=\'${2}\' + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' else write_lobj=none fi - if test "$build_old_libs" = yes; then - write_oldobj=\'${3}\' + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' else write_oldobj=none fi @@ -1450,7 +2973,7 @@ func_write_libtool_object () $opt_dry_run || { cat >${write_libobj}T </dev/null` - if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | - $SED -e "$lt_sed_naive_backslashify"` + $SED -e "$sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi @@ -1514,18 +3038,19 @@ func_convert_core_file_wine_to_w32 () # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { - $opt_debug + $debug_cmd + # unfortunately, winepath doesn't convert paths, only file names - func_convert_core_path_wine_to_w32_result="" + func_convert_core_path_wine_to_w32_result= if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" - if test -n "$func_convert_core_file_wine_to_w32_result" ; then + if test -n "$func_convert_core_file_wine_to_w32_result"; then if test -z "$func_convert_core_path_wine_to_w32_result"; then - func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi @@ -1554,7 +3079,8 @@ func_convert_core_path_wine_to_w32 () # environment variable; do not put it in $PATH. func_cygpath () { - $opt_debug + $debug_cmd + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then @@ -1563,7 +3089,7 @@ func_cygpath () fi else func_cygpath_result= - func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" fi } #end: func_cygpath @@ -1574,10 +3100,11 @@ func_cygpath () # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { - $opt_debug + $debug_cmd + # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | - $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 @@ -1588,13 +3115,14 @@ func_convert_core_msys_to_w32 () # func_to_host_file_result to ARG1). func_convert_file_check () { - $opt_debug - if test -z "$2" && test -n "$1" ; then + $debug_cmd + + if test -z "$2" && test -n "$1"; then func_error "Could not determine host file name corresponding to" - func_error " \`$1'" + func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: - func_to_host_file_result="$1" + func_to_host_file_result=$1 fi } # end func_convert_file_check @@ -1606,10 +3134,11 @@ func_convert_file_check () # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { - $opt_debug + $debug_cmd + if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" - func_error " \`$3'" + func_error " '$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. @@ -1618,7 +3147,7 @@ func_convert_path_check () func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else - func_to_host_path_result="$3" + func_to_host_path_result=$3 fi fi } @@ -1630,9 +3159,10 @@ func_convert_path_check () # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { - $opt_debug + $debug_cmd + case $4 in - $1 ) func_to_host_path_result="$3$func_to_host_path_result" + $1 ) func_to_host_path_result=$3$func_to_host_path_result ;; esac case $4 in @@ -1646,7 +3176,7 @@ func_convert_path_front_back_pathsep () ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## -# invoked via `$to_host_file_cmd ARG' +# invoked via '$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. @@ -1657,7 +3187,8 @@ func_convert_path_front_back_pathsep () # in func_to_host_file_result. func_to_host_file () { - $opt_debug + $debug_cmd + $to_host_file_cmd "$1" } # end func_to_host_file @@ -1669,7 +3200,8 @@ func_to_host_file () # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { - $opt_debug + $debug_cmd + case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 @@ -1687,7 +3219,7 @@ func_to_tool_file () # Copy ARG to func_to_host_file_result. func_convert_file_noop () { - func_to_host_file_result="$1" + func_to_host_file_result=$1 } # end func_convert_file_noop @@ -1698,11 +3230,12 @@ func_convert_file_noop () # func_to_host_file_result. func_convert_file_msys_to_w32 () { - $opt_debug - func_to_host_file_result="$1" + $debug_cmd + + func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" - func_to_host_file_result="$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_convert_core_msys_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } @@ -1714,8 +3247,9 @@ func_convert_file_msys_to_w32 () # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { - $opt_debug - func_to_host_file_result="$1" + $debug_cmd + + func_to_host_file_result=$1 if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. @@ -1731,11 +3265,12 @@ func_convert_file_cygwin_to_w32 () # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { - $opt_debug - func_to_host_file_result="$1" + $debug_cmd + + func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" - func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } @@ -1747,12 +3282,13 @@ func_convert_file_nix_to_w32 () # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { - $opt_debug - func_to_host_file_result="$1" + $debug_cmd + + func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" - func_to_host_file_result="$func_cygpath_result" + func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } @@ -1765,13 +3301,14 @@ func_convert_file_msys_to_cygwin () # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { - $opt_debug - func_to_host_file_result="$1" + $debug_cmd + + func_to_host_file_result=$1 if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" - func_to_host_file_result="$func_cygpath_result" + func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } @@ -1781,7 +3318,7 @@ func_convert_file_nix_to_cygwin () ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# -# invoked via `$to_host_path_cmd ARG' +# invoked via '$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. @@ -1805,10 +3342,11 @@ func_convert_file_nix_to_cygwin () to_host_path_cmd= func_init_to_host_path_cmd () { - $opt_debug + $debug_cmd + if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" - to_host_path_cmd="func_convert_path_${func_stripname_result}" + to_host_path_cmd=func_convert_path_$func_stripname_result fi } @@ -1818,7 +3356,8 @@ func_init_to_host_path_cmd () # in func_to_host_path_result. func_to_host_path () { - $opt_debug + $debug_cmd + func_init_to_host_path_cmd $to_host_path_cmd "$1" } @@ -1829,7 +3368,7 @@ func_to_host_path () # Copy ARG to func_to_host_path_result. func_convert_path_noop () { - func_to_host_path_result="$1" + func_to_host_path_result=$1 } # end func_convert_path_noop @@ -1840,8 +3379,9 @@ func_convert_path_noop () # func_to_host_path_result. func_convert_path_msys_to_w32 () { - $opt_debug - func_to_host_path_result="$1" + $debug_cmd + + func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; @@ -1849,7 +3389,7 @@ func_convert_path_msys_to_w32 () func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result="$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_convert_core_msys_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" @@ -1863,8 +3403,9 @@ func_convert_path_msys_to_w32 () # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { - $opt_debug - func_to_host_path_result="$1" + $debug_cmd + + func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" @@ -1883,14 +3424,15 @@ func_convert_path_cygwin_to_w32 () # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { - $opt_debug - func_to_host_path_result="$1" + $debug_cmd + + func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" @@ -1904,15 +3446,16 @@ func_convert_path_nix_to_w32 () # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { - $opt_debug - func_to_host_path_result="$1" + $debug_cmd + + func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" - func_to_host_path_result="$func_cygpath_result" + func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" @@ -1927,8 +3470,9 @@ func_convert_path_msys_to_cygwin () # func_to_host_file_result. func_convert_path_nix_to_cygwin () { - $opt_debug - func_to_host_path_result="$1" + $debug_cmd + + func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them @@ -1937,7 +3481,7 @@ func_convert_path_nix_to_cygwin () func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" - func_to_host_path_result="$func_cygpath_result" + func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" @@ -1946,13 +3490,31 @@ func_convert_path_nix_to_cygwin () # end func_convert_path_nix_to_cygwin +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + # func_mode_compile arg... func_mode_compile () { - $opt_debug + $debug_cmd + # Get the compilation command and the source file. base_compile= - srcfile="$nonopt" # always keep a non-empty value in "srcfile" + srcfile=$nonopt # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal @@ -1965,12 +3527,12 @@ func_mode_compile () case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile - lastarg="$arg" + lastarg=$arg arg_mode=normal ;; target ) - libobj="$arg" + libobj=$arg arg_mode=normal continue ;; @@ -1980,7 +3542,7 @@ func_mode_compile () case $arg in -o) test -n "$libobj" && \ - func_fatal_error "you cannot specify \`-o' more than once" + func_fatal_error "you cannot specify '-o' more than once" arg_mode=target continue ;; @@ -2009,12 +3571,12 @@ func_mode_compile () func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= - save_ifs="$IFS"; IFS=',' + save_ifs=$IFS; IFS=, for arg in $args; do - IFS="$save_ifs" + IFS=$save_ifs func_append_quoted lastarg "$arg" done - IFS="$save_ifs" + IFS=$save_ifs func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result @@ -2027,8 +3589,8 @@ func_mode_compile () # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # - lastarg="$srcfile" - srcfile="$arg" + lastarg=$srcfile + srcfile=$arg ;; esac # case $arg ;; @@ -2043,13 +3605,13 @@ func_mode_compile () func_fatal_error "you must specify an argument for -Xcompile" ;; target) - func_fatal_error "you must specify a target with \`-o'" + func_fatal_error "you must specify a target with '-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" - libobj="$func_basename_result" + libobj=$func_basename_result } ;; esac @@ -2069,7 +3631,7 @@ func_mode_compile () case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) - func_fatal_error "cannot determine name of library object from \`$libobj'" + func_fatal_error "cannot determine name of library object from '$libobj'" ;; esac @@ -2078,8 +3640,8 @@ func_mode_compile () for arg in $later; do case $arg in -shared) - test "$build_libtool_libs" != yes && \ - func_fatal_configuration "can not build a shared library" + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" build_old_libs=no continue ;; @@ -2102,20 +3664,20 @@ func_mode_compile () esac done - func_quote_for_eval "$libobj" - test "X$libobj" != "X$func_quote_for_eval_result" \ + func_quote_arg pretty "$libobj" + test "X$libobj" != "X$func_quote_arg_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ - && func_warning "libobj name \`$libobj' may not contain shell special characters." + && func_warning "libobj name '$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" - objname="$func_basename_result" - xdir="$func_dirname_result" - lobj=${xdir}$objdir/$objname + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. - if test "$build_old_libs" = yes; then + if test yes = "$build_old_libs"; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" @@ -2127,16 +3689,16 @@ func_mode_compile () pic_mode=default ;; esac - if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c - if test "$compiler_c_o" = no; then - output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} - lockfile="$output_obj.lock" + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock else output_obj= need_locks=no @@ -2145,12 +3707,12 @@ func_mode_compile () # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file - if test "$need_locks" = yes; then + if test yes = "$need_locks"; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done - elif test "$need_locks" = warn; then + elif test warn = "$need_locks"; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: @@ -2158,7 +3720,7 @@ func_mode_compile () This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you +your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." @@ -2176,15 +3738,15 @@ compiler." func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result - func_quote_for_eval "$srcfile" - qsrcfile=$func_quote_for_eval_result + func_quote_arg pretty "$srcfile" + qsrcfile=$func_quote_arg_result # Only build a PIC object if we are building libtool libraries. - if test "$build_libtool_libs" = yes; then + if test yes = "$build_libtool_libs"; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile - if test "$pic_mode" != no; then + if test no != "$pic_mode"; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code @@ -2201,7 +3763,7 @@ compiler." func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' - if test "$need_locks" = warn && + if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: @@ -2212,7 +3774,7 @@ $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you +your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." @@ -2228,20 +3790,20 @@ compiler." fi # Allow error messages only from the first compilation. - if test "$suppress_opt" = yes; then + if test yes = "$suppress_opt"; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. - if test "$build_old_libs" = yes; then - if test "$pic_mode" != yes; then + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi - if test "$compiler_c_o" = yes; then + if test yes = "$compiler_c_o"; then func_append command " -o $obj" fi @@ -2250,7 +3812,7 @@ compiler." func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' - if test "$need_locks" = warn && + if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: @@ -2261,7 +3823,7 @@ $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you +your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." @@ -2281,7 +3843,7 @@ compiler." func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked - if test "$need_locks" != no; then + if test no != "$need_locks"; then removelist=$lockfile $RM "$lockfile" fi @@ -2291,7 +3853,7 @@ compiler." } $opt_help || { - test "$opt_mode" = compile && func_mode_compile ${1+"$@"} + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} } func_mode_help () @@ -2311,7 +3873,7 @@ func_mode_help () Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated @@ -2330,16 +3892,17 @@ This mode accepts the following additional options: -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only - -shared do not build a \`.o' file suitable for static linking - -static only build a \`.o' file suitable for static linking - -Wc,FLAG pass FLAG directly to the compiler + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG + -Xcompiler FLAG pass FLAG directly to the compiler -COMPILE-COMMAND is a command to be used in creating a \`standard' object file +COMPILE-COMMAND is a command to be used in creating a 'standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from -SOURCEFILE, then substituting the C source code suffix \`.c' with the -library object suffix, \`.lo'." +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." ;; execute) @@ -2352,7 +3915,7 @@ This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path -This mode sets the library path environment variable according to \`-dlopen' +This mode sets the library path environment variable according to '-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated @@ -2371,7 +3934,7 @@ Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use -the \`--dry-run' option if you just want to see what would be executed." +the '--dry-run' option if you just want to see what would be executed." ;; install) @@ -2381,7 +3944,7 @@ the \`--dry-run' option if you just want to see what would be executed." Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be -either the \`install' or \`cp' program. +either the 'install' or 'cp' program. The following components of INSTALL-COMMAND are treated specially: @@ -2407,7 +3970,7 @@ The following components of LINK-COMMAND are treated specially: -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) - -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE @@ -2421,7 +3984,8 @@ The following components of LINK-COMMAND are treated specially: -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects - -objectlist FILE Use a list of object files found in FILE to specify objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information @@ -2437,24 +4001,26 @@ The following components of LINK-COMMAND are treated specially: -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wa,FLAG + -Xassembler FLAG pass linker-specific FLAG directly to the assembler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) -All other options (arguments beginning with \`-') are ignored. +All other options (arguments beginning with '-') are ignored. -Every other argument is treated as a filename. Files ending in \`.la' are +Every other argument is treated as a filename. Files ending in '.la' are treated as uninstalled libtool libraries, other files are standard or library object files. -If the OUTPUT-FILE ends in \`.la', then a libtool library is created, -only library objects (\`.lo' files) may be specified, and \`-rpath' is +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is required, except when creating a convenience library. -If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created -using \`ar' and \`ranlib', or on Windows using \`lib'. +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. -If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file is created, otherwise an executable program is created." ;; @@ -2465,7 +4031,7 @@ is created, otherwise an executable program is created." Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. @@ -2473,17 +4039,17 @@ Otherwise, only FILE itself is deleted using RM." ;; *) - func_fatal_help "invalid operation mode \`$opt_mode'" + func_fatal_help "invalid operation mode '$opt_mode'" ;; esac echo - $ECHO "Try \`$progname --help' for more information about other modes." + $ECHO "Try '$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then - if test "$opt_help" = :; then + if test : = "$opt_help"; then func_mode_help else { @@ -2491,7 +4057,7 @@ if $opt_help; then for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done - } | sed -n '1p; 2,$s/^Usage:/ or: /p' + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do @@ -2499,7 +4065,7 @@ if $opt_help; then func_mode_help done } | - sed '1d + $SED '1d /^When reporting/,/^Report/{ H d @@ -2516,16 +4082,17 @@ fi # func_mode_execute arg... func_mode_execute () { - $opt_debug + $debug_cmd + # The first argument is the command name. - cmd="$nonopt" + cmd=$nonopt test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ - || func_fatal_help "\`$file' is not a file" + || func_fatal_help "'$file' is not a file" dir= case $file in @@ -2535,7 +4102,7 @@ func_mode_execute () # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ - || func_fatal_help "\`$lib' is not a valid libtool archive" + || func_fatal_help "'$lib' is not a valid libtool archive" # Read the libtool library. dlname= @@ -2546,18 +4113,18 @@ func_mode_execute () if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ - func_warning "\`$file' was not linked with \`-export-dynamic'" + func_warning "'$file' was not linked with '-export-dynamic'" continue fi func_dirname "$file" "" "." - dir="$func_dirname_result" + dir=$func_dirname_result if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then - func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" fi fi ;; @@ -2565,18 +4132,18 @@ func_mode_execute () *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." - dir="$func_dirname_result" + dir=$func_dirname_result ;; *) - func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` - test -n "$absdir" && dir="$absdir" + test -n "$absdir" && dir=$absdir # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then @@ -2588,7 +4155,7 @@ func_mode_execute () # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. - libtool_execute_magic="$magic" + libtool_execute_magic=$magic # Check if any of the arguments is a wrapper script. args= @@ -2601,12 +4168,12 @@ func_mode_execute () if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. - file="$progdir/$program" + file=$progdir/$program elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. - file="$progdir/$program" + file=$progdir/$program fi ;; esac @@ -2614,7 +4181,15 @@ func_mode_execute () func_append_quoted args "$file" done - if test "X$opt_dry_run" = Xfalse; then + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" @@ -2631,25 +4206,18 @@ func_mode_execute () done # Now prepare to actually exec the command. - exec_cmd="\$cmd$args" - else - # Display what would be done. - if test -n "$shlibpath_var"; then - eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" - echo "export $shlibpath_var" - fi - $ECHO "$cmd$args" - exit $EXIT_SUCCESS + exec_cmd=\$cmd$args fi } -test "$opt_mode" = execute && func_mode_execute ${1+"$@"} +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { - $opt_debug + $debug_cmd + libs= libdirs= admincmds= @@ -2663,11 +4231,11 @@ func_mode_finish () if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else - func_warning "\`$opt' is not a valid libtool archive" + func_warning "'$opt' is not a valid libtool archive" fi else - func_fatal_error "invalid argument \`$opt'" + func_fatal_error "invalid argument '$opt'" fi done @@ -2682,12 +4250,12 @@ func_mode_finish () # Remove sysroot references if $opt_dry_run; then for lib in $libs; do - echo "removing references to $lt_sysroot and \`=' prefixes from $lib" + echo "removing references to $lt_sysroot and '=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do - sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done @@ -2712,7 +4280,7 @@ func_mode_finish () fi # Exit here if they wanted silent mode. - $opt_silent && exit $EXIT_SUCCESS + $opt_quiet && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" @@ -2723,27 +4291,27 @@ func_mode_finish () echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" - echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then - echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " - add LIBDIR to the '$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then - echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " - add LIBDIR to the '$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" - $ECHO " - use the \`$flag' linker flag" + $ECHO " - use the '$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then - echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" fi echo @@ -2762,21 +4330,23 @@ func_mode_finish () exit $EXIT_SUCCESS } -test "$opt_mode" = finish && func_mode_finish ${1+"$@"} +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { - $opt_debug + $debug_cmd + # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). - if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || # Allow the use of GNU shtool's install command. - case $nonopt in *shtool*) :;; *) false;; esac; then + case $nonopt in *shtool*) :;; *) false;; esac + then # Aesthetically quote it. - func_quote_for_eval "$nonopt" - install_prog="$func_quote_for_eval_result " + func_quote_arg pretty "$nonopt" + install_prog="$func_quote_arg_result " arg=$1 shift else @@ -2786,8 +4356,8 @@ func_mode_install () # The real first argument should be the name of the installation program. # Aesthetically quote it. - func_quote_for_eval "$arg" - func_append install_prog "$func_quote_for_eval_result" + func_quote_arg pretty "$arg" + func_append install_prog "$func_quote_arg_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; @@ -2800,7 +4370,7 @@ func_mode_install () opts= prev= install_type= - isdir=no + isdir=false stripme= no_mode=: for arg @@ -2813,7 +4383,7 @@ func_mode_install () fi case $arg in - -d) isdir=yes ;; + -d) isdir=: ;; -f) if $install_cp; then :; else prev=$arg @@ -2831,7 +4401,7 @@ func_mode_install () *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then - if test "x$prev" = x-m && test -n "$install_override_mode"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi @@ -2844,24 +4414,24 @@ func_mode_install () esac # Aesthetically quote the argument. - func_quote_for_eval "$arg" - func_append install_prog " $func_quote_for_eval_result" + func_quote_arg pretty "$arg" + func_append install_prog " $func_quote_arg_result" if test -n "$arg2"; then - func_quote_for_eval "$arg2" + func_quote_arg pretty "$arg2" fi - func_append install_shared_prog " $func_quote_for_eval_result" + func_append install_shared_prog " $func_quote_arg_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ - func_fatal_help "the \`$prev' option requires an argument" + func_fatal_help "the '$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else - func_quote_for_eval "$install_override_mode" - func_append install_shared_prog " -m $func_quote_for_eval_result" + func_quote_arg pretty "$install_override_mode" + func_append install_shared_prog " -m $func_quote_arg_result" fi fi @@ -2878,19 +4448,19 @@ func_mode_install () dest=$func_stripname_result # Check to see that the destination is a directory. - test -d "$dest" && isdir=yes - if test "$isdir" = yes; then - destdir="$dest" + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest destname= else func_dirname_and_basename "$dest" "" "." - destdir="$func_dirname_result" - destname="$func_basename_result" + destdir=$func_dirname_result + destname=$func_basename_result # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ - func_fatal_help "\`$dest' is not a directory" + func_fatal_help "'$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; @@ -2899,7 +4469,7 @@ func_mode_install () case $file in *.lo) ;; *) - func_fatal_help "\`$destdir' must be an absolute directory name" + func_fatal_help "'$destdir' must be an absolute directory name" ;; esac done @@ -2908,7 +4478,7 @@ func_mode_install () # This variable tells wrapper scripts just to set variables rather # than running their programs. - libtool_install_magic="$magic" + libtool_install_magic=$magic staticlibs= future_libdirs= @@ -2928,7 +4498,7 @@ func_mode_install () # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ - || func_fatal_help "\`$file' is not a valid libtool archive" + || func_fatal_help "'$file' is not a valid libtool archive" library_names= old_library= @@ -2950,7 +4520,7 @@ func_mode_install () fi func_dirname "$file" "/" "" - dir="$func_dirname_result" + dir=$func_dirname_result func_append dir "$objdir" if test -n "$relink_command"; then @@ -2964,7 +4534,7 @@ func_mode_install () # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ - func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. @@ -2973,29 +4543,36 @@ func_mode_install () relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi - func_warning "relinking \`$file'" + func_warning "relinking '$file'" func_show_eval "$relink_command" \ - 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then - realname="$1" + realname=$1 shift - srcname="$realname" - test -n "$relink_command" && srcname="$realname"T + srcname=$realname + test -n "$relink_command" && srcname=${realname}T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' - tstripme="$stripme" + tstripme=$stripme case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) - tstripme="" + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= ;; esac ;; @@ -3006,7 +4583,7 @@ func_mode_install () if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. - # Try `ln -sf' first, because the `ln' binary might depend on + # Try 'ln -sf' first, because the 'ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname @@ -3017,14 +4594,14 @@ func_mode_install () fi # Do each command in the postinstall commands. - lib="$destdir/$realname" + lib=$destdir/$realname func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" - name="$func_basename_result" - instname="$dir/$name"i + name=$func_basename_result + instname=$dir/${name}i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. @@ -3036,11 +4613,11 @@ func_mode_install () # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then - destfile="$destdir/$destname" + destfile=$destdir/$destname else func_basename "$file" - destfile="$func_basename_result" - destfile="$destdir/$destfile" + destfile=$func_basename_result + destfile=$destdir/$destfile fi # Deduce the name of the destination old-style object file. @@ -3050,11 +4627,11 @@ func_mode_install () staticdest=$func_lo2o_result ;; *.$objext) - staticdest="$destfile" + staticdest=$destfile destfile= ;; *) - func_fatal_help "cannot copy a libtool object to \`$destfile'" + func_fatal_help "cannot copy a libtool object to '$destfile'" ;; esac @@ -3063,7 +4640,7 @@ func_mode_install () func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. - if test "$build_old_libs" = yes; then + if test yes = "$build_old_libs"; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result @@ -3075,23 +4652,23 @@ func_mode_install () *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then - destfile="$destdir/$destname" + destfile=$destdir/$destname else func_basename "$file" - destfile="$func_basename_result" - destfile="$destdir/$destfile" + destfile=$func_basename_result + destfile=$destdir/$destfile fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install - stripped_ext="" + stripped_ext= case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result - stripped_ext=".exe" + stripped_ext=.exe fi ;; esac @@ -3119,19 +4696,19 @@ func_mode_install () # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ - func_fatal_error "invalid libtool wrapper script \`$wrapper'" + func_fatal_error "invalid libtool wrapper script '$wrapper'" - finalize=yes + finalize=: for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi - libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` if test -n "$libdir" && test ! -f "$libfile"; then - func_warning "\`$lib' has not been installed in \`$libdir'" - finalize=no + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false fi done @@ -3139,29 +4716,29 @@ func_mode_install () func_source "$wrapper" outputname= - if test "$fast_install" = no && test -n "$relink_command"; then + if test no = "$fast_install" && test -n "$relink_command"; then $opt_dry_run || { - if test "$finalize" = yes; then + if $finalize; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" - file="$func_basename_result" - outputname="$tmpdir/$file" + file=$func_basename_result + outputname=$tmpdir/$file # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` - $opt_silent || { - func_quote_for_expand "$relink_command" - eval "func_echo $func_quote_for_expand_result" + $opt_quiet || { + func_quote_arg expand,pretty "$relink_command" + eval "func_echo $func_quote_arg_result" } if eval "$relink_command"; then : else - func_error "error: relink \`$file' with the above command before installing it" + func_error "error: relink '$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi - file="$outputname" + file=$outputname else - func_warning "cannot relink \`$file'" + func_warning "cannot relink '$file'" fi } else @@ -3198,10 +4775,10 @@ func_mode_install () for file in $staticlibs; do func_basename "$file" - name="$func_basename_result" + name=$func_basename_result # Set up the ranlib parameters. - oldlib="$destdir/$name" + oldlib=$destdir/$name func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result @@ -3216,18 +4793,18 @@ func_mode_install () done test -n "$future_libdirs" && \ - func_warning "remember to run \`$progname --finish$future_libdirs'" + func_warning "remember to run '$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" - exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } -test "$opt_mode" = install && func_mode_install ${1+"$@"} +test install = "$opt_mode" && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p @@ -3235,16 +4812,17 @@ test "$opt_mode" = install && func_mode_install ${1+"$@"} # a dlpreopen symbol table. func_generate_dlsyms () { - $opt_debug - my_outputname="$1" - my_originator="$2" - my_pic_p="${3-no}" - my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then if test -n "$NM" && test -n "$global_symbol_pipe"; then - my_dlsyms="${my_outputname}S.c" + my_dlsyms=${my_outputname}S.c else func_error "not configured to extract global symbols from dlpreopened files" fi @@ -3255,7 +4833,7 @@ func_generate_dlsyms () "") ;; *.c) # Discover the nlist of each of the dlfiles. - nlist="$output_objdir/${my_outputname}.nm" + nlist=$output_objdir/$my_outputname.nm func_show_eval "$RM $nlist ${nlist}S ${nlist}T" @@ -3263,34 +4841,36 @@ func_generate_dlsyms () func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ -/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ -/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif -#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -/* DATA imports from DLLs on WIN32 con't be const, because runtime +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST -#elif defined(__osf__) +#elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + /* External symbol declarations for the compiler. */\ " - if test "$dlself" = yes; then - func_verbose "generating symbol list for \`$output'" + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" @@ -3298,7 +4878,7 @@ extern \"C\" { progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 - func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done @@ -3318,10 +4898,10 @@ extern \"C\" { # Prepare the list of exported symbols if test -z "$export_symbols"; then - export_symbols="$output_objdir/$outputname.exp" + export_symbols=$output_objdir/$outputname.exp $opt_dry_run || { $RM $export_symbols - eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' @@ -3331,7 +4911,7 @@ extern \"C\" { } else $opt_dry_run || { - eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in @@ -3345,22 +4925,22 @@ extern \"C\" { fi for dlprefile in $dlprefiles; do - func_verbose "extracting global C symbols from \`$dlprefile'" + func_verbose "extracting global C symbols from '$dlprefile'" func_basename "$dlprefile" - name="$func_basename_result" + name=$func_basename_result case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" - dlprefile_dlbasename="" + dlprefile_dlbasename= if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` - if test -n "$dlprefile_dlname" ; then + if test -n "$dlprefile_dlname"; then func_basename "$dlprefile_dlname" - dlprefile_dlbasename="$func_basename_result" + dlprefile_dlbasename=$func_basename_result else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" @@ -3368,7 +4948,7 @@ extern \"C\" { fi fi $opt_dry_run || { - if test -n "$dlprefile_dlbasename" ; then + if test -n "$dlprefile_dlbasename"; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" @@ -3424,6 +5004,11 @@ extern \"C\" { echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ @@ -3432,11 +5017,30 @@ typedef struct { void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist -lt_${my_prefix}_LTX_preloaded_symbols[]; +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = -{\ - { \"$my_originator\", (void *) 0 }," +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi case $need_lib_prefix in no) @@ -3478,9 +5082,7 @@ static const void *lt_preloaded_setup() { *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) - if test "X$my_pic_p" != Xno; then - pic_flag_for_symtable=" $pic_flag" - fi + $my_pic_p && pic_flag_for_symtable=" $pic_flag" ;; esac ;; @@ -3497,10 +5099,10 @@ static const void *lt_preloaded_setup() { func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. - func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' # Transform the symbol file into the correct name. - symfileobj="$output_objdir/${my_outputname}S.$objext" + symfileobj=$output_objdir/${my_outputname}S.$objext case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then @@ -3518,7 +5120,7 @@ static const void *lt_preloaded_setup() { esac ;; *) - func_fatal_error "unknown suffix for \`$my_dlsyms'" + func_fatal_error "unknown suffix for '$my_dlsyms'" ;; esac else @@ -3532,6 +5134,32 @@ static const void *lt_preloaded_setup() { fi } +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + # func_win32_libid arg # return the library type of file 'arg' # @@ -3541,8 +5169,9 @@ static const void *lt_preloaded_setup() { # Despite the name, also deal with 64 bit binaries. func_win32_libid () { - $opt_debug - win32_libid_type="unknown" + $debug_cmd + + win32_libid_type=unknown win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import @@ -3552,16 +5181,29 @@ func_win32_libid () # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then - func_to_tool_file "$1" func_convert_file_msys_to_w32 - win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | - $SED -n -e ' + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' 1,100{ / I /{ - s,.*,import, + s|.*|import| p q } }'` + ;; + esac case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; @@ -3593,7 +5235,8 @@ func_win32_libid () # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { - $opt_debug + $debug_cmd + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } @@ -3610,7 +5253,8 @@ func_cygming_dll_for_implib () # specified import library. func_cygming_dll_for_implib_fallback_core () { - $opt_debug + $debug_cmd + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ @@ -3646,8 +5290,8 @@ func_cygming_dll_for_implib_fallback_core () /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the - # archive which possess that section. Heuristic: eliminate - # all those which have a first or second character that is + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually @@ -3658,30 +5302,6 @@ func_cygming_dll_for_implib_fallback_core () $SED -e '/^\./d;/^.\./d;q' } -# func_cygming_gnu_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is a GNU/binutils-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_gnu_implib_p () -{ - $opt_debug - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` - test -n "$func_cygming_gnu_implib_tmp" -} - -# func_cygming_ms_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is an MS-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_ms_implib_p () -{ - $opt_debug - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` - test -n "$func_cygming_ms_implib_tmp" -} - # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified @@ -3695,16 +5315,17 @@ func_cygming_ms_implib_p () # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { - $opt_debug - if func_cygming_gnu_implib_p "$1" ; then + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` - elif func_cygming_ms_implib_p "$1" ; then + elif func_cygming_ms_implib_p "$1"; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown - sharedlib_from_linklib_result="" + sharedlib_from_linklib_result= fi } @@ -3712,10 +5333,11 @@ func_cygming_dll_for_implib_fallback () # func_extract_an_archive dir oldlib func_extract_an_archive () { - $opt_debug - f_ex_an_ar_dir="$1"; shift - f_ex_an_ar_oldlib="$1" - if test "$lock_old_archive_extraction" = yes; then + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" @@ -3724,7 +5346,7 @@ func_extract_an_archive () fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' - if test "$lock_old_archive_extraction" = yes; then + if test yes = "$lock_old_archive_extraction"; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then @@ -3738,22 +5360,23 @@ func_extract_an_archive () # func_extract_archives gentop oldlib ... func_extract_archives () { - $opt_debug - my_gentop="$1"; shift + $debug_cmd + + my_gentop=$1; shift my_oldlibs=${1+"$@"} - my_oldobjs="" - my_xlib="" - my_xabs="" - my_xdir="" + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in - [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" - my_xlib="$func_basename_result" + my_xlib=$func_basename_result my_xlib_u=$my_xlib while :; do case " $extracted_archives " in @@ -3765,7 +5388,7 @@ func_extract_archives () esac done extracted_archives="$extracted_archives $my_xlib_u" - my_xdir="$my_gentop/$my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u func_mkdir_p "$my_xdir" @@ -3778,22 +5401,23 @@ func_extract_archives () cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` - darwin_base_archive=`basename "$darwin_archive"` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" - for darwin_arch in $darwin_arches ; do - func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" - $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" - cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" - func_extract_an_archive "`pwd`" "${darwin_base_archive}" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" cd "$darwin_curdir" - $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) - darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do @@ -3815,7 +5439,7 @@ func_extract_archives () my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done - func_extract_archives_result="$my_oldobjs" + func_extract_archives_result=$my_oldobjs } @@ -3830,7 +5454,7 @@ func_extract_archives () # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script -# will assume that the directory in which it is stored is +# will assume that the directory where it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () @@ -3841,7 +5465,7 @@ func_emit_wrapper () #! $SHELL # $output - temporary wrapper script for $objdir/$outputname -# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. @@ -3883,7 +5507,8 @@ else if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" - qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + func_quote_arg pretty "$ECHO" + qECHO=$func_quote_arg_result $ECHO "\ # A function that is used when there is no print builtin or printf. @@ -3893,14 +5518,14 @@ func_fallback_echo () \$1 _LTECHO_EOF' } - ECHO=\"$qECHO\" + ECHO=$qECHO fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper -# /script/ and the wrapper /executable/ which is used only on +# /script/ and the wrapper /executable/ that is used only on # windows platforms, and (c) all begin with the string "--lt-" -# (application programs are unlikely to have options which match +# (application programs are unlikely to have options that match # this pattern). # # There are only two supported options: --lt-debug and @@ -3933,7 +5558,7 @@ func_parse_lt_options () # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then - echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 fi } @@ -3944,7 +5569,7 @@ func_lt_dump_args () lt_dump_args_N=1; for lt_arg do - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } @@ -3958,7 +5583,7 @@ func_exec_program_core () *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} @@ -3968,7 +5593,7 @@ func_exec_program_core () *) $ECHO "\ if test -n \"\$lt_option_debug\"; then - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} @@ -4043,13 +5668,13 @@ func_exec_program () test -n \"\$absdir\" && thisdir=\"\$absdir\" " - if test "$fast_install" = yes; then + if test yes = "$fast_install"; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || - { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" @@ -4066,7 +5691,7 @@ func_exec_program () if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else - $ECHO \"\$relink_command_output\" >&2 + \$ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi @@ -4101,7 +5726,7 @@ func_exec_program () fi # Export our shlibpath_var if we have one. - if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" @@ -4121,7 +5746,7 @@ func_exec_program () fi else # The program doesn't exist. - \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 @@ -4140,7 +5765,7 @@ func_emit_cwrapperexe_src () cat < #include +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + /* declarations of non-ANSI functions */ -#if defined(__MINGW32__) +#if defined __MINGW32__ # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif -#elif defined(__CYGWIN__) +#elif defined __CYGWIN__ # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif -/* #elif defined (other platforms) ... */ +/* #elif defined other_platform || defined ... */ #endif /* portability defines, excluding path handling macros */ -#if defined(_MSC_VER) +#if defined _MSC_VER # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC -# ifndef _INTPTR_T_DEFINED -# define _INTPTR_T_DEFINED -# define intptr_t int -# endif -#elif defined(__MINGW32__) +#elif defined __MINGW32__ # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv -#elif defined(__CYGWIN__) +#elif defined __CYGWIN__ # define HAVE_SETENV # define FOPEN_WB "wb" -/* #elif defined (other platforms) ... */ +/* #elif defined other platforms ... */ #endif -#if defined(PATH_MAX) +#if defined PATH_MAX # define LT_PATHMAX PATH_MAX -#elif defined(MAXPATHLEN) +#elif defined MAXPATHLEN # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 @@ -4234,8 +5857,8 @@ int setenv (const char *, const char *, int); # define PATH_SEPARATOR ':' #endif -#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ - defined (__OS2__) +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 @@ -4268,10 +5891,10 @@ int setenv (const char *, const char *, int); #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ - if (stale) { free ((void *) stale); stale = 0; } \ + if (stale) { free (stale); stale = 0; } \ } while (0) -#if defined(LT_DEBUGWRAPPER) +#if defined LT_DEBUGWRAPPER static int lt_debug = 1; #else static int lt_debug = 0; @@ -4300,11 +5923,16 @@ void lt_dump_script (FILE *f); EOF cat < 0) && IS_PATH_SEPARATOR (new_value[len-1])) + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { - new_value[len-1] = '\0'; + new_value[--len] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); @@ -5082,27 +6710,47 @@ EOF # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { - $opt_debug + $debug_cmd + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + # func_mode_link arg... func_mode_link () { - $opt_debug + $debug_cmd + case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out - # which system we are compiling for in order to pass an extra + # what system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying - # to make a dll which has undefined symbols, in which case not + # to make a dll that has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. @@ -5146,10 +6794,11 @@ func_mode_link () module=no no_install=no objs= + os2dllname= non_pic_objects= precious_files_regex= prefer_static_libs=no - preload=no + preload=false prev= prevarg= release= @@ -5161,7 +6810,7 @@ func_mode_link () vinfo= vinfo_number=no weak_libs= - single_module="${wl}-single_module" + single_module=$wl-single_module func_infer_tag $base_compile # We need to know -static, to get the right output filenames. @@ -5169,15 +6818,15 @@ func_mode_link () do case $arg in -shared) - test "$build_libtool_libs" != yes && \ - func_fatal_configuration "can not build a shared library" + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) - if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then @@ -5210,11 +6859,11 @@ func_mode_link () # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do - arg="$1" + arg=$1 shift - func_quote_for_eval "$arg" - qarg=$func_quote_for_eval_unquoted_result - func_append libtool_args " $func_quote_for_eval_result" + func_quote_arg pretty,unquoted "$arg" + qarg=$func_quote_arg_unquoted_result + func_append libtool_args " $func_quote_arg_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then @@ -5227,21 +6876,21 @@ func_mode_link () case $prev in bindir) - bindir="$arg" + bindir=$arg prev= continue ;; dlfiles|dlprefiles) - if test "$preload" = no; then + $preload || { # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" - preload=yes - fi + preload=: + } case $arg in *.la | *.lo) ;; # We handle these cases below. force) - if test "$dlself" = no; then + if test no = "$dlself"; then dlself=needless export_dynamic=yes fi @@ -5249,9 +6898,9 @@ func_mode_link () continue ;; self) - if test "$prev" = dlprefiles; then + if test dlprefiles = "$prev"; then dlself=yes - elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then dlself=yes else dlself=needless @@ -5261,7 +6910,7 @@ func_mode_link () continue ;; *) - if test "$prev" = dlfiles; then + if test dlfiles = "$prev"; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" @@ -5272,14 +6921,14 @@ func_mode_link () esac ;; expsyms) - export_symbols="$arg" + export_symbols=$arg test -f "$arg" \ - || func_fatal_error "symbol file \`$arg' does not exist" + || func_fatal_error "symbol file '$arg' does not exist" prev= continue ;; expsyms_regex) - export_symbols_regex="$arg" + export_symbols_regex=$arg prev= continue ;; @@ -5297,7 +6946,13 @@ func_mode_link () continue ;; inst_prefix) - inst_prefix_dir="$arg" + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. prev= continue ;; @@ -5321,21 +6976,21 @@ func_mode_link () if test -z "$pic_object" || test -z "$non_pic_object" || - test "$pic_object" = none && - test "$non_pic_object" = none; then - func_fatal_error "cannot find name of object for \`$arg'" + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" - xdir="$func_dirname_result" + xdir=$func_dirname_result - if test "$pic_object" != none; then + if test none != "$pic_object"; then # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" + pic_object=$xdir$pic_object - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue @@ -5346,7 +7001,7 @@ func_mode_link () fi # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then + if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= @@ -5354,23 +7009,23 @@ func_mode_link () # A PIC object. func_append libobjs " $pic_object" - arg="$pic_object" + arg=$pic_object fi # Non-PIC object. - if test "$non_pic_object" != none; then + if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" + non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. - non_pic_object="$pic_object" + non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else @@ -5378,7 +7033,7 @@ func_mode_link () if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" - xdir="$func_dirname_result" + xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result @@ -5386,24 +7041,29 @@ func_mode_link () func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else - func_fatal_error "\`$arg' is not a valid libtool object" + func_fatal_error "'$arg' is not a valid libtool object" fi fi done else - func_fatal_error "link input file \`$arg' does not exist" + func_fatal_error "link input file '$arg' does not exist" fi arg=$save_arg prev= continue ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; precious_regex) - precious_files_regex="$arg" + precious_files_regex=$arg prev= continue ;; release) - release="-$arg" + release=-$arg prev= continue ;; @@ -5415,7 +7075,7 @@ func_mode_link () func_fatal_error "only absolute run-paths are allowed" ;; esac - if test "$prev" = rpath; then + if test rpath = "$prev"; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; @@ -5430,7 +7090,7 @@ func_mode_link () continue ;; shrext) - shrext_cmds="$arg" + shrext_cmds=$arg prev= continue ;; @@ -5439,6 +7099,13 @@ func_mode_link () prev= continue ;; + xassembler) + func_append compiler_flags " -Xassembler $qarg" + prev= + func_append compile_command " -Xassembler $qarg" + func_append finalize_command " -Xassembler $qarg" + continue + ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" @@ -5470,7 +7137,7 @@ func_mode_link () esac fi # test -n "$prev" - prevarg="$arg" + prevarg=$arg case $arg in -all-static) @@ -5484,7 +7151,7 @@ func_mode_link () -allow-undefined) # FIXME: remove this flag sometime in the future. - func_fatal_error "\`-allow-undefined' must not be used because it is the default" + func_fatal_error "'-allow-undefined' must not be used because it is the default" ;; -avoid-version) @@ -5516,7 +7183,7 @@ func_mode_link () if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi - if test "X$arg" = "X-export-symbols"; then + if test X-export-symbols = "X$arg"; then prev=expsyms else prev=expsyms_regex @@ -5550,9 +7217,9 @@ func_mode_link () func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then - func_fatal_error "require no space between \`-L' and \`$1'" + func_fatal_error "require no space between '-L' and '$1'" else - func_fatal_error "need path for \`-L' option" + func_fatal_error "need path for '-L' option" fi fi func_resolve_sysroot "$func_stripname_result" @@ -5563,8 +7230,8 @@ func_mode_link () *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ - func_fatal_error "cannot determine absolute directory name of \`$dir'" - dir="$absdir" + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir ;; esac case "$deplibs " in @@ -5599,7 +7266,7 @@ func_mode_link () ;; -l*) - if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + if test X-lc = "X$arg" || test X-lm = "X$arg"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) @@ -5607,11 +7274,11 @@ func_mode_link () ;; *-*-os2*) # These systems don't actually have a C library (as such) - test "X$arg" = "X-lc" && continue + test X-lc = "X$arg" && continue ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig* | *-*-midnightbsd*) # Do not include libc due to us having libc/libc_r. - test "X$arg" = "X-lc" && continue + test X-lc = "X$arg" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework @@ -5620,16 +7287,16 @@ func_mode_link () ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype - test "X$arg" = "X-lc" && continue + test X-lc = "X$arg" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work - test "X$arg" = "X-lc" && continue + test X-lc = "X$arg" && continue ;; esac - elif test "X$arg" = "X-lc_r"; then + elif test X-lc_r = "X$arg"; then case $host in - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig* | *-*-midnightbsd*) # Do not include libc_r directly, use -pthread flag. continue ;; @@ -5639,6 +7306,11 @@ func_mode_link () continue ;; + -mllvm) + prev=mllvm + continue + ;; + -module) module=yes continue @@ -5654,8 +7326,20 @@ func_mode_link () prev=xcompiler continue ;; - - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + # Solaris ld rejects as of 11.4. Refer to Oracle bug 22985199. + -pthread) + case $host in + *solaris2*) ;; + *) + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + ;; + esac + continue + ;; + -mt|-mthreads|-kthread|-Kthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" @@ -5668,7 +7352,7 @@ func_mode_link () ;; -multi_module) - single_module="${wl}-multi_module" + single_module=$wl-multi_module continue ;; @@ -5682,8 +7366,8 @@ func_mode_link () *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. - func_warning "\`-no-install' is ignored for $host" - func_warning "assuming \`-no-fast-install' instead" + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; @@ -5701,6 +7385,11 @@ func_mode_link () continue ;; + -os2dllname) + prev=os2dllname + continue + ;; + -o) prev=output ;; -precious-files-regex) @@ -5788,14 +7477,14 @@ func_mode_link () func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= - save_ifs="$IFS"; IFS=',' + save_ifs=$IFS; IFS=, for flag in $args; do - IFS="$save_ifs" - func_quote_for_eval "$flag" - func_append arg " $func_quote_for_eval_result" - func_append compiler_flags " $func_quote_for_eval_result" + IFS=$save_ifs + func_quote_arg pretty "$flag" + func_append arg " $func_quote_arg_result" + func_append compiler_flags " $func_quote_arg_result" done - IFS="$save_ifs" + IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; @@ -5804,19 +7493,24 @@ func_mode_link () func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= - save_ifs="$IFS"; IFS=',' + save_ifs=$IFS; IFS=, for flag in $args; do - IFS="$save_ifs" - func_quote_for_eval "$flag" - func_append arg " $wl$func_quote_for_eval_result" - func_append compiler_flags " $wl$func_quote_for_eval_result" - func_append linker_flags " $func_quote_for_eval_result" + IFS=$save_ifs + func_quote_arg pretty "$flag" + func_append arg " $wl$func_quote_arg_result" + func_append compiler_flags " $wl$func_quote_arg_result" + func_append linker_flags " $func_quote_arg_result" done - IFS="$save_ifs" + IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; + -Xassembler) + prev=xassembler + continue + ;; + -Xcompiler) prev=xcompiler continue @@ -5834,8 +7528,8 @@ func_mode_link () # -msg_* for osf cc -msg_*) - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result ;; # Flags to be passed through unchanged, with rationale: @@ -5847,25 +7541,51 @@ func_mode_link () # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support - # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -specs=* GCC specs files + # -stdlib=* select c++ std lib with clang + # -fsanitize=* Clang/GCC memory and address sanitizer + # -fuse-ld=* Linker select flags for GCC + # -Wa,* Pass flags directly to the assembler -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ - -O*|-flto*|-fwhopr*|-fuse-linker-plugin) - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ + -specs=*|-fsanitize=*|-fuse-ld=*|-Wa,*) + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result + fi + ;; + # Some other compiler flag. -* | +*) - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result ;; *.$objext) @@ -5886,21 +7606,21 @@ func_mode_link () if test -z "$pic_object" || test -z "$non_pic_object" || - test "$pic_object" = none && - test "$non_pic_object" = none; then - func_fatal_error "cannot find name of object for \`$arg'" + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" - xdir="$func_dirname_result" + xdir=$func_dirname_result - if test "$pic_object" != none; then + test none = "$pic_object" || { # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" + pic_object=$xdir$pic_object - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue @@ -5911,7 +7631,7 @@ func_mode_link () fi # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then + if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= @@ -5919,23 +7639,23 @@ func_mode_link () # A PIC object. func_append libobjs " $pic_object" - arg="$pic_object" - fi + arg=$pic_object + } # Non-PIC object. - if test "$non_pic_object" != none; then + if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" + non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. - non_pic_object="$pic_object" + non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else @@ -5943,7 +7663,7 @@ func_mode_link () if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" - xdir="$func_dirname_result" + xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result @@ -5951,7 +7671,7 @@ func_mode_link () func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else - func_fatal_error "\`$arg' is not a valid libtool object" + func_fatal_error "'$arg' is not a valid libtool object" fi fi ;; @@ -5967,11 +7687,11 @@ func_mode_link () # A libtool-controlled library. func_resolve_sysroot "$arg" - if test "$prev" = dlfiles; then + if test dlfiles = "$prev"; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= - elif test "$prev" = dlprefiles; then + elif test dlprefiles = "$prev"; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= @@ -5985,8 +7705,8 @@ func_mode_link () *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result ;; esac # arg @@ -5998,9 +7718,9 @@ func_mode_link () done # argument parsing loop test -n "$prev" && \ - func_fatal_help "the \`$prevarg' option requires an argument" + func_fatal_help "the '$prevarg' option requires an argument" - if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" @@ -6009,20 +7729,23 @@ func_mode_link () oldlibs= # calculate the name of the file, without its directory func_basename "$output" - outputname="$func_basename_result" - libobjs_save="$libobjs" + outputname=$func_basename_result + libobjs_save=$libobjs if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var - eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + func_dirname "$output" "/" "" - output_objdir="$func_dirname_result$objdir" + output_objdir=$func_dirname_result$objdir func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. @@ -6045,7 +7768,7 @@ func_mode_link () # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do - if $opt_preserve_dup_deps ; then + if $opt_preserve_dup_deps; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac @@ -6053,7 +7776,7 @@ func_mode_link () func_append libs " $deplib" done - if test "$linkmode" = lib; then + if test lib = "$linkmode"; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps @@ -6085,7 +7808,7 @@ func_mode_link () case $file in *.la) ;; *) - func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" ;; esac done @@ -6093,7 +7816,7 @@ func_mode_link () prog) compile_deplibs= finalize_deplibs= - alldeplibs=no + alldeplibs=false newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" @@ -6105,29 +7828,29 @@ func_mode_link () for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... - if test "$linkmode,$pass" = "lib,link"; then + if test lib,link = "$linkmode,$pass"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done - deplibs="$tmp_deplibs" + deplibs=$tmp_deplibs fi - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan"; then - libs="$deplibs" + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs deplibs= fi - if test "$linkmode" = prog; then + if test prog = "$linkmode"; then case $pass in - dlopen) libs="$dlfiles" ;; - dlpreopen) libs="$dlprefiles" ;; + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi - if test "$linkmode,$pass" = "lib,dlpreopen"; then + if test lib,dlpreopen = "$linkmode,$pass"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs @@ -6148,26 +7871,26 @@ func_mode_link () esac done done - libs="$dlprefiles" + libs=$dlprefiles fi - if test "$pass" = dlopen; then + if test dlopen = "$pass"; then # Collect dlpreopened libraries - save_deplibs="$deplibs" + save_deplibs=$deplibs deplibs= fi for deplib in $libs; do lib= - found=no + found=false case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) - if test "$linkmode,$pass" = "prog,link"; then + if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" - if test "$linkmode" = lib ; then + if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; @@ -6177,13 +7900,13 @@ func_mode_link () continue ;; -l*) - if test "$linkmode" != lib && test "$linkmode" != prog; then - func_warning "\`-l' is ignored for archives/objects" + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result - if test "$linkmode" = lib; then + if test lib = "$linkmode"; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" @@ -6191,31 +7914,22 @@ func_mode_link () for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library - lib="$searchdir/lib${name}${search_ext}" + lib=$searchdir/lib$name$search_ext if test -f "$lib"; then - if test "$search_ext" = ".la"; then - found=yes + if test .la = "$search_ext"; then + found=: else - found=no + found=false fi break 2 fi done done - if test "$found" != yes; then - # deplib doesn't seem to be a libtool library - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" - fi - continue - else # deplib is a libtool library + if $found; then + # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then @@ -6223,19 +7937,19 @@ func_mode_link () old_library= func_source "$lib" for l in $old_library $library_names; do - ll="$l" + ll=$l done - if test "X$ll" = "X$old_library" ; then # only static version available - found=no + if test "X$ll" = "X$old_library"; then # only static version available + found=false func_dirname "$lib" "" "." - ladir="$func_dirname_result" + ladir=$func_dirname_result lib=$ladir/$old_library - if test "$linkmode,$pass" = "prog,link"; then + if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi @@ -6244,15 +7958,25 @@ func_mode_link () *) ;; esac fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue fi ;; # -l *.ltframework) - if test "$linkmode,$pass" = "prog,link"; then + if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" - if test "$linkmode" = lib ; then + if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; @@ -6265,18 +7989,18 @@ func_mode_link () case $linkmode in lib) deplibs="$deplib $deplibs" - test "$pass" = conv && continue + test conv = "$pass" && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) - if test "$pass" = conv; then + if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi - if test "$pass" = scan; then + if test scan = "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" @@ -6287,13 +8011,13 @@ func_mode_link () func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) - func_warning "\`-L' is ignored for archives/objects" + func_warning "'-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) - if test "$pass" = link; then + if test link = "$pass"; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result @@ -6311,7 +8035,7 @@ func_mode_link () lib=$func_resolve_sysroot_result ;; *.$libext) - if test "$pass" = conv; then + if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi @@ -6322,21 +8046,26 @@ func_mode_link () case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) - valid_a_lib=no + valid_a_lib=false case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then - valid_a_lib=yes + valid_a_lib=: fi ;; pass_all) - valid_a_lib=yes + valid_a_lib=: ;; esac - if test "$valid_a_lib" != yes; then + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" @@ -6344,18 +8073,13 @@ func_mode_link () echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." - else - echo - $ECHO "*** Warning: Linking the shared library $output against the" - $ECHO "*** static library $deplib is not portable!" - deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) - if test "$pass" != link; then + if test link != "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" @@ -6366,10 +8090,10 @@ func_mode_link () esac # linkmode ;; # *.$libext *.lo | *.$objext) - if test "$pass" = conv; then + if test conv = "$pass"; then deplibs="$deplib $deplibs" - elif test "$linkmode" = prog; then - if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" @@ -6382,22 +8106,20 @@ func_mode_link () continue ;; %DEPLIBS%) - alldeplibs=yes + alldeplibs=: continue ;; esac # case $deplib - if test "$found" = yes || test -f "$lib"; then : - else - func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" - fi + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ - || func_fatal_error "\`$lib' is not a valid libtool archive" + || func_fatal_error "'$lib' is not a valid libtool archive" func_dirname "$lib" "" "." - ladir="$func_dirname_result" + ladir=$func_dirname_result dlname= dlopen= @@ -6427,30 +8149,30 @@ func_mode_link () done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan" || - { test "$linkmode" != prog && test "$linkmode" != lib; }; then + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi - if test "$pass" = conv; then + if test conv = "$pass"; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then - func_fatal_error "cannot find name of link library for \`$lib'" + func_fatal_error "cannot find name of link library for '$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" - elif test "$linkmode" != prog && test "$linkmode" != lib; then - func_fatal_error "\`$lib' is not a convenience library" + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" fi tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" - if $opt_preserve_dup_deps ; then + if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac @@ -6464,26 +8186,26 @@ func_mode_link () # Get the name of the library we link against. linklib= if test -n "$old_library" && - { test "$prefer_static_libs" = yes || - test "$prefer_static_libs,$installed" = "built,no"; }; then + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then linklib=$old_library else for l in $old_library $library_names; do - linklib="$l" + linklib=$l done fi if test -z "$linklib"; then - func_fatal_error "cannot find name of link library for \`$lib'" + func_fatal_error "cannot find name of link library for '$lib'" fi # This library was specified with -dlopen. - if test "$pass" = dlopen; then - if test -z "$libdir"; then - func_fatal_error "cannot -dlopen a convenience library: \`$lib'" - fi + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" if test -z "$dlname" || - test "$dlopen_support" != yes || - test "$build_libtool_libs" = no; then + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't @@ -6497,40 +8219,40 @@ func_mode_link () # We need an absolute path. case $ladir in - [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then - func_warning "cannot determine absolute directory name of \`$ladir'" + func_warning "cannot determine absolute directory name of '$ladir'" func_warning "passing it literally to the linker, although it might fail" - abs_ladir="$ladir" + abs_ladir=$ladir fi ;; esac func_basename "$lib" - laname="$func_basename_result" + laname=$func_basename_result # Find the relevant object directory and library name. - if test "X$installed" = Xyes; then + if test yes = "$installed"; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then - func_warning "library \`$lib' was moved." - dir="$ladir" - absdir="$abs_ladir" - libdir="$abs_ladir" + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir else - dir="$lt_sysroot$libdir" - absdir="$lt_sysroot$libdir" + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir fi - test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + test yes = "$hardcode_automatic" && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then - dir="$ladir" - absdir="$abs_ladir" + dir=$ladir + absdir=$abs_ladir # Remove this search path later func_append notinst_path " $abs_ladir" else - dir="$ladir/$objdir" - absdir="$abs_ladir/$objdir" + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir # Remove this search path later func_append notinst_path " $abs_ladir" fi @@ -6539,11 +8261,11 @@ func_mode_link () name=$func_stripname_result # This library was specified with -dlpreopen. - if test "$pass" = dlpreopen; then - if test -z "$libdir" && test "$linkmode" = prog; then - func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" fi - case "$host" in + case $host in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both @@ -6587,9 +8309,9 @@ func_mode_link () if test -z "$libdir"; then # Link the convenience library - if test "$linkmode" = lib; then + if test lib = "$linkmode"; then deplibs="$dir/$old_library $deplibs" - elif test "$linkmode,$pass" = "prog,link"; then + elif test prog,link = "$linkmode,$pass"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else @@ -6599,14 +8321,14 @@ func_mode_link () fi - if test "$linkmode" = prog && test "$pass" != link; then + if test prog = "$linkmode" && test link != "$pass"; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" - linkalldeplibs=no - if test "$link_all_deplibs" != no || test -z "$library_names" || - test "$build_libtool_libs" = no; then - linkalldeplibs=yes + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: fi tmp_libs= @@ -6618,14 +8340,14 @@ func_mode_link () ;; esac # Need to link against all dependency_libs? - if test "$linkalldeplibs" = yes; then + if $linkalldeplibs; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi - if $opt_preserve_dup_deps ; then + if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac @@ -6635,15 +8357,15 @@ func_mode_link () continue fi # $linkmode = prog... - if test "$linkmode,$pass" = "prog,link"; then + if test prog,link = "$linkmode,$pass"; then if test -n "$library_names" && - { { test "$prefer_static_libs" = no || - test "$prefer_static_libs,$installed" = "built,yes"; } || + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || test -z "$old_library"; }; then # We need to hardcode the library path - if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then # Make sure the rpath contains only unique directories. - case "$temp_rpath:" in + case $temp_rpath: in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac @@ -6672,9 +8394,9 @@ func_mode_link () esac fi # $linkmode,$pass = prog,link... - if test "$alldeplibs" = yes && - { test "$deplibs_check_method" = pass_all || - { test "$build_libtool_libs" = yes && + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && test -n "$library_names"; }; }; then # We only need to search for static libraries continue @@ -6683,19 +8405,19 @@ func_mode_link () link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs - if test "$use_static_libs" = built && test "$installed" = yes; then + if test built = "$use_static_libs" && test yes = "$installed"; then use_static_libs=no fi if test -n "$library_names" && - { test "$use_static_libs" = no || test -z "$old_library"; }; then + { test no = "$use_static_libs" || test -z "$old_library"; }; then case $host in - *cygwin* | *mingw* | *cegcc*) + *cygwin* | *mingw* | *cegcc* | *os2*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) - if test "$installed" = no; then + if test no = "$installed"; then func_append notinst_deplibs " $lib" need_relink=yes fi @@ -6705,24 +8427,24 @@ func_mode_link () # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! - dlopenmodule="" + dlopenmodule= for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then - dlopenmodule="$dlpremoduletest" + dlopenmodule=$dlpremoduletest break fi done - if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then echo - if test "$linkmode" = prog; then + if test prog = "$linkmode"; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi - if test "$linkmode" = lib && - test "$hardcode_into_libs" = yes; then + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. @@ -6750,43 +8472,43 @@ func_mode_link () # figure out the soname set dummy $library_names shift - realname="$1" + realname=$1 shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then - soname="$dlname" + soname=$dlname elif test -n "$soname_spec"; then # bleh windows case $host in - *cygwin* | mingw* | *cegcc*) + *cygwin* | mingw* | *cegcc* | *os2*) func_arith $current - $age major=$func_arith_result - versuffix="-$major" + versuffix=-$major ;; esac eval soname=\"$soname_spec\" else - soname="$realname" + soname=$realname fi # Make a new name for the extract_expsyms_cmds to use - soroot="$soname" + soroot=$soname func_basename "$soroot" - soname="$func_basename_result" + soname=$func_basename_result func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else - func_verbose "extracting exported symbol list from \`$soname'" + func_verbose "extracting exported symbol list from '$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else - func_verbose "generating import library for \`$soname'" + func_verbose "generating import library for '$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library @@ -6794,58 +8516,58 @@ func_mode_link () linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" - if test "$linkmode" = prog || test "$opt_mode" != relink; then + if test prog = "$linkmode" || test relink != "$opt_mode"; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) - if test "$hardcode_direct" = no; then - add="$dir/$linklib" + if test no = "$hardcode_direct"; then + add=$dir/$linklib case $host in - *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; - *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ - *-*-unixware7*) add_dir="-L$dir" ;; + *-*-unixware7*) add_dir=-L$dir ;; *-*-darwin* ) - # if the lib is a (non-dlopened) module then we can not + # if the lib is a (non-dlopened) module then we cannot # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | - $GREP ": [^:]* bundle" >/dev/null ; then + $GREP ": [^:]* bundle" >/dev/null; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" - if test -z "$old_library" ; then + if test -z "$old_library"; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else - add="$dir/$old_library" + add=$dir/$old_library fi elif test -n "$old_library"; then - add="$dir/$old_library" + add=$dir/$old_library fi fi esac - elif test "$hardcode_minus_L" = no; then + elif test no = "$hardcode_minus_L"; then case $host in - *-*-sunos*) add_shlibpath="$dir" ;; + *-*-sunos*) add_shlibpath=$dir ;; esac - add_dir="-L$dir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = no; then - add_shlibpath="$dir" - add="-l$name" + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name else lib_linked=no fi ;; relink) - if test "$hardcode_direct" = yes && - test "$hardcode_direct_absolute" = no; then - add="$dir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$absdir" + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in @@ -6854,10 +8576,10 @@ func_mode_link () ;; esac fi - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then - add_shlibpath="$dir" - add="-l$name" + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name else lib_linked=no fi @@ -6865,7 +8587,7 @@ func_mode_link () *) lib_linked=no ;; esac - if test "$lib_linked" != yes; then + if test yes != "$lib_linked"; then func_fatal_configuration "unsupported hardcode properties" fi @@ -6875,15 +8597,15 @@ func_mode_link () *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi - if test "$linkmode" = prog; then + if test prog = "$linkmode"; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" - if test "$hardcode_direct" != yes && - test "$hardcode_minus_L" != yes && - test "$hardcode_shlibpath_var" = yes; then + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; @@ -6892,33 +8614,33 @@ func_mode_link () fi fi - if test "$linkmode" = prog || test "$opt_mode" = relink; then + if test prog = "$linkmode" || test relink = "$opt_mode"; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. - if test "$hardcode_direct" = yes && - test "$hardcode_direct_absolute" = no; then - add="$libdir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$libdir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac - add="-l$name" - elif test "$hardcode_automatic" = yes; then + add=-l$name + elif test yes = "$hardcode_automatic"; then if test -n "$inst_prefix_dir" && - test -f "$inst_prefix_dir$libdir/$linklib" ; then - add="$inst_prefix_dir$libdir/$linklib" + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib else - add="$libdir/$linklib" + add=$libdir/$linklib fi else # We cannot seem to hardcode it, guess we'll fake it. - add_dir="-L$libdir" + add_dir=-L$libdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in @@ -6927,10 +8649,10 @@ func_mode_link () ;; esac fi - add="-l$name" + add=-l$name fi - if test "$linkmode" = prog; then + if test prog = "$linkmode"; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else @@ -6938,43 +8660,43 @@ func_mode_link () test -n "$add" && deplibs="$add $deplibs" fi fi - elif test "$linkmode" = prog; then + elif test prog = "$linkmode"; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. - if test "$hardcode_direct" != unsupported; then - test -n "$old_library" && linklib="$old_library" + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi - elif test "$build_libtool_libs" = yes; then + elif test yes = "$build_libtool_libs"; then # Not a shared library - if test "$deplibs_check_method" != pass_all; then + if test pass_all != "$deplibs_check_method"; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo - $ECHO "*** Warning: This system can not link to static lib archive $lib." + $ECHO "*** Warning: This system cannot link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." - if test "$module" = yes; then + if test yes = "$module"; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." - echo "*** \`nm' from GNU binutils and a full rebuild may help." + echo "*** 'nm' from GNU binutils and a full rebuild may help." fi - if test "$build_old_libs" = no; then + if test no = "$build_old_libs"; then build_libtool_libs=module build_old_libs=yes else @@ -6987,11 +8709,11 @@ func_mode_link () fi fi # link shared/static library? - if test "$linkmode" = lib; then + if test lib = "$linkmode"; then if test -n "$dependency_libs" && - { test "$hardcode_into_libs" != yes || - test "$build_old_libs" = yes || - test "$link_static" = yes; }; then + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do @@ -7005,12 +8727,12 @@ func_mode_link () *) func_append temp_deplibs " $libdir";; esac done - dependency_libs="$temp_deplibs" + dependency_libs=$temp_deplibs fi func_append newlib_search_path " $absdir" # Link against this library - test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do @@ -7020,7 +8742,7 @@ func_mode_link () func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac - if $opt_preserve_dup_deps ; then + if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; @@ -7029,12 +8751,12 @@ func_mode_link () func_append tmp_libs " $func_resolve_sysroot_result" done - if test "$link_all_deplibs" != no; then + if test no != "$link_all_deplibs"; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in - -L*) path="$deplib" ;; + -L*) path=$deplib ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result @@ -7042,12 +8764,12 @@ func_mode_link () dir=$func_dirname_result # We need an absolute path. case $dir in - [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then - func_warning "cannot determine absolute directory name of \`$dir'" - absdir="$dir" + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir fi ;; esac @@ -7055,35 +8777,35 @@ func_mode_link () case $host in *-*-darwin*) depdepl= - eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` - if test -n "$deplibrary_names" ; then - for tmp in $deplibrary_names ; do + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do depdepl=$tmp done - if test -f "$absdir/$objdir/$depdepl" ; then - depdepl="$absdir/$objdir/$depdepl" - darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then - darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi - func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" - func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" path= fi fi ;; *) - path="-L$absdir/$objdir" + path=-L$absdir/$objdir ;; esac else - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ - func_fatal_error "\`$deplib' is not a valid libtool archive" + func_fatal_error "'$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ - func_warning "\`$deplib' seems to be moved" + func_warning "'$deplib' seems to be moved" - path="-L$absdir" + path=-L$absdir fi ;; esac @@ -7095,23 +8817,23 @@ func_mode_link () fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs - if test "$pass" = link; then - if test "$linkmode" = "prog"; then + if test link = "$pass"; then + if test prog = "$linkmode"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi - dependency_libs="$newdependency_libs" - if test "$pass" = dlpreopen; then + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi - if test "$pass" != dlopen; then - if test "$pass" != conv; then + if test dlopen != "$pass"; then + test conv = "$pass" || { # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do @@ -7121,12 +8843,12 @@ func_mode_link () esac done newlib_search_path= - fi + } - if test "$linkmode,$pass" != "prog,link"; then - vars="deplibs" - else + if test prog,link = "$linkmode,$pass"; then vars="compile_deplibs finalize_deplibs" + else + vars=deplibs fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order @@ -7184,62 +8906,93 @@ func_mode_link () eval $var=\"$tmp_libs\" done # for var fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | $SED 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= - for i in $dependency_libs ; do + for i in $dependency_libs; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) - i="" + i= ;; esac - if test -n "$i" ; then + if test -n "$i"; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass - if test "$linkmode" = prog; then - dlfiles="$newdlfiles" + if test prog = "$linkmode"; then + dlfiles=$newdlfiles fi - if test "$linkmode" = prog || test "$linkmode" = lib; then - dlprefiles="$newdlprefiles" + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles fi case $linkmode in oldlib) - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - func_warning "\`-dlopen' is ignored for archives" + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) - func_warning "\`-l' and \`-L' are ignored for archives" ;; + func_warning "'-l' and '-L' are ignored for archives" ;; esac test -n "$rpath" && \ - func_warning "\`-rpath' is ignored for archives" + func_warning "'-rpath' is ignored for archives" test -n "$xrpath" && \ - func_warning "\`-R' is ignored for archives" + func_warning "'-R' is ignored for archives" test -n "$vinfo" && \ - func_warning "\`-version-info/-version-number' is ignored for archives" + func_warning "'-version-info/-version-number' is ignored for archives" test -n "$release" && \ - func_warning "\`-release' is ignored for archives" + func_warning "'-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ - func_warning "\`-export-symbols' is ignored for archives" + func_warning "'-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no - oldlibs="$output" + oldlibs=$output func_append objs "$old_deplibs" ;; lib) - # Make sure we only generate libraries of the form `libNAME.la'. + # Make sure we only generate libraries of the form 'libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" @@ -7248,10 +9001,10 @@ func_mode_link () eval libname=\"$libname_spec\" ;; *) - test "$module" = no && \ - func_fatal_help "libtool library \`$output' must begin with \`lib'" + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" - if test "$need_lib_prefix" != no; then + if test no != "$need_lib_prefix"; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result @@ -7265,8 +9018,8 @@ func_mode_link () esac if test -n "$objs"; then - if test "$deplibs_check_method" != pass_all; then - func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" @@ -7275,21 +9028,21 @@ func_mode_link () fi fi - test "$dlself" != no && \ - func_warning "\`-dlopen self' is ignored for libtool libraries" + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" set dummy $rpath shift - test "$#" -gt 1 && \ - func_warning "ignoring multiple \`-rpath's for a libtool library" + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" - install_libdir="$1" + install_libdir=$1 oldlibs= if test -z "$rpath"; then - if test "$build_libtool_libs" = yes; then + if test yes = "$build_libtool_libs"; then # Building a libtool convenience library. - # Some compilers have problems with a `.al' extension so + # Some compilers have problems with a '.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" @@ -7298,20 +9051,20 @@ func_mode_link () fi test -n "$vinfo" && \ - func_warning "\`-version-info/-version-number' is ignored for convenience libraries" + func_warning "'-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ - func_warning "\`-release' is ignored for convenience libraries" + func_warning "'-release' is ignored for convenience libraries" else # Parse the version information argument. - save_ifs="$IFS"; IFS=':' + save_ifs=$IFS; IFS=: set dummy $vinfo 0 0 0 shift - IFS="$save_ifs" + IFS=$save_ifs test -n "$7" && \ - func_fatal_help "too many parameters to \`-version-info'" + func_fatal_help "too many parameters to '-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts @@ -7319,42 +9072,42 @@ func_mode_link () case $vinfo_number in yes) - number_major="$1" - number_minor="$2" - number_revision="$3" + number_major=$1 + number_minor=$2 + number_revision=$3 # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix - # which has an extra 1 added just for fun + # that has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor - darwin|linux|osf|windows|none) + darwin|freebsd-elf|linux|midnightbsd-elf|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result - age="$number_minor" - revision="$number_revision" + age=$number_minor + revision=$number_revision ;; - freebsd-aout|freebsd-elf|qnx|sunos) - current="$number_major" - revision="$number_minor" - age="0" + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result - age="$number_minor" - revision="$number_minor" + age=$number_minor + revision=$number_minor lt_irix_increment=no ;; esac ;; no) - current="$1" - revision="$2" - age="$3" + current=$1 + revision=$2 + age=$3 ;; esac @@ -7362,30 +9115,30 @@ func_mode_link () case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) - func_error "CURRENT \`$current' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) - func_error "REVISION \`$revision' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) - func_error "AGE \`$age' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then - func_error "AGE \`$age' is greater than the current interface number \`$current'" - func_fatal_error "\`$vinfo' is not valid version information" + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" fi # Calculate the version variables. @@ -7400,26 +9153,36 @@ func_mode_link () # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result - versuffix="$major.$age.$revision" + versuffix=$major.$age.$revision # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result - xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac ;; freebsd-aout) - major=".$current" - versuffix=".$current.$revision"; + major=.$current + versuffix=.$current.$revision ;; - freebsd-elf) - major=".$current" - versuffix=".$current" + freebsd-elf | midnightbsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision ;; irix | nonstopux) - if test "X$lt_irix_increment" = "Xno"; then + if test no = "$lt_irix_increment"; then func_arith $current - $age else func_arith $current - $age + 1 @@ -7430,69 +9193,74 @@ func_mode_link () nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac - verstring="$verstring_prefix$major.$revision" + verstring=$verstring_prefix$major.$revision # Add in all the interfaces that we are compatible with. loop=$revision - while test "$loop" -ne 0; do + while test 0 -ne "$loop"; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result - verstring="$verstring_prefix$major.$iface:$verstring" + verstring=$verstring_prefix$major.$iface:$verstring done - # Before this point, $major must not contain `.'. + # Before this point, $major must not contain '.'. major=.$major - versuffix="$major.$revision" + versuffix=$major.$revision ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result - versuffix="$major.$age.$revision" + versuffix=$major.$age.$revision ;; osf) func_arith $current - $age major=.$func_arith_result - versuffix=".$current.$age.$revision" - verstring="$current.$age.$revision" + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision # Add in all the interfaces that we are compatible with. loop=$age - while test "$loop" -ne 0; do + while test 0 -ne "$loop"; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result - verstring="$verstring:${iface}.0" + verstring=$verstring:$iface.0 done # Make executables depend on our current version. - func_append verstring ":${current}.0" + func_append verstring ":$current.0" ;; qnx) - major=".$current" - versuffix=".$current" + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current ;; sunos) - major=".$current" - versuffix=".$current.$revision" + major=.$current + versuffix=.$current.$revision ;; windows) # Use '-' rather than '.', since we only want one - # extension on DOS 8.3 filesystems. + # extension on DOS 8.3 file systems. func_arith $current - $age major=$func_arith_result - versuffix="-$major" + versuffix=-$major ;; *) - func_fatal_configuration "unknown library version type \`$version_type'" + func_fatal_configuration "unknown library version type '$version_type'" ;; esac @@ -7506,42 +9274,45 @@ func_mode_link () verstring= ;; *) - verstring="0.0" + verstring=0.0 ;; esac - if test "$need_version" = no; then + if test no = "$need_version"; then versuffix= else - versuffix=".0.0" + versuffix=.0.0 fi fi # Remove version info from name if versioning should be avoided - if test "$avoid_version" = yes && test "$need_version" = no; then + if test yes,no = "$avoid_version,$need_version"; then major= versuffix= - verstring="" + verstring= fi # Check to see if the archive will have undefined symbols. - if test "$allow_undefined" = yes; then - if test "$allow_undefined_flag" = unsupported; then - func_warning "undefined symbols not allowed in $host shared libraries" - build_libtool_libs=no - build_old_libs=yes + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi fi else # Don't allow undefined symbols. - allow_undefined_flag="$no_undefined_flag" + allow_undefined_flag=$no_undefined_flag fi fi - func_generate_dlsyms "$libname" "$libname" "yes" + func_generate_dlsyms "$libname" "$libname" : func_append libobjs " $symfileobj" - test "X$libobjs" = "X " && libobjs= + test " " = "$libobjs" && libobjs= - if test "$opt_mode" != relink; then + if test relink != "$opt_mode"; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= @@ -7550,8 +9321,8 @@ func_mode_link () case $p in *.$objext | *.gcno) ;; - $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) - if test "X$precious_files_regex" != "X"; then + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue @@ -7567,11 +9338,11 @@ func_mode_link () fi # Now set the variables for building old libraries. - if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. - oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. @@ -7592,13 +9363,13 @@ func_mode_link () *) func_append finalize_rpath " $libdir" ;; esac done - if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened - old_dlfiles="$dlfiles" + old_dlfiles=$dlfiles dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in @@ -7608,7 +9379,7 @@ func_mode_link () done # Make sure dlprefiles contains only unique files - old_dlprefiles="$dlprefiles" + old_dlprefiles=$dlprefiles dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in @@ -7617,7 +9388,7 @@ func_mode_link () esac done - if test "$build_libtool_libs" = yes; then + if test yes = "$build_libtool_libs"; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) @@ -7630,7 +9401,7 @@ func_mode_link () *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-midnightbsd*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) @@ -7641,7 +9412,7 @@ func_mode_link () ;; *) # Add libc to deplibs on all other systems if necessary. - if test "$build_libtool_need_lc" = "yes"; then + if test yes = "$build_libtool_need_lc"; then func_append deplibs " -lc" fi ;; @@ -7657,9 +9428,9 @@ func_mode_link () # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? - release="" - versuffix="" - major="" + release= + versuffix= + major= newdeplibs= droppeddeps=no case $deplibs_check_method in @@ -7688,20 +9459,20 @@ EOF -l*) func_stripname -l '' "$i" name=$func_stripname_result - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $i "*) func_append newdeplibs " $i" - i="" + i= ;; esac fi - if test -n "$i" ; then + if test -n "$i"; then libname=`eval "\\$ECHO \"$libname_spec\""` deplib_matches=`eval "\\$ECHO \"$library_names_spec\""` set dummy $deplib_matches; shift deplib_match=$1 - if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0; then func_append newdeplibs " $i" else droppeddeps=yes @@ -7731,20 +9502,20 @@ EOF $opt_dry_run || $RM conftest if $LTCC $LTCFLAGS -o conftest conftest.c $i; then ldd_output=`ldd conftest` - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $i "*) func_append newdeplibs " $i" - i="" + i= ;; esac fi - if test -n "$i" ; then + if test -n "$i"; then libname=`eval "\\$ECHO \"$libname_spec\""` deplib_matches=`eval "\\$ECHO \"$library_names_spec\""` set dummy $deplib_matches; shift deplib_match=$1 - if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0; then func_append newdeplibs " $i" else droppeddeps=yes @@ -7781,24 +9552,24 @@ EOF -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" - a_deplib="" + a_deplib= ;; esac fi - if test -n "$a_deplib" ; then + if test -n "$a_deplib"; then libname=`eval "\\$ECHO \"$libname_spec\""` if test -n "$file_magic_glob"; then libnameglob=`func_echo_all "$libname" | $SED -e $file_magic_glob` else libnameglob=$libname fi - test "$want_nocaseglob" = yes && nocaseglob=`shopt -p nocaseglob` + test yes = "$want_nocaseglob" && nocaseglob=`shopt -p nocaseglob` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do - if test "$want_nocaseglob" = yes; then + if test yes = "$want_nocaseglob"; then shopt -s nocaseglob potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` $nocaseglob @@ -7816,25 +9587,25 @@ EOF # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? - potlib="$potent_lib" + potlib=$potent_lib while test -h "$potlib" 2>/dev/null; do - potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` case $potliblink in - [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; - *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" - a_deplib="" + a_deplib= break 2 fi done done fi - if test -n "$a_deplib" ; then + if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." @@ -7842,7 +9613,7 @@ EOF echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then + if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" @@ -7865,30 +9636,30 @@ EOF -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" - a_deplib="" + a_deplib= ;; esac fi - if test -n "$a_deplib" ; then + if test -n "$a_deplib"; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do - potlib="$potent_lib" # see symlink-check above in file_magic test + potlib=$potent_lib # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" - a_deplib="" + a_deplib= break 2 fi done done fi - if test -n "$a_deplib" ; then + if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." @@ -7896,7 +9667,7 @@ EOF echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then + if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" @@ -7912,18 +9683,18 @@ EOF done # Gone through all deplibs. ;; none | unknown | *) - newdeplibs="" + newdeplibs= tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - for i in $predeps $postdeps ; do + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do # can't use Xsed below, because $i might contain '/' - tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` done fi case $tmp_deplibs in *[!\ \ ]*) echo - if test "X$deplibs_check_method" = "Xnone"; then + if test none = "$deplibs_check_method"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." @@ -7947,8 +9718,8 @@ EOF ;; esac - if test "$droppeddeps" = yes; then - if test "$module" = yes; then + if test yes = "$droppeddeps"; then + if test yes = "$module"; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" @@ -7957,12 +9728,12 @@ EOF if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." - echo "*** \`nm' from GNU binutils and a full rebuild may help." + echo "*** 'nm' from GNU binutils and a full rebuild may help." fi - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else @@ -7973,14 +9744,14 @@ EOF echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." - if test "$allow_undefined" = no; then + if test no = "$allow_undefined"; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else @@ -8026,7 +9797,7 @@ EOF *) func_append new_libs " $deplib" ;; esac done - deplibs="$new_libs" + deplibs=$new_libs # All the library-specific variables (install_libdir is set above). library_names= @@ -8034,25 +9805,25 @@ EOF dlname= # Test again, we may have decided not to build it any more - if test "$build_libtool_libs" = yes; then - # Remove ${wl} instances when linking with ld. + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac - if test "$hardcode_into_libs" = yes; then + if test yes = "$hardcode_into_libs"; then # Hardcode the library paths hardcode_libdirs= dep_rpath= - rpath="$finalize_rpath" - test "$opt_mode" != relink && rpath="$compile_rpath$rpath" + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" + hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in @@ -8077,7 +9848,7 @@ EOF # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" + libdir=$hardcode_libdirs eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then @@ -8091,8 +9862,8 @@ EOF test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi - shlibpath="$finalize_shlibpath" - test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi @@ -8102,19 +9873,19 @@ EOF eval library_names=\"$library_names_spec\" set dummy $library_names shift - realname="$1" + realname=$1 shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else - soname="$realname" + soname=$realname fi if test -z "$dlname"; then dlname=$soname fi - lib="$output_objdir/$realname" + lib=$output_objdir/$realname linknames= for link do @@ -8128,7 +9899,7 @@ EOF delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" - export_symbols="$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp func_append delfiles " $export_symbols" fi @@ -8137,31 +9908,31 @@ EOF cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile - if test "x`$SED 1q $export_symbols`" != xEXPORTS; then + func_dll_def_p "$export_symbols" || { # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. - orig_export_symbols="$export_symbols" + orig_export_symbols=$export_symbols export_symbols= always_export_symbols=yes - fi + } fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then - if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then - func_verbose "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds - save_ifs="$IFS"; IFS='~' + save_ifs=$IFS; IFS='~' for cmd1 in $cmds; do - IFS="$save_ifs" + IFS=$save_ifs # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in @@ -8175,7 +9946,7 @@ EOF try_normal_branch=no ;; esac - if test "$try_normal_branch" = yes \ + if test yes = "$try_normal_branch" \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then @@ -8186,7 +9957,7 @@ EOF output_la=$func_basename_result save_libobjs=$libobjs save_output=$output - output=${output_objdir}/${output_la}.nm + output=$output_objdir/$output_la.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" @@ -8209,8 +9980,8 @@ EOF break fi done - IFS="$save_ifs" - if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi @@ -8218,16 +9989,16 @@ EOF fi if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols="$export_symbols" - test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi - if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands which not all seds can handle. GNU sed should be fine + # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. @@ -8246,11 +10017,11 @@ EOF ;; esac done - deplibs="$tmp_deplibs" + deplibs=$tmp_deplibs if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && - test "$compiler_needs_object" = yes && + test yes = "$compiler_needs_object" && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. @@ -8261,7 +10032,7 @@ EOF eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else - gentop="$output_objdir/${outputname}x" + gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $convenience @@ -8270,18 +10041,18 @@ EOF fi fi - if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking - if test "$opt_mode" = relink; then + if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then + if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds @@ -8299,7 +10070,7 @@ EOF fi fi - if test "X$skipped_export" != "X:" && + if test : != "$skipped_export" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then @@ -8332,8 +10103,8 @@ EOF last_robj= k=1 - if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then - output=${output_objdir}/${output_la}.lnkscript + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs @@ -8345,14 +10116,14 @@ EOF func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result - elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then - output=${output_objdir}/${output_la}.lnk + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= - if test "$compiler_needs_object" = yes; then + if test yes = "$compiler_needs_object"; then firstobj="$1 " shift fi @@ -8367,7 +10138,7 @@ EOF else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." - output=$output_objdir/$output_la-${k}.$objext + output=$output_objdir/$output_la-$k.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result @@ -8379,13 +10150,13 @@ EOF func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result - if test "X$objlist" = X || + if test -z "$objlist" || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. - if test "$k" -eq 1 ; then + if test 1 -eq "$k"; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" @@ -8395,10 +10166,10 @@ EOF reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi - last_robj=$output_objdir/$output_la-${k}.$objext + last_robj=$output_objdir/$output_la-$k.$objext func_arith $k + 1 k=$func_arith_result - output=$output_objdir/$output_la-${k}.$objext + output=$output_objdir/$output_la-$k.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result @@ -8410,9 +10181,9 @@ EOF # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" - eval concat_cmds=\"\${concat_cmds}$reload_cmds\" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" if test -n "$last_robj"; then - eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi func_append delfiles " $output" @@ -8420,9 +10191,9 @@ EOF output= fi - if ${skipped_export-false}; then - func_verbose "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. @@ -8431,24 +10202,24 @@ EOF if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi - fi + } test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. - save_ifs="$IFS"; IFS='~' + save_ifs=$IFS; IFS='~' for cmd in $concat_cmds; do - IFS="$save_ifs" - $opt_silent || { - func_quote_for_expand "$cmd" - eval "func_echo $func_quote_for_expand_result" + IFS=$save_ifs + $opt_quiet || { + func_quote_arg expand,pretty "$cmd" + eval "func_echo $func_quote_arg_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then + if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) @@ -8457,7 +10228,7 @@ EOF exit $lt_exit } done - IFS="$save_ifs" + IFS=$save_ifs if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' @@ -8465,18 +10236,18 @@ EOF fi fi - if ${skipped_export-false}; then + ${skipped_export-false} && { if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols="$export_symbols" - test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands which not all seds can handle. GNU sed should be fine + # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. @@ -8485,7 +10256,7 @@ EOF export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi - fi + } libobjs=$output # Restore the value of output. @@ -8499,7 +10270,7 @@ EOF # value of $libobjs for piecewise linking. # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then + if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else @@ -8521,7 +10292,7 @@ EOF # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then - gentop="$output_objdir/${outputname}x" + gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles @@ -8529,19 +10300,20 @@ EOF test "X$libobjs" = "X " && libobjs= fi - save_ifs="$IFS"; IFS='~' + save_ifs=$IFS; IFS='~' for cmd in $cmds; do - IFS="$save_ifs" + IFS=$sp$nl eval cmd=\"$cmd\" - $opt_silent || { - func_quote_for_expand "$cmd" - eval "func_echo $func_quote_for_expand_result" + IFS=$save_ifs + $opt_quiet || { + func_quote_arg expand,pretty "$cmd" + eval "func_echo $func_quote_arg_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then + if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) @@ -8550,10 +10322,10 @@ EOF exit $lt_exit } done - IFS="$save_ifs" + IFS=$save_ifs # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then + if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then @@ -8573,39 +10345,39 @@ EOF done # If -module or -export-dynamic was specified, set the dlname. - if test "$module" = yes || test "$export_dynamic" = yes; then + if test yes = "$module" || test yes = "$export_dynamic"; then # On all known operating systems, these are identical. - dlname="$soname" + dlname=$soname fi fi ;; obj) - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - func_warning "\`-dlopen' is ignored for objects" + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) - func_warning "\`-l' and \`-L' are ignored for objects" ;; + func_warning "'-l' and '-L' are ignored for objects" ;; esac test -n "$rpath" && \ - func_warning "\`-rpath' is ignored for objects" + func_warning "'-rpath' is ignored for objects" test -n "$xrpath" && \ - func_warning "\`-R' is ignored for objects" + func_warning "'-R' is ignored for objects" test -n "$vinfo" && \ - func_warning "\`-version-info' is ignored for objects" + func_warning "'-version-info' is ignored for objects" test -n "$release" && \ - func_warning "\`-release' is ignored for objects" + func_warning "'-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ - func_fatal_error "cannot build library object \`$output' from non-libtool objects" + func_fatal_error "cannot build library object '$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" @@ -8613,7 +10385,7 @@ EOF ;; *) libobj= - obj="$output" + obj=$output ;; esac @@ -8626,17 +10398,19 @@ EOF # the extraction. reload_conv_objs= gentop= - # reload_cmds runs $LD directly, so let us get rid of - # -Wl from whole_archive_flag_spec and hope we can get by with - # turning comma into space.. - wl= - + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" - reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags else - gentop="$output_objdir/${obj}x" + gentop=$output_objdir/${obj}x func_append generated " $gentop" func_extract_archives $gentop $convenience @@ -8645,12 +10419,12 @@ EOF fi # If we're not building shared, we need to use non_pic_objs - test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects # Create the old-style object. - reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs - output="$obj" + output=$obj func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. @@ -8662,7 +10436,7 @@ EOF exit $EXIT_SUCCESS fi - if test "$build_libtool_libs" != yes; then + test yes = "$build_libtool_libs" || { if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi @@ -8672,12 +10446,12 @@ EOF # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS - fi + } - if test -n "$pic_flag" || test "$pic_mode" != default; then + if test -n "$pic_flag" || test default != "$pic_mode"; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" - output="$libobj" + output=$libobj func_execute_cmds "$reload_cmds" 'exit $?' fi @@ -8694,16 +10468,14 @@ EOF output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ - func_warning "\`-version-info' is ignored for programs" + func_warning "'-version-info' is ignored for programs" test -n "$release" && \ - func_warning "\`-release' is ignored for programs" + func_warning "'-release' is ignored for programs" - test "$preload" = yes \ - && test "$dlopen_support" = unknown \ - && test "$dlopen_self" = unknown \ - && test "$dlopen_self_static" = unknown && \ - func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) @@ -8717,11 +10489,11 @@ EOF *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). - if test "$tagname" = CXX ; then + if test CXX = "$tagname"; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) - func_append compile_command " ${wl}-bind_at_load" - func_append finalize_command " ${wl}-bind_at_load" + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" ;; esac fi @@ -8757,7 +10529,7 @@ EOF *) func_append new_libs " $deplib" ;; esac done - compile_deplibs="$new_libs" + compile_deplibs=$new_libs func_append compile_command " $compile_deplibs" @@ -8781,7 +10553,7 @@ EOF if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" + hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in @@ -8804,7 +10576,7 @@ EOF fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; @@ -8821,10 +10593,10 @@ EOF # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" + libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi - compile_rpath="$rpath" + compile_rpath=$rpath rpath= hardcode_libdirs= @@ -8832,7 +10604,7 @@ EOF if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" + hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in @@ -8857,45 +10629,43 @@ EOF # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" + libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi - finalize_rpath="$rpath" + finalize_rpath=$rpath - if test -n "$libobjs" && test "$build_old_libs" = yes; then + if test -n "$libobjs" && test yes = "$build_old_libs"; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi - func_generate_dlsyms "$outputname" "@PROGRAM@" "no" + func_generate_dlsyms "$outputname" "@PROGRAM@" false # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi - wrappers_required=yes + wrappers_required=: case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. - wrappers_required=no + wrappers_required=false ;; *cygwin* | *mingw* ) - if test "$build_libtool_libs" != yes; then - wrappers_required=no - fi + test yes = "$build_libtool_libs" || wrappers_required=false ;; *) - if test "$need_relink" = no || test "$build_libtool_libs" != yes; then - wrappers_required=no + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false fi ;; esac - if test "$wrappers_required" = no; then + $wrappers_required || { # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` - link_command="$compile_command$compile_rpath" + link_command=$compile_command$compile_rpath # We have no uninstalled library dependencies, so finalize right now. exit_status=0 @@ -8908,12 +10678,12 @@ EOF fi # Delete the generated files. - if test -f "$output_objdir/${outputname}S.${objext}"; then - func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' fi exit $exit_status - fi + } if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" @@ -8943,9 +10713,9 @@ EOF fi fi - if test "$no_install" = yes; then + if test yes = "$no_install"; then # We don't need to create a wrapper script. - link_command="$compile_var$compile_command$compile_rpath" + link_command=$compile_var$compile_command$compile_rpath # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. @@ -8962,27 +10732,28 @@ EOF exit $EXIT_SUCCESS fi - if test "$hardcode_action" = relink; then - # Fast installation is not supported - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath - func_warning "this platform does not like uninstalled shared libraries" - func_warning "\`$output' will be relinked during installation" - else - if test "$fast_install" != no; then - link_command="$finalize_var$compile_command$finalize_rpath" - if test "$fast_install" = yes; then - relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` - else - # fast_install is set to needless - relink_command= - fi - else - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - fi - fi + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` @@ -9010,12 +10781,13 @@ EOF elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else - func_quote_for_eval "$var_value" - relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + func_quote_arg pretty "$var_value" + relink_command="$var=$func_quote_arg_result; export $var; $relink_command" fi done - relink_command="(cd `pwd`; $relink_command)" - relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + func_quote eval cd "`pwd`" + func_quote_arg pretty,unquoted "($func_quote_result; $relink_command)" + relink_command=$func_quote_arg_unquoted_result fi # Only actually do things if not in dry run mode. @@ -9039,8 +10811,8 @@ EOF func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result - cwrappersource="$output_path/$objdir/lt-$output_name.c" - cwrapper="$output_path/$output_name.exe" + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 @@ -9061,7 +10833,7 @@ EOF trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. - if test "x$build" = "x$host" ; then + if test "x$build" = "x$host"; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result @@ -9084,25 +10856,27 @@ EOF # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do - if test "$build_libtool_libs" = convenience; then - oldobjs="$libobjs_save $symfileobj" - addlibs="$convenience" - build_libtool_libs=no - else - if test "$build_libtool_libs" = module; then - oldobjs="$libobjs_save" + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience build_libtool_libs=no - else + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) oldobjs="$old_deplibs $non_pic_objects" - if test "$preload" = yes && test -f "$symfileobj"; then - func_append oldobjs " $symfileobj" - fi - fi - addlibs="$old_convenience" - fi + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac if test -n "$addlibs"; then - gentop="$output_objdir/${outputname}x" + gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $addlibs @@ -9110,13 +10884,13 @@ EOF fi # Do each command in the archive commands. - if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then - gentop="$output_objdir/${outputname}x" + gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles @@ -9137,7 +10911,7 @@ EOF : else echo "copying selected object files to avoid basename conflicts..." - gentop="$output_objdir/${outputname}x" + gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs @@ -9146,7 +10920,7 @@ EOF for obj in $save_oldobjs do func_basename "$obj" - objbase="$func_basename_result" + objbase=$func_basename_result case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) @@ -9215,18 +10989,18 @@ EOF else # the above command should be used before it gets too long oldobjs=$objlist - if test "$obj" = "$last_oldobj" ; then + if test "$obj" = "$last_oldobj"; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist - if test "X$oldobjs" = "X" ; then + if test -z "$oldobjs"; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" @@ -9243,7 +11017,7 @@ EOF case $output in *.la) old_library= - test "$build_old_libs" = yes && old_library="$libname.$libext" + test yes = "$build_old_libs" && old_library=$libname.$libext func_verbose "creating $output" # Preserve any variables that may affect compiler behavior @@ -9253,36 +11027,38 @@ EOF elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else - func_quote_for_eval "$var_value" - relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + func_quote_arg pretty,unquoted "$var_value" + relink_command="$var=$func_quote_arg_unquoted_result; export $var; $relink_command" fi done # Quote the link command for shipping. - relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" - relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` - if test "$hardcode_automatic" = yes ; then + func_quote eval cd "`pwd`" + relink_command="($func_quote_result; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + func_quote_arg pretty,unquoted "$relink_command" + relink_command=$func_quote_arg_unquoted_result + if test yes = "$hardcode_automatic"; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do - if test "$installed" = yes; then + if test yes = "$installed"; then if test -z "$install_libdir"; then break fi - output="$output_objdir/$outputname"i + output=$output_objdir/${outputname}i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" - name="$func_basename_result" + name=$func_basename_result func_resolve_sysroot "$deplib" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ - func_fatal_error "\`$deplib' is not a valid libtool archive" + func_fatal_error "'$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) @@ -9298,23 +11074,23 @@ EOF *) func_append newdependency_libs " $deplib" ;; esac done - dependency_libs="$newdependency_libs" + dependency_libs=$newdependency_libs newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" - name="$func_basename_result" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ - func_fatal_error "\`$lib' is not a valid libtool archive" + func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done - dlfiles="$newdlfiles" + dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in @@ -9324,34 +11100,34 @@ EOF # didn't already link the preopened objects directly into # the library: func_basename "$lib" - name="$func_basename_result" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ - func_fatal_error "\`$lib' is not a valid libtool archive" + func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done - dlprefiles="$newdlprefiles" + dlprefiles=$newdlprefiles else newdlfiles= for lib in $dlfiles; do case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done - dlfiles="$newdlfiles" + dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done - dlprefiles="$newdlprefiles" + dlprefiles=$newdlprefiles fi $RM $output # place dlname in correct position for cygwin @@ -9367,10 +11143,9 @@ EOF case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. - if test "x$bindir" != x ; - then + if test -n "$bindir"; then func_relative_path "$install_libdir" "$bindir" - tdlname=$func_relative_path_result$dlname + tdlname=$func_relative_path_result/$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname @@ -9379,7 +11154,7 @@ EOF esac $ECHO > $output "\ # $outputname - a libtool library file -# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. @@ -9393,7 +11168,7 @@ library_names='$library_names' # The name of the static archive. old_library='$old_library' -# Linker flags that can not go in dependency_libs. +# Linker flags that cannot go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. @@ -9419,7 +11194,7 @@ dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" - if test "$installed" = no && test "$need_relink" = yes; then + if test no,yes = "$installed,$need_relink"; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi @@ -9434,27 +11209,29 @@ relink_command=\"$relink_command\"" exit $EXIT_SUCCESS } -{ test "$opt_mode" = link || test "$opt_mode" = relink; } && - func_mode_link ${1+"$@"} +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi # func_mode_uninstall arg... func_mode_uninstall () { - $opt_debug - RM="$nonopt" + $debug_cmd + + RM=$nonopt files= - rmforce= + rmforce=false exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. - libtool_install_magic="$magic" + libtool_install_magic=$magic for arg do case $arg in - -f) func_append RM " $arg"; rmforce=yes ;; + -f) func_append RM " $arg"; rmforce=: ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac @@ -9467,18 +11244,18 @@ func_mode_uninstall () for file in $files; do func_dirname "$file" "" "." - dir="$func_dirname_result" - if test "X$dir" = X.; then - odir="$objdir" + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir else - odir="$dir/$objdir" + odir=$dir/$objdir fi func_basename "$file" - name="$func_basename_result" - test "$opt_mode" = uninstall && odir="$dir" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir # Remember odir for removal later, being careful to avoid duplicates - if test "$opt_mode" = clean; then + if test clean = "$opt_mode"; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; @@ -9493,11 +11270,11 @@ func_mode_uninstall () elif test -d "$file"; then exit_status=1 continue - elif test "$rmforce" = yes; then + elif $rmforce; then continue fi - rmfiles="$file" + rmfiles=$file case $name in *.la) @@ -9511,7 +11288,7 @@ func_mode_uninstall () done test -n "$old_library" && func_append rmfiles " $odir/$old_library" - case "$opt_mode" in + case $opt_mode in clean) case " $library_names " in *" $dlname "*) ;; @@ -9522,12 +11299,12 @@ func_mode_uninstall () uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. - func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. - func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; @@ -9543,21 +11320,19 @@ func_mode_uninstall () func_source $dir/$name # Add PIC object to the list of files to remove. - if test -n "$pic_object" && - test "$pic_object" != none; then + if test -n "$pic_object" && test none != "$pic_object"; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. - if test -n "$non_pic_object" && - test "$non_pic_object" != none; then + if test -n "$non_pic_object" && test none != "$non_pic_object"; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) - if test "$opt_mode" = clean ; then + if test clean = "$opt_mode"; then noexename=$name case $file in *.exe) @@ -9584,12 +11359,12 @@ func_mode_uninstall () # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles - func_append rmfiles " $odir/$name $odir/${name}S.${objext}" - if test "$fast_install" = yes && test -n "$relink_command"; then + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi - if test "X$noexename" != "X$name" ; then - func_append rmfiles " $odir/lt-${noexename}.c" + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" fi fi fi @@ -9598,7 +11373,7 @@ func_mode_uninstall () func_show_eval "$RM $rmfiles" 'exit_status=1' done - # Try to remove the ${objdir}s in the directories where we deleted files + # Try to remove the $objdir's in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" @@ -9608,16 +11383,17 @@ func_mode_uninstall () exit $exit_status } -{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && - func_mode_uninstall ${1+"$@"} +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi test -z "$opt_mode" && { - help="$generic_help" + help=$generic_help func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ - func_fatal_help "invalid operation mode \`$opt_mode'" + func_fatal_help "invalid operation mode '$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" @@ -9628,7 +11404,7 @@ exit $exit_status # The TAGs below are defined such that we never get into a situation -# in which we disable both kinds of libraries. Given conflicting +# where we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support @@ -9651,5 +11427,3 @@ build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # mode:shell-script # sh-indentation:2 # End: -# vi:sw=2 - diff --git a/build-aux/missing b/build-aux/missing index 86a8fc3..1fe1611 100755 --- a/build-aux/missing +++ b/build-aux/missing @@ -1,11 +1,10 @@ #! /bin/sh -# Common stub for a few missing GNU programs while installing. +# Common wrapper for a few potentially missing GNU programs. -scriptversion=2012-01-06.13; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, -# 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. -# Originally by Fran,cois Pinard , 1996. +# Copyright (C) 1996-2021 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,7 +17,7 @@ scriptversion=2012-01-06.13; # UTC # GNU General Public License for more details. # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -26,68 +25,40 @@ scriptversion=2012-01-06.13; # UTC # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then - echo 1>&2 "Try \`$0 --help' for more information" + echo 1>&2 "Try '$0 --help' for more information" exit 1 fi -run=: -sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' -sed_minuso='s/.* -o \([^ ]*\).*/\1/p' - -# In the cases where this matters, `missing' is being run in the -# srcdir already. -if test -f configure.ac; then - configure_ac=configure.ac -else - configure_ac=configure.in -fi +case $1 in -msg="missing on your system" + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; -case $1 in ---run) - # Try to run requested program, and just exit if it succeeds. - run= - shift - "$@" && exit 0 - # Exit code 63 means version mismatch. This often happens - # when the user try to use an ancient version of a tool on - # a file that requires a minimum version. In this case we - # we should proceed has if the program had been absent, or - # if --run hadn't been passed. - if test $? = 63; then - run=: - msg="probably too old" - fi - ;; + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... -Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an -error status if there is no known handling for PROGRAM. +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit - --run try to run the given command, and emulate it if it fails Supported PROGRAM values: - aclocal touch file \`aclocal.m4' - autoconf touch file \`configure' - autoheader touch file \`config.h.in' - autom4te touch the output file, or create a stub one - automake touch all \`Makefile.in' files - bison create \`y.tab.[ch]', if possible, from existing .[ch] - flex create \`lex.yy.c', if possible, from existing .c - help2man touch the output file - lex create \`lex.yy.c', if possible, from existing .c - makeinfo touch the output file - yacc create \`y.tab.[ch]', if possible, from existing .[ch] + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man -Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and -\`g' are ignored when checking the name. +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. Send bug reports to ." exit $? @@ -99,233 +70,146 @@ Send bug reports to ." ;; -*) - echo 1>&2 "$0: Unknown \`$1' option" - echo 1>&2 "Try \`$0 --help' for more information" + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac -# normalize program name to check for. -program=`echo "$1" | sed ' - s/^gnu-//; t - s/^gnu//; t - s/^g//; t'` - -# Now exit if we have it, but it failed. Also exit now if we -# don't have it and --version was passed (most likely to detect -# the program). This is about non-GNU programs, so use $1 not -# $program. -case $1 in - lex*|yacc*) - # Not GNU programs, they don't have --version. - ;; - - *) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - elif test "x$2" = "x--version" || test "x$2" = "x--help"; then - # Could not run --version or --help. This is probably someone - # running `$TOOL --version' or `$TOOL --help' to check whether - # $TOOL exists and not knowing $TOOL uses missing. - exit 1 - fi - ;; -esac - -# If it does not exist, or fails to run (possibly an outdated version), -# try to emulate it. -case $program in - aclocal*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`acinclude.m4' or \`${configure_ac}'. You might want - to install the \`Automake' and \`Perl' packages. Grab them from - any GNU archive site." - touch aclocal.m4 - ;; - - autoconf*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`${configure_ac}'. You might want to install the - \`Autoconf' and \`GNU m4' packages. Grab them from any GNU - archive site." - touch configure - ;; - - autoheader*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`acconfig.h' or \`${configure_ac}'. You might want - to install the \`Autoconf' and \`GNU m4' packages. Grab them - from any GNU archive site." - files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` - test -z "$files" && files="config.h" - touch_files= - for f in $files; do - case $f in - *:*) touch_files="$touch_files "`echo "$f" | - sed -e 's/^[^:]*://' -e 's/:.*//'`;; - *) touch_files="$touch_files $f.in";; - esac - done - touch $touch_files - ;; - - automake*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. - You might want to install the \`Automake' and \`Perl' packages. - Grab them from any GNU archive site." - find . -type f -name Makefile.am -print | - sed 's/\.am$/.in/' | - while read f; do touch "$f"; done - ;; - - autom4te*) - echo 1>&2 "\ -WARNING: \`$1' is needed, but is $msg. - You might have modified some files without having the - proper tools for further handling them. - You can get \`$1' as part of \`Autoconf' from any GNU - archive site." - - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo "#! /bin/sh" - echo "# Created by GNU Automake missing as a replacement of" - echo "# $ $@" - echo "exit 0" - chmod +x $file - exit 1 - fi - ;; - - bison*|yacc*) - echo 1>&2 "\ -WARNING: \`$1' $msg. You should only need it if - you modified a \`.y' file. You may need the \`Bison' package - in order for those modifications to take effect. You can get - \`Bison' from any GNU archive site." - rm -f y.tab.c y.tab.h - if test $# -ne 1; then - eval LASTARG=\${$#} - case $LASTARG in - *.y) - SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" y.tab.c - fi - SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" y.tab.h - fi - ;; - esac - fi - if test ! -f y.tab.h; then - echo >y.tab.h - fi - if test ! -f y.tab.c; then - echo 'main() { return 0; }' >y.tab.c - fi - ;; - - lex*|flex*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a \`.l' file. You may need the \`Flex' package - in order for those modifications to take effect. You can get - \`Flex' from any GNU archive site." - rm -f lex.yy.c - if test $# -ne 1; then - eval LASTARG=\${$#} - case $LASTARG in - *.l) - SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" lex.yy.c - fi - ;; - esac - fi - if test ! -f lex.yy.c; then - echo 'main() { return 0; }' >lex.yy.c - fi - ;; - - help2man*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a dependency of a manual page. You may need the - \`Help2man' package in order for those modifications to take - effect. You can get \`Help2man' from any GNU archive site." - - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo ".ab help2man is required to generate this page" - exit $? - fi - ;; - - makeinfo*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a \`.texi' or \`.texinfo' file, or any other file - indirectly affecting the aspect of the manual. The spurious - call might also be the consequence of using a buggy \`make' (AIX, - DU, IRIX). You might want to install the \`Texinfo' package or - the \`GNU make' package. Grab either from any GNU archive site." - # The file to touch is that specified with -o ... - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -z "$file"; then - # ... or it is the one specified with @setfilename ... - infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` - file=`sed -n ' - /^@setfilename/{ - s/.* \([^ ]*\) *$/\1/ - p - q - }' $infile` - # ... or it is derived from the source name (dir/f.texi becomes f.info) - test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info - fi - # If the file does not exist, the user really needs makeinfo; - # let's fail without touching anything. - test -f $file || exit 1 - touch $file - ;; +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi - *) - echo 1>&2 "\ -WARNING: \`$1' is needed, and is $msg. - You might have modified some files without having the - proper tools for further handling them. Check the \`README' file, - it often tells you about the needed prerequisites for installing - this package. You may also peek at any GNU archive site, in case - some other package would contain this missing \`$1' program." - exit 1 +perl_URL=https://www.perl.org/ +flex_URL=https://github.com/westes/flex +gnu_software_URL=https://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" ;; -esac - -exit 0 + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/build-aux/test-driver b/build-aux/test-driver new file mode 100755 index 0000000..be73b80 --- /dev/null +++ b/build-aux/test-driver @@ -0,0 +1,153 @@ +#! /bin/sh +# test-driver - basic testsuite driver script. + +scriptversion=2018-03-07.03; # UTC + +# Copyright (C) 2011-2021 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +usage_error () +{ + echo "$0: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat <"$log_file" +"$@" >>"$log_file" 2>&1 +estatus=$? + +if test $enable_hard_errors = no && test $estatus -eq 99; then + tweaked_estatus=1 +else + tweaked_estatus=$estatus +fi + +case $tweaked_estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; + 0:*) col=$grn res=PASS recheck=no gcopy=no;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; + 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; + *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; + *:*) col=$red res=FAIL recheck=yes gcopy=yes;; +esac + +# Report the test outcome and exit status in the logs, so that one can +# know whether the test passed or failed simply by looking at the '.log' +# file, without the need of also peaking into the corresponding '.trs' +# file (automake bug#11814). +echo "$res $test_name (exit status: $estatus)" >>"$log_file" + +# Report outcome to console. +echo "${col}${res}${std}: $test_name" + +# Register the test result, and other relevant metadata. +echo ":test-result: $res" > $trs_file +echo ":global-test-result: $res" >> $trs_file +echo ":recheck: $recheck" >> $trs_file +echo ":copy-in-global-log: $gcopy" >> $trs_file + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/configure b/configure index 701bd27..30a871d 100755 --- a/configure +++ b/configure @@ -1,11 +1,10 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for libnl 3.2.22. +# Generated by GNU Autoconf 2.71 for libnl 3.9.0. # # -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software -# Foundation, Inc. +# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, +# Inc. # # # This configure script is free software; the Free Software Foundation @@ -16,14 +15,16 @@ # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : +as_nop=: +if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 +then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST -else +else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( @@ -33,46 +34,46 @@ esac fi + +# Reset variables that may have inherited troublesome values from +# the environment. + +# IFS needs to be set, to space, tab, and newline, in precisely that order. +# (If _AS_PATH_WALK were called with IFS unset, it would have the +# side effect of setting IFS to empty, thus disabling word splitting.) +# Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi +IFS=" "" $as_nl" + +PS1='$ ' +PS2='> ' +PS4='+ ' + +# Ensure predictable behavior from utilities with locale-dependent output. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# We cannot yet rely on "unset" to work, but we need these variables +# to be unset--not just set to an empty or harmless value--now, to +# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct +# also avoids known problems related to "unset" and subshell syntax +# in other old shells (e.g. bash 2.01 and pdksh 5.2.14). +for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH +do eval test \${$as_var+y} \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done + +# Ensure that fds 0, 1, and 2 are open. +if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi +if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then +if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || @@ -81,13 +82,6 @@ if test "${PATH_SEPARATOR+set}" != set; then fi -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( @@ -96,8 +90,12 @@ case $0 in #(( for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS @@ -109,40 +107,47 @@ if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then - as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + as_bourne_compatible="as_nop=: +if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 +then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST -else +else \$as_nop case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( @@ -162,12 +167,16 @@ as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } -if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : +if ( set x; as_fn_ret_success y && test x = \"\$1\" ) +then : -else +else \$as_nop exitcode=1; echo positional parameters were not saved. fi -test x\$exitcode = x0 || exit 1" +test x\$exitcode = x0 || exit 1 +blah=\$(echo \$(echo blah)) +test x\"\$blah\" = xblah || exit 1 +test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && @@ -181,30 +190,38 @@ test x\$exitcode = x0 || exit 1" test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" - if (eval "$as_required") 2>/dev/null; then : + if (eval "$as_required") 2>/dev/null +then : as_have_required=yes -else +else $as_nop as_have_required=no fi - if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null +then : -else +else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. - as_shell=$as_dir/$as_base + as_shell=$as_dir$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null +then : CONFIG_SHELL=$as_shell as_have_required=yes - if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null +then : break 2 fi fi @@ -212,39 +229,51 @@ fi esac as_found=false done -$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : - CONFIG_SHELL=$SHELL as_have_required=yes -fi; } IFS=$as_save_IFS +if $as_found +then : - - if test "x$CONFIG_SHELL" != x; then : - # We cannot yet assume a decent shell, so we have to provide a - # neutralization value for shells without unset; and this also - # works around shells that cannot unset nonexistent variables. - # Preserve -v and -x to the replacement shell. - BASH_ENV=/dev/null - ENV=/dev/null - (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV - export CONFIG_SHELL - case $- in # (((( - *v*x* | *x*v* ) as_opts=-vx ;; - *v* ) as_opts=-v ;; - *x* ) as_opts=-x ;; - * ) as_opts= ;; - esac - exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} +else $as_nop + if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null +then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi fi - if test x$as_have_required = xno; then : - $as_echo "$0: This script requires a shell more modern than all" - $as_echo "$0: the shells that I found on your system." - if test x${ZSH_VERSION+set} = xset ; then - $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" - $as_echo "$0: be upgraded to zsh 4.3.4 or later." + + if test "x$CONFIG_SHELL" != x +then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno +then : + printf "%s\n" "$0: This script requires a shell more modern than all" + printf "%s\n" "$0: the shells that I found on your system." + if test ${ZSH_VERSION+y} ; then + printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" + printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." else - $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, + printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." @@ -271,6 +300,7 @@ as_fn_unset () } as_unset=as_fn_unset + # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. @@ -288,6 +318,14 @@ as_fn_exit () as_fn_set_status $1 exit $1 } # as_fn_exit +# as_fn_nop +# --------- +# Do nothing but, unlike ":", preserve the value of $?. +as_fn_nop () +{ + return $? +} +as_nop=as_fn_nop # as_fn_mkdir_p # ------------- @@ -302,7 +340,7 @@ as_fn_mkdir_p () as_dirs= while :; do case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" @@ -311,7 +349,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | +printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -336,18 +374,27 @@ $as_echo X"$as_dir" | } # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null +then : eval 'as_fn_append () { eval $1+=\$2 }' -else +else $as_nop as_fn_append () { eval $1=\$$1\$2 @@ -359,18 +406,27 @@ fi # as_fn_append # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null +then : eval 'as_fn_arith () { as_val=$(( $* )) }' -else +else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith +# as_fn_nop +# --------- +# Do nothing but, unlike ":", preserve the value of $?. +as_fn_nop () +{ + return $? +} +as_nop=as_fn_nop # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- @@ -382,9 +438,9 @@ as_fn_error () as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi - $as_echo "$as_me: error: $2" >&2 + printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error @@ -411,7 +467,7 @@ as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | +printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q @@ -455,8 +511,12 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || - { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). @@ -465,6 +525,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits exit } + +# Determine whether it's possible to make 'echo' print without a newline. +# These variables are no longer used directly by Autoconf, but are AC_SUBSTed +# for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) @@ -478,6 +542,13 @@ case `echo -n x` in #((((( ECHO_N='-n';; esac +# For backward compatibility with old third-party macros, we provide +# the shell variables $as_echo and $as_echo_n. New code should use +# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. +as_echo='printf %s\n' +as_echo_n='printf %s' + + rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file @@ -491,16 +562,16 @@ if (echo >conf$$.file) 2>/dev/null; then # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. + # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' + as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null @@ -512,28 +583,8 @@ else as_mkdir_p=false fi -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in #( - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x +as_test_x='test -x' +as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" @@ -567,62 +618,62 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='libnl' PACKAGE_TARNAME='libnl' -PACKAGE_VERSION='3.2.22' -PACKAGE_STRING='libnl 3.2.22' +PACKAGE_VERSION='3.9.0' +PACKAGE_STRING='libnl 3.9.0' PACKAGE_BUGREPORT='' PACKAGE_URL='http://www.infradead.org/~tgr/libnl/' # Factoring default headers for most tests. ac_includes_default="\ -#include -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_STAT_H -# include +#include +#ifdef HAVE_STDIO_H +# include #endif -#ifdef STDC_HEADERS +#ifdef HAVE_STDLIB_H # include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif #endif #ifdef HAVE_STRING_H -# if !defined STDC_HEADERS && defined HAVE_MEMORY_H -# include -# endif # include #endif -#ifdef HAVE_STRINGS_H -# include -#endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif #ifdef HAVE_UNISTD_H # include #endif" +ac_header_c_list= enable_option_checking=no ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS subdirs -ENABLE_DEBUG_FALSE -ENABLE_DEBUG_TRUE +ENABLE_STATIC_FALSE +ENABLE_STATIC_TRUE DISABLE_PTHREADS_FALSE DISABLE_PTHREADS_TRUE +ENABLE_CLI_INSTALL_SBIN_FALSE +ENABLE_CLI_INSTALL_SBIN_TRUE +ENABLE_CLI_INSTALL_BIN_FALSE +ENABLE_CLI_INSTALL_BIN_TRUE ENABLE_CLI_FALSE ENABLE_CLI_TRUE pkgconfigdir -ENABLE_UNIT_TESTS_FALSE -ENABLE_UNIT_TESTS_TRUE +WITH_CHECK_FALSE +WITH_CHECK_TRUE CHECK_LIBS CHECK_CFLAGS PKG_CONFIG_LIBDIR @@ -630,7 +681,7 @@ PKG_CONFIG_PATH PKG_CONFIG YACC FLEX -CPP +LT_SYS_LIBRARY_PATH OTOOL64 OTOOL LIPO @@ -640,6 +691,7 @@ MANIFEST_TOOL RANLIB DLLTOOL OBJDUMP +FILECMD LN_S NM ac_ct_DUMPBIN @@ -672,7 +724,6 @@ am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE -am__quote am__include DEPDIR OBJEXT @@ -688,6 +739,9 @@ AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V +CSCOPE +ETAGS +CTAGS am__untar am__tar AMTAR @@ -730,6 +784,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -748,7 +803,8 @@ PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR -SHELL' +SHELL +am__quote' ac_subst_files='' ac_user_opts=' enable_option_checking @@ -758,6 +814,7 @@ enable_shared enable_static with_pic enable_fast_install +with_aix_soname with_gnu_ld with_sysroot enable_libtool_lock @@ -774,7 +831,7 @@ CFLAGS LDFLAGS LIBS CPPFLAGS -CPP +LT_SYS_LIBRARY_PATH PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR @@ -818,6 +875,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -847,8 +905,6 @@ do *) ac_optarg=yes ;; esac - # Accept the important Cygnus configure options, so we can diagnose typos. - case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; @@ -889,9 +945,9 @@ do ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" + as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" @@ -915,9 +971,9 @@ do ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" + as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" @@ -1070,6 +1126,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1119,9 +1184,9 @@ do ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" + as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" @@ -1135,9 +1200,9 @@ do ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" + as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" @@ -1181,9 +1246,9 @@ Try \`$0 --help' for more information" *) # FIXME: should be removed in autoconf 3.0. - $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; @@ -1199,7 +1264,7 @@ if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; - *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi @@ -1207,7 +1272,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1235,8 +1300,6 @@ target=$target_alias if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe - $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used" >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi @@ -1265,7 +1328,7 @@ $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_myself" | +printf "%s\n" X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -1322,7 +1385,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures libnl 3.2.22 to adapt to many kinds of systems. +\`configure' configures libnl 3.9.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1362,6 +1425,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -1392,7 +1456,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of libnl 3.2.22:";; + short | recursive ) echo "Configuration of libnl 3.9.0:";; esac cat <<\_ACEOF @@ -1400,16 +1464,22 @@ Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --enable-silent-rules less verbose build output (undo: `make V=1') - --disable-silent-rules verbose build output (undo: `make V=0') - --disable-dependency-tracking speeds up one-time build - --enable-dependency-tracking do not reject slow dependency extractors + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) - --disable-cli Do not build command line interface utils + --enable-cli=yes|no|no-inst|bin|sbin + Whether to build command line interface utils. + Defaults to 'yes' which is a synonym for 'bin'. + 'no-inst' means only build, not installing. + 'bin'/'sbin' means installing to bin/sbin directory --disable-pthreads Disable pthreads support --disable-debug Do not include debugging statements @@ -1418,9 +1488,12 @@ Optional Packages: --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] + --with-aix-soname=aix|svr4|both + shared library versioning (aka "SONAME") variant to + provide on AIX, [default=aix]. --with-gnu-ld assume the C compiler uses GNU ld [default=no] - --with-sysroot=DIR Search for dependent libraries within DIR - (or the compiler's sysroot if not specified). + --with-sysroot[=DIR] Search for dependent libraries within DIR (or the + compiler's sysroot if not specified). --with-pkgconfigdir=PATH Path to the pkgconfig directory [[LIBDIR/pkgconfig]] @@ -1432,7 +1505,8 @@ Some influential environment variables: LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory - CPP C preprocessor + LT_SYS_LIBRARY_PATH + User-defined run-time library search path. PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path @@ -1462,9 +1536,9 @@ if test "$ac_init_help" = "recursive"; then case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; @@ -1492,7 +1566,8 @@ esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } - # Check for guested configure. + # Check for configure.gnu first; this name is used for a wrapper for + # Metaconfig's "Configure" on case-insensitive file systems. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive @@ -1500,7 +1575,7 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix echo && $SHELL "$ac_srcdir/configure" --help=recursive else - $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done @@ -1509,10 +1584,10 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -libnl configure 3.2.22 -generated by GNU Autoconf 2.68 +libnl configure 3.9.0 +generated by GNU Autoconf 2.71 -Copyright (C) 2010 Free Software Foundation, Inc. +Copyright (C) 2021 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF @@ -1529,14 +1604,14 @@ fi ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext + rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then @@ -1544,14 +1619,15 @@ $as_echo "$ac_try_echo"; } >&5 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err - } && test -s conftest.$ac_objext; then : + } && test -s conftest.$ac_objext +then : ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 @@ -1567,14 +1643,14 @@ fi ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext conftest$ac_exeext + rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then @@ -1582,17 +1658,18 @@ $as_echo "$ac_try_echo"; } >&5 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then : + test -x conftest$ac_exeext + } +then : ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 @@ -1614,120 +1691,44 @@ fi ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +printf %s "checking for $2... " >&6; } +if eval test \${$3+y} +then : + printf %s "(cached) " >&6 +else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO" +then : eval "$3=yes" -else +else $as_nop eval "$3=no" fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile -# ac_fn_c_try_cpp LINENO -# ---------------------- -# Try to preprocess conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_cpp () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } > conftest.i && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_cpp - -# ac_fn_c_try_run LINENO -# ---------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes -# that executables *can* be run. -ac_fn_c_try_run () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then : - ac_retval=0 -else - $as_echo "$as_me: program exited with status $ac_status" >&5 - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=$ac_status -fi - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_run - # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +printf %s "checking for $2... " >&6; } +if eval test \${$3+y} +then : + printf %s "(cached) " >&6 +else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. @@ -1735,16 +1736,9 @@ else #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $2 (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif + which can conflict with char $2 (); below. */ +#include #undef $2 /* Override any GCC internal prototype to avoid an error. @@ -1762,35 +1756,108 @@ choke me #endif int -main () +main (void) { return $2 (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +if ac_fn_c_try_link "$LINENO" +then : eval "$3=yes" -else +else $as_nop eval "$3=no" fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func + +# ac_fn_check_decl LINENO SYMBOL VAR INCLUDES EXTRA-OPTIONS FLAG-VAR +# ------------------------------------------------------------------ +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. Pass EXTRA-OPTIONS to the compiler, using FLAG-VAR. +ac_fn_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +printf %s "checking whether $as_decl_name is declared... " >&6; } +if eval test \${$3+y} +then : + printf %s "(cached) " >&6 +else $as_nop + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + eval ac_save_FLAGS=\$$6 + as_fn_append $6 " $5" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main (void) +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + eval "$3=yes" +else $as_nop + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + eval $6=\$ac_save_FLAGS + +fi +eval ac_res=\$$3 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_check_decl +ac_configure_args_raw= +for ac_arg +do + case $ac_arg in + *\'*) + ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append ac_configure_args_raw " '$ac_arg'" +done + +case $ac_configure_args_raw in + *$as_nl*) + ac_safe_unquote= ;; + *) + ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab. + ac_unsafe_a="$ac_unsafe_z#~" + ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g" + ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;; +esac + cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by libnl $as_me 3.2.22, which was -generated by GNU Autoconf 2.68. Invocation command line was +It was created by libnl $as_me 3.9.0, which was +generated by GNU Autoconf 2.71. Invocation command line was - $ $0 $@ + $ $0$ac_configure_args_raw _ACEOF exec 5>>config.log @@ -1823,8 +1890,12 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - $as_echo "PATH: $as_dir" + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + printf "%s\n" "PATH: $as_dir" done IFS=$as_save_IFS @@ -1859,7 +1930,7 @@ do | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) - ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; @@ -1894,11 +1965,13 @@ done # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? + # Sanitize IFS. + IFS=" "" $as_nl" # Save into config.log some information that might help in debugging. { echo - $as_echo "## ---------------- ## + printf "%s\n" "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo @@ -1909,8 +1982,8 @@ trap 'exit_status=$? case $ac_val in #( *${as_nl}*) case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( @@ -1934,7 +2007,7 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; ) echo - $as_echo "## ----------------- ## + printf "%s\n" "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo @@ -1942,14 +2015,14 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; do eval ac_val=\$$ac_var case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac - $as_echo "$ac_var='\''$ac_val'\''" + printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then - $as_echo "## ------------------- ## + printf "%s\n" "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo @@ -1957,15 +2030,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; do eval ac_val=\$$ac_var case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac - $as_echo "$ac_var='\''$ac_val'\''" + printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then - $as_echo "## ----------- ## + printf "%s\n" "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo @@ -1973,8 +2046,8 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; echo fi test "$ac_signal" != 0 && - $as_echo "$as_me: caught signal $ac_signal" - $as_echo "$as_me: exit $exit_status" + printf "%s\n" "$as_me: caught signal $ac_signal" + printf "%s\n" "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && @@ -1988,63 +2061,48 @@ ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h -$as_echo "/* confdefs.h */" > confdefs.h +printf "%s\n" "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF +printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF +printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF +printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF +printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF +printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h -cat >>confdefs.h <<_ACEOF -#define PACKAGE_URL "$PACKAGE_URL" -_ACEOF +printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. -ac_site_file1=NONE -ac_site_file2=NONE if test -n "$CONFIG_SITE"; then - # We do not want a PATH search for config.site. - case $CONFIG_SITE in #(( - -*) ac_site_file1=./$CONFIG_SITE;; - */*) ac_site_file1=$CONFIG_SITE;; - *) ac_site_file1=./$CONFIG_SITE;; - esac + ac_site_files="$CONFIG_SITE" elif test "x$prefix" != xNONE; then - ac_site_file1=$prefix/share/config.site - ac_site_file2=$prefix/etc/config.site + ac_site_files="$prefix/share/config.site $prefix/etc/config.site" else - ac_site_file1=$ac_default_prefix/share/config.site - ac_site_file2=$ac_default_prefix/etc/config.site + ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi -for ac_site_file in "$ac_site_file1" "$ac_site_file2" + +for ac_site_file in $ac_site_files do - test "x$ac_site_file" = xNONE && continue - if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 -$as_echo "$as_me: loading site script $ac_site_file" >&6;} + case $ac_site_file in #( + */*) : + ;; #( + *) : + ac_site_file=./$ac_site_file ;; +esac + if test -f "$ac_site_file" && test -r "$ac_site_file"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ - || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi @@ -2054,122 +2112,512 @@ if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 -$as_echo "$as_me: loading cache $cache_file" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +printf "%s\n" "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else - { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 -$as_echo "$as_me: creating cache $cache_file" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +printf "%s\n" "$as_me: creating cache $cache_file" >&6;} >$cache_file fi -# Check that the precious variables saved in the cache have kept the same -# value. -ac_cache_corrupted=false -for ac_var in $ac_precious_vars; do - eval ac_old_set=\$ac_cv_env_${ac_var}_set - eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val=\$ac_cv_env_${ac_var}_value - eval ac_new_val=\$ac_env_${ac_var}_value - case $ac_old_set,$ac_new_set in - set,) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,);; - *) - if test "x$ac_old_val" != "x$ac_new_val"; then - # differences in whitespace do not lead to failure. - ac_old_val_w=`echo x $ac_old_val` - ac_new_val_w=`echo x $ac_new_val` - if test "$ac_old_val_w" != "$ac_new_val_w"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 -$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - ac_cache_corrupted=: - else - { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 -$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} - eval $ac_var=\$ac_old_val - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 -$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 -$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} - fi;; - esac - # Pass precious variables to config.status. - if test "$ac_new_set" = set; then - case $ac_new_val in - *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; - *) ac_arg=$ac_var=$ac_new_val ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) as_fn_append ac_configure_args " '$ac_arg'" ;; - esac - fi -done -if $ac_cache_corrupted; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 -$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 -fi -## -------------------- ## -## Main body of script. ## -## -------------------- ## - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -ac_config_headers="$ac_config_headers lib/defs.h" - -ac_aux_dir= -for ac_dir in build-aux "$srcdir"/build-aux; do - if test -f "$ac_dir/install-sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f "$ac_dir/install.sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f "$ac_dir/shtool"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi -done -if test -z "$ac_aux_dir"; then - as_fn_error $? "cannot find install-sh, install.sh, or shtool in build-aux \"$srcdir\"/build-aux" "$LINENO" 5 -fi +# Test code for whether the C compiler supports C89 (global declarations) +ac_c_conftest_c89_globals=' +/* Does the compiler advertise C89 conformance? + Do not test the value of __STDC__, because some compilers set it to 0 + while being otherwise adequately conformant. */ +#if !defined __STDC__ +# error "Compiler does not advertise C89 conformance" +#endif -# These three variables are undocumented and unsupported, -# and are intended to be withdrawn in a future Autoconf release. -# They can cause serious problems if a builder's source tree is in a directory -# whose full name contains unusual characters. -ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. -ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. -ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ +struct buf { int x; }; +struct buf * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not \xHH hex character constants. + These do not provoke an error unfortunately, instead are silently treated + as an "x". The following induces an error, until -std is added to get + proper ANSI mode. Curiously \x00 != x always comes out true, for an + array size at least. It is necessary to write \x00 == 0 to get something + that is true only with -std. */ +int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) '\''x'\'' +int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int), + int, int);' + +# Test code for whether the C compiler supports C89 (body of main). +ac_c_conftest_c89_main=' +ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); +' + +# Test code for whether the C compiler supports C99 (global declarations) +ac_c_conftest_c99_globals=' +// Does the compiler advertise C99 conformance? +#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L +# error "Compiler does not advertise C99 conformance" +#endif + +#include +extern int puts (const char *); +extern int printf (const char *, ...); +extern int dprintf (int, const char *, ...); +extern void *malloc (size_t); + +// Check varargs macros. These examples are taken from C99 6.10.3.5. +// dprintf is used instead of fprintf to avoid needing to declare +// FILE and stderr. +#define debug(...) dprintf (2, __VA_ARGS__) +#define showlist(...) puts (#__VA_ARGS__) +#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +static void +test_varargs_macros (void) +{ + int x = 1234; + int y = 5678; + debug ("Flag"); + debug ("X = %d\n", x); + showlist (The first, second, and third items.); + report (x>y, "x is %d but y is %d", x, y); +} + +// Check long long types. +#define BIG64 18446744073709551615ull +#define BIG32 4294967295ul +#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +#if !BIG_OK + #error "your preprocessor is broken" +#endif +#if BIG_OK +#else + #error "your preprocessor is broken" +#endif +static long long int bignum = -9223372036854775807LL; +static unsigned long long int ubignum = BIG64; + +struct incomplete_array +{ + int datasize; + double data[]; +}; + +struct named_init { + int number; + const wchar_t *name; + double average; +}; +typedef const char *ccp; +static inline int +test_restrict (ccp restrict text) +{ + // See if C++-style comments work. + // Iterate through items via the restricted pointer. + // Also check for declarations in for loops. + for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) + continue; + return 0; +} -am__api_version='1.11' +// Check varargs and va_copy. +static bool +test_varargs (const char *format, ...) +{ + va_list args; + va_start (args, format); + va_list args_copy; + va_copy (args_copy, args); + + const char *str = ""; + int number = 0; + float fnumber = 0; -# Find a good install program. We prefer a C program (faster), + while (*format) + { + switch (*format++) + { + case '\''s'\'': // string + str = va_arg (args_copy, const char *); + break; + case '\''d'\'': // int + number = va_arg (args_copy, int); + break; + case '\''f'\'': // float + fnumber = va_arg (args_copy, double); + break; + default: + break; + } + } + va_end (args_copy); + va_end (args); + + return *str && number && fnumber; +} +' + +# Test code for whether the C compiler supports C99 (body of main). +ac_c_conftest_c99_main=' + // Check bool. + _Bool success = false; + success |= (argc != 0); + + // Check restrict. + if (test_restrict ("String literal") == 0) + success = true; + char *restrict newvar = "Another string"; + + // Check varargs. + success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); + test_varargs_macros (); + + // Check flexible array members. + struct incomplete_array *ia = + malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = i * 1.234; + + // Check named initializers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; + + ni.number = 58; + + int dynamic_array[ni.number]; + dynamic_array[0] = argv[0][0]; + dynamic_array[ni.number - 1] = 543; + + // work around unused variable warnings + ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' + || dynamic_array[ni.number - 1] != 543); +' + +# Test code for whether the C compiler supports C11 (global declarations) +ac_c_conftest_c11_globals=' +// Does the compiler advertise C11 conformance? +#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L +# error "Compiler does not advertise C11 conformance" +#endif + +// Check _Alignas. +char _Alignas (double) aligned_as_double; +char _Alignas (0) no_special_alignment; +extern char aligned_as_int; +char _Alignas (0) _Alignas (int) aligned_as_int; + +// Check _Alignof. +enum +{ + int_alignment = _Alignof (int), + int_array_alignment = _Alignof (int[100]), + char_alignment = _Alignof (char) +}; +_Static_assert (0 < -_Alignof (int), "_Alignof is signed"); + +// Check _Noreturn. +int _Noreturn does_not_return (void) { for (;;) continue; } + +// Check _Static_assert. +struct test_static_assert +{ + int x; + _Static_assert (sizeof (int) <= sizeof (long int), + "_Static_assert does not work in struct"); + long int y; +}; + +// Check UTF-8 literals. +#define u8 syntax error! +char const utf8_literal[] = u8"happens to be ASCII" "another string"; + +// Check duplicate typedefs. +typedef long *long_ptr; +typedef long int *long_ptr; +typedef long_ptr long_ptr; + +// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. +struct anonymous +{ + union { + struct { int i; int j; }; + struct { int k; long int l; } w; + }; + int m; +} v1; +' + +# Test code for whether the C compiler supports C11 (body of main). +ac_c_conftest_c11_main=' + _Static_assert ((offsetof (struct anonymous, i) + == offsetof (struct anonymous, w.k)), + "Anonymous union alignment botch"); + v1.i = 2; + v1.w.k = 5; + ok |= v1.i != 5; +' + +# Test code for whether the C compiler supports C11 (complete). +ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} +${ac_c_conftest_c99_globals} +${ac_c_conftest_c11_globals} + +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_c_conftest_c89_main} + ${ac_c_conftest_c99_main} + ${ac_c_conftest_c11_main} + return ok; +} +" + +# Test code for whether the C compiler supports C99 (complete). +ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} +${ac_c_conftest_c99_globals} + +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_c_conftest_c89_main} + ${ac_c_conftest_c99_main} + return ok; +} +" + +# Test code for whether the C compiler supports C89 (complete). +ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} + +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_c_conftest_c89_main} + return ok; +} +" + +as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H" +as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H" +as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H" +as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H" +as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H" +as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H" +as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H" +as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" +as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" + +# Auxiliary files required by this configure script. +ac_aux_files="config.guess config.sub ltmain.sh compile ar-lib missing install-sh" + +# Locations in which to look for auxiliary files. +ac_aux_dir_candidates="${srcdir}/build-aux" + +# Search for a directory containing all of the required auxiliary files, +# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates. +# If we don't find one directory that contains all the files we need, +# we report the set of missing files from the *first* directory in +# $ac_aux_dir_candidates and give up. +ac_missing_aux_files="" +ac_first_candidate=: +printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5 +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in $ac_aux_dir_candidates +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + as_found=: + + printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5 + ac_aux_dir_found=yes + ac_install_sh= + for ac_aux in $ac_aux_files + do + # As a special case, if "install-sh" is required, that requirement + # can be satisfied by any of "install-sh", "install.sh", or "shtool", + # and $ac_install_sh is set appropriately for whichever one is found. + if test x"$ac_aux" = x"install-sh" + then + if test -f "${as_dir}install-sh"; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5 + ac_install_sh="${as_dir}install-sh -c" + elif test -f "${as_dir}install.sh"; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5 + ac_install_sh="${as_dir}install.sh -c" + elif test -f "${as_dir}shtool"; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5 + ac_install_sh="${as_dir}shtool install -c" + else + ac_aux_dir_found=no + if $ac_first_candidate; then + ac_missing_aux_files="${ac_missing_aux_files} install-sh" + else + break + fi + fi + else + if test -f "${as_dir}${ac_aux}"; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5 + else + ac_aux_dir_found=no + if $ac_first_candidate; then + ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}" + else + break + fi + fi + fi + done + if test "$ac_aux_dir_found" = yes; then + ac_aux_dir="$as_dir" + break + fi + ac_first_candidate=false + + as_found=false +done +IFS=$as_save_IFS +if $as_found +then : + +else $as_nop + as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 +fi + + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +if test -f "${ac_aux_dir}config.guess"; then + ac_config_guess="$SHELL ${ac_aux_dir}config.guess" +fi +if test -f "${ac_aux_dir}config.sub"; then + ac_config_sub="$SHELL ${ac_aux_dir}config.sub" +fi +if test -f "$ac_aux_dir/configure"; then + ac_configure="$SHELL ${ac_aux_dir}configure" +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file' + and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_config_headers="$ac_config_headers include/config.h" + + + +am__api_version='1.16' + + + + # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install @@ -2183,20 +2631,25 @@ am__api_version='1.11' # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 -$as_echo_n "checking for a BSD-compatible install... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +printf %s "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then -if ${ac_cv_path_install+:} false; then : - $as_echo_n "(cached) " >&6 -else +if test ${ac_cv_path_install+y} +then : + printf %s "(cached) " >&6 +else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in #(( - ./ | .// | /[cC]/* | \ + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + # Account for fact that we put trailing slashes in our PATH walk. +case $as_dir in #(( + ./ | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; @@ -2206,13 +2659,13 @@ case $as_dir/ in #(( # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else @@ -2220,12 +2673,12 @@ case $as_dir/ in #(( echo one > conftest.one echo two > conftest.two mkdir conftest.dir - if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c" break 3 fi fi @@ -2241,7 +2694,7 @@ IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi - if test "${ac_cv_path_install+set}" = set; then + if test ${ac_cv_path_install+y}; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a @@ -2251,8 +2704,8 @@ fi INSTALL=$ac_install_sh fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 -$as_echo "$INSTALL" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +printf "%s\n" "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. @@ -2262,11 +2715,8 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 -$as_echo_n "checking whether build environment is sane... " >&6; } -# Just in case -sleep 1 -echo timestamp > conftest.file +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +printf %s "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' @@ -2277,32 +2727,40 @@ case `pwd` in esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) - as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac -# Do `set' in a subshell so we don't clobber the current shell's +# Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( - set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` - if test "$*" = "X"; then - # -L didn't work. - set X `ls -t "$srcdir/configure" conftest.file` - fi - rm -f conftest.file - if test "$*" != "X $srcdir/configure conftest.file" \ - && test "$*" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - as_fn_error $? "ls -t appears to fail. Make sure there is not a broken -alias in your environment" "$LINENO" 5 - fi - + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done test "$2" = conftest.file ) then @@ -2312,8 +2770,18 @@ else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. @@ -2322,29 +2790,26 @@ test "$program_suffix" != NONE && # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' -program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` +program_transform_name=`printf "%s\n" "$program_transform_name" | sed "$ac_script"` -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` -if test x"${MISSING+set}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; - *) - MISSING="\${SHELL} $am_aux_dir/missing" ;; - esac +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + + + if test x"${MISSING+set}" != xset; then + MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL -if eval "$MISSING --run true"; then - am_missing_run="$MISSING --run " +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " else am_missing_run= - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 -$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +printf "%s\n" "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi -if test x"${install_sh}" != xset; then +if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; @@ -2353,19 +2818,20 @@ if test x"${install_sh}" != xset; then esac fi -# Installed binaries are usually stripped using `strip' when the user -# run `make install-strip'. However `strip' might not be the right +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake -# will honor the `STRIP' environment variable to overrule this program. +# will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_STRIP+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else @@ -2373,11 +2839,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -2388,11 +2858,11 @@ fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +printf "%s\n" "$STRIP" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -2401,11 +2871,12 @@ if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_STRIP+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else @@ -2413,11 +2884,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -2428,11 +2903,11 @@ fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 -$as_echo "$ac_ct_STRIP" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +printf "%s\n" "$ac_ct_STRIP" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then @@ -2440,8 +2915,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP @@ -2453,25 +2928,31 @@ fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 -$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a race-free mkdir -p" >&5 +printf %s "checking for a race-free mkdir -p... " >&6; } if test -z "$MKDIR_P"; then - if ${ac_cv_path_mkdir+:} false; then : - $as_echo_n "(cached) " >&6 -else + if test ${ac_cv_path_mkdir+y} +then : + printf %s "(cached) " >&6 +else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do - { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue - case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( - 'mkdir (GNU coreutils) '* | \ - 'mkdir (coreutils) '* | \ + as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext" || continue + case `"$as_dir$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir ('*'coreutils) '* | \ + 'BusyBox '* | \ 'mkdir (fileutils) '4.1*) - ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + ac_cv_path_mkdir=$as_dir$ac_prog$ac_exec_ext break 3;; esac done @@ -2482,7 +2963,7 @@ IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version - if test "${ac_cv_path_mkdir+set}" = set; then + if test ${ac_cv_path_mkdir+y}; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a @@ -2492,24 +2973,19 @@ fi MKDIR_P="$ac_install_sh -d" fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 -$as_echo "$MKDIR_P" >&6; } - -mkdir_p="$MKDIR_P" -case $mkdir_p in - [\\/$]* | ?:[\\/]*) ;; - */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; -esac +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +printf "%s\n" "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AWK+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_AWK+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else @@ -2517,11 +2993,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -2532,24 +3012,25 @@ fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 -$as_echo "$AWK" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +printf "%s\n" "$AWK" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi test -n "$AWK" && break done -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 -$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} -ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` -if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : - $as_echo_n "(cached) " >&6 -else +ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval test \${ac_cv_prog_make_${ac_make}_set+y} +then : + printf %s "(cached) " >&6 +else $as_nop cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @@ -2565,12 +3046,12 @@ esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } SET_MAKE= else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi @@ -2583,6 +3064,47 @@ else fi rmdir .tst 2>/dev/null +# Check whether --enable-silent-rules was given. +if test ${enable_silent_rules+y} +then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +printf %s "checking whether $am_make supports nested variables... " >&6; } +if test ${am_cv_make_support_nested_variables+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if printf "%s\n" 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +printf "%s\n" "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." @@ -2605,17 +3127,13 @@ fi # Define the identity of the package. PACKAGE='libnl' - VERSION='3.2.22' + VERSION='3.9.0' -cat >>confdefs.h <<_ACEOF -#define PACKAGE "$PACKAGE" -_ACEOF +printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h -cat >>confdefs.h <<_ACEOF -#define VERSION "$VERSION" -_ACEOF +printf "%s\n" "#define VERSION \"$VERSION\"" >>confdefs.h # Some tools Automake needs. @@ -2633,35 +3151,104 @@ AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar pax cpio none' + am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' +# Variables for tags utilities; see am/tags.am +if test -z "$CTAGS"; then + CTAGS=ctags +fi + +if test -z "$ETAGS"; then + ETAGS=etags +fi + +if test -z "$CSCOPE"; then + CSCOPE=cscope +fi + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + # Check whether --enable-silent-rules was given. -if test "${enable_silent_rules+set}" = set; then : +if test ${enable_silent_rules+y} +then : enableval=$enable_silent_rules; fi -case $enable_silent_rules in -yes) AM_DEFAULT_VERBOSITY=0;; -no) AM_DEFAULT_VERBOSITY=1;; -*) AM_DEFAULT_VERBOSITY=0;; +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=0;; esac am_make=${MAKE-make} -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 -$as_echo_n "checking whether $am_make supports nested variables... " >&6; } -if ${am_cv_make_support_nested_variables+:} false; then : - $as_echo_n "(cached) " >&6 -else - if $as_echo 'TRUE=$(BAR$(V)) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +printf %s "checking whether $am_make supports nested variables... " >&6; } +if test ${am_cv_make_support_nested_variables+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if printf "%s\n" 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 @@ -2673,8 +3260,8 @@ else am_cv_make_support_nested_variables=no fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 -$as_echo "$am_cv_make_support_nested_variables" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +printf "%s\n" "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' @@ -2684,52 +3271,62 @@ else fi AM_BACKSLASH='\' + + + + + + + + + DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" - -am_make=${MAKE-make} -cat > confinc << 'END' +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 +printf %s "checking whether ${MAKE-make} supports the include directive... " >&6; } +cat > confinc.mk << 'END' am__doit: - @echo this is the am__doit target + @echo this is the am__doit target >confinc.out .PHONY: am__doit END -# If we don't find an include directive, just comment out the code. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 -$as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from `make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 + (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + case $?:`cat confinc.out 2>/dev/null` in #( + '0:this is the am__doit target') : + case $s in #( + BSD) : + am__include='.include' am__quote='"' ;; #( + *) : + am__include='include' am__quote='' ;; +esac ;; #( + *) : ;; - esac -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 -$as_echo "$_am_result" >&6; } -rm -f confinc confmf +esac + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 +printf "%s\n" "${_am_result}" >&6; } # Check whether --enable-dependency-tracking was given. -if test "${enable_dependency_tracking+set}" = set; then : +if test ${enable_dependency_tracking+y} +then : enableval=$enable_dependency_tracking; fi @@ -2755,11 +3352,12 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else @@ -2767,11 +3365,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -2782,11 +3384,11 @@ fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -2795,11 +3397,12 @@ if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else @@ -2807,11 +3410,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -2822,11 +3429,11 @@ fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +printf "%s\n" "$ac_ct_CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then @@ -2834,8 +3441,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC @@ -2848,11 +3455,12 @@ if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else @@ -2860,11 +3468,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -2875,11 +3487,11 @@ fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -2888,11 +3500,12 @@ fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else @@ -2901,15 +3514,19 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -2925,33 +3542,144 @@ if test $ac_prog_rejected = yes; then # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +printf "%s\n" "$ac_ct_CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC fi fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then - for ac_prog in cl.exe - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else + # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. +set dummy ${ac_tool_prefix}clang; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else @@ -2959,11 +3687,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}clang" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -2974,28 +3706,25 @@ fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi - test -n "$CC" && break - done fi -if test -z "$CC"; then +if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC - for ac_prog in cl.exe -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else + # Extract the first word of "clang", so it can be a program name with args. +set dummy clang; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else @@ -3003,11 +3732,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="clang" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -3018,50 +3751,48 @@ fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +printf "%s\n" "$ac_ct_CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi - - test -n "$ac_ct_CC" && break -done - if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi +else + CC="$ac_cv_prog_CC" fi fi -test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 -for ac_option in --version -v -V -qversion; do +for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then @@ -3071,7 +3802,7 @@ $as_echo "$ac_try_echo"; } >&5 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done @@ -3079,7 +3810,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { ; @@ -3091,9 +3822,9 @@ ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 -$as_echo_n "checking whether the C compiler works... " >&6; } -ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +printf %s "checking whether the C compiler works... " >&6; } +ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" @@ -3114,11 +3845,12 @@ case "(($ac_try" in *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, @@ -3135,7 +3867,7 @@ do # certainly right. break;; *.* ) - if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi @@ -3151,44 +3883,46 @@ do done test "$ac_cv_exeext" = no && ac_cv_exeext= -else +else $as_nop ac_file='' fi -if test -z "$ac_file"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -$as_echo "$as_me: failed program was:" >&5 +if test -z "$ac_file" +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 -$as_echo_n "checking for C compiler default output file name... " >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 -$as_echo "$ac_file" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +printf %s "checking for C compiler default output file name... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +printf "%s\n" "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 -$as_echo_n "checking for suffix of executables... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +printf %s "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with @@ -3202,15 +3936,15 @@ for ac_file in conftest.exe conftest conftest.*; do * ) break;; esac done -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +else $as_nop + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 -$as_echo "$ac_cv_exeext" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +printf "%s\n" "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext @@ -3219,7 +3953,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main () +main (void) { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; @@ -3231,8 +3965,8 @@ _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 -$as_echo_n "checking whether we are cross compiling... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +printf %s "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in @@ -3240,10 +3974,10 @@ case "(($ac_try" in *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in @@ -3251,39 +3985,40 @@ $as_echo "$ac_try_echo"; } >&5 *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot run C compiled programs. + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 -$as_echo "$cross_compiling" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +printf "%s\n" "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 -$as_echo_n "checking for suffix of object files... " >&6; } -if ${ac_cv_objext+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +printf %s "checking for suffix of object files... " >&6; } +if test ${ac_cv_objext+y} +then : + printf %s "(cached) " >&6 +else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { ; @@ -3297,11 +4032,12 @@ case "(($ac_try" in *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in @@ -3310,31 +4046,32 @@ $as_echo "$ac_try_echo"; } >&5 break;; esac done -else - $as_echo "$as_me: failed program was:" >&5 +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 -$as_echo "$ac_cv_objext" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +printf "%s\n" "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 -$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if ${ac_cv_c_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 +printf %s "checking whether the compiler supports GNU C... " >&6; } +if test ${ac_cv_c_compiler_gnu+y} +then : + printf %s "(cached) " >&6 +else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { #ifndef __GNUC__ choke me @@ -3344,29 +4081,33 @@ main () return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO" +then : ac_compiler_gnu=yes -else +else $as_nop ac_compiler_gnu=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -$as_echo "$ac_cv_c_compiler_gnu" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } +ac_compiler_gnu=$ac_cv_c_compiler_gnu + if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi -ac_test_CFLAGS=${CFLAGS+set} +ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -$as_echo_n "checking whether $CC accepts -g... " >&6; } -if ${ac_cv_prog_cc_g+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +printf %s "checking whether $CC accepts -g... " >&6; } +if test ${ac_cv_prog_cc_g+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no @@ -3375,57 +4116,60 @@ else /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO" +then : ac_cv_prog_cc_g=yes -else +else $as_nop CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO" +then : -else +else $as_nop ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO" +then : ac_cv_prog_cc_g=yes fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -$as_echo "$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; then +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +printf "%s\n" "$ac_cv_prog_cc_g" >&6; } +if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then @@ -3440,116 +4184,227 @@ else CFLAGS= fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 -$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if ${ac_cv_prog_cc_c89+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_prog_cc_c89=no +ac_prog_cc_stdc=no +if test x$ac_prog_cc_stdc = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 +printf %s "checking for $CC option to enable C11 features... " >&6; } +if test ${ac_cv_prog_cc_c11+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -#include -#include -#include -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; +$ac_c_conftest_c11_program +_ACEOF +for ac_arg in '' -std=gnu11 +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_prog_cc_c11=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cc_c11" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC +fi -/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters - inside strings and character constants. */ -#define FOO(x) 'x' -int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; +if test "x$ac_cv_prog_cc_c11" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cc_c11" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 +printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } + CC="$CC $ac_cv_prog_cc_c11" +fi + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 + ac_prog_cc_stdc=c11 +fi +fi +if test x$ac_prog_cc_stdc = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 +printf %s "checking for $CC option to enable C99 features... " >&6; } +if test ${ac_cv_prog_cc_c99+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cc_c99=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_c_conftest_c99_program +_ACEOF +for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_prog_cc_c99=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cc_c99" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC +fi -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} +if test "x$ac_cv_prog_cc_c99" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cc_c99" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 +printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } + CC="$CC $ac_cv_prog_cc_c99" +fi + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 + ac_prog_cc_stdc=c99 +fi +fi +if test x$ac_prog_cc_stdc = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 +printf %s "checking for $CC option to enable C89 features... " >&6; } +if test ${ac_cv_prog_cc_c89+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_c_conftest_c89_program _ACEOF -for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ - -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" - if ac_fn_c_try_compile "$LINENO"; then : + if ac_fn_c_try_compile "$LINENO" +then : ac_cv_prog_cc_c89=$ac_arg fi -rm -f core conftest.err conftest.$ac_objext +rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC - fi -# AC_CACHE_VAL -case "x$ac_cv_prog_cc_c89" in - x) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -$as_echo "none needed" >&6; } ;; - xno) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -$as_echo "unsupported" >&6; } ;; - *) - CC="$CC $ac_cv_prog_cc_c89" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 -$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; -esac -if test "x$ac_cv_prog_cc_c89" != xno; then : +if test "x$ac_cv_prog_cc_c89" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cc_c89" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } + CC="$CC $ac_cv_prog_cc_c89" +fi + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 + ac_prog_cc_stdc=c89 fi +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +printf %s "checking whether $CC understands -c and -o together... " >&6; } +if test ${am_cv_prog_cc_c_o+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int +main (void) +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +printf "%s\n" "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu + depcc="$CC" am_compiler_list= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CC_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +printf %s "checking dependency style of $depcc... " >&6; } +if test ${am_cv_CC_dependencies_compiler_type+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're @@ -3584,16 +4439,16 @@ else : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with - # Solaris 8's {/usr,}/bin/sh. - touch sub/conftst$i.h + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - # We check with `-c' and `-o' for the sake of the "dashmstdout" + # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in @@ -3602,8 +4457,8 @@ else test "$am__universal" = false || continue ;; nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else @@ -3611,7 +4466,7 @@ else fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok `-c -o', but also, the minuso test has + # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} @@ -3650,8 +4505,8 @@ else fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if @@ -3666,16 +4521,18 @@ fi -if test -n "$ac_tool_prefix"; then + + if test -n "$ac_tool_prefix"; then for ac_prog in ar lib "link -lib" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AR+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_AR+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else @@ -3683,11 +4540,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -3698,11 +4559,11 @@ fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 -$as_echo "$AR" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +printf "%s\n" "$AR" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -3715,11 +4576,12 @@ if test -z "$AR"; then do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_AR+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_AR+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else @@ -3727,11 +4589,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -3742,11 +4608,11 @@ fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 -$as_echo "$ac_ct_AR" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +printf "%s\n" "$ac_ct_AR" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -3758,8 +4624,8 @@ done else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR @@ -3768,22 +4634,30 @@ fi : ${AR=ar} -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5 -$as_echo_n "checking the archiver ($AR) interface... " >&6; } -if ${am_cv_ar_interface+:} false; then : - $as_echo_n "(cached) " >&6 -else - am_cv_ar_interface=ar +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5 +printf %s "checking the archiver ($AR) interface... " >&6; } +if test ${am_cv_ar_interface+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + am_cv_ar_interface=ar cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int some_variable = 0; _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO" +then : am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 (eval $am_ar_try) 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then am_cv_ar_interface=ar @@ -3792,7 +4666,7 @@ if ac_fn_c_try_compile "$LINENO"; then : { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 (eval $am_ar_try) 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then am_cv_ar_interface=lib @@ -3803,11 +4677,16 @@ if ac_fn_c_try_compile "$LINENO"; then : rm -f conftest.lib libconftest.a fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5 -$as_echo "$am_cv_ar_interface" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5 +printf "%s\n" "$am_cv_ar_interface" >&6; } case $am_cv_ar_interface in ar) @@ -3829,18 +4708,20 @@ esac MAJ_VERSION=3 -MIN_VERSION=2 +MIN_VERSION=9 + +MIC_VERSION=0 -MIC_VERSION=22 +LIBNL_GIT_SHA=bdf83151326e365f137fe0e36dc9b1b7aeb1cf33 -LIBNL_VERSION=3.2.22 +LIBNL_VERSION=3.9.0 -LT_CURRENT=217 +LT_CURRENT=226 LT_REVISION=0 -LT_AGE=17 +LT_AGE=26 ac_ext=c @@ -3851,11 +4732,12 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else @@ -3863,11 +4745,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -3878,11 +4764,11 @@ fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -3891,11 +4777,12 @@ if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else @@ -3903,11 +4790,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -3918,11 +4809,11 @@ fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +printf "%s\n" "$ac_ct_CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then @@ -3930,8 +4821,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC @@ -3944,11 +4835,12 @@ if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else @@ -3956,11 +4848,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -3971,11 +4867,11 @@ fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -3984,11 +4880,12 @@ fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else @@ -3997,15 +4894,19 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -4021,33 +4922,144 @@ if test $ac_prog_rejected = yes; then # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +printf "%s\n" "$ac_ct_CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then - for ac_prog in cl.exe - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else + # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. +set dummy ${ac_tool_prefix}clang; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else @@ -4055,11 +5067,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}clang" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -4070,28 +5086,25 @@ fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi - test -n "$CC" && break - done fi -if test -z "$CC"; then +if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC - for ac_prog in cl.exe -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else + # Extract the first word of "clang", so it can be a program name with args. +set dummy clang; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else @@ -4099,11 +5112,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="clang" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -4114,50 +5131,48 @@ fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +printf "%s\n" "$ac_ct_CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi - - test -n "$ac_ct_CC" && break -done - if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi +else + CC="$ac_cv_prog_CC" fi fi -test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 -for ac_option in --version -v -V -qversion; do +for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then @@ -4167,20 +5182,21 @@ $as_echo "$ac_try_echo"; } >&5 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 -$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if ${ac_cv_c_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 +printf %s "checking whether the compiler supports GNU C... " >&6; } +if test ${ac_cv_c_compiler_gnu+y} +then : + printf %s "(cached) " >&6 +else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { #ifndef __GNUC__ choke me @@ -4190,29 +5206,33 @@ main () return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO" +then : ac_compiler_gnu=yes -else +else $as_nop ac_compiler_gnu=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -$as_echo "$ac_cv_c_compiler_gnu" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } +ac_compiler_gnu=$ac_cv_c_compiler_gnu + if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi -ac_test_CFLAGS=${CFLAGS+set} +ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -$as_echo_n "checking whether $CC accepts -g... " >&6; } -if ${ac_cv_prog_cc_g+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +printf %s "checking whether $CC accepts -g... " >&6; } +if test ${ac_cv_prog_cc_g+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no @@ -4221,57 +5241,60 @@ else /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO" +then : ac_cv_prog_cc_g=yes -else +else $as_nop CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO" +then : -else +else $as_nop ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO" +then : ac_cv_prog_cc_g=yes fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -$as_echo "$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; then +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +printf "%s\n" "$ac_cv_prog_cc_g" >&6; } +if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then @@ -4286,116 +5309,227 @@ else CFLAGS= fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 -$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if ${ac_cv_prog_cc_c89+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_prog_cc_c89=no +ac_prog_cc_stdc=no +if test x$ac_prog_cc_stdc = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 +printf %s "checking for $CC option to enable C11 features... " >&6; } +if test ${ac_cv_prog_cc_c11+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -#include -#include -#include -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; +$ac_c_conftest_c11_program +_ACEOF +for ac_arg in '' -std=gnu11 +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_prog_cc_c11=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cc_c11" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC +fi -/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters - inside strings and character constants. */ -#define FOO(x) 'x' -int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; +if test "x$ac_cv_prog_cc_c11" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cc_c11" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 +printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } + CC="$CC $ac_cv_prog_cc_c11" +fi + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 + ac_prog_cc_stdc=c11 +fi +fi +if test x$ac_prog_cc_stdc = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 +printf %s "checking for $CC option to enable C99 features... " >&6; } +if test ${ac_cv_prog_cc_c99+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cc_c99=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_c_conftest_c99_program +_ACEOF +for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_prog_cc_c99=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cc_c99" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC +fi -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} +if test "x$ac_cv_prog_cc_c99" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cc_c99" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 +printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } + CC="$CC $ac_cv_prog_cc_c99" +fi + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 + ac_prog_cc_stdc=c99 +fi +fi +if test x$ac_prog_cc_stdc = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 +printf %s "checking for $CC option to enable C89 features... " >&6; } +if test ${ac_cv_prog_cc_c89+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_c_conftest_c89_program _ACEOF -for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ - -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" - if ac_fn_c_try_compile "$LINENO"; then : + if ac_fn_c_try_compile "$LINENO" +then : ac_cv_prog_cc_c89=$ac_arg fi -rm -f core conftest.err conftest.$ac_objext +rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC - fi -# AC_CACHE_VAL -case "x$ac_cv_prog_cc_c89" in - x) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -$as_echo "none needed" >&6; } ;; - xno) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -$as_echo "unsupported" >&6; } ;; - *) - CC="$CC $ac_cv_prog_cc_c89" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 -$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; -esac -if test "x$ac_cv_prog_cc_c89" != xno; then : +if test "x$ac_cv_prog_cc_c89" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cc_c89" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } + CC="$CC $ac_cv_prog_cc_c89" +fi + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 + ac_prog_cc_stdc=c89 fi +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +printf %s "checking whether $CC understands -c and -o together... " >&6; } +if test ${am_cv_prog_cc_c_o+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +printf "%s\n" "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu + depcc="$CC" am_compiler_list= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CC_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +printf %s "checking dependency style of $depcc... " >&6; } +if test ${am_cv_CC_dependencies_compiler_type+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're @@ -4430,16 +5564,16 @@ else : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with - # Solaris 8's {/usr,}/bin/sh. - touch sub/conftst$i.h + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - # We check with `-c' and `-o' for the sake of the "dashmstdout" + # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in @@ -4448,8 +5582,8 @@ else test "$am__universal" = false || continue ;; nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else @@ -4457,7 +5591,7 @@ else fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok `-c -o', but also, the minuso test has + # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} @@ -4496,8 +5630,8 @@ else fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if @@ -4511,143 +5645,21 @@ else fi -if test "x$CC" != xcc; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 -$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 -$as_echo_n "checking whether cc understands -c and -o together... " >&6; } -fi -set dummy $CC; ac_cc=`$as_echo "$2" | - sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` -if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -int -main () -{ - ; - return 0; -} -_ACEOF -# Make sure it works both with $CC and with simple cc. -# We do the test twice because some compilers refuse to overwrite an -# existing .o file with -o, though they will create one. -ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' -rm -f conftest2.* -if { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && - test -f conftest2.$ac_objext && { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; -then - eval ac_cv_prog_cc_${ac_cc}_c_o=yes - if test "x$CC" != xcc; then - # Test first that cc exists at all. - if { ac_try='cc -c conftest.$ac_ext >&5' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then - ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' - rm -f conftest2.* - if { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && - test -f conftest2.$ac_objext && { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; +case `pwd` in + *\ * | *\ *) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +printf "%s\n" "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; - then - # cc works too. - : - else - # cc exists but doesn't like -o. - eval ac_cv_prog_cc_${ac_cc}_c_o=no - fi - fi - fi -else - eval ac_cv_prog_cc_${ac_cc}_c_o=no -fi -rm -f core conftest* - -fi -if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h - -fi - -# FIXME: we rely on the cache variable name because -# there is no other way. -set dummy $CC -am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` -eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o -if test "$am_t" != yes; then - # Losing compiler, so override with the script. - # FIXME: It is wrong to rewrite CC. - # But if we don't then we get into trouble of one sort or another. - # A longer-term fix would be to have automake use am__CC in this case, - # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" - CC="$am_aux_dir/compile $CC" -fi -case `pwd` in - *\ * | *\ *) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 -$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; -esac +macro_version='2.4.7' +macro_revision='2.4.7' -macro_version='2.4.2' -macro_revision='1.3337' @@ -4659,30 +5671,31 @@ macro_revision='1.3337' +ltmain=$ac_aux_dir/ltmain.sh -ltmain="$ac_aux_dir/ltmain.sh" -# Make sure we can run config.sub. -$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + # Make sure we can run config.sub. +$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 -$as_echo_n "checking build system type... " >&6; } -if ${ac_cv_build+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +printf %s "checking build system type... " >&6; } +if test ${ac_cv_build+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_build_alias=$build_alias test "x$ac_build_alias" = x && - ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` + ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 -ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 +ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5 fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 -$as_echo "$ac_cv_build" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +printf "%s\n" "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; @@ -4701,21 +5714,22 @@ IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 -$as_echo_n "checking host system type... " >&6; } -if ${ac_cv_host+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +printf %s "checking host system type... " >&6; } +if test ${ac_cv_host+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else - ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 + ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` || + as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5 fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 -$as_echo "$ac_cv_host" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +printf "%s\n" "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; @@ -4755,8 +5769,8 @@ ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 -$as_echo_n "checking how to print strings... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +printf %s "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then @@ -4781,13 +5795,13 @@ func_echo_all () $ECHO "" } -case "$ECHO" in - printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 -$as_echo "printf" >&6; } ;; - print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 -$as_echo "print -r" >&6; } ;; - *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 -$as_echo "cat" >&6; } ;; +case $ECHO in + printf*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +printf "%s\n" "printf" >&6; } ;; + print*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +printf "%s\n" "print -r" >&6; } ;; + *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +printf "%s\n" "cat" >&6; } ;; esac @@ -4803,11 +5817,12 @@ esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 -$as_echo_n "checking for a sed that does not truncate output... " >&6; } -if ${ac_cv_path_SED+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +printf %s "checking for a sed that does not truncate output... " >&6; } +if test ${ac_cv_path_SED+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" @@ -4821,11 +5836,16 @@ else for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in sed gsed; do + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_prog in sed gsed + do for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue + ac_path_SED="$as_dir$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in @@ -4833,13 +5853,13 @@ case `"$ac_path_SED" --version 2>&1` in ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 - $as_echo_n 0123456789 >"conftest.in" + printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" - $as_echo '' >> "conftest.nl" + printf "%s\n" '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val @@ -4867,8 +5887,8 @@ else fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 -$as_echo "$ac_cv_path_SED" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +printf "%s\n" "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed @@ -4885,11 +5905,12 @@ Xsed="$SED -e 1s/^X//" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 -$as_echo_n "checking for grep that handles long lines and -e... " >&6; } -if ${ac_cv_path_GREP+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +printf %s "checking for grep that handles long lines and -e... " >&6; } +if test ${ac_cv_path_GREP+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST @@ -4897,11 +5918,16 @@ else for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in grep ggrep; do + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_prog in grep ggrep + do for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue + ac_path_GREP="$as_dir$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in @@ -4909,13 +5935,13 @@ case `"$ac_path_GREP" --version 2>&1` in ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 - $as_echo_n 0123456789 >"conftest.in" + printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" - $as_echo 'GREP' >> "conftest.nl" + printf "%s\n" 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val @@ -4943,16 +5969,17 @@ else fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 -$as_echo "$ac_cv_path_GREP" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +printf "%s\n" "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 -$as_echo_n "checking for egrep... " >&6; } -if ${ac_cv_path_EGREP+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +printf %s "checking for egrep... " >&6; } +if test ${ac_cv_path_EGREP+y} +then : + printf %s "(cached) " >&6 +else $as_nop if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else @@ -4963,11 +5990,16 @@ else for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in egrep; do + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_prog in egrep + do for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue + ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in @@ -4975,13 +6007,13 @@ case `"$ac_path_EGREP" --version 2>&1` in ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 - $as_echo_n 0123456789 >"conftest.in" + printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" - $as_echo 'EGREP' >> "conftest.nl" + printf "%s\n" 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val @@ -5010,16 +6042,17 @@ fi fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 -$as_echo "$ac_cv_path_EGREP" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +printf "%s\n" "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 -$as_echo_n "checking for fgrep... " >&6; } -if ${ac_cv_path_FGREP+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +printf %s "checking for fgrep... " >&6; } +if test ${ac_cv_path_FGREP+y} +then : + printf %s "(cached) " >&6 +else $as_nop if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else @@ -5030,11 +6063,16 @@ else for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in fgrep; do + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_prog in fgrep + do for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue + ac_path_FGREP="$as_dir$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in @@ -5042,13 +6080,13 @@ case `"$ac_path_FGREP" --version 2>&1` in ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 - $as_echo_n 0123456789 >"conftest.in" + printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" - $as_echo 'FGREP' >> "conftest.nl" + printf "%s\n" 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val @@ -5077,8 +6115,8 @@ fi fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 -$as_echo "$ac_cv_path_FGREP" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +printf "%s\n" "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" @@ -5103,20 +6141,21 @@ test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. -if test "${with_gnu_ld+set}" = set; then : - withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes -else +if test ${with_gnu_ld+y} +then : + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +else $as_nop with_gnu_ld=no fi ac_prog=ld -if test "$GCC" = yes; then +if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 -$as_echo_n "checking for ld used by $CC... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +printf %s "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw + # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; @@ -5130,7 +6169,7 @@ $as_echo_n "checking for ld used by $CC... " >&6; } while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done - test -z "$LD" && LD="$ac_prog" + test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. @@ -5141,56 +6180,58 @@ $as_echo_n "checking for ld used by $CC... " >&6; } with_gnu_ld=unknown ;; esac -elif test "$with_gnu_ld" = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 -$as_echo_n "checking for GNU ld... " >&6; } +elif test yes = "$with_gnu_ld"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +printf %s "checking for GNU ld... " >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 -$as_echo_n "checking for non-GNU ld... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +printf %s "checking for non-GNU ld... " >&6; } fi -if ${lt_cv_path_LD+:} false; then : - $as_echo_n "(cached) " >&6 -else +if test ${lt_cv_path_LD+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" + lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 -$as_echo "$LD" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 +printf "%s\n" "$LD" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 -$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } -if ${lt_cv_prog_gnu_ld+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +printf %s "checking if the linker ($LD) is GNU ld... " >&6; } +if test ${lt_cv_prog_gnu_ld+y} +then : + printf %s "(cached) " >&6 +else $as_nop # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &1 &5 -$as_echo "$lt_cv_prog_gnu_ld" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5 +printf "%s\n" "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld @@ -5213,40 +6254,46 @@ with_gnu_ld=$lt_cv_prog_gnu_ld -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 -$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } -if ${lt_cv_path_NM+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +printf %s "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if test ${lt_cv_path_NM+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$NM"; then # Let the user override the test. - lt_cv_path_NM="$NM" + lt_cv_path_NM=$NM else - lt_nm_to_check="${ac_tool_prefix}nm" + lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/$lt_tmp_nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" - break + break 2 ;; *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" - break + break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but @@ -5257,15 +6304,15 @@ else esac fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 -$as_echo "$lt_cv_path_NM" >&6; } -if test "$lt_cv_path_NM" != "no"; then - NM="$lt_cv_path_NM" +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +printf "%s\n" "$lt_cv_path_NM" >&6; } +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : @@ -5276,11 +6323,12 @@ else do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_DUMPBIN+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_DUMPBIN+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else @@ -5288,11 +6336,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -5303,11 +6355,11 @@ fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 -$as_echo "$DUMPBIN" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +printf "%s\n" "$DUMPBIN" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -5320,11 +6372,12 @@ if test -z "$DUMPBIN"; then do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_DUMPBIN+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else @@ -5332,11 +6385,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -5347,11 +6404,11 @@ fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 -$as_echo "$ac_ct_DUMPBIN" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +printf "%s\n" "$ac_ct_DUMPBIN" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -5363,17 +6420,17 @@ done else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi - case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in *COFF*) - DUMPBIN="$DUMPBIN -symbols" + DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: @@ -5381,8 +6438,8 @@ fi esac fi - if test "$DUMPBIN" != ":"; then - NM="$DUMPBIN" + if test : != "$DUMPBIN"; then + NM=$DUMPBIN fi fi test -z "$NM" && NM=nm @@ -5392,11 +6449,12 @@ test -z "$NM" && NM=nm -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 -$as_echo_n "checking the name lister ($NM) interface... " >&6; } -if ${lt_cv_nm_interface+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +printf %s "checking the name lister ($NM) interface... " >&6; } +if test ${lt_cv_nm_interface+y} +then : + printf %s "(cached) " >&6 +else $as_nop lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) @@ -5412,28 +6470,29 @@ else fi rm -f conftest* fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 -$as_echo "$lt_cv_nm_interface" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +printf "%s\n" "$lt_cv_nm_interface" >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 -$as_echo_n "checking whether ln -s works... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +printf %s "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 -$as_echo "no, using $LN_S" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +printf "%s\n" "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 -$as_echo_n "checking the maximum length of command line arguments... " >&6; } -if ${lt_cv_sys_max_cmd_len+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +printf %s "checking the maximum length of command line arguments... " >&6; } +if test ${lt_cv_sys_max_cmd_len+y} +then : + printf %s "(cached) " >&6 +else $as_nop i=0 - teststring="ABCD" + teststring=ABCD case $build_os in msdosdjgpp*) @@ -5473,7 +6532,7 @@ else lt_cv_sys_max_cmd_len=8192; ;; - netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` @@ -5516,29 +6575,30 @@ else sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then - lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` - if test -n "$lt_cv_sys_max_cmd_len"; then + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. - for i in 1 2 3 4 5 6 7 8 ; do + for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. - while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && - test $i != 17 # 1/2 MB should be enough + test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring @@ -5556,12 +6616,12 @@ else fi -if test -n $lt_cv_sys_max_cmd_len ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 -$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +if test -n "$lt_cv_sys_max_cmd_len"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +printf "%s\n" "$lt_cv_sys_max_cmd_len" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 -$as_echo "none" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5 +printf "%s\n" "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len @@ -5574,30 +6634,6 @@ max_cmd_len=$lt_cv_sys_max_cmd_len : ${MV="mv -f"} : ${RM="rm -f"} -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 -$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } -# Try some XSI features -xsi_shell=no -( _lt_dummy="a/b/c" - test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ - = c,a/b,b/c, \ - && eval 'test $(( 1 + 1 )) -eq 2 \ - && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ - && xsi_shell=yes -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 -$as_echo "$xsi_shell" >&6; } - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 -$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } -lt_shell_append=no -( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ - >/dev/null 2>&1 \ - && lt_shell_append=yes -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 -$as_echo "$lt_shell_append" >&6; } - - if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else @@ -5629,11 +6665,12 @@ esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 -$as_echo_n "checking how to convert $build file names to $host format... " >&6; } -if ${lt_cv_to_host_file_cmd+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +printf %s "checking how to convert $build file names to $host format... " >&6; } +if test ${lt_cv_to_host_file_cmd+y} +then : + printf %s "(cached) " >&6 +else $as_nop case $host in *-*-mingw* ) case $build in @@ -5669,18 +6706,19 @@ esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 -$as_echo "$lt_cv_to_host_file_cmd" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +printf "%s\n" "$lt_cv_to_host_file_cmd" >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 -$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } -if ${lt_cv_to_tool_file_cmd+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +printf %s "checking how to convert $build file names to toolchain format... " >&6; } +if test ${lt_cv_to_tool_file_cmd+y} +then : + printf %s "(cached) " >&6 +else $as_nop #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in @@ -5696,22 +6734,23 @@ esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 -$as_echo "$lt_cv_to_tool_file_cmd" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +printf "%s\n" "$lt_cv_to_tool_file_cmd" >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 -$as_echo_n "checking for $LD option to reload object files... " >&6; } -if ${lt_cv_ld_reload_flag+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +printf %s "checking for $LD option to reload object files... " >&6; } +if test ${lt_cv_ld_reload_flag+y} +then : + printf %s "(cached) " >&6 +else $as_nop lt_cv_ld_reload_flag='-r' fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 -$as_echo "$lt_cv_ld_reload_flag" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +printf "%s\n" "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; @@ -5720,13 +6759,13 @@ esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) - if test "$GCC" != yes; then + if test yes != "$GCC"; then reload_cmds=false fi ;; darwin*) - if test "$GCC" = yes; then - reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + if test yes = "$GCC"; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi @@ -5742,13 +6781,122 @@ esac if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}file", so it can be a program name with args. +set dummy ${ac_tool_prefix}file; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_FILECMD+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$FILECMD"; then + ac_cv_prog_FILECMD="$FILECMD" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_FILECMD="${ac_tool_prefix}file" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +FILECMD=$ac_cv_prog_FILECMD +if test -n "$FILECMD"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FILECMD" >&5 +printf "%s\n" "$FILECMD" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_FILECMD"; then + ac_ct_FILECMD=$FILECMD + # Extract the first word of "file", so it can be a program name with args. +set dummy file; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_FILECMD+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ac_ct_FILECMD"; then + ac_cv_prog_ac_ct_FILECMD="$ac_ct_FILECMD" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_FILECMD="file" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_FILECMD=$ac_cv_prog_ac_ct_FILECMD +if test -n "$ac_ct_FILECMD"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_FILECMD" >&5 +printf "%s\n" "$ac_ct_FILECMD" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + if test "x$ac_ct_FILECMD" = x; then + FILECMD=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + FILECMD=$ac_ct_FILECMD + fi +else + FILECMD="$ac_cv_prog_FILECMD" +fi + + + + + + + +if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_OBJDUMP+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_OBJDUMP+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else @@ -5756,11 +6904,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -5771,11 +6923,11 @@ fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 -$as_echo "$OBJDUMP" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +printf "%s\n" "$OBJDUMP" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -5784,11 +6936,12 @@ if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_OBJDUMP+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else @@ -5796,11 +6949,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -5811,11 +6968,11 @@ fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 -$as_echo "$ac_ct_OBJDUMP" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +printf "%s\n" "$ac_ct_OBJDUMP" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then @@ -5823,8 +6980,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP @@ -5843,24 +7000,25 @@ test -z "$OBJDUMP" && OBJDUMP=objdump -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 -$as_echo_n "checking how to recognize dependent libraries... " >&6; } -if ${lt_cv_deplibs_check_method+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +printf %s "checking how to recognize dependent libraries... " >&6; } +if test ${lt_cv_deplibs_check_method+y} +then : + printf %s "(cached) " >&6 +else $as_nop lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. -# `unknown' -- same as none, but documents that we really don't know. +# 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path -# which responds to the $file_magic_cmd with a given extended regex. -# If you have `file' or equivalent on your system and you're not sure -# whether `pass_all' will *always* work, you probably want this one. +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) @@ -5873,7 +7031,7 @@ beos*) bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' - lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_cmd='$FILECMD -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; @@ -5887,8 +7045,7 @@ mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. - # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. - if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else @@ -5908,14 +7065,14 @@ darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; -freebsd* | dragonfly*) +freebsd* | dragonfly* | midnightbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_cmd=$FILECMD lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac @@ -5924,16 +7081,12 @@ freebsd* | dragonfly*) fi ;; -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_cmd=$FILECMD case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' @@ -5966,7 +7119,7 @@ irix5* | irix6* | nonstopux*) ;; # This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; @@ -5980,7 +7133,7 @@ netbsd*) newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_cmd=$FILECMD lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; @@ -5988,8 +7141,8 @@ newos6*) lt_cv_deplibs_check_method=pass_all ;; -openbsd*) - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' @@ -6042,11 +7195,14 @@ sysv4 | sysv4.3*) tpf*) lt_cv_deplibs_check_method=pass_all ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; esac fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 -$as_echo "$lt_cv_deplibs_check_method" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +printf "%s\n" "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no @@ -6090,11 +7246,12 @@ test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_DLLTOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_DLLTOOL+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else @@ -6102,11 +7259,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -6117,11 +7278,11 @@ fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 -$as_echo "$DLLTOOL" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +printf "%s\n" "$DLLTOOL" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -6130,11 +7291,12 @@ if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_DLLTOOL+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else @@ -6142,11 +7304,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -6157,11 +7323,11 @@ fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 -$as_echo "$ac_ct_DLLTOOL" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +printf "%s\n" "$ac_ct_DLLTOOL" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then @@ -6169,8 +7335,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL @@ -6190,17 +7356,18 @@ test -z "$DLLTOOL" && DLLTOOL=dlltool -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 -$as_echo_n "checking how to associate runtime and link libraries... " >&6; } -if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +printf %s "checking how to associate runtime and link libraries... " >&6; } +if test ${lt_cv_sharedlib_from_linklib_cmd+y} +then : + printf %s "(cached) " >&6 +else $as_nop lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) - # two different shell functions defined in ltmain.sh - # decide which to use based on capabilities of $DLLTOOL + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib @@ -6212,13 +7379,13 @@ cygwin* | mingw* | pw32* | cegcc*) ;; *) # fallback: assume linklib IS sharedlib - lt_cv_sharedlib_from_linklib_cmd="$ECHO" + lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 -$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +printf "%s\n" "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO @@ -6233,11 +7400,12 @@ if test -n "$ac_tool_prefix"; then do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AR+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_AR+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else @@ -6245,11 +7413,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -6260,11 +7432,11 @@ fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 -$as_echo "$AR" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +printf "%s\n" "$AR" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -6277,11 +7449,12 @@ if test -z "$AR"; then do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_AR+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_AR+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else @@ -6289,11 +7462,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -6304,11 +7481,11 @@ fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 -$as_echo "$ac_ct_AR" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +printf "%s\n" "$ac_ct_AR" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -6320,8 +7497,8 @@ done else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR @@ -6329,65 +7506,83 @@ esac fi : ${AR=ar} -: ${AR_FLAGS=cru} +# Use ARFLAGS variable as AR's operation code to sync the variable naming with +# Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have +# higher priority because thats what people were doing historically (setting +# ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS +# variable obsoleted/removed. +test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr} +lt_ar_flags=$AR_FLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 -$as_echo_n "checking for archiver @FILE support... " >&6; } -if ${lt_cv_ar_at_file+:} false; then : - $as_echo_n "(cached) " >&6 -else + + +# Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override +# by AR_FLAGS because that was never working and AR_FLAGS is about to die. + + + + + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +printf %s "checking for archiver @FILE support... " >&6; } +if test ${lt_cv_ar_at_file+y} +then : + printf %s "(cached) " >&6 +else $as_nop lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO" +then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - if test "$ac_status" -eq 0; then + if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - if test "$ac_status" -ne 0; then + if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 -$as_echo "$lt_cv_ar_at_file" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +printf "%s\n" "$lt_cv_ar_at_file" >&6; } -if test "x$lt_cv_ar_at_file" = xno; then +if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file @@ -6402,11 +7597,12 @@ fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_STRIP+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else @@ -6414,11 +7610,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -6429,11 +7629,11 @@ fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +printf "%s\n" "$STRIP" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -6442,11 +7642,12 @@ if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_STRIP+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else @@ -6454,11 +7655,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -6469,11 +7674,11 @@ fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 -$as_echo "$ac_ct_STRIP" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +printf "%s\n" "$ac_ct_STRIP" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then @@ -6481,8 +7686,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP @@ -6501,11 +7706,12 @@ test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_RANLIB+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_RANLIB+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else @@ -6513,11 +7719,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -6528,11 +7738,11 @@ fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 -$as_echo "$RANLIB" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +printf "%s\n" "$RANLIB" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -6541,11 +7751,12 @@ if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_RANLIB+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else @@ -6553,11 +7764,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -6568,11 +7783,11 @@ fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 -$as_echo "$ac_ct_RANLIB" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +printf "%s\n" "$ac_ct_RANLIB" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then @@ -6580,8 +7795,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB @@ -6604,7 +7819,7 @@ old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in - openbsd*) + bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) @@ -6670,11 +7885,12 @@ compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 -$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } -if ${lt_cv_sys_global_symbol_pipe+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +printf %s "checking command to parse $NM output from $compiler object... " >&6; } +if test ${lt_cv_sys_global_symbol_pipe+y} +then : + printf %s "(cached) " >&6 +else $as_nop # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] @@ -6694,7 +7910,7 @@ cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then symcode='[ABCDEGRST]' fi ;; @@ -6727,14 +7943,44 @@ case `$NM -V 2>&1` in symcode='[ABCDGIRSTW]' ;; esac +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" +lt_cv_sys_global_symbol_to_cdecl="$SED -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= @@ -6752,26 +7998,29 @@ for ac_symprfx in "" "_"; do # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Fake it for dumpbin and say T for any non-static function - # and D for any global variable. - # Also find C++ and __fastcall symbols from MSVC++, + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++ or ICC, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ -" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ -" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ -" s[1]~/^[@?]/{print s[1], s[1]; next};"\ -" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi - lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no @@ -6793,14 +8042,14 @@ _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then @@ -6814,11 +8063,11 @@ _LT_EOF if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -/* DATA imports from DLLs on WIN32 con't be const, because runtime +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST -#elif defined(__osf__) +#elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else @@ -6844,7 +8093,7 @@ lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; @@ -6864,13 +8113,13 @@ _LT_EOF mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS - LIBS="conftstm.$ac_objext" + LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest${ac_exeext}; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS @@ -6891,7 +8140,7 @@ _LT_EOF rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then + if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= @@ -6904,11 +8153,11 @@ if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 -$as_echo "failed" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +printf "%s\n" "failed" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 -$as_echo "ok" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +printf "%s\n" "ok" >&6; } fi # Response file support. @@ -6944,82 +8193,183 @@ fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 -$as_echo_n "checking for sysroot... " >&6; } + + + + + + + + + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +printf %s "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. -if test "${with_sysroot+set}" = set; then : +if test ${with_sysroot+y} +then : withval=$with_sysroot; -else +else $as_nop with_sysroot=no fi lt_sysroot= -case ${with_sysroot} in #( +case $with_sysroot in #( yes) - if test "$GCC" = yes; then + if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) - lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 -$as_echo "${with_sysroot}" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 +printf "%s\n" "$with_sysroot" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 -$as_echo "${lt_sysroot:-no}" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +printf "%s\n" "${lt_sysroot:-no}" >&6; } + + + + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 +printf %s "checking for a working dd... " >&6; } +if test ${ac_cv_path_lt_DD+y} +then : + printf %s "(cached) " >&6 +else $as_nop + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +if test -z "$lt_DD"; then + ac_path_lt_DD_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_prog in dd + do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_lt_DD="$as_dir$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_lt_DD" || continue +if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi + $ac_path_lt_DD_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_lt_DD"; then + : + fi +else + ac_cv_path_lt_DD=$lt_DD +fi + +rm -f conftest.i conftest2.i conftest.out +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 +printf "%s\n" "$ac_cv_path_lt_DD" >&6; } + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 +printf %s "checking how to truncate binary pipes... " >&6; } +if test ${lt_cv_truncate_bin+y} +then : + printf %s "(cached) " >&6 +else $as_nop + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 +printf "%s\n" "$lt_cv_truncate_bin" >&6; } + + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} # Check whether --enable-libtool-lock was given. -if test "${enable_libtool_lock+set}" = set; then : +if test ${enable_libtool_lock+y} +then : enableval=$enable_libtool_lock; fi -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes +test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - case `/usr/bin/file conftest.$ac_objext` in + case `$FILECMD conftest.$ac_objext` in *ELF-32*) - HPUX_IA64_MODE="32" + HPUX_IA64_MODE=32 ;; *ELF-64*) - HPUX_IA64_MODE="64" + HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - if test "$lt_cv_prog_gnu_ld" = yes; then - case `/usr/bin/file conftest.$ac_objext` in + if test yes = "$lt_cv_prog_gnu_ld"; then + case `$FILECMD conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; @@ -7031,7 +8381,7 @@ ia64-*-hpux*) ;; esac else - case `/usr/bin/file conftest.$ac_objext` in + case `$FILECMD conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; @@ -7047,25 +8397,76 @@ ia64-*-hpux*) rm -rf conftest* ;; -x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + emul=elf + case `$FILECMD conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `$FILECMD conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `$FILECMD conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - case `/usr/bin/file conftest.o` in + case `$FILECMD conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) - LD="${LD-ld} -m elf_i386" + case `$FILECMD conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac ;; - ppc64-*linux*|powerpc64-*linux*) + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) @@ -7084,7 +8485,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; - ppc*-*linux*|powerpc*-*linux*) + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) @@ -7102,13 +8506,14 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" + SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 -$as_echo_n "checking whether the C compiler needs -belf... " >&6; } -if ${lt_cv_cc_needs_belf+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +printf %s "checking whether the C compiler needs -belf... " >&6; } +if test ${lt_cv_cc_needs_belf+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -7119,19 +8524,20 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +if ac_fn_c_try_link "$LINENO" +then : lt_cv_cc_needs_belf=yes -else +else $as_nop lt_cv_cc_needs_belf=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -7140,27 +8546,28 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 -$as_echo "$lt_cv_cc_needs_belf" >&6; } - if test x"$lt_cv_cc_needs_belf" != x"yes"; then +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +printf "%s\n" "$lt_cv_cc_needs_belf" >&6; } + if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" + CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - case `/usr/bin/file conftest.o` in + case `$FILECMD conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in - i?86-*-solaris*) + i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) @@ -7169,7 +8576,7 @@ $as_echo "$lt_cv_cc_needs_belf" >&6; } esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then - LD="${LD-ld}_sol2" + LD=${LD-ld}_sol2 fi ;; *) @@ -7185,16 +8592,17 @@ $as_echo "$lt_cv_cc_needs_belf" >&6; } ;; esac -need_locks="$enable_libtool_lock" +need_locks=$enable_libtool_lock if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_MANIFEST_TOOL+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else @@ -7202,11 +8610,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -7217,11 +8629,11 @@ fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 -$as_echo "$MANIFEST_TOOL" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +printf "%s\n" "$MANIFEST_TOOL" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -7230,11 +8642,12 @@ if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_MANIFEST_TOOL+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else @@ -7242,11 +8655,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -7257,11 +8674,11 @@ fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 -$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +printf "%s\n" "$ac_ct_MANIFEST_TOOL" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then @@ -7269,8 +8686,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL @@ -7280,11 +8697,12 @@ else fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 -$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } -if ${lt_cv_path_mainfest_tool+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +printf %s "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if test ${lt_cv_path_mainfest_tool+y} +then : + printf %s "(cached) " >&6 +else $as_nop lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out @@ -7294,9 +8712,9 @@ else fi rm -f conftest* fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 -$as_echo "$lt_cv_path_mainfest_tool" >&6; } -if test "x$lt_cv_path_mainfest_tool" != xyes; then +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +printf "%s\n" "$lt_cv_path_mainfest_tool" >&6; } +if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi @@ -7310,11 +8728,12 @@ fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_DSYMUTIL+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_DSYMUTIL+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else @@ -7322,11 +8741,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -7337,11 +8760,11 @@ fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 -$as_echo "$DSYMUTIL" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +printf "%s\n" "$DSYMUTIL" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -7350,11 +8773,12 @@ if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_DSYMUTIL+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else @@ -7362,11 +8786,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -7377,11 +8805,11 @@ fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 -$as_echo "$ac_ct_DSYMUTIL" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +printf "%s\n" "$ac_ct_DSYMUTIL" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then @@ -7389,8 +8817,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL @@ -7402,11 +8830,12 @@ fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_NMEDIT+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_NMEDIT+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else @@ -7414,11 +8843,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -7429,11 +8862,11 @@ fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 -$as_echo "$NMEDIT" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +printf "%s\n" "$NMEDIT" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -7442,11 +8875,12 @@ if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_NMEDIT+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else @@ -7454,11 +8888,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -7469,11 +8907,11 @@ fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 -$as_echo "$ac_ct_NMEDIT" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +printf "%s\n" "$ac_ct_NMEDIT" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then @@ -7481,8 +8919,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT @@ -7494,11 +8932,12 @@ fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_LIPO+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_LIPO+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else @@ -7506,11 +8945,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -7521,11 +8964,11 @@ fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 -$as_echo "$LIPO" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +printf "%s\n" "$LIPO" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -7534,11 +8977,12 @@ if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_LIPO+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_LIPO+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else @@ -7546,11 +8990,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -7561,11 +9009,11 @@ fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 -$as_echo "$ac_ct_LIPO" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +printf "%s\n" "$ac_ct_LIPO" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then @@ -7573,8 +9021,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO @@ -7586,11 +9034,12 @@ fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_OTOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_OTOOL+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else @@ -7598,11 +9047,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -7613,11 +9066,11 @@ fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 -$as_echo "$OTOOL" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +printf "%s\n" "$OTOOL" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -7626,11 +9079,12 @@ if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_OTOOL+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else @@ -7638,11 +9092,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -7653,11 +9111,11 @@ fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 -$as_echo "$ac_ct_OTOOL" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +printf "%s\n" "$ac_ct_OTOOL" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then @@ -7665,8 +9123,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL @@ -7678,11 +9136,12 @@ fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_OTOOL64+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_OTOOL64+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else @@ -7690,11 +9149,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -7705,11 +9168,11 @@ fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 -$as_echo "$OTOOL64" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +printf "%s\n" "$OTOOL64" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -7718,11 +9181,12 @@ if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_OTOOL64+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else @@ -7730,11 +9194,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -7745,11 +9213,11 @@ fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 -$as_echo "$ac_ct_OTOOL64" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +printf "%s\n" "$ac_ct_OTOOL64" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then @@ -7757,8 +9225,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 @@ -7793,13 +9261,14 @@ fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 -$as_echo_n "checking for -single_module linker flag... " >&6; } -if ${lt_cv_apple_cc_single_mod+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +printf %s "checking for -single_module linker flag... " >&6; } +if test ${lt_cv_apple_cc_single_mod+y} +then : + printf %s "(cached) " >&6 +else $as_nop lt_cv_apple_cc_single_mod=no - if test -z "${LT_MULTI_MODULE}"; then + if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the @@ -7817,7 +9286,7 @@ else cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. - elif test -f libconftest.dylib && test $_lt_result -eq 0; then + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 @@ -7826,14 +9295,15 @@ else rm -f conftest.* fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 -$as_echo "$lt_cv_apple_cc_single_mod" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +printf "%s\n" "$lt_cv_apple_cc_single_mod" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 -$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } -if ${lt_cv_ld_exported_symbols_list+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +printf %s "checking for -exported_symbols_list linker flag... " >&6; } +if test ${lt_cv_ld_exported_symbols_list+y} +then : + printf %s "(cached) " >&6 +else $as_nop lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym @@ -7842,39 +9312,41 @@ else /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +if ac_fn_c_try_link "$LINENO" +then : lt_cv_ld_exported_symbols_list=yes -else +else $as_nop lt_cv_ld_exported_symbols_list=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 -$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +printf "%s\n" "$lt_cv_ld_exported_symbols_list" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 -$as_echo_n "checking for -force_load linker flag... " >&6; } -if ${lt_cv_ld_force_load+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +printf %s "checking for -force_load linker flag... " >&6; } +if test ${lt_cv_ld_force_load+y} +then : + printf %s "(cached) " >&6 +else $as_nop lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 - echo "$AR cru libconftest.a conftest.o" >&5 - $AR cru libconftest.a conftest.o 2>&5 + echo "$AR $AR_FLAGS libconftest.a conftest.o" >&5 + $AR $AR_FLAGS libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF @@ -7885,7 +9357,7 @@ _LT_EOF _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 - elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&5 @@ -7894,323 +9366,110 @@ _LT_EOF rm -rf conftest.dSYM fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 -$as_echo "$lt_cv_ld_force_load" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +printf "%s\n" "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) - _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; - darwin*) # darwin 5.x on - # if running on 10.5 or later, the deployment target defaults - # to the OS version, if on x86, and 10.4, the deployment - # target defaults to 10.4. Don't you love it? - case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in - 10.0,*86*-darwin8*|10.0,*-darwin[91]*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - 10.[012]*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; - 10.*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) + case $MACOSX_DEPLOYMENT_TARGET,$host in + 10.[012],*|,*powerpc*-darwin[5-8]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + *) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac - if test "$lt_cv_apple_cc_single_mod" = "yes"; then + if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi - if test "$lt_cv_ld_exported_symbols_list" = "yes"; then - _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi - if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' - else - _lt_dsymutil= - fi - ;; - esac - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 -$as_echo_n "checking how to run the C preprocessor... " >&6; } -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= -fi -if test -z "$CPP"; then - if ${ac_cv_prog_CPP+:} false; then : - $as_echo_n "(cached) " >&6 -else - # Double quotes because CPP needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" - do - ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - break -fi - - done - ac_cv_prog_CPP=$CPP - -fi - CPP=$ac_cv_prog_CPP -else - ac_cv_prog_CPP=$CPP -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 -$as_echo "$CPP" >&6; } -ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if ${ac_cv_header_stdc+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes -else - ac_cv_header_stdc=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi + else + _lt_dsymutil= + fi + ;; + esac -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : +ac_header= ac_cache= +for ac_item in $ac_header_c_list +do + if test $ac_cache; then + ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" + if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then + printf "%s\n" "#define $ac_item 1" >> confdefs.h + fi + ac_header= ac_cache= + elif test $ac_header; then + ac_cache=$ac_item + else + ac_header=$ac_item + fi +done -else - ac_cv_header_stdc=no -fi -rm -f conftest* -fi -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : -else - ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then -$as_echo "#define STDC_HEADERS 1" >>confdefs.h -fi +if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes +then : -# On IRIX 5.3, sys/types and inttypes.h are conflicting. -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default -" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF +printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h fi - -done - - -for ac_header in dlfcn.h -do : - ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " -if test "x$ac_cv_header_dlfcn_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_DLFCN_H 1 -_ACEOF +if test "x$ac_cv_header_dlfcn_h" = xyes +then : + printf "%s\n" "#define HAVE_DLFCN_H 1" >>confdefs.h fi -done - @@ -8226,7 +9485,8 @@ done # Check whether --enable-shared was given. -if test "${enable_shared+set}" = set; then : +if test ${enable_shared+y} +then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; @@ -8234,17 +9494,17 @@ if test "${enable_shared+set}" = set; then : *) enable_shared=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac -else +else $as_nop enable_shared=yes fi @@ -8257,7 +9517,8 @@ fi # Check whether --enable-static was given. -if test "${enable_static+set}" = set; then : +if test ${enable_static+y} +then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; @@ -8265,17 +9526,17 @@ if test "${enable_static+set}" = set; then : *) enable_static=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac -else +else $as_nop enable_static=yes fi @@ -8289,30 +9550,29 @@ fi # Check whether --with-pic was given. -if test "${with_pic+set}" = set; then : +if test ${with_pic+y} +then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac -else +else $as_nop pic_mode=default fi -test -z "$pic_mode" && pic_mode=default - @@ -8320,7 +9580,8 @@ test -z "$pic_mode" && pic_mode=default # Check whether --enable-fast-install was given. -if test "${enable_fast_install+set}" = set; then : +if test ${enable_fast_install+y} +then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; @@ -8328,17 +9589,17 @@ if test "${enable_fast_install+set}" = set; then : *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac -else +else $as_nop enable_fast_install=yes fi @@ -8349,11 +9610,65 @@ fi + shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[5-9]*,yes) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 +printf %s "checking which variant of shared library versioning to provide... " >&6; } + +# Check whether --with-aix-soname was given. +if test ${with_aix_soname+y} +then : + withval=$with_aix_soname; case $withval in + aix|svr4|both) + ;; + *) + as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname +else $as_nop + if test ${lt_cv_with_aix_soname+y} +then : + printf %s "(cached) " >&6 +else $as_nop + lt_cv_with_aix_soname=aix +fi + + with_aix_soname=$lt_cv_with_aix_soname +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 +printf "%s\n" "$with_aix_soname" >&6; } + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + + + + + + + # This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ltmain" +LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' @@ -8402,15 +9717,16 @@ test -z "$LN_S" && LN_S="ln -s" -if test -n "${ZSH_VERSION+set}" ; then +if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 -$as_echo_n "checking for objdir... " >&6; } -if ${lt_cv_objdir+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +printf %s "checking for objdir... " >&6; } +if test ${lt_cv_objdir+y} +then : + printf %s "(cached) " >&6 +else $as_nop rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then @@ -8421,17 +9737,15 @@ else fi rmdir .libs 2>/dev/null fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 -$as_echo "$lt_cv_objdir" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +printf "%s\n" "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir -cat >>confdefs.h <<_ACEOF -#define LT_OBJDIR "$lt_cv_objdir/" -_ACEOF +printf "%s\n" "#define LT_OBJDIR \"$lt_cv_objdir/\"" >>confdefs.h @@ -8441,7 +9755,7 @@ aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then + if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi @@ -8452,14 +9766,14 @@ esac ofile=libtool can_build_shared=yes -# All known linkers require a `.a' archive for static linking (except MSVC, -# which needs '.lib'). +# All known linkers require a '.a' archive for static linking (except MSVC and +# ICC, which need '.lib'). libext=a -with_gnu_ld="$lt_cv_prog_gnu_ld" +with_gnu_ld=$lt_cv_prog_gnu_ld -old_CC="$CC" -old_CFLAGS="$CFLAGS" +old_CC=$CC +old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc @@ -8468,15 +9782,8 @@ test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o -for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +func_cc_basename $compiler +cc_basename=$func_cc_basename_result # Only perform the check for file, if the check method requires it @@ -8484,29 +9791,30 @@ test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 -$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } -if ${lt_cv_path_MAGIC_CMD+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +printf %s "checking for ${ac_tool_prefix}file... " >&6; } +if test ${lt_cv_path_MAGIC_CMD+y} +then : + printf %s "(cached) " >&6 +else $as_nop case $MAGIC_CMD in [\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/${ac_tool_prefix}file; then - lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -f "$ac_dir/${ac_tool_prefix}file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : @@ -8529,19 +9837,19 @@ _LT_EOF break fi done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 -$as_echo "$MAGIC_CMD" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +printf "%s\n" "$MAGIC_CMD" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -8550,29 +9858,30 @@ fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 -$as_echo_n "checking for file... " >&6; } -if ${lt_cv_path_MAGIC_CMD+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +printf %s "checking for file... " >&6; } +if test ${lt_cv_path_MAGIC_CMD+y} +then : + printf %s "(cached) " >&6 +else $as_nop case $MAGIC_CMD in [\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/file; then - lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -f "$ac_dir/file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : @@ -8595,19 +9904,19 @@ _LT_EOF break fi done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 -$as_echo "$MAGIC_CMD" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +printf "%s\n" "$MAGIC_CMD" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -8622,7 +9931,7 @@ esac # Use C for the default configuration in the libtool script -lt_save_CC="$CC" +lt_save_CC=$CC ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -8684,7 +9993,7 @@ if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= -if test "$GCC" = yes; then +if test yes = "$GCC"; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; @@ -8692,15 +10001,16 @@ if test "$GCC" = yes; then lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 -$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } -if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +printf %s "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if test ${lt_cv_prog_compiler_rtti_exceptions+y} +then : + printf %s "(cached) " >&6 +else $as_nop lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="-fno-rtti -fno-exceptions" + lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins @@ -8727,10 +10037,10 @@ else $RM conftest* fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 -$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +printf "%s\n" "$lt_cv_prog_compiler_rtti_exceptions" >&6; } -if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then +if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : @@ -8748,17 +10058,18 @@ lt_prog_compiler_pic= lt_prog_compiler_static= - if test "$GCC" = yes; then + if test yes = "$GCC"; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi + lt_prog_compiler_pic='-fPIC' ;; amigaos*) @@ -8769,8 +10080,8 @@ lt_prog_compiler_static= ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac @@ -8786,6 +10097,11 @@ lt_prog_compiler_static= # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac ;; darwin* | rhapsody*) @@ -8856,7 +10172,7 @@ lt_prog_compiler_static= case $host_os in aix*) lt_prog_compiler_wl='-Wl,' - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else @@ -8864,10 +10180,29 @@ lt_prog_compiler_static= fi ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac ;; hpux9* | hpux10* | hpux11*) @@ -8883,7 +10218,7 @@ lt_prog_compiler_static= ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? - lt_prog_compiler_static='${wl}-a ${wl}archive' + lt_prog_compiler_static='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) @@ -8892,9 +10227,9 @@ lt_prog_compiler_static= lt_prog_compiler_static='-non_shared' ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in - # old Intel for x86_64 which still supported -KPIC. + # old Intel for x86_64, which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' @@ -8919,6 +10254,12 @@ lt_prog_compiler_static= lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) @@ -8938,7 +10279,7 @@ lt_prog_compiler_static= lt_prog_compiler_static='-qstaticlink' ;; *) - case `$CC -V 2>&1 | sed 5q` in + case `$CC -V 2>&1 | $SED 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' @@ -9016,7 +10357,7 @@ lt_prog_compiler_static= ;; sysv4*MP*) - if test -d /usr/nec ;then + if test -d /usr/nec; then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi @@ -9045,7 +10386,7 @@ lt_prog_compiler_static= fi case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: + # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; @@ -9054,30 +10395,32 @@ case $host_os in ;; esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 -$as_echo_n "checking for $compiler option to produce PIC... " >&6; } -if ${lt_cv_prog_compiler_pic+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +printf %s "checking for $compiler option to produce PIC... " >&6; } +if test ${lt_cv_prog_compiler_pic+y} +then : + printf %s "(cached) " >&6 +else $as_nop lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 -$as_echo "$lt_cv_prog_compiler_pic" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +printf "%s\n" "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 -$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } -if ${lt_cv_prog_compiler_pic_works+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +printf %s "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if test ${lt_cv_prog_compiler_pic_works+y} +then : + printf %s "(cached) " >&6 +else $as_nop lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins @@ -9104,10 +10447,10 @@ else $RM conftest* fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 -$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +printf "%s\n" "$lt_cv_prog_compiler_pic_works" >&6; } -if test x"$lt_cv_prog_compiler_pic_works" = xyes; then +if test yes = "$lt_cv_prog_compiler_pic_works"; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; @@ -9133,13 +10476,14 @@ fi # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 -$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } -if ${lt_cv_prog_compiler_static_works+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +printf %s "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if test ${lt_cv_prog_compiler_static_works+y} +then : + printf %s "(cached) " >&6 +else $as_nop lt_cv_prog_compiler_static_works=no - save_LDFLAGS="$LDFLAGS" + save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then @@ -9158,13 +10502,13 @@ else fi fi $RM -r conftest* - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 -$as_echo "$lt_cv_prog_compiler_static_works" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +printf "%s\n" "$lt_cv_prog_compiler_static_works" >&6; } -if test x"$lt_cv_prog_compiler_static_works" = xyes; then +if test yes = "$lt_cv_prog_compiler_static_works"; then : else lt_prog_compiler_static= @@ -9176,11 +10520,12 @@ fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 -$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } -if ${lt_cv_prog_compiler_c_o+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if test ${lt_cv_prog_compiler_c_o+y} +then : + printf %s "(cached) " >&6 +else $as_nop lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest @@ -9223,19 +10568,20 @@ else $RM conftest* fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 -$as_echo "$lt_cv_prog_compiler_c_o" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 -$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } -if ${lt_cv_prog_compiler_c_o+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if test ${lt_cv_prog_compiler_c_o+y} +then : + printf %s "(cached) " >&6 +else $as_nop lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest @@ -9278,28 +10624,28 @@ else $RM conftest* fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 -$as_echo "$lt_cv_prog_compiler_c_o" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; } -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 -$as_echo_n "checking if we can lock with hard links... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +printf %s "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 -$as_echo "$hard_links" >&6; } - if test "$hard_links" = no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +printf "%s\n" "$hard_links" >&6; } + if test no = "$hard_links"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +printf "%s\n" "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else @@ -9311,8 +10657,8 @@ fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= @@ -9342,9 +10688,9 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if @@ -9356,18 +10702,18 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie case $host_os in cygwin* | mingw* | pw32* | cegcc*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time + # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then + # Microsoft Visual C++ or Intel C++ Compiler. + if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) + # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC) with_gnu_ld=yes ;; - openbsd*) + openbsd* | bitrig*) with_gnu_ld=no ;; esac @@ -9377,7 +10723,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility @@ -9399,24 +10745,24 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie esac fi - if test "$lt_use_gnu_ld_interface" = yes; then + if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' + wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - export_dynamic_flag_spec='${wl}--export-dynamic' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + export_dynamic_flag_spec='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no - case `$LD -v 2>&1` in + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... @@ -9429,7 +10775,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then + if test ia64 != "$host_cpu"; then ld_shlibs=no cat <<_LT_EOF 1>&2 @@ -9448,7 +10794,7 @@ _LT_EOF case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) @@ -9464,7 +10810,7 @@ _LT_EOF allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME - archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs=no fi @@ -9474,7 +10820,7 @@ _LT_EOF # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' - export_dynamic_flag_spec='${wl}--export-all-symbols' + export_dynamic_flag_spec='$wl--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes @@ -9482,61 +10828,90 @@ _LT_EOF exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs=yes ;; + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + file_list_spec='@' + ;; + interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - export_dynamic_flag_spec='${wl}-E' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no - if test "$host_os" = linux-dietlibc; then + if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ - && test "$tmp_diet" = no + && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; @@ -9547,42 +10922,47 @@ _LT_EOF lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes ;; esac - case `$CC -V 2>&1 | sed 5q` in + case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C 5.9 - whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac - archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then + if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in + tcc*) + export_dynamic_flag_spec='-rdynamic' + ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then + if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac @@ -9596,8 +10976,8 @@ _LT_EOF archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; @@ -9615,8 +10995,8 @@ _LT_EOF _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi @@ -9628,7 +11008,7 @@ _LT_EOF ld_shlibs=no cat <<_LT_EOF 1>&2 -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify @@ -9643,9 +11023,9 @@ _LT_EOF # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi @@ -9662,15 +11042,15 @@ _LT_EOF *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac - if test "$ld_shlibs" = no; then + if test no = "$ld_shlibs"; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= @@ -9686,7 +11066,7 @@ _LT_EOF # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported @@ -9694,34 +11074,57 @@ _LT_EOF ;; aix[4-9]*) - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' - no_entry_flag="" + no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - # Also, AIX nm treats weak defined symbols like other global - # defined symbols, whereas GNU nm marks them as "W". + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else - export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi ;; esac @@ -9740,13 +11143,21 @@ _LT_EOF hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes - file_list_spec='${wl}-f,' + file_list_spec='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct=no + hardcode_direct_absolute=no + ;; + esac - if test "$GCC" = yes; then + if test yes = "$GCC"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` + collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then @@ -9765,52 +11176,61 @@ _LT_EOF ;; esac shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' else # not using gcc - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' else - shared_flag='${wl}-bM:SRE' + shared_flag='$wl-bM:SRE' fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' fi fi - export_dynamic_flag_spec='${wl}-bexpall' + export_dynamic_flag_spec='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes - if test "$aix_use_runtimelinking" = yes; then + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. - if test "${lt_cv_aix_libpath+set}" = set; then + if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else - if ${lt_cv_aix_libpath_+:} false; then : - $as_echo_n "(cached) " >&6 -else + if test ${lt_cv_aix_libpath_+y} +then : + printf %s "(cached) " >&6 +else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +if ac_fn_c_try_link "$LINENO" +then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { @@ -9825,10 +11245,10 @@ if ac_fn_c_try_link "$LINENO"; then : lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_="/usr/lib:/lib" + lt_cv_aix_libpath_=/usr/lib:/lib fi fi @@ -9836,34 +11256,36 @@ fi aix_libpath=$lt_cv_aix_libpath_ fi - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. - if test "${lt_cv_aix_libpath+set}" = set; then + if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else - if ${lt_cv_aix_libpath_+:} false; then : - $as_echo_n "(cached) " >&6 -else + if test ${lt_cv_aix_libpath_+y} +then : + printf %s "(cached) " >&6 +else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +if ac_fn_c_try_link "$LINENO" +then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { @@ -9878,10 +11300,10 @@ if ac_fn_c_try_link "$LINENO"; then : lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_="/usr/lib:/lib" + lt_cv_aix_libpath_=/usr/lib:/lib fi fi @@ -9889,21 +11311,33 @@ fi aix_libpath=$lt_cv_aix_libpath_ fi - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. - no_undefined_flag=' ${wl}-bernotok' - allow_undefined_flag=' ${wl}-berok' - if test "$with_gnu_ld" = yes; then + no_undefined_flag=' $wl-bernotok' + allow_undefined_flag=' $wl-berok' + if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. - whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes - # This is similar to how AIX traditionally builds its shared libraries. - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' fi fi ;; @@ -9912,7 +11346,7 @@ fi case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) @@ -9929,12 +11363,12 @@ fi cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. + # Microsoft Visual C++ or Intel C++ Compiler. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in - cl*) - # Native MSVC + cl* | icl*) + # Native MSVC or ICC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes @@ -9942,16 +11376,17 @@ fi # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" + shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' - archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; - else - sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes @@ -9960,27 +11395,27 @@ fi # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile="$lt_outputfile.exe" - lt_tool_outputfile="$lt_tool_outputfile.exe" - ;; - esac~ - if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' ;; *) - # Assume MSVC wrapper + # Assume MSVC and ICC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" + shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. @@ -9999,24 +11434,24 @@ fi hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported - if test "$lt_cv_ld_force_load" = "yes"; then - whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes - allow_undefined_flag="$_lt_dar_allow_undefined" + allow_undefined_flag=$_lt_dar_allow_undefined case $cc_basename in - ifort*) _lt_dar_can_shared=yes ;; + ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac - if test "$_lt_dar_can_shared" = "yes"; then + if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all - archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" - module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" - archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" - module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" else ld_shlibs=no @@ -10050,7 +11485,7 @@ fi ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly*) + freebsd* | dragonfly* | midnightbsd*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes @@ -10058,33 +11493,33 @@ fi ;; hpux9*) - if test "$GCC" = yes; then - archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + if test yes = "$GCC"; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else - archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes - export_dynamic_flag_spec='${wl}-E' + export_dynamic_flag_spec='$wl-E' ;; hpux10*) - if test "$GCC" = yes && test "$with_gnu_ld" = no; then - archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + if test yes,no = "$GCC,$with_gnu_ld"; then + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes - export_dynamic_flag_spec='${wl}-E' + export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes @@ -10092,37 +11527,38 @@ fi ;; hpux11*) - if test "$GCC" = yes && test "$with_gnu_ld" = no; then + if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) - archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) - archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 -$as_echo_n "checking if $CC understands -b... " >&6; } -if ${lt_cv_prog_compiler__b+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +printf %s "checking if $CC understands -b... " >&6; } +if test ${lt_cv_prog_compiler__b+y} +then : + printf %s "(cached) " >&6 +else $as_nop lt_cv_prog_compiler__b=no - save_LDFLAGS="$LDFLAGS" + save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then @@ -10141,14 +11577,14 @@ else fi fi $RM -r conftest* - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 -$as_echo "$lt_cv_prog_compiler__b" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +printf "%s\n" "$lt_cv_prog_compiler__b" >&6; } -if test x"$lt_cv_prog_compiler__b" = xyes; then - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +if test yes = "$lt_cv_prog_compiler__b"; then + archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi @@ -10156,8 +11592,8 @@ fi ;; esac fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: case $host_cpu in @@ -10168,7 +11604,7 @@ fi *) hardcode_direct=yes hardcode_direct_absolute=yes - export_dynamic_flag_spec='${wl}-E' + export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. @@ -10179,48 +11615,60 @@ fi ;; irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + if test yes = "$GCC"; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 -$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } -if ${lt_cv_irix_exported_symbol+:} false; then : - $as_echo_n "(cached) " >&6 -else - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +printf %s "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if test ${lt_cv_irix_exported_symbol+y} +then : + printf %s "(cached) " >&6 +else $as_nop + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +if ac_fn_c_try_link "$LINENO" +then : lt_cv_irix_exported_symbol=yes -else +else $as_nop lt_cv_irix_exported_symbol=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 -$as_echo "$lt_cv_irix_exported_symbol" >&6; } - if test "$lt_cv_irix_exported_symbol" = yes; then - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; } + if test yes = "$lt_cv_irix_exported_symbol"; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi else - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + ld_shlibs=yes + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out @@ -10235,7 +11683,7 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; @@ -10243,27 +11691,19 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } *nto* | *qnx*) ;; - openbsd*) + openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - export_dynamic_flag_spec='${wl}-E' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' else - case $host_os in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-R$libdir' - ;; - *) - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - ;; - esac + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' fi else ld_shlibs=no @@ -10274,33 +11714,54 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported - archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + file_list_spec='@' ;; osf3*) - if test "$GCC" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi archive_cmds_need_lc='no' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' else allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' @@ -10311,24 +11772,24 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } solaris*) no_undefined_flag=' -z defs' - if test "$GCC" = yes; then - wlarc='${wl}' - archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + wlarc='$wl' + archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' - archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) - wlarc='${wl}' - archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + wlarc='$wl' + archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi @@ -10338,11 +11799,11 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. GCC discards it without `$wl', + # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) - if test "$GCC" = yes; then - whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + if test yes = "$GCC"; then + whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi @@ -10352,10 +11813,10 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } ;; sunos4*) - if test "x$host_vendor" = xsequent; then + if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. - archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi @@ -10404,43 +11865,43 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) - no_undefined_flag='${wl}-z,text' + no_undefined_flag='$wl-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' - if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not + # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. - no_undefined_flag='${wl}-z,text' - allow_undefined_flag='${wl}-z,nodefs' + no_undefined_flag='$wl-z,text' + allow_undefined_flag='$wl-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='${wl}-R,$libdir' + hardcode_libdir_flag_spec='$wl-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes - export_dynamic_flag_spec='${wl}-Bexport' + export_dynamic_flag_spec='$wl-Bexport' runpath_var='LD_RUN_PATH' - if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; @@ -10455,18 +11916,18 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } ;; esac - if test x$host_vendor = xsni; then + if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - export_dynamic_flag_spec='${wl}-Blargedynsym' + export_dynamic_flag_spec='$wl-Blargedynsym' ;; esac fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 -$as_echo "$ld_shlibs" >&6; } -test "$ld_shlibs" = no && can_build_shared=no +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +printf "%s\n" "$ld_shlibs" >&6; } +test no = "$ld_shlibs" && can_build_shared=no with_gnu_ld=$with_gnu_ld @@ -10492,7 +11953,7 @@ x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes - if test "$enable_shared" = yes && test "$GCC" = yes; then + if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. @@ -10501,18 +11962,19 @@ x|xyes) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 -$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } -if ${lt_cv_archive_cmds_need_lc+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +printf %s "checking whether -lc should be explicitly linked in... " >&6; } +if test ${lt_cv_archive_cmds_need_lc+y} +then : + printf %s "(cached) " >&6 +else $as_nop $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest @@ -10530,7 +11992,7 @@ else if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no @@ -10544,8 +12006,8 @@ else $RM conftest* fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 -$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +printf "%s\n" "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac @@ -10704,17 +12166,17 @@ esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 -$as_echo_n "checking dynamic linker characteristics... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +printf %s "checking dynamic linker characteristics... " >&6; } -if test "$GCC" = yes; then +if test yes = "$GCC"; then case $host_os in - darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; - *) lt_awk_arg="/^libraries:/" ;; + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in - mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; - *) lt_sed_strip_eq="s,=/,/,g" ;; + mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in @@ -10730,28 +12192,35 @@ if test "$GCC" = yes; then ;; esac # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary. + # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= - lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path/$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" - else + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' -BEGIN {RS=" "; FS="/|\n";} { - lt_foo=""; - lt_count=0; +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { - lt_foo="/" $lt_i lt_foo; + lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } @@ -10765,7 +12234,7 @@ BEGIN {RS=" "; FS="/|\n";} { # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ - $SED 's,/\([A-Za-z]:\),\1,g'` ;; + $SED 's|/\([A-Za-z]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else @@ -10774,7 +12243,7 @@ fi library_names_spec= libname_spec='lib$name' soname_spec= -shrext_cmds=".so" +shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= @@ -10791,14 +12260,16 @@ hardcode_into_libs=no # flags to be left without arguments need_version=unknown + + case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' + soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) @@ -10806,41 +12277,91 @@ aix[4-9]*) need_lib_prefix=no need_version=no hardcode_into_libs=yes - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' - echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac shlibpath_var=LIBPATH fi ;; @@ -10850,18 +12371,18 @@ amigaos*) powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) - library_names_spec='${libname}${shared_ext}' + library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; @@ -10869,8 +12390,8 @@ beos*) bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" @@ -10882,7 +12403,7 @@ bsdi[45]*) cygwin* | mingw* | pw32* | cegcc*) version_type=windows - shrext_cmds=".dll" + shrext_cmds=.dll need_version=no need_lib_prefix=no @@ -10891,8 +12412,8 @@ cygwin* | mingw* | pw32* | cegcc*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ @@ -10908,27 +12429,27 @@ cygwin* | mingw* | pw32* | cegcc*) case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; - *,cl*) - # Native MSVC + *,cl* | *,icl*) + # Native MSVC or ICC libname_spec='$name' - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - library_names_spec='${libname}.dll.lib' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' case $build_os in mingw*) @@ -10944,7 +12465,7 @@ cygwin* | mingw* | pw32* | cegcc*) done IFS=$lt_save_ifs # Convert to MSYS style. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form @@ -10955,7 +12476,7 @@ cygwin* | mingw* | pw32* | cegcc*) sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) - sys_lib_search_path_spec="$LIB" + sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` @@ -10968,8 +12489,8 @@ cygwin* | mingw* | pw32* | cegcc*) esac # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' @@ -10981,8 +12502,8 @@ cygwin* | mingw* | pw32* | cegcc*) ;; *) - # Assume MSVC wrapper - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + # Assume MSVC and ICC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac @@ -10995,8 +12516,8 @@ darwin* | rhapsody*) version_type=darwin need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' @@ -11009,12 +12530,12 @@ dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; -freebsd* | dragonfly*) +freebsd* | dragonfly* | midnightbsd*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then @@ -11028,12 +12549,13 @@ freebsd* | dragonfly*) version_type=freebsd-$objformat case $version_type in freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac @@ -11058,26 +12580,15 @@ freebsd* | dragonfly*) esac ;; -gnu*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=yes + shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; @@ -11095,14 +12606,15 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' @@ -11110,8 +12622,8 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; @@ -11120,8 +12632,8 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... @@ -11134,8 +12646,8 @@ interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -11146,7 +12658,7 @@ irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) - if test "$lt_cv_prog_gnu_ld" = yes; then + if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix @@ -11154,8 +12666,8 @@ irix5* | irix6* | nonstopux*) esac need_lib_prefix=no need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= @@ -11174,8 +12686,8 @@ irix5* | irix6* | nonstopux*) esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; @@ -11184,21 +12696,42 @@ linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec='-L$libdir' + ;; + # This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH - if ${lt_cv_shlibpath_overrides_runpath+:} false; then : - $as_echo_n "(cached) " >&6 -else + if test ${lt_cv_shlibpath_overrides_runpath+y} +then : + printf %s "(cached) " >&6 +else $as_nop lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir @@ -11208,19 +12741,21 @@ else /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : +if ac_fn_c_try_link "$LINENO" +then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null +then : lt_cv_shlibpath_overrides_runpath=yes fi fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir @@ -11237,11 +12772,15 @@ fi # Add ABI-specific directories to the system library path. sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" - # Append ld.so.conf contents to the search path + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" - fi # We used to test for /lib/ld.so.1 and disable shared libraries on @@ -11258,12 +12797,12 @@ netbsd*) need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH @@ -11273,7 +12812,7 @@ netbsd*) newsos6) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; @@ -11282,58 +12821,68 @@ newsos6) version_type=qnx need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; -openbsd*) +openbsd* | bitrig*) version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" + sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no else - shlibpath_overrides_runpath=yes + need_version=yes fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' - shrext_cmds=".dll" + version_type=windows + shrext_cmds=.dll + need_version=no need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) @@ -11344,8 +12893,8 @@ solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes @@ -11355,11 +12904,11 @@ solaris*) sunos4*) version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes @@ -11367,8 +12916,8 @@ sunos4*) sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) @@ -11389,24 +12938,24 @@ sysv4 | sysv4.3*) ;; sysv4*MP*) - if test -d /usr/nec ;then + if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf + version_type=sco need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' @@ -11424,7 +12973,7 @@ tpf*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes @@ -11432,8 +12981,8 @@ tpf*) uts4*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; @@ -11441,22 +12990,31 @@ uts4*) dynamic_linker=no ;; esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 -$as_echo "$dynamic_linker" >&6; } -test "$dynamic_linker" = no && can_build_shared=no +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +printf "%s\n" "$dynamic_linker" >&6; } +test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then +if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi -if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then - sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi -if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then - sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH @@ -11548,20 +13106,26 @@ fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 -$as_echo_n "checking how to hardcode library paths into programs... " >&6; } + + + + + + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +printf %s "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || - test "X$hardcode_automatic" = "Xyes" ; then + test yes = "$hardcode_automatic"; then # We can hardcode non-existent directories. - if test "$hardcode_direct" != no && + if test no != "$hardcode_direct" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one - ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && - test "$hardcode_minus_L" != no; then + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && + test no != "$hardcode_minus_L"; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else @@ -11573,15 +13137,15 @@ else # directories. hardcode_action=unsupported fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 -$as_echo "$hardcode_action" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +printf "%s\n" "$hardcode_action" >&6; } -if test "$hardcode_action" = relink || - test "$inherit_rpath" = yes; then +if test relink = "$hardcode_action" || + test yes = "$inherit_rpath"; then # Fast installation is not supported enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi @@ -11591,7 +13155,7 @@ fi - if test "x$enable_dlopen" != xyes; then + if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown @@ -11601,28 +13165,29 @@ else case $host_os in beos*) - lt_cv_dlopen="load_add_on" + lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) - lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) - lt_cv_dlopen="dlopen" + lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) - # if libdl is installed we need to link against it - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 -$as_echo_n "checking for dlopen in -ldl... " >&6; } -if ${ac_cv_lib_dl_dlopen+:} false; then : - $as_echo_n "(cached) " >&6 -else + # if libdl is installed we need to link against it + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +printf %s "checking for dlopen in -ldl... " >&6; } +if test ${ac_cv_lib_dl_dlopen+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -11631,34 +13196,33 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif char dlopen (); int -main () +main (void) { return dlopen (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +if ac_fn_c_try_link "$LINENO" +then : ac_cv_lib_dl_dlopen=yes -else +else $as_nop ac_cv_lib_dl_dlopen=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 -$as_echo "$ac_cv_lib_dl_dlopen" >&6; } -if test "x$ac_cv_lib_dl_dlopen" = xyes; then : - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes +then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else $as_nop - lt_cv_dlopen="dyld" + lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes @@ -11666,16 +13230,26 @@ fi ;; + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" -if test "x$ac_cv_func_shl_load" = xyes; then : - lt_cv_dlopen="shl_load" -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 -$as_echo_n "checking for shl_load in -ldld... " >&6; } -if ${ac_cv_lib_dld_shl_load+:} false; then : - $as_echo_n "(cached) " >&6 -else +if test "x$ac_cv_func_shl_load" = xyes +then : + lt_cv_dlopen=shl_load +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +printf %s "checking for shl_load in -ldld... " >&6; } +if test ${ac_cv_lib_dld_shl_load+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -11684,41 +13258,42 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif char shl_load (); int -main () +main (void) { return shl_load (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +if ac_fn_c_try_link "$LINENO" +then : ac_cv_lib_dld_shl_load=yes -else +else $as_nop ac_cv_lib_dld_shl_load=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 -$as_echo "$ac_cv_lib_dld_shl_load" >&6; } -if test "x$ac_cv_lib_dld_shl_load" = xyes; then : - lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +printf "%s\n" "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes +then : + lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld +else $as_nop ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" -if test "x$ac_cv_func_dlopen" = xyes; then : - lt_cv_dlopen="dlopen" -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 -$as_echo_n "checking for dlopen in -ldl... " >&6; } -if ${ac_cv_lib_dl_dlopen+:} false; then : - $as_echo_n "(cached) " >&6 -else +if test "x$ac_cv_func_dlopen" = xyes +then : + lt_cv_dlopen=dlopen +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +printf %s "checking for dlopen in -ldl... " >&6; } +if test ${ac_cv_lib_dl_dlopen+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -11727,37 +13302,37 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif char dlopen (); int -main () +main (void) { return dlopen (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +if ac_fn_c_try_link "$LINENO" +then : ac_cv_lib_dl_dlopen=yes -else +else $as_nop ac_cv_lib_dl_dlopen=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 -$as_echo "$ac_cv_lib_dl_dlopen" >&6; } -if test "x$ac_cv_lib_dl_dlopen" = xyes; then : - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 -$as_echo_n "checking for dlopen in -lsvld... " >&6; } -if ${ac_cv_lib_svld_dlopen+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes +then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +printf %s "checking for dlopen in -lsvld... " >&6; } +if test ${ac_cv_lib_svld_dlopen+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -11766,37 +13341,37 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif char dlopen (); int -main () +main (void) { return dlopen (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +if ac_fn_c_try_link "$LINENO" +then : ac_cv_lib_svld_dlopen=yes -else +else $as_nop ac_cv_lib_svld_dlopen=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 -$as_echo "$ac_cv_lib_svld_dlopen" >&6; } -if test "x$ac_cv_lib_svld_dlopen" = xyes; then : - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 -$as_echo_n "checking for dld_link in -ldld... " >&6; } -if ${ac_cv_lib_dld_dld_link+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +printf "%s\n" "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes +then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +printf %s "checking for dld_link in -ldld... " >&6; } +if test ${ac_cv_lib_dld_dld_link+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -11805,31 +13380,30 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif char dld_link (); int -main () +main (void) { return dld_link (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +if ac_fn_c_try_link "$LINENO" +then : ac_cv_lib_dld_dld_link=yes -else +else $as_nop ac_cv_lib_dld_dld_link=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 -$as_echo "$ac_cv_lib_dld_dld_link" >&6; } -if test "x$ac_cv_lib_dld_dld_link" = xyes; then : - lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +printf "%s\n" "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes +then : + lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld fi @@ -11850,29 +13424,30 @@ fi ;; esac - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else + if test no = "$lt_cv_dlopen"; then enable_dlopen=no + else + enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - save_LDFLAGS="$LDFLAGS" + save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - save_LIBS="$LIBS" + save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 -$as_echo_n "checking whether a program can dlopen itself... " >&6; } -if ${lt_cv_dlopen_self+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +printf %s "checking whether a program can dlopen itself... " >&6; } +if test ${lt_cv_dlopen_self+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test yes = "$cross_compiling"; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 @@ -11919,9 +13494,9 @@ else # endif #endif -/* When -fvisbility=hidden is used, assume the code has been annotated +/* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ -#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif @@ -11950,8 +13525,8 @@ _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in @@ -11968,17 +13543,18 @@ rm -fr conftest* fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 -$as_echo "$lt_cv_dlopen_self" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +printf "%s\n" "$lt_cv_dlopen_self" >&6; } - if test "x$lt_cv_dlopen_self" = xyes; then + if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 -$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } -if ${lt_cv_dlopen_self_static+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +printf %s "checking whether a statically linked program can dlopen itself... " >&6; } +if test ${lt_cv_dlopen_self_static+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test yes = "$cross_compiling"; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 @@ -12025,9 +13601,9 @@ else # endif #endif -/* When -fvisbility=hidden is used, assume the code has been annotated +/* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ -#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif @@ -12056,8 +13632,8 @@ _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in @@ -12074,13 +13650,13 @@ rm -fr conftest* fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 -$as_echo "$lt_cv_dlopen_self_static" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +printf "%s\n" "$lt_cv_dlopen_self_static" >&6; } fi - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS ;; esac @@ -12113,32 +13689,43 @@ fi striplib= old_striplib= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 -$as_echo_n "checking whether stripping libraries is possible... " >&6; } -if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +printf %s "checking whether stripping libraries is possible... " >&6; } +if test -z "$STRIP"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +else + if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + old_striplib="$STRIP --strip-debug" + striplib="$STRIP --strip-unneeded" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + else + case $host_os in + darwin*) + # FIXME - insert some real tests, host_os isn't really good enough striplib="$STRIP -x" old_striplib="$STRIP -S" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - fi - ;; - *) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - ;; - esac + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + ;; + freebsd*) + if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then + old_striplib="$STRIP --strip-debug" + striplib="$STRIP --strip-unneeded" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + fi + ;; + *) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + ;; + esac + fi fi @@ -12152,21 +13739,21 @@ fi - # Report which library types will actually be built - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 -$as_echo_n "checking if libtool supports shared libraries... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 -$as_echo "$can_build_shared" >&6; } + # Report what library types will actually be built + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +printf %s "checking if libtool supports shared libraries... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +printf "%s\n" "$can_build_shared" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 -$as_echo_n "checking whether to build shared libraries... " >&6; } - test "$can_build_shared" = "no" && enable_shared=no + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +printf %s "checking whether to build shared libraries... " >&6; } + test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) - test "$enable_shared" = yes && enable_static=no + test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' @@ -12174,20 +13761,24 @@ $as_echo_n "checking whether to build shared libraries... " >&6; } ;; aix[4-9]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac fi ;; esac - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 -$as_echo "$enable_shared" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +printf "%s\n" "$enable_shared" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 -$as_echo_n "checking whether to build static libraries... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +printf %s "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 -$as_echo "$enable_static" >&6; } + test yes = "$enable_shared" || enable_static=yes + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +printf "%s\n" "$enable_static" >&6; } @@ -12199,7 +13790,7 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -CC="$lt_save_CC" +CC=$lt_save_CC @@ -12223,15 +13814,17 @@ CC="$lt_save_CC" # Only expand once: + for ac_prog in 'flex' do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_FLEX+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_FLEX+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$FLEX"; then ac_cv_prog_FLEX="$FLEX" # Let the user override the test. else @@ -12239,11 +13832,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_FLEX="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -12254,11 +13851,11 @@ fi fi FLEX=$ac_cv_prog_FLEX if test -n "$FLEX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FLEX" >&5 -$as_echo "$FLEX" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FLEX" >&5 +printf "%s\n" "$FLEX" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -12269,11 +13866,12 @@ for ac_prog in 'bison -y' do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_YACC+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_YACC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$YACC"; then ac_cv_prog_YACC="$YACC" # Let the user override the test. else @@ -12281,11 +13879,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_YACC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -12296,11 +13898,11 @@ fi fi YACC=$ac_cv_prog_YACC if test -n "$YACC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5 -$as_echo "$YACC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5 +printf "%s\n" "$YACC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -12308,29 +13910,30 @@ fi done -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 -$as_echo_n "checking for an ANSI C-conforming const... " >&6; } -if ${ac_cv_c_const+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +printf %s "checking for an ANSI C-conforming const... " >&6; } +if test ${ac_cv_c_const+y} +then : + printf %s "(cached) " >&6 +else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { -/* FIXME: Include the comments suggested by Paul. */ + #ifndef __cplusplus - /* Ultrix mips cc rejects this. */ + /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; - const charset cs; + const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; - /* AIX XL C 1.02.0.0 rejects this. + /* IBM XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ @@ -12340,8 +13943,9 @@ main () ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; - { /* SCO 3.2v4 cc rejects this. */ - char *t; + { /* SCO 3.2v4 cc rejects this sort of thing. */ + char tx; + char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; @@ -12357,10 +13961,10 @@ main () iptr p = 0; ++p; } - { /* AIX XL C 1.02.0.0 rejects this saying + { /* IBM XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ - struct s { int j; const int *ap[3]; }; - struct s *b; b->j = 5; + struct s { int j; const int *ap[3]; } bx; + struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; @@ -12373,47 +13977,50 @@ main () return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO" +then : ac_cv_c_const=yes -else +else $as_nop ac_cv_c_const=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 -$as_echo "$ac_cv_c_const" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +printf "%s\n" "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then -$as_echo "#define const /**/" >>confdefs.h +printf "%s\n" "#define const /**/" >>confdefs.h fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 -$as_echo_n "checking for inline... " >&6; } -if ${ac_cv_c_inline+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +printf %s "checking for inline... " >&6; } +if test ${ac_cv_c_inline+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; -static $ac_kw foo_t static_foo () {return 0; } -$ac_kw foo_t foo () {return 0; } +static $ac_kw foo_t static_foo (void) {return 0; } +$ac_kw foo_t foo (void) {return 0; } #endif _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO" +then : ac_cv_c_inline=$ac_kw fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 -$as_echo "$ac_cv_c_inline" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +printf "%s\n" "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; @@ -12437,15 +14044,17 @@ esac + if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_PKG_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_PKG_CONFIG+y} +then : + printf %s "(cached) " >&6 +else $as_nop case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. @@ -12455,11 +14064,15 @@ else for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -12471,11 +14084,11 @@ esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 -$as_echo "$PKG_CONFIG" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +printf "%s\n" "$PKG_CONFIG" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -12484,11 +14097,12 @@ if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_ac_pt_PKG_CONFIG+y} +then : + printf %s "(cached) " >&6 +else $as_nop case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. @@ -12498,11 +14112,15 @@ else for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -12514,11 +14132,11 @@ esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 -$as_echo "$ac_pt_PKG_CONFIG" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +printf "%s\n" "$ac_pt_PKG_CONFIG" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then @@ -12526,8 +14144,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG @@ -12539,32 +14157,33 @@ fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 - { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 -$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +printf %s "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } PKG_CONFIG="" fi fi pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CHECK" >&5 -$as_echo_n "checking for CHECK... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for check >= 0.9.0" >&5 +printf %s "checking for check >= 0.9.0... " >&6; } if test -n "$CHECK_CFLAGS"; then pkg_cv_CHECK_CFLAGS="$CHECK_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"check >= 0.9.0\""; } >&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"check >= 0.9.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "check >= 0.9.0") 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_CHECK_CFLAGS=`$PKG_CONFIG --cflags "check >= 0.9.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi @@ -12575,12 +14194,13 @@ if test -n "$CHECK_LIBS"; then pkg_cv_CHECK_LIBS="$CHECK_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"check >= 0.9.0\""; } >&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"check >= 0.9.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "check >= 0.9.0") 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_CHECK_LIBS=`$PKG_CONFIG --libs "check >= 0.9.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi @@ -12591,8 +14211,8 @@ fi if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes @@ -12600,57 +14220,63 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - CHECK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "check >= 0.9.0" 2>&1` + CHECK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "check >= 0.9.0" 2>&1` else - CHECK_PKG_ERRORS=`$PKG_CONFIG --print-errors "check >= 0.9.0" 2>&1` + CHECK_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "check >= 0.9.0" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$CHECK_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$CHECK_PKG_ERRORS" >&5 - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Disabling building of unit tests" >&5 -$as_echo "$as_me: WARNING: *** Disabling building of unit tests" >&2;} - enable_unit_tests="no" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** Disabling building of unit tests" >&5 +printf "%s\n" "$as_me: WARNING: *** Disabling building of unit tests" >&2;} + has_check="no" elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Disabling building of unit tests" >&5 -$as_echo "$as_me: WARNING: *** Disabling building of unit tests" >&2;} - enable_unit_tests="no" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** Disabling building of unit tests" >&5 +printf "%s\n" "$as_me: WARNING: *** Disabling building of unit tests" >&2;} + has_check="no" else - CHECK_CFLAGS=$pkg_cv_CHECK_CFLAGS - CHECK_LIBS=$pkg_cv_CHECK_LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - enable_unit_tests="yes" + CHECK_CFLAGS=$pkg_cv_CHECK_CFLAGS + CHECK_LIBS=$pkg_cv_CHECK_LIBS + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + has_check="yes" fi - - if test "$enable_unit_tests" = "yes"; then - ENABLE_UNIT_TESTS_TRUE= - ENABLE_UNIT_TESTS_FALSE='#' + if test "$has_check" = 'yes'; then + WITH_CHECK_TRUE= + WITH_CHECK_FALSE='#' else - ENABLE_UNIT_TESTS_TRUE='#' - ENABLE_UNIT_TESTS_FALSE= + WITH_CHECK_TRUE='#' + WITH_CHECK_FALSE= fi # Check whether --with-pkgconfigdir was given. -if test "${with_pkgconfigdir+set}" = set; then : +if test ${with_pkgconfigdir+y} +then : withval=$with_pkgconfigdir; pkgconfigdir="$withval" -else +else $as_nop pkgconfigdir='${libdir}/pkgconfig' fi # Check whether --enable-cli was given. -if test "${enable_cli+set}" = set; then : +if test ${enable_cli+y} +then : enableval=$enable_cli; enable_cli="$enableval" -else +else $as_nop enable_cli="yes" fi - if test "$enable_cli" = "yes"; then +if test "$enable_cli" != "no" && + test "$enable_cli" != "no-inst" && + test "$enable_cli" != "sbin"; then + enable_cli="bin" +fi + if test "$enable_cli" != "no"; then ENABLE_CLI_TRUE= ENABLE_CLI_FALSE='#' else @@ -12658,97 +14284,58 @@ else ENABLE_CLI_FALSE= fi - -# Check whether --enable-pthreads was given. -if test "${enable_pthreads+set}" = set; then : - enableval=$enable_pthreads; enable_pthreads="$enableval" + if test "$enable_cli" = "bin"; then + ENABLE_CLI_INSTALL_BIN_TRUE= + ENABLE_CLI_INSTALL_BIN_FALSE='#' else - enable_pthreads="yes" + ENABLE_CLI_INSTALL_BIN_TRUE='#' + ENABLE_CLI_INSTALL_BIN_FALSE= fi - if test "$enable_pthreads" = "no"; then - DISABLE_PTHREADS_TRUE= - DISABLE_PTHREADS_FALSE='#' + if test "$enable_cli" = "sbin"; then + ENABLE_CLI_INSTALL_SBIN_TRUE= + ENABLE_CLI_INSTALL_SBIN_FALSE='#' else - DISABLE_PTHREADS_TRUE='#' - DISABLE_PTHREADS_FALSE= + ENABLE_CLI_INSTALL_SBIN_TRUE='#' + ENABLE_CLI_INSTALL_SBIN_FALSE= fi -# Check whether --enable-debug was given. -if test "${enable_debug+set}" = set; then : - enableval=$enable_debug; enable_debug="$enableval" -else - enable_debug="yes" -fi +ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default" +if test "x$ac_cv_header_dlfcn_h" = xyes +then : + printf "%s\n" "#define HAVE_DLFCN_H 1" >>confdefs.h - if test "$enable_debug" = "no" ; then - ENABLE_DEBUG_TRUE= - ENABLE_DEBUG_FALSE='#' -else - ENABLE_DEBUG_TRUE='#' - ENABLE_DEBUG_FALSE= fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pow in -lm" >&5 -$as_echo_n "checking for pow in -lm... " >&6; } -if ${ac_cv_lib_m_pow+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lm $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char pow (); -int -main () -{ -return pow (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_m_pow=yes -else - ac_cv_lib_m_pow=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS +# Check whether --enable-pthreads was given. +if test ${enable_pthreads+y} +then : + enableval=$enable_pthreads; enable_pthreads="$enableval" +else $as_nop + enable_pthreads="yes" fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_pow" >&5 -$as_echo "$ac_cv_lib_m_pow" >&6; } -if test "x$ac_cv_lib_m_pow" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBM 1 -_ACEOF - - LIBS="-lm $LIBS" + if test "$enable_pthreads" = "no"; then + DISABLE_PTHREADS_TRUE= + DISABLE_PTHREADS_FALSE='#' else - as_fn_error $? "libm is required" "$LINENO" 5 + DISABLE_PTHREADS_TRUE='#' + DISABLE_PTHREADS_FALSE= fi - if test "x$enable_pthreads" = "xno"; then -$as_echo "#define DISABLE_PTHREADS 1" >>confdefs.h +printf "%s\n" "#define DISABLE_PTHREADS 1" >>confdefs.h else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_lock in -lpthread" >&5 -$as_echo_n "checking for pthread_mutex_lock in -lpthread... " >&6; } -if ${ac_cv_lib_pthread_pthread_mutex_lock+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_lock in -lpthread" >&5 +printf %s "checking for pthread_mutex_lock in -lpthread... " >&6; } +if test ${ac_cv_lib_pthread_pthread_mutex_lock+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -12757,45 +14344,59 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif char pthread_mutex_lock (); int -main () +main (void) { return pthread_mutex_lock (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +if ac_fn_c_try_link "$LINENO" +then : ac_cv_lib_pthread_pthread_mutex_lock=yes -else +else $as_nop ac_cv_lib_pthread_pthread_mutex_lock=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_lock" >&5 -$as_echo "$ac_cv_lib_pthread_pthread_mutex_lock" >&6; } -if test "x$ac_cv_lib_pthread_pthread_mutex_lock" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBPTHREAD 1 -_ACEOF +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_lock" >&5 +printf "%s\n" "$ac_cv_lib_pthread_pthread_mutex_lock" >&6; } +if test "x$ac_cv_lib_pthread_pthread_mutex_lock" = xyes +then : + printf "%s\n" "#define HAVE_LIBPTHREAD 1" >>confdefs.h LIBS="-lpthread $LIBS" -else +else $as_nop as_fn_error $? "libpthread is required" "$LINENO" 5 fi fi + if test "$enable_static" != "no"; then + ENABLE_STATIC_TRUE= + ENABLE_STATIC_FALSE='#' +else + ENABLE_STATIC_TRUE='#' + ENABLE_STATIC_FALSE= +fi + + +# Check whether --enable-debug was given. +if test ${enable_debug+y} +then : + enableval=$enable_debug; enable_debug="$enableval" +else $as_nop + enable_debug="yes" +fi + if test "x$enable_debug" = "xyes"; then -$as_echo "#define NL_DEBUG 1" >>confdefs.h +printf "%s\n" "#define NL_DEBUG 1" >>confdefs.h fi @@ -12804,18 +14405,130 @@ fi subdirs="$subdirs doc" -ac_config_files="$ac_config_files Makefile libnl-3.0.pc libnl-route-3.0.pc libnl-genl-3.0.pc libnl-nf-3.0.pc libnl-cli-3.0.pc lib/Makefile include/Makefile src/Makefile src/lib/Makefile tests/Makefile man/Makefile python/Makefile python/setup.py python/netlink/Makefile python/netlink/route/Makefile include/netlink/version.h" +ac_fn_c_check_func "$LINENO" "strerror_l" "ac_cv_func_strerror_l" +if test "x$ac_cv_func_strerror_l" = xyes +then : + printf "%s\n" "#define HAVE_STRERROR_L 1" >>confdefs.h + +fi + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5 +printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; } +if test ${ac_cv_c_undeclared_builtin_options+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_save_CFLAGS=$CFLAGS + ac_cv_c_undeclared_builtin_options='cannot detect' + for ac_arg in '' -fno-builtin; do + CFLAGS="$ac_save_CFLAGS $ac_arg" + # This test program should *not* compile successfully. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +(void) strchr; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + +else $as_nop + # This test program should compile successfully. + # No library function is consistently available on + # freestanding implementations, so test against a dummy + # declaration. Include always-available headers on the + # off chance that they somehow elicit warnings. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +extern void ac_decl (int, char *); + +int +main (void) +{ +(void) ac_decl (0, (char *) 0); + (void) ac_decl; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + if test x"$ac_arg" = x +then : + ac_cv_c_undeclared_builtin_options='none needed' +else $as_nop + ac_cv_c_undeclared_builtin_options=$ac_arg +fi + break +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + done + CFLAGS=$ac_save_CFLAGS + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_undeclared_builtin_options" >&5 +printf "%s\n" "$ac_cv_c_undeclared_builtin_options" >&6; } + case $ac_cv_c_undeclared_builtin_options in #( + 'cannot detect') : + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot make $CC report undeclared builtins +See \`config.log' for more details" "$LINENO" 5; } ;; #( + 'none needed') : + ac_c_undeclared_builtin_options='' ;; #( + *) : + ac_c_undeclared_builtin_options=$ac_cv_c_undeclared_builtin_options ;; +esac + +ac_fn_check_decl "$LINENO" "getprotobyname_r" "ac_cv_have_decl_getprotobyname_r" " + #include + +" "$ac_c_undeclared_builtin_options" "CFLAGS" +if test "x$ac_cv_have_decl_getprotobyname_r" = xyes +then : + ac_have_decl=1 +else $as_nop + ac_have_decl=0 +fi +printf "%s\n" "#define HAVE_DECL_GETPROTOBYNAME_R $ac_have_decl" >>confdefs.h +ac_fn_check_decl "$LINENO" "getprotobynumber_r" "ac_cv_have_decl_getprotobynumber_r" " + #include + +" "$ac_c_undeclared_builtin_options" "CFLAGS" +if test "x$ac_cv_have_decl_getprotobynumber_r" = xyes +then : + ac_have_decl=1 +else $as_nop + ac_have_decl=0 +fi +printf "%s\n" "#define HAVE_DECL_GETPROTOBYNUMBER_R $ac_have_decl" >>confdefs.h + + +ac_config_files="$ac_config_files Makefile libnl-3.0.pc libnl-route-3.0.pc libnl-genl-3.0.pc libnl-nf-3.0.pc libnl-cli-3.0.pc libnl-xfrm-3.0.pc libnl-idiag-3.0.pc python/setup.py include/netlink/version.h" ac_errcount=0 if test -z "$YACC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: bison not found. Please install before continuing." >&5 -$as_echo "$as_me: WARNING: bison not found. Please install before continuing." >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: bison not found. Please install before continuing." >&5 +printf "%s\n" "$as_me: WARNING: bison not found. Please install before continuing." >&2;} ac_errcount=$((ac_errcount + 1)) fi if test -z "$FLEX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: flex not found. Please install before continuing." >&5 -$as_echo "$as_me: WARNING: flex not found. Please install before continuing." >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: flex not found. Please install before continuing." >&5 +printf "%s\n" "$as_me: WARNING: flex not found. Please install before continuing." >&2;} ac_errcount=$((ac_errcount + 1)) fi if test $ac_errcount -gt 0; then @@ -12849,8 +14562,8 @@ _ACEOF case $ac_val in #( *${as_nl}*) case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( @@ -12880,15 +14593,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; /^ac_cv_env_/b end t clear :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 -$as_echo "$as_me: updating cache $cache_file" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +printf "%s\n" "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else @@ -12902,8 +14615,8 @@ $as_echo "$as_me: updating cache $cache_file" >&6;} fi fi else - { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 -$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache @@ -12920,7 +14633,7 @@ U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' - ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" @@ -12931,6 +14644,14 @@ LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +printf %s "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: done" >&5 +printf "%s\n" "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' @@ -12951,20 +14672,28 @@ if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${ENABLE_UNIT_TESTS_TRUE}" && test -z "${ENABLE_UNIT_TESTS_FALSE}"; then - as_fn_error $? "conditional \"ENABLE_UNIT_TESTS\" was never defined. +if test -z "${WITH_CHECK_TRUE}" && test -z "${WITH_CHECK_FALSE}"; then + as_fn_error $? "conditional \"WITH_CHECK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_CLI_TRUE}" && test -z "${ENABLE_CLI_FALSE}"; then as_fn_error $? "conditional \"ENABLE_CLI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${ENABLE_CLI_INSTALL_BIN_TRUE}" && test -z "${ENABLE_CLI_INSTALL_BIN_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_CLI_INSTALL_BIN\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_CLI_INSTALL_SBIN_TRUE}" && test -z "${ENABLE_CLI_INSTALL_SBIN_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_CLI_INSTALL_SBIN\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${DISABLE_PTHREADS_TRUE}" && test -z "${DISABLE_PTHREADS_FALSE}"; then as_fn_error $? "conditional \"DISABLE_PTHREADS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${ENABLE_DEBUG_TRUE}" && test -z "${ENABLE_DEBUG_FALSE}"; then - as_fn_error $? "conditional \"ENABLE_DEBUG\" was never defined. +if test -z "${ENABLE_STATIC_TRUE}" && test -z "${ENABLE_STATIC_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_STATIC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi @@ -12972,8 +14701,8 @@ fi ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 -$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL @@ -12996,14 +14725,16 @@ cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : +as_nop=: +if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 +then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST -else +else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( @@ -13013,46 +14744,46 @@ esac fi + +# Reset variables that may have inherited troublesome values from +# the environment. + +# IFS needs to be set, to space, tab, and newline, in precisely that order. +# (If _AS_PATH_WALK were called with IFS unset, it would have the +# side effect of setting IFS to empty, thus disabling word splitting.) +# Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi +IFS=" "" $as_nl" + +PS1='$ ' +PS2='> ' +PS4='+ ' + +# Ensure predictable behavior from utilities with locale-dependent output. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# We cannot yet rely on "unset" to work, but we need these variables +# to be unset--not just set to an empty or harmless value--now, to +# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct +# also avoids known problems related to "unset" and subshell syntax +# in other old shells (e.g. bash 2.01 and pdksh 5.2.14). +for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH +do eval test \${$as_var+y} \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done + +# Ensure that fds 0, 1, and 2 are open. +if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi +if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then +if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || @@ -13061,13 +14792,6 @@ if test "${PATH_SEPARATOR+set}" != set; then fi -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( @@ -13076,8 +14800,12 @@ case $0 in #(( for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS @@ -13089,30 +14817,10 @@ if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] @@ -13125,13 +14833,14 @@ as_fn_error () as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi - $as_echo "$as_me: error: $2" >&2 + printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error + # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. @@ -13158,18 +14867,20 @@ as_fn_unset () { eval $1=; unset $1;} } as_unset=as_fn_unset + # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null +then : eval 'as_fn_append () { eval $1+=\$2 }' -else +else $as_nop as_fn_append () { eval $1=\$$1\$2 @@ -13181,12 +14892,13 @@ fi # as_fn_append # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null +then : eval 'as_fn_arith () { as_val=$(( $* )) }' -else +else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` @@ -13217,7 +14929,7 @@ as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | +printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q @@ -13239,6 +14951,10 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits + +# Determine whether it's possible to make 'echo' print without a newline. +# These variables are no longer used directly by Autoconf, but are AC_SUBSTed +# for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) @@ -13252,6 +14968,12 @@ case `echo -n x` in #((((( ECHO_N='-n';; esac +# For backward compatibility with old third-party macros, we provide +# the shell variables $as_echo and $as_echo_n. New code should use +# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. +as_echo='printf %s\n' +as_echo_n='printf %s' + rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file @@ -13265,16 +14987,16 @@ if (echo >conf$$.file) 2>/dev/null; then # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. + # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' + as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null @@ -13293,7 +15015,7 @@ as_fn_mkdir_p () as_dirs= while :; do case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" @@ -13302,7 +15024,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | +printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -13334,28 +15056,16 @@ else as_mkdir_p=false fi -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in #( - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" @@ -13376,8 +15086,8 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by libnl $as_me 3.2.22, which was -generated by GNU Autoconf 2.68. Invocation command line was +This file was extended by libnl $as_me 3.9.0, which was +generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -13440,14 +15150,16 @@ Report bugs to the package provider. libnl home page: ." _ACEOF +ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` +ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -libnl config.status 3.2.22 -configured by $0, generated by GNU Autoconf 2.68, +libnl config.status 3.9.0 +configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" -Copyright (C) 2010 Free Software Foundation, Inc. +Copyright (C) 2021 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." @@ -13487,15 +15199,15 @@ do -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - $as_echo "$ac_cs_version"; exit ;; + printf "%s\n" "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) - $as_echo "$ac_cs_config"; exit ;; + printf "%s\n" "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" @@ -13503,7 +15215,7 @@ do --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; @@ -13512,7 +15224,7 @@ do as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) - $as_echo "$ac_cs_usage"; exit ;; + printf "%s\n" "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; @@ -13538,9 +15250,9 @@ fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then - set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift - \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" @@ -13554,7 +15266,7 @@ exec 5>>config.log sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX - $as_echo "$ac_log" + printf "%s\n" "$ac_log" } >&5 _ACEOF @@ -13562,7 +15274,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # -AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" +AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" # The HP-UX ksh and POSIX shell print the target directory to stdout @@ -13578,6 +15290,7 @@ enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' @@ -13605,6 +15318,7 @@ lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_q lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +FILECMD='`$ECHO "$FILECMD" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' @@ -13613,6 +15327,7 @@ want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +lt_ar_flags='`$ECHO "$lt_ar_flags" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' @@ -13627,10 +15342,13 @@ compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' @@ -13695,7 +15413,8 @@ finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' -sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' +configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' +configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' @@ -13729,6 +15448,7 @@ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ +FILECMD \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ @@ -13737,7 +15457,6 @@ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ -AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ @@ -13746,9 +15465,12 @@ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_import \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +lt_cv_nm_interface \ nm_file_list_spec \ +lt_cv_truncate_bin \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ @@ -13783,7 +15505,7 @@ old_striplib \ striplib; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -13810,10 +15532,11 @@ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ -sys_lib_dlsearch_path_spec; do +configure_time_dlsearch_path \ +configure_time_lt_sys_library_path; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -13822,19 +15545,16 @@ sys_lib_dlsearch_path_spec; do done ac_aux_dir='$ac_aux_dir' -xsi_shell='$xsi_shell' -lt_shell_append='$lt_shell_append' -# See if we are running on zsh, and set the options which allow our +# See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. -if test -n "\${ZSH_VERSION+set}" ; then +if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' - TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' @@ -13849,7 +15569,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 for ac_config_target in $ac_config_targets do case $ac_config_target in - "lib/defs.h") CONFIG_HEADERS="$CONFIG_HEADERS lib/defs.h" ;; + "include/config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; @@ -13858,16 +15578,9 @@ do "libnl-genl-3.0.pc") CONFIG_FILES="$CONFIG_FILES libnl-genl-3.0.pc" ;; "libnl-nf-3.0.pc") CONFIG_FILES="$CONFIG_FILES libnl-nf-3.0.pc" ;; "libnl-cli-3.0.pc") CONFIG_FILES="$CONFIG_FILES libnl-cli-3.0.pc" ;; - "lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;; - "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; - "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; - "src/lib/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib/Makefile" ;; - "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; - "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; - "python/Makefile") CONFIG_FILES="$CONFIG_FILES python/Makefile" ;; + "libnl-xfrm-3.0.pc") CONFIG_FILES="$CONFIG_FILES libnl-xfrm-3.0.pc" ;; + "libnl-idiag-3.0.pc") CONFIG_FILES="$CONFIG_FILES libnl-idiag-3.0.pc" ;; "python/setup.py") CONFIG_FILES="$CONFIG_FILES python/setup.py" ;; - "python/netlink/Makefile") CONFIG_FILES="$CONFIG_FILES python/netlink/Makefile" ;; - "python/netlink/route/Makefile") CONFIG_FILES="$CONFIG_FILES python/netlink/route/Makefile" ;; "include/netlink/version.h") CONFIG_FILES="$CONFIG_FILES include/netlink/version.h" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; @@ -13880,9 +15593,9 @@ done # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files - test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers - test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands + test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files + test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers + test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree @@ -14218,7 +15931,7 @@ do esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac - case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done @@ -14226,17 +15939,17 @@ do # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` - $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" - { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 -$as_echo "$as_me: creating $ac_file" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +printf "%s\n" "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) - ac_sed_conf_input=`$as_echo "$configure_input" | + ac_sed_conf_input=`printf "%s\n" "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac @@ -14253,7 +15966,7 @@ $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$ac_file" | +printf "%s\n" X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -14277,9 +15990,9 @@ $as_echo X"$ac_file" | case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; @@ -14341,8 +16054,8 @@ ac_sed_dataroot=' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' @@ -14386,9 +16099,9 @@ test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 -$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" @@ -14404,20 +16117,20 @@ which seems to be undefined. Please make sure it is defined" >&2;} # if test x"$ac_file" != x-; then { - $as_echo "/* $configure_input */" \ + printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then - { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 -$as_echo "$as_me: $ac_file is unchanged" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +printf "%s\n" "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else - $as_echo "/* $configure_input */" \ + printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi @@ -14437,7 +16150,7 @@ $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$_am_arg" | +printf "%s\n" X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -14457,40 +16170,46 @@ $as_echo X"$_am_arg" | s/.*/./; q'`/stamp-h$_am_stamp_count ;; - :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 -$as_echo "$as_me: executing $ac_file commands" >&6;} + :C) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +printf "%s\n" "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { - # Autoconf 2.62 quotes --file arguments for eval, but not when files + # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + case $CONFIG_FILES in #( + *\'*) : + eval set x "$CONFIG_FILES" ;; #( + *) : + set x $CONFIG_FILES ;; #( + *) : + ;; +esac shift - for mf + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf do # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named `Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line + am_mf=`printf "%s\n" "$am_mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`$as_dirname -- "$mf" || -$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$mf" : 'X\(//\)[^/]' \| \ - X"$mf" : 'X\(//\)$' \| \ - X"$mf" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$mf" | + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`$as_dirname -- "$am_mf" || +$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$am_mf" : 'X\(//\)[^/]' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +printf "%s\n" X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -14508,108 +16227,101 @@ $as_echo X"$mf" | q } s/.*/./; q'` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running `make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # When using ansi2knr, U may be empty or an underscore; expand it - U=`sed -n 's/^U = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`$as_dirname -- "$file" || -$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$file" : 'X\(//\)[^/]' \| \ - X"$file" : 'X\(//\)$' \| \ - X"$file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ + am_filepart=`$as_basename -- "$am_mf" || +$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +printf "%s\n" X/"$am_mf" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } - /^X\(\/\/\)$/{ + /^X\/\(\/\/\)$/{ s//\1/ q } - /^X\(\/\).*/{ + /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` - as_dir=$dirpart/$fdir; as_fn_mkdir_p - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done + { echo "$as_me:$LINENO: cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles" >&5 + (cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } || am_rc=$? done + if test $am_rc -ne 0; then + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE=\"gmake\" (or whatever is + necessary). You can also try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking). +See \`config.log' for more details" "$LINENO" 5; } + fi + { am_dirpart=; unset am_dirpart;} + { am_filepart=; unset am_filepart;} + { am_mf=; unset am_mf;} + { am_rc=; unset am_rc;} + rm -f conftest-deps.mk } ;; "libtool":C) - # See if we are running on zsh, and set the options which allow our + # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then + if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi - cfgfile="${ofile}T" + cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL - -# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Generated automatically by $as_me ($PACKAGE) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. # -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# Written by Gordon Matzigkeit, 1996 -# -# This file is part of GNU Libtool. -# -# GNU Libtool is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# -# As a special exception to the GNU General Public License, -# if you distribute this file as part of a program or library that -# is built using GNU Libtool, you may include this file under the -# same distribution terms that you use for the rest of that program. +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. # -# GNU Libtool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, or -# obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# along with this program. If not, see . # The names of the tagged configurations supported by this script. -available_tags="" +available_tags='' + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG @@ -14629,6 +16341,9 @@ pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec=$shared_archive_member_spec + # Shell to use when invoking shell scripts. SHELL=$lt_SHELL @@ -14693,6 +16408,9 @@ to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd +# A file(cmd) program that detects file types. +FILECMD=$lt_FILECMD + # An object symbol dumper. OBJDUMP=$lt_OBJDUMP @@ -14717,8 +16435,11 @@ sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR +# Flags to create an archive (by configure). +lt_ar_flags=$lt_ar_flags + # Flags to create an archive. -AR_FLAGS=$lt_AR_FLAGS +AR_FLAGS=\${ARFLAGS-"\$lt_ar_flags"} # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec @@ -14746,18 +16467,27 @@ global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import + # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix +# The name lister interface. +nm_interface=$lt_lt_cv_nm_interface + # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec -# The root where to search for dependent libraries,and in which our libraries should be installed. +# The root where to search for dependent libraries,and where our libraries should be installed. lt_sysroot=$lt_sysroot +# Command to truncate a binary pipe. +lt_truncate_bin=$lt_lt_cv_truncate_bin + # The name of the directory that contains temporary libtool files. objdir=$objdir @@ -14848,8 +16578,11 @@ hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec -# Run-time system search path for libraries. -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path # Whether dlopen is supported. dlopen_support=$enable_dlopen @@ -14942,13 +16675,13 @@ hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator -# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct -# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is -# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute @@ -15000,13 +16733,72 @@ hardcode_action=$hardcode_action _LT_EOF + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then +if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi @@ -15015,175 +16807,17 @@ _LT_EOF esac -ltmain="$ac_aux_dir/ltmain.sh" + +ltmain=$ac_aux_dir/ltmain.sh # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? - sed '$q' "$ltmain" >> "$cfgfile" \ + $SED '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) - if test x"$xsi_shell" = xyes; then - sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ -func_dirname ()\ -{\ -\ case ${1} in\ -\ */*) func_dirname_result="${1%/*}${2}" ;;\ -\ * ) func_dirname_result="${3}" ;;\ -\ esac\ -} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_basename ()$/,/^} # func_basename /c\ -func_basename ()\ -{\ -\ func_basename_result="${1##*/}"\ -} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ -func_dirname_and_basename ()\ -{\ -\ case ${1} in\ -\ */*) func_dirname_result="${1%/*}${2}" ;;\ -\ * ) func_dirname_result="${3}" ;;\ -\ esac\ -\ func_basename_result="${1##*/}"\ -} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ -func_stripname ()\ -{\ -\ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ -\ # positional parameters, so assign one to ordinary parameter first.\ -\ func_stripname_result=${3}\ -\ func_stripname_result=${func_stripname_result#"${1}"}\ -\ func_stripname_result=${func_stripname_result%"${2}"}\ -} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ -func_split_long_opt ()\ -{\ -\ func_split_long_opt_name=${1%%=*}\ -\ func_split_long_opt_arg=${1#*=}\ -} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ -func_split_short_opt ()\ -{\ -\ func_split_short_opt_arg=${1#??}\ -\ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ -} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ -func_lo2o ()\ -{\ -\ case ${1} in\ -\ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ -\ *) func_lo2o_result=${1} ;;\ -\ esac\ -} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_xform ()$/,/^} # func_xform /c\ -func_xform ()\ -{\ - func_xform_result=${1%.*}.lo\ -} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_arith ()$/,/^} # func_arith /c\ -func_arith ()\ -{\ - func_arith_result=$(( $* ))\ -} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_len ()$/,/^} # func_len /c\ -func_len ()\ -{\ - func_len_result=${#1}\ -} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - -fi - -if test x"$lt_shell_append" = xyes; then - sed -e '/^func_append ()$/,/^} # func_append /c\ -func_append ()\ -{\ - eval "${1}+=\\${2}"\ -} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ -func_append_quoted ()\ -{\ -\ func_quote_for_eval "${2}"\ -\ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ -} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - # Save a `func_append' function call where possible by direct use of '+=' - sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") - test 0 -eq $? || _lt_function_replace_fail=: -else - # Save a `func_append' function call even when '+=' is not available - sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") - test 0 -eq $? || _lt_function_replace_fail=: -fi - -if test x"$_lt_function_replace_fail" = x":"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 -$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} -fi - - mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" @@ -15262,7 +16896,7 @@ if test "$no_recursion" != yes; then ;; *) case $ac_arg in - *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append ac_sub_configure_args " '$ac_arg'" ;; esac @@ -15272,7 +16906,7 @@ if test "$no_recursion" != yes; then # in subdir configurations. ac_arg="--prefix=$prefix" case $ac_arg in - *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args" @@ -15293,17 +16927,17 @@ if test "$no_recursion" != yes; then test -d "$srcdir/$ac_dir" || continue ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)" - $as_echo "$as_me:${as_lineno-$LINENO}: $ac_msg" >&5 - $as_echo "$ac_msg" >&6 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_msg" >&5 + printf "%s\n" "$ac_msg" >&6 as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; @@ -15333,17 +16967,15 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" - # Check for guested configure; otherwise get Cygnus style configure. + # Check for configure.gnu first; this name is used for a wrapper for + # Metaconfig's "Configure" on case-insensitive file systems. if test -f "$ac_srcdir/configure.gnu"; then ac_sub_configure=$ac_srcdir/configure.gnu elif test -f "$ac_srcdir/configure"; then ac_sub_configure=$ac_srcdir/configure - elif test -f "$ac_srcdir/configure.in"; then - # This should be Cygnus configure. - ac_sub_configure=$ac_aux_dir/configure else - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in $ac_dir" >&5 -$as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in $ac_dir" >&5 +printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} ac_sub_configure= fi @@ -15356,8 +16988,8 @@ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} ac_sub_cache_file=$ac_top_build_prefix$cache_file ;; esac - { $as_echo "$as_me:${as_lineno-$LINENO}: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 -$as_echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 +printf "%s\n" "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} # The eval makes quoting arguments work. eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \ --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" || @@ -15368,31 +17000,19 @@ $as_echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cach done fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 -$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} -fi - - -echo "-------------------------------------------------------------------------------" -echo " NOTE" -echo "" -echo " There have been some changes starting with 3.2 regarding where and how libnl" -echo " is being installed on the system in order to allow multiple libnl versions" -echo " to be installed in parallel:" -echo "" -echo " - Headers will be installed in ${includedir}/libnl${MAJ_VERSION}, therefore" -echo " you will need to add \"-I/usr/include/libnl${MAJ_VERSION}\" to CFLAGS" -echo "" -echo " - The library basename was renamed to libnl-${MAJ_VERSION}, i.e. the SO names become" -echo " libnl-${MAJ_VERSION}.so., libnl-route-${MAJ_VERSION}.so, etc." -echo "" -echo " - libtool versioning was assumed, to ease detection of compatible library" -echo " versions." -echo "" -echo " If you are using pkg-config for detecting and linking against the library " -echo " things will continue magically as if nothing every happened. If you are " -echo " linking manually you need to adapt your Makefiles or switch to using " -echo " pkg-config files." -echo "" -echo "-------------------------------------------------------------------------------" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + +echo +echo "libnl $LIBNL_VERSION configuration${LIBNL_GIT_SHA:+ (git:$LIBNL_GIT_SHA)}:" +echo " --enable-pthreads=$enable_pthreads" +echo " --enable-static=$enable_static" +echo +echo " --enable-debug=$enable_debug" +echo " --enable-cli=$enable_cli" +echo +echo " check: $has_check" +echo diff --git a/configure.ac b/configure.ac index 34e8c9f..bc8b390 100644 --- a/configure.ac +++ b/configure.ac @@ -1,19 +1,14 @@ -# -# configure.in -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation version 2.1 -# of the License. +# SPDX-License-Identifier: LGPL-2.1-only + # # Copyright (c) 2003-2013 Thomas Graf # - # copied from glib m4_define([libnl_major_version], [3]) -m4_define([libnl_minor_version], [2]) -m4_define([libnl_micro_version], [22]) +m4_define([libnl_minor_version], [9]) +m4_define([libnl_micro_version], [0]) +m4_define([libnl_git_sha], [m4_esyscmd([ ( [ -d ./.git/ ] && [ "$(readlink -f ./.git/)" = "$(readlink -f "$(git rev-parse --git-dir 2>/dev/null)" 2>/dev/null)" ] && git rev-parse --verify -q HEAD 2>/dev/null ) || true ])]) # The following explanation may help to understand the above rules a bit @@ -34,18 +29,18 @@ m4_define([libnl_micro_version], [22]) # 3. Programs may need to be changed, recompiled, relinked in order to use # the new version. Bump current, set revision and age to 0. -m4_define([libnl_lt_current], [217]) -m4_define([libnl_lt_revision], [0]) -m4_define([libnl_lt_age], [17]) +m4_define([libnl_lt_current], [226]) +m4_define([libnl_lt_revision], [0]) +m4_define([libnl_lt_age], [26]) m4_define([libnl_version], [libnl_major_version.libnl_minor_version.libnl_micro_version]) -AC_INIT(libnl, [libnl_version], [], [], [http://www.infradead.org/~tgr/libnl/]) -AC_CONFIG_HEADERS([lib/defs.h]) +AC_INIT([libnl],[libnl_version],[],[],[http://www.infradead.org/~tgr/libnl/]) +AC_CONFIG_HEADERS([include/config.h]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([m4]) -AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) +AM_INIT_AUTOMAKE([-Wall -Wno-portability foreign subdir-objects]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)], []) m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) @@ -55,6 +50,7 @@ MIN_VERSION=libnl_minor_version AC_SUBST(MIN_VERSION) MIC_VERSION=libnl_micro_version AC_SUBST(MIC_VERSION) +LIBNL_GIT_SHA=libnl_git_sha LIBNL_VERSION=libnl_version AC_SUBST(LIBNL_VERSION) @@ -68,7 +64,8 @@ AC_SUBST(LT_AGE) AC_PROG_CC AM_PROG_CC_C_O AC_PROG_INSTALL -AM_PROG_LIBTOOL +LT_INIT +AC_PROG_MKDIR_P AC_CHECK_PROGS(FLEX, 'flex') AC_CHECK_PROGS(YACC, 'bison -y') @@ -76,11 +73,10 @@ AC_C_CONST AC_C_INLINE PKG_CHECK_MODULES([CHECK], [check >= 0.9.0], - [enable_unit_tests="yes"], + [has_check="yes"], [AC_MSG_WARN([*** Disabling building of unit tests]) - enable_unit_tests="no"]) - -AM_CONDITIONAL([ENABLE_UNIT_TESTS], [test "$enable_unit_tests" = "yes"]) + has_check="no"]) +AM_CONDITIONAL(WITH_CHECK, [test "$has_check" = 'yes']) AC_ARG_WITH([pkgconfigdir], AS_HELP_STRING([--with-pkgconfigdir=PATH], [Path to the pkgconfig directory [[LIBDIR/pkgconfig]]]), @@ -88,34 +84,46 @@ AC_ARG_WITH([pkgconfigdir], AS_HELP_STRING([--with-pkgconfigdir=PATH], AC_SUBST([pkgconfigdir]) AC_ARG_ENABLE([cli], - AS_HELP_STRING([--disable-cli], [Do not build command line interface utils]), + AS_HELP_STRING([--enable-cli=yes|no|no-inst|bin|sbin], [Whether to build command line interface utils. Defaults to 'yes' which is a synonym for 'bin'. 'no-inst' means only build, not installing. 'bin'/'sbin' means installing to bin/sbin directory]), [enable_cli="$enableval"], [enable_cli="yes"]) -AM_CONDITIONAL([ENABLE_CLI], [test "$enable_cli" = "yes"]) +if test "$enable_cli" != "no" && + test "$enable_cli" != "no-inst" && + test "$enable_cli" != "sbin"; then + enable_cli="bin" +fi +AM_CONDITIONAL([ENABLE_CLI], [test "$enable_cli" != "no"]) +AM_CONDITIONAL([ENABLE_CLI_INSTALL_BIN], [test "$enable_cli" = "bin"]) +AM_CONDITIONAL([ENABLE_CLI_INSTALL_SBIN], [test "$enable_cli" = "sbin"]) + +AC_CHECK_HEADERS(dlfcn.h, [], []) AC_ARG_ENABLE([pthreads], AS_HELP_STRING([--disable-pthreads], [Disable pthreads support]), [enable_pthreads="$enableval"], [enable_pthreads="yes"]) AM_CONDITIONAL([DISABLE_PTHREADS], [test "$enable_pthreads" = "no"]) - -AC_ARG_ENABLE([debug], - AS_HELP_STRING([--disable-debug], [Do not include debugging statements]), - [enable_debug="$enableval"], [enable_debug="yes"]) -AM_CONDITIONAL([ENABLE_DEBUG], [test "$enable_debug" = "no" ]) - -AC_CHECK_LIB([m], [pow], [], AC_MSG_ERROR([libm is required])) - if test "x$enable_pthreads" = "xno"; then AC_DEFINE([DISABLE_PTHREADS], [1], [Define to 1 to disable pthreads]) else AC_CHECK_LIB([pthread], [pthread_mutex_lock], [], AC_MSG_ERROR([libpthread is required])) fi +AM_CONDITIONAL([ENABLE_STATIC], [test "$enable_static" != "no"]) + +AC_ARG_ENABLE([debug], + AS_HELP_STRING([--disable-debug], [Do not include debugging statements]), + [enable_debug="$enableval"], [enable_debug="yes"]) if test "x$enable_debug" = "xyes"; then AC_DEFINE([NL_DEBUG], [1], [Define to 1 to enable debugging]) fi AC_CONFIG_SUBDIRS([doc]) +AC_CHECK_FUNCS([strerror_l]) + +AC_CHECK_DECLS([getprotobyname_r, getprotobynumber_r], [], [], [[ + #include +]]) + AC_CONFIG_FILES([ Makefile libnl-3.0.pc @@ -123,16 +131,9 @@ libnl-route-3.0.pc libnl-genl-3.0.pc libnl-nf-3.0.pc libnl-cli-3.0.pc -lib/Makefile -include/Makefile -src/Makefile -src/lib/Makefile -tests/Makefile -man/Makefile -python/Makefile +libnl-xfrm-3.0.pc +libnl-idiag-3.0.pc python/setup.py -python/netlink/Makefile -python/netlink/route/Makefile include/netlink/version.h ]) @@ -151,26 +152,13 @@ fi AC_OUTPUT -echo "-------------------------------------------------------------------------------" -echo " NOTE" -echo "" -echo " There have been some changes starting with 3.2 regarding where and how libnl" -echo " is being installed on the system in order to allow multiple libnl versions" -echo " to be installed in parallel:" -echo "" -echo " - Headers will be installed in ${includedir}/libnl${MAJ_VERSION}, therefore" -echo " you will need to add \"-I/usr/include/libnl${MAJ_VERSION}\" to CFLAGS" -echo "" -echo " - The library basename was renamed to libnl-${MAJ_VERSION}, i.e. the SO names become" -echo " libnl-${MAJ_VERSION}.so., libnl-route-${MAJ_VERSION}.so, etc." -echo "" -echo " - libtool versioning was assumed, to ease detection of compatible library" -echo " versions." -echo "" -echo " If you are using pkg-config for detecting and linking against the library " -echo " things will continue magically as if nothing every happened. If you are " -echo " linking manually you need to adapt your Makefiles or switch to using " -echo " pkg-config files." -echo "" -echo "-------------------------------------------------------------------------------" - +echo +echo "libnl $LIBNL_VERSION configuration${LIBNL_GIT_SHA:+ (git:$LIBNL_GIT_SHA)}:" +echo " --enable-pthreads=$enable_pthreads" +echo " --enable-static=$enable_static" +echo +echo " --enable-debug=$enable_debug" +echo " --enable-cli=$enable_cli" +echo +echo " check: $has_check" +echo diff --git a/etc/pktloc b/etc/pktloc index 505c44e..8559161 100644 --- a/etc/pktloc +++ b/etc/pktloc @@ -58,7 +58,7 @@ tcp.flag.urg u8 tcp+13 0x20 5 tcp.flag.ack u8 tcp+13 0x10 4 tcp.flag.psh u8 tcp+13 0x08 3 tcp.flag.rst u8 tcp+13 0x04 2 -tpc.flag.syn u8 tcp+13 0x02 1 +tcp.flag.syn u8 tcp+13 0x02 1 tcp.flag.fin u8 tcp+13 0x01 tcp.win u16 tcp+14 diff --git a/include/Makefile.am b/include/Makefile.am deleted file mode 100644 index 3488c52..0000000 --- a/include/Makefile.am +++ /dev/null @@ -1,135 +0,0 @@ -# -*- Makefile -*- - -libnlincludedir = $(includedir)/libnl@MAJ_VERSION@ - -nobase_libnlinclude_HEADERS = \ - netlink/fib_lookup/lookup.h \ - netlink/fib_lookup/request.h \ - netlink/genl/ctrl.h \ - netlink/genl/family.h \ - netlink/genl/genl.h \ - netlink/genl/mngt.h \ - netlink/netfilter/ct.h \ - netlink/netfilter/exp.h \ - netlink/netfilter/log.h \ - netlink/netfilter/log_msg.h \ - netlink/netfilter/netfilter.h \ - netlink/netfilter/nfnl.h \ - netlink/netfilter/queue.h \ - netlink/netfilter/queue_msg.h \ - netlink/addr.h \ - netlink/attr.h \ - netlink/cache.h \ - netlink/data.h \ - netlink/errno.h \ - netlink/handlers.h \ - netlink/hash.h \ - netlink/hashtable.h \ - netlink/list.h \ - netlink/msg.h \ - netlink/netlink-compat.h \ - netlink/netlink-kernel.h \ - netlink/netlink.h \ - netlink/object.h \ - netlink/route/cls/ematch/cmp.h \ - netlink/route/cls/ematch/meta.h \ - netlink/route/cls/ematch/nbyte.h \ - netlink/route/cls/ematch/text.h \ - netlink/route/cls/basic.h \ - netlink/route/cls/cgroup.h \ - netlink/route/cls/ematch.h \ - netlink/route/cls/fw.h \ - netlink/route/cls/police.h \ - netlink/route/cls/u32.h \ - netlink/route/link/bonding.h \ - netlink/route/link/bridge.h \ - netlink/route/link/can.h \ - netlink/route/link/inet.h \ - netlink/route/link/vlan.h \ - netlink/route/qdisc/cbq.h \ - netlink/route/qdisc/dsmark.h \ - netlink/route/qdisc/fifo.h \ - netlink/route/qdisc/htb.h \ - netlink/route/qdisc/netem.h \ - netlink/route/qdisc/prio.h \ - netlink/route/qdisc/red.h \ - netlink/route/qdisc/sfq.h \ - netlink/route/qdisc/tbf.h \ - netlink/route/qdisc/plug.h \ - netlink/route/addr.h \ - netlink/route/class.h \ - netlink/route/classifier.h \ - netlink/route/link.h \ - netlink/route/neighbour.h \ - netlink/route/neightbl.h \ - netlink/route/nexthop.h \ - netlink/route/pktloc.h \ - netlink/route/qdisc.h \ - netlink/route/route.h \ - netlink/route/rtnl.h \ - netlink/route/rule.h \ - netlink/route/tc.h \ - netlink/socket.h \ - netlink/types.h \ - netlink/utils.h \ - netlink/version.h \ - netlink/cache-api.h \ - netlink/object-api.h \ - netlink/route/link/api.h \ - netlink/route/link/info-api.h \ - netlink/route/tc-api.h - - -if ENABLE_CLI -nobase_libnlinclude_HEADERS += \ - netlink/cli/addr.h \ - netlink/cli/class.h \ - netlink/cli/cls.h \ - netlink/cli/ct.h \ - netlink/cli/exp.h \ - netlink/cli/link.h \ - netlink/cli/neigh.h \ - netlink/cli/qdisc.h \ - netlink/cli/route.h \ - netlink/cli/rule.h \ - netlink/cli/tc.h \ - netlink/cli/utils.h -endif - -noinst_HEADERS = \ - linux/fib_rules.h \ - linux/genetlink.h \ - linux/gen_stats.h \ - linux/if_addr.h \ - linux/if_arp.h \ - linux/if_ether.h \ - linux/if.h \ - linux/if_bridge.h \ - linux/if_link.h \ - linux/if_vlan.h \ - linux/inetdevice.h \ - linux/ip_mp_alg.h \ - linux/ipv6.h \ - linux/can/netlink.h \ - linux/neighbour.h \ - linux/netfilter.h \ - linux/netfilter/nf_conntrack_common.h \ - linux/netfilter/nfnetlink_compat.h \ - linux/netfilter/nfnetlink_conntrack.h \ - linux/netfilter/nfnetlink.h \ - linux/netfilter/nfnetlink_log.h \ - linux/netfilter/nfnetlink_queue.h \ - linux/netlink.h \ - linux/pkt_cls.h \ - linux/pkt_sched.h \ - linux/rtnetlink.h \ - linux/snmp.h \ - linux/tc_ematch/tc_em_meta.h \ - netlink-private/genl.h \ - netlink-private/netlink.h \ - netlink-private/tc.h \ - netlink-private/types.h \ - netlink-private/cache-api.h \ - netlink-private/object-api.h \ - netlink-private/route/link/api.h \ - netlink-private/route/tc-api.h diff --git a/include/Makefile.in b/include/Makefile.in deleted file mode 100644 index 142c716..0000000 --- a/include/Makefile.in +++ /dev/null @@ -1,640 +0,0 @@ -# Makefile.in generated by automake 1.11.6 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -# -*- Makefile -*- - -VPATH = @srcdir@ -am__make_dryrun = \ - { \ - am__dry=no; \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ - esac; \ - test $$am__dry = yes; \ - } -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -@ENABLE_CLI_TRUE@am__append_1 = \ -@ENABLE_CLI_TRUE@ netlink/cli/addr.h \ -@ENABLE_CLI_TRUE@ netlink/cli/class.h \ -@ENABLE_CLI_TRUE@ netlink/cli/cls.h \ -@ENABLE_CLI_TRUE@ netlink/cli/ct.h \ -@ENABLE_CLI_TRUE@ netlink/cli/exp.h \ -@ENABLE_CLI_TRUE@ netlink/cli/link.h \ -@ENABLE_CLI_TRUE@ netlink/cli/neigh.h \ -@ENABLE_CLI_TRUE@ netlink/cli/qdisc.h \ -@ENABLE_CLI_TRUE@ netlink/cli/route.h \ -@ENABLE_CLI_TRUE@ netlink/cli/rule.h \ -@ENABLE_CLI_TRUE@ netlink/cli/tc.h \ -@ENABLE_CLI_TRUE@ netlink/cli/utils.h - -subdir = include -DIST_COMMON = $(am__nobase_libnlinclude_HEADERS_DIST) \ - $(noinst_HEADERS) $(srcdir)/Makefile.am $(srcdir)/Makefile.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/lib/defs.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -SOURCES = -DIST_SOURCES = -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__nobase_libnlinclude_HEADERS_DIST = netlink/fib_lookup/lookup.h \ - netlink/fib_lookup/request.h netlink/genl/ctrl.h \ - netlink/genl/family.h netlink/genl/genl.h netlink/genl/mngt.h \ - netlink/netfilter/ct.h netlink/netfilter/exp.h \ - netlink/netfilter/log.h netlink/netfilter/log_msg.h \ - netlink/netfilter/netfilter.h netlink/netfilter/nfnl.h \ - netlink/netfilter/queue.h netlink/netfilter/queue_msg.h \ - netlink/addr.h netlink/attr.h netlink/cache.h netlink/data.h \ - netlink/errno.h netlink/handlers.h netlink/hash.h \ - netlink/hashtable.h netlink/list.h netlink/msg.h \ - netlink/netlink-compat.h netlink/netlink-kernel.h \ - netlink/netlink.h netlink/object.h \ - netlink/route/cls/ematch/cmp.h netlink/route/cls/ematch/meta.h \ - netlink/route/cls/ematch/nbyte.h \ - netlink/route/cls/ematch/text.h netlink/route/cls/basic.h \ - netlink/route/cls/cgroup.h netlink/route/cls/ematch.h \ - netlink/route/cls/fw.h netlink/route/cls/police.h \ - netlink/route/cls/u32.h netlink/route/link/bonding.h \ - netlink/route/link/bridge.h netlink/route/link/can.h \ - netlink/route/link/inet.h netlink/route/link/vlan.h \ - netlink/route/qdisc/cbq.h netlink/route/qdisc/dsmark.h \ - netlink/route/qdisc/fifo.h netlink/route/qdisc/htb.h \ - netlink/route/qdisc/netem.h netlink/route/qdisc/prio.h \ - netlink/route/qdisc/red.h netlink/route/qdisc/sfq.h \ - netlink/route/qdisc/tbf.h netlink/route/qdisc/plug.h \ - netlink/route/addr.h netlink/route/class.h \ - netlink/route/classifier.h netlink/route/link.h \ - netlink/route/neighbour.h netlink/route/neightbl.h \ - netlink/route/nexthop.h netlink/route/pktloc.h \ - netlink/route/qdisc.h netlink/route/route.h \ - netlink/route/rtnl.h netlink/route/rule.h netlink/route/tc.h \ - netlink/socket.h netlink/types.h netlink/utils.h \ - netlink/version.h netlink/cache-api.h netlink/object-api.h \ - netlink/route/link/api.h netlink/route/link/info-api.h \ - netlink/route/tc-api.h netlink/cli/addr.h netlink/cli/class.h \ - netlink/cli/cls.h netlink/cli/ct.h netlink/cli/exp.h \ - netlink/cli/link.h netlink/cli/neigh.h netlink/cli/qdisc.h \ - netlink/cli/route.h netlink/cli/rule.h netlink/cli/tc.h \ - netlink/cli/utils.h -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -am__installdirs = "$(DESTDIR)$(libnlincludedir)" -HEADERS = $(nobase_libnlinclude_HEADERS) $(noinst_HEADERS) -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CHECK_CFLAGS = @CHECK_CFLAGS@ -CHECK_LIBS = @CHECK_LIBS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -FLEX = @FLEX@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBNL_VERSION = @LIBNL_VERSION@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_AGE = @LT_AGE@ -LT_CURRENT = @LT_CURRENT@ -LT_REVISION = @LT_REVISION@ -MAJ_VERSION = @MAJ_VERSION@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MIC_VERSION = @MIC_VERSION@ -MIN_VERSION = @MIN_VERSION@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -YACC = @YACC@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgconfigdir = @pkgconfigdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -subdirs = @subdirs@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -libnlincludedir = $(includedir)/libnl@MAJ_VERSION@ -nobase_libnlinclude_HEADERS = netlink/fib_lookup/lookup.h \ - netlink/fib_lookup/request.h netlink/genl/ctrl.h \ - netlink/genl/family.h netlink/genl/genl.h netlink/genl/mngt.h \ - netlink/netfilter/ct.h netlink/netfilter/exp.h \ - netlink/netfilter/log.h netlink/netfilter/log_msg.h \ - netlink/netfilter/netfilter.h netlink/netfilter/nfnl.h \ - netlink/netfilter/queue.h netlink/netfilter/queue_msg.h \ - netlink/addr.h netlink/attr.h netlink/cache.h netlink/data.h \ - netlink/errno.h netlink/handlers.h netlink/hash.h \ - netlink/hashtable.h netlink/list.h netlink/msg.h \ - netlink/netlink-compat.h netlink/netlink-kernel.h \ - netlink/netlink.h netlink/object.h \ - netlink/route/cls/ematch/cmp.h netlink/route/cls/ematch/meta.h \ - netlink/route/cls/ematch/nbyte.h \ - netlink/route/cls/ematch/text.h netlink/route/cls/basic.h \ - netlink/route/cls/cgroup.h netlink/route/cls/ematch.h \ - netlink/route/cls/fw.h netlink/route/cls/police.h \ - netlink/route/cls/u32.h netlink/route/link/bonding.h \ - netlink/route/link/bridge.h netlink/route/link/can.h \ - netlink/route/link/inet.h netlink/route/link/vlan.h \ - netlink/route/qdisc/cbq.h netlink/route/qdisc/dsmark.h \ - netlink/route/qdisc/fifo.h netlink/route/qdisc/htb.h \ - netlink/route/qdisc/netem.h netlink/route/qdisc/prio.h \ - netlink/route/qdisc/red.h netlink/route/qdisc/sfq.h \ - netlink/route/qdisc/tbf.h netlink/route/qdisc/plug.h \ - netlink/route/addr.h netlink/route/class.h \ - netlink/route/classifier.h netlink/route/link.h \ - netlink/route/neighbour.h netlink/route/neightbl.h \ - netlink/route/nexthop.h netlink/route/pktloc.h \ - netlink/route/qdisc.h netlink/route/route.h \ - netlink/route/rtnl.h netlink/route/rule.h netlink/route/tc.h \ - netlink/socket.h netlink/types.h netlink/utils.h \ - netlink/version.h netlink/cache-api.h netlink/object-api.h \ - netlink/route/link/api.h netlink/route/link/info-api.h \ - netlink/route/tc-api.h $(am__append_1) -noinst_HEADERS = \ - linux/fib_rules.h \ - linux/genetlink.h \ - linux/gen_stats.h \ - linux/if_addr.h \ - linux/if_arp.h \ - linux/if_ether.h \ - linux/if.h \ - linux/if_bridge.h \ - linux/if_link.h \ - linux/if_vlan.h \ - linux/inetdevice.h \ - linux/ip_mp_alg.h \ - linux/ipv6.h \ - linux/can/netlink.h \ - linux/neighbour.h \ - linux/netfilter.h \ - linux/netfilter/nf_conntrack_common.h \ - linux/netfilter/nfnetlink_compat.h \ - linux/netfilter/nfnetlink_conntrack.h \ - linux/netfilter/nfnetlink.h \ - linux/netfilter/nfnetlink_log.h \ - linux/netfilter/nfnetlink_queue.h \ - linux/netlink.h \ - linux/pkt_cls.h \ - linux/pkt_sched.h \ - linux/rtnetlink.h \ - linux/snmp.h \ - linux/tc_ematch/tc_em_meta.h \ - netlink-private/genl.h \ - netlink-private/netlink.h \ - netlink-private/tc.h \ - netlink-private/types.h \ - netlink-private/cache-api.h \ - netlink-private/object-api.h \ - netlink-private/route/link/api.h \ - netlink-private/route/tc-api.h - -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign include/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -install-nobase_libnlincludeHEADERS: $(nobase_libnlinclude_HEADERS) - @$(NORMAL_INSTALL) - @list='$(nobase_libnlinclude_HEADERS)'; test -n "$(libnlincludedir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(libnlincludedir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(libnlincludedir)" || exit 1; \ - fi; \ - $(am__nobase_list) | while read dir files; do \ - xfiles=; for file in $$files; do \ - if test -f "$$file"; then xfiles="$$xfiles $$file"; \ - else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ - test -z "$$xfiles" || { \ - test "x$$dir" = x. || { \ - echo " $(MKDIR_P) '$(DESTDIR)$(libnlincludedir)/$$dir'"; \ - $(MKDIR_P) "$(DESTDIR)$(libnlincludedir)/$$dir"; }; \ - echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(libnlincludedir)/$$dir'"; \ - $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(libnlincludedir)/$$dir" || exit $$?; }; \ - done - -uninstall-nobase_libnlincludeHEADERS: - @$(NORMAL_UNINSTALL) - @list='$(nobase_libnlinclude_HEADERS)'; test -n "$(libnlincludedir)" || list=; \ - $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ - dir='$(DESTDIR)$(libnlincludedir)'; $(am__uninstall_files_from_dir) - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - set x; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(HEADERS) -installdirs: - for dir in "$(DESTDIR)$(libnlincludedir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: install-nobase_libnlincludeHEADERS - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-nobase_libnlincludeHEADERS - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ - clean-libtool ctags distclean distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-nobase_libnlincludeHEADERS \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags uninstall uninstall-am \ - uninstall-nobase_libnlincludeHEADERS - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/include/base/nl-base-utils.h b/include/base/nl-base-utils.h new file mode 100644 index 0000000..03d568e --- /dev/null +++ b/include/base/nl-base-utils.h @@ -0,0 +1,842 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2003-2012 Thomas Graf + */ + +#ifndef __NETLINK_BASE_NL_BASE_UTILS_H__ +#define __NETLINK_BASE_NL_BASE_UTILS_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef DISABLE_PTHREADS +#include +#endif + +/*****************************************************************************/ + +#if __BYTE_ORDER == __BIG_ENDIAN +#define ntohll(x) (x) +#elif __BYTE_ORDER == __LITTLE_ENDIAN +#define ntohll(x) bswap_64((x)) +#endif +#define htonll(x) ntohll(x) + +/*****************************************************************************/ + +#define _NL_STRINGIFY_ARG(contents) #contents +#define _NL_STRINGIFY(macro_or_string) _NL_STRINGIFY_ARG(macro_or_string) + +/*****************************************************************************/ + +#if defined(__GNUC__) +#define _NL_PRAGMA_WARNING_DO(warning) \ + _NL_STRINGIFY(GCC diagnostic ignored warning) +#elif defined(__clang__) +#define _NL_PRAGMA_WARNING_DO(warning) \ + _NL_STRINGIFY(clang diagnostic ignored warning) +#endif + +/* you can only suppress a specific warning that the compiler + * understands. Otherwise you will get another compiler warning + * about invalid pragma option. + * It's not that bad however, because gcc and clang often have the + * same name for the same warning. */ + +#if defined(__GNUC__) && \ + (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#define _NL_PRAGMA_WARNING_DISABLE(warning) \ + _Pragma("GCC diagnostic push") \ + _Pragma(_NL_PRAGMA_WARNING_DO("-Wpragmas")) \ + _Pragma(_NL_PRAGMA_WARNING_DO(warning)) +#elif defined(__clang__) +#define _NL_PRAGMA_WARNING_DISABLE(warning) \ + _Pragma("clang diagnostic push") \ + _Pragma(_NL_PRAGMA_WARNING_DO("-Wunknown-warning-option")) \ + _Pragma(_NL_PRAGMA_WARNING_DO(warning)) +#else +#define _NL_PRAGMA_WARNING_DISABLE(warning) +#endif + +#if defined(__GNUC__) && \ + (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#define _NL_PRAGMA_WARNING_REENABLE _Pragma("GCC diagnostic pop") +#elif defined(__clang__) +#define _NL_PRAGMA_WARNING_REENABLE _Pragma("clang diagnostic pop") +#else +#define _NL_PRAGMA_WARNING_REENABLE +#endif + +/*****************************************************************************/ + +#define _nl_packed __attribute__((__packed__)) +#define _nl_unused __attribute__((__unused__)) +#define _nl_always_inline __attribute__((__always_inline__)) +#define _nl_used __attribute__((__used__)) +#define _nl_pure __attribute__((__pure__)) +#define _nl_const __attribute__((__const__)) +#define _nl_noreturn __attribute__((__noreturn__)) +#define _nl_warn_unused_result __attribute__((__warn_unused_result__)) +#define _nl_printf(a, b) __attribute__((__format__(__printf__, a, b))) +#define _nl_align(s) __attribute__((__aligned__(s))) +#define _nl_section(s) __attribute__((__section__(s))) +#define _nl_alignof(type) __alignof(type) +#define _nl_alignas(type) _nl_align(_nl_alignof(type)) +#define _nl_deprecated(msg) __attribute__((__deprecated__(msg))) +#define _nl_init __attribute__((constructor)) +#define _nl_exit __attribute__((destructor)) +#define _nl_auto(fcn) __attribute__((__cleanup__(fcn))) + +/*****************************************************************************/ + +#ifdef thread_local +#define _nl_thread_local thread_local +/* + * Don't break on glibc < 2.16 that doesn't define __STDC_NO_THREADS__ + * see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769 + */ +#elif __STDC_VERSION__ >= 201112L && \ + !(defined(__STDC_NO_THREADS__) || \ + (defined(__GNU_LIBRARY__) && __GLIBC__ == 2 && \ + __GLIBC_MINOR__ < 16)) +#define _nl_thread_local _Thread_local +#else +#define _nl_thread_local __thread +#endif + +/*****************************************************************************/ + +#define _NL_STATIC_ASSERT(cond) ((void)sizeof(char[(cond) ? 1 : -1])) + +/*****************************************************************************/ + +#if defined(NL_MORE_ASSERTS) && NL_MORE_ASSERTS > 0 +#define _nl_assert(cond) assert(cond) +#else +#define _nl_assert(cond) \ + do { \ + if (0) { \ + assert(cond); \ + } \ + } while (0) +#endif + +#define _nl_assert_not_reached() assert(0) + +/*****************************************************************************/ + +#define _NL_BIT(n) (1ull << (n)) + +/*****************************************************************************/ + +#define _NL_PASTE_ARGS(identifier1, identifier2) identifier1##identifier2 +#define _NL_PASTE(identifier1, identifier2) \ + _NL_PASTE_ARGS(identifier1, identifier2) + +/* Taken from systemd's UNIQ_T and UNIQ macros. */ + +#define _NL_UNIQ_T(x, uniq) _NL_PASTE(__unique_prefix_, _NL_PASTE(x, uniq)) +#define _NL_UNIQ __COUNTER__ + +/*****************************************************************************/ + +#define _nl_assert_addr_family_or_unspec(addr_family) \ + do { \ + typeof(addr_family) _addr_family = (addr_family); \ + \ + _nl_assert(_addr_family == AF_UNSPEC || \ + _addr_family == AF_INET || \ + _addr_family == AF_INET6); \ + } while (0) + +#define _nl_assert_addr_family(addr_family) \ + do { \ + typeof(addr_family) _addr_family = (addr_family); \ + \ + _nl_assert(_addr_family == AF_INET || \ + _addr_family == AF_INET6); \ + } while (0) + +/*****************************************************************************/ + +#define _NL_SWAP(pa, pb) \ + do { \ + typeof(*(pa)) *_pa = (pa); \ + typeof(*(pb)) *_pb = (pb); \ + typeof(*_pa) _tmp; \ + \ + _nl_assert(_pa); \ + _nl_assert(_pb); \ + _tmp = *_pa; \ + *_pa = *_pb; \ + *_pb = _tmp; \ + } while (0) + +/*****************************************************************************/ + +#define _NL_N_ELEMENTS(arr) (sizeof(arr) / sizeof((arr)[0])) + +#define ARRAY_SIZE(arr) _NL_N_ELEMENTS(arr) + +/*****************************************************************************/ + +/* This is also defined in stddef.h */ +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER) +#endif + +/*****************************************************************************/ + +static inline uintptr_t _nl_ptr_to_uintptr(const void *p) +{ + /* in C, pointers can only be compared (with less-than or greater-than) under certain + * circumstances. Since uintptr_t is supposed to be able to represent the pointer + * as a plain integer and also support to convert the integer back to the pointer, + * it should be safer to compare the pointers directly. + * + * Of course, this function isn't very useful beyond that its use makes it clear + * that we want to compare pointers by value, which otherwise may not be valid. */ + return (uintptr_t)p; +} + +/*****************************************************************************/ + +static inline int _nl_strcmp0(const char *s1, const char *s2) +{ + int c; + + /* like g_strcmp0(), but this is inlinable. + * + * Also, it is guaranteed to return either -1, 0, or 1. */ + if (s1 == s2) + return 0; + if (!s1) + return -1; + if (!s2) + return 1; + c = strcmp(s1, s2); + if (c < 0) + return -1; + if (c > 0) + return 1; + return 0; +} + +static inline bool _nl_streq(const char *a, const char *b) +{ + return !strcmp(a, b); +} + +static inline bool _nl_streq0(const char *a, const char *b) +{ + return a == b || (a && b && _nl_streq(a, b)); +} + +static inline int _nl_memcmp(const void *s1, const void *s2, size_t n) +{ + /* Workaround undefined behavior in memcmp() with NULL pointers. */ + if (n == 0) + return 0; + _nl_assert(s1); + _nl_assert(s2); + return memcmp(s1, s2, n); +} + +static inline bool _nl_memeq(const void *s1, const void *s2, size_t len) +{ + return _nl_memcmp(s1, s2, len) == 0; +} + +static inline void *_nl_memcpy(void *restrict dest, const void *restrict src, + size_t n) +{ + /* Workaround undefined behavior in memcpy() with NULL pointers. */ + if (n == 0) + return dest; + + _nl_assert(src); + return memcpy(dest, src, n); +} + +/*****************************************************************************/ + +#define _NL_INT_IS_SIGNED(arg) (!(((typeof(arg))-1) > 0)) + +#define _NL_INT_SAME_SIGNEDNESS(arg1, arg2) \ + (_NL_INT_IS_SIGNED(arg1) == _NL_INT_IS_SIGNED(arg2)) + +/*****************************************************************************/ + +/* glib's MIN()/MAX() macros don't have function-like behavior, in that they evaluate + * the argument possibly twice. + * + * Taken from systemd's MIN()/MAX() macros. */ + +#define _NL_MIN(a, b) __NL_MIN(_NL_UNIQ, a, _NL_UNIQ, b) +#define __NL_MIN(aq, a, bq, b) \ + ({ \ + typeof(a) _NL_UNIQ_T(A, aq) = (a); \ + typeof(b) _NL_UNIQ_T(B, bq) = (b); \ + \ + _NL_STATIC_ASSERT(_NL_INT_SAME_SIGNEDNESS(_NL_UNIQ_T(A, aq), \ + _NL_UNIQ_T(B, bq))); \ + \ + ((_NL_UNIQ_T(A, aq) < _NL_UNIQ_T(B, bq)) ? _NL_UNIQ_T(A, aq) : \ + _NL_UNIQ_T(B, bq)); \ + }) + +#define _NL_MAX(a, b) __NL_MAX(_NL_UNIQ, a, _NL_UNIQ, b) +#define __NL_MAX(aq, a, bq, b) \ + ({ \ + typeof(a) _NL_UNIQ_T(A, aq) = (a); \ + typeof(b) _NL_UNIQ_T(B, bq) = (b); \ + \ + _NL_STATIC_ASSERT(_NL_INT_SAME_SIGNEDNESS(_NL_UNIQ_T(A, aq), \ + _NL_UNIQ_T(B, bq))); \ + \ + ((_NL_UNIQ_T(A, aq) > _NL_UNIQ_T(B, bq)) ? _NL_UNIQ_T(A, aq) : \ + _NL_UNIQ_T(B, bq)); \ + }) + +#define _NL_CLAMP(x, low, high) \ + __NL_CLAMP(_NL_UNIQ, x, _NL_UNIQ, low, _NL_UNIQ, high) +#define __NL_CLAMP(xq, x, lowq, low, highq, high) \ + ({ \ + typeof(x) _NL_UNIQ_T(X, xq) = (x); \ + typeof(low) _NL_UNIQ_T(LOW, lowq) = (low); \ + typeof(high) _NL_UNIQ_T(HIGH, highq) = (high); \ + \ + _NL_STATIC_ASSERT(_NL_INT_SAME_SIGNEDNESS( \ + _NL_UNIQ_T(X, xq), _NL_UNIQ_T(LOW, lowq))); \ + _NL_STATIC_ASSERT(_NL_INT_SAME_SIGNEDNESS( \ + _NL_UNIQ_T(X, xq), _NL_UNIQ_T(HIGH, highq))); \ + \ + ((_NL_UNIQ_T(X, xq) > _NL_UNIQ_T(HIGH, highq)) ? \ + _NL_UNIQ_T(HIGH, highq) : \ + (_NL_UNIQ_T(X, xq) < _NL_UNIQ_T(LOW, lowq)) ? \ + _NL_UNIQ_T(LOW, lowq) : \ + _NL_UNIQ_T(X, xq)); \ + }) + +#define _NL_MAX_WITH_CMP(cmp, a, b) \ + ({ \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + \ + (((cmp(_a, _b)) >= 0) ? _a : _b); \ + }) + +/* evaluates to (void) if _A or _B are not constant or of different types */ +#define _NL_CONST_MAX(_A, _B) \ + (__builtin_choose_expr( \ + (__builtin_constant_p(_A) && __builtin_constant_p(_B) && \ + __builtin_types_compatible_p(typeof(_A), typeof(_B))), \ + ((_A) > (_B)) ? (_A) : (_B), ((void)0))) + +/*****************************************************************************/ + +#define _NL_CMP_RETURN(c) \ + do { \ + const int _cc = (c); \ + \ + if (_cc) \ + return _cc < 0 ? -1 : 1; \ + } while (0) + +#define _NL_CMP_RETURN_DIRECT(c) \ + /* Usually we want that our CMP functions return strictly + * -1, 0, or 1. _NL_CMP_RETURN_DIRECT() is like _NL_CMP_RETURN(), + * except, it does not clamp the integer value. */ \ + do { \ + const int _cc = (c); \ + \ + if (_cc) \ + return _cc; \ + } while (0) + +#define _NL_CMP_SELF(a, b) \ + do { \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + \ + if (_a == _b) \ + return 0; \ + if (!_a) \ + return -1; \ + if (!_b) \ + return 1; \ + } while (0) + +/*****************************************************************************/ + +#define _NL_CMP_DIRECT(a, b) \ + do { \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + \ + _NL_STATIC_ASSERT(_NL_INT_SAME_SIGNEDNESS(_a, _b)); \ + \ + if (_a != _b) \ + return (_a < _b) ? -1 : 1; \ + } while (0) + +#define _NL_CMP_DIRECT_UNSAFE(a, b) \ + /* This variant is "unsafe", because it evaluates the arguments more then once. + * This is only useful for bitfields, for which typeof() doesn't work. + * Don't use otherwise. */ \ + do { \ + if ((a) != (b)) \ + return ((a) < (b)) ? -1 : 1; \ + } while (0) + +/* In the general case, direct pointer comparison is undefined behavior in C. + * Avoid that by casting pointers to void* and then to uintptr_t. This comparison + * is not really meaningful, except that it provides some kind of stable sort order + * between pointers (that can otherwise not be compared). */ +#define _NL_CMP_DIRECT_PTR(a, b) \ + _NL_CMP_DIRECT(_nl_ptr_to_uintptr(a), _nl_ptr_to_uintptr(b)) + +#define _NL_CMP_DIRECT_BOOL(a, b) _NL_CMP_DIRECT(!!(a), !!(b)) + +#define _NL_CMP_DIRECT_MEMCMP(a, b, size) \ + _NL_CMP_RETURN(_nl_memcmp((a), (b), (size))) + +#define _NL_CMP_DIRECT_STRCMP(a, b) _NL_CMP_RETURN_DIRECT(strcmp((a), (b))) + +#define _NL_CMP_DIRECT_STRCMP0(a, b) \ + _NL_CMP_RETURN_DIRECT(_nl_strcmp0((a), (b))) + +#define _NL_CMP_DIRECT_STR_INTERNED(a, b) \ + /* This is interned strings, which are first checked for equality only using pointer + * comparison. Only in case of differences, the sort order is still determined by strcmp(). */ \ + do { \ + const char *const _a = (a); \ + const char *const _b = (b); \ + \ + if (_a != _b) \ + _NL_CMP_RETURN_DIRECT(_nl_strcmp0(_a, _b)); \ + } while (0) + +#define _NL_CMP_DIRECT_IN6ADDR(a, b) \ + do { \ + const struct in6_addr *const _a = (a); \ + const struct in6_addr *const _b = (b); \ + \ + _NL_CMP_RETURN(memcmp(_a, _b, sizeof(struct in6_addr))); \ + } while (0) + +/*****************************************************************************/ + +#define _NL_CMP_FIELD(a, b, field) _NL_CMP_DIRECT(((a)->field), ((b)->field)) + +#define _NL_CMP_FIELD_UNSAFE(a, b, field) \ + /* This variant is "unsafe", because it evaluates the arguments more then once. + * This is only useful for bitfields, for which typeof() doesn't work. + * Don't use otherwise. */ \ + _NL_CMP_DIRECT_UNSAFE(((a)->field), ((b)->field)) + +#define _NL_CMP_FIELD_BOOL(a, b, field) \ + _NL_CMP_DIRECT_BOOL(((a)->field), ((b)->field)) + +#define _NL_CMP_FIELD_STR(a, b, field) \ + _NL_CMP_DIRECT_STRCMP(((a)->field), ((b)->field)) + +#define _NL_CMP_FIELD_STR0(a, b, field) \ + _NL_CMP_DIRECT_STRCMP0(((a)->field), ((b)->field)) + +#define _NL_CMP_FIELD_STR_INTERNED(a, b, field) \ + _NL_CMP_DIRECT_STR_INTERNED(((a)->field), ((b)->field)) + +#define _NL_CMP_FIELD_MEMCMP_LEN(a, b, field, len) \ + _NL_CMP_DIRECT_MEMCMP(&((a)->field), &((b)->field), \ + _NL_MIN(len, sizeof((a)->field))) + +#define _NL_CMP_FIELD_MEMCMP(a, b, field) \ + _NL_CMP_DIRECT_MEMCMP(&((a)->field), &((b)->field), sizeof((a)->field)) + +#define _NL_CMP_FIELD_IN6ADDR(a, b, field) \ + _NL_CMP_DIRECT_IN6ADDR(&((a)->field), &((b)->field)) + +/*****************************************************************************/ + +/* internal macro to calculate the size of a struct @type up to (and including) @field. + * this will be used for .minlen policy fields, so that we require only a field of up + * to the given size. */ +#define _nl_offsetofend(type, field) \ + (offsetof(type, field) + sizeof(((type *)NULL)->field)) + +/*****************************************************************************/ + +#define _nl_clear_pointer(pp, destroy) \ + ({ \ + __typeof__(*(pp)) *_pp = (pp); \ + __typeof__(*_pp) _p; \ + int _changed = 0; \ + \ + if (_pp && (_p = *_pp)) { \ + _nl_unused const void *const _p_check_is_pointer = _p; \ + \ + *_pp = NULL; \ + \ + (destroy)(_p); \ + \ + _changed = 1; \ + } \ + _changed; \ + }) + +#define _nl_clear_free(pp) _nl_clear_pointer(pp, free) + +#define _nl_steal_pointer(pp) \ + ({ \ + __typeof__(*(pp)) *const _pp = (pp); \ + __typeof__(*_pp) _p = NULL; \ + \ + if (_pp && (_p = *_pp)) { \ + *_pp = NULL; \ + } \ + \ + _p; \ + }) + +/*****************************************************************************/ + +#define _nl_malloc_maybe_a(alloca_maxlen, bytes, to_free) \ + ({ \ + const size_t _bytes = (bytes); \ + __typeof__(to_free) _to_free = (to_free); \ + __typeof__(*_to_free) _ptr; \ + \ + _NL_STATIC_ASSERT((alloca_maxlen) <= 500); \ + _nl_assert(_to_free && !*_to_free); \ + \ + if (_bytes <= (alloca_maxlen)) { \ + _ptr = alloca(_bytes); \ + } else { \ + _ptr = malloc(_bytes); \ + *_to_free = _ptr; \ + }; \ + \ + _ptr; \ + }) + +/*****************************************************************************/ + +static inline char *_nl_strncpy_trunc(char *dst, const char *src, size_t len) +{ + /* we don't use/reimplement strlcpy(), because we want the fill-all-with-NUL + * behavior of strncpy(). This is just strncpy() with gracefully handling truncation + * (and disabling the "-Wstringop-truncation" warning). + * + * Note that truncation is silently accepted. + */ + + _NL_PRAGMA_WARNING_DISABLE("-Wstringop-truncation"); + _NL_PRAGMA_WARNING_DISABLE("-Wstringop-overflow"); + + if (len > 0) { + _nl_assert(dst); + _nl_assert(src); + + strncpy(dst, src, len); + + dst[len - 1] = '\0'; + } + + _NL_PRAGMA_WARNING_REENABLE; + _NL_PRAGMA_WARNING_REENABLE; + + return dst; +} + +static inline char *_nl_strncpy_assert(char *dst, const char *src, size_t len) +{ + /* we don't use/reimplement strlcpy(), because we want the fill-all-with-NUL + * behavior of strncpy(). This is just strncpy() with assertion against truncation + * (and disabling the "-Wstringop-truncation" warning). + * + * Note that truncation is still a bug and there is an _nl_assert() + * against that. + */ + + _NL_PRAGMA_WARNING_DISABLE("-Wstringop-truncation"); + _NL_PRAGMA_WARNING_DISABLE("-Wstringop-overflow"); + + if (len > 0) { + _nl_assert(dst); + _nl_assert(src); + + strncpy(dst, src, len); + + _nl_assert(dst[len - 1] == '\0'); + + dst[len - 1] = '\0'; + } + + _NL_PRAGMA_WARNING_REENABLE; + _NL_PRAGMA_WARNING_REENABLE; + + return dst; +} + +#define _NL_RETURN_ON_ERR(cmd) \ + do { \ + int _err; \ + \ + _err = (cmd); \ + if (_err < 0) \ + return _err; \ + } while (0) + +#define _NL_RETURN_E_ON_ERR(e, cmd) \ + do { \ + int _err; \ + \ + _err = (cmd); \ + if (_err < 0) { \ + _NL_STATIC_ASSERT((e) > 0); \ + return -(e); \ + } \ + } while (0) + +/* _NL_RETURN_ON_PUT_ERR() shall only be used with a put command (nla_put or nlmsg_append). + * These commands can either fail with a regular error code (which gets propagated) + * or with -NLE_NOMEM. However, they don't really try to allocate memory, so we don't + * want to propagate -NLE_NOMEM. Instead, we coerce such failure to -NLE_MSGSIZE. */ +#define _NL_RETURN_ON_PUT_ERR(put_cmd) \ + do { \ + int _err; \ + \ + _err = (put_cmd); \ + if (_err < 0) { \ + if (_err == -NLE_NOMEM) { \ + /* nla_put() returns -NLE_NOMEM in case of out of buffer size. We don't + * want to propagate that error and map it to -NLE_MSGSIZE. */ \ + return -NLE_MSGSIZE; \ + } \ + /* any other error can only be due to invalid parameters. Propagate the + * error, however also assert that it cannot be reached. */ \ + _nl_assert_not_reached(); \ + return _err; \ + } else \ + _nl_assert(_err == 0); \ + } while (0) + +static inline int _nl_close(int fd) +{ + int r; + + r = close(fd); + _nl_assert(r == 0 || fd < 0 || errno != EBADF); + return r; +} + +static inline void *_nl_memdup(const void *ptr, size_t len) +{ + void *p; + + if (len == 0) { + /* malloc() leaves it implementation defined whether to return NULL. + * Callers rely on returning NULL if len is zero. */ + return NULL; + } + + p = malloc(len); + if (!p) + return NULL; + memcpy(p, ptr, len); + return p; +} + +#define _nl_memdup_ptr(ptr) ((__typeof__(ptr))_nl_memdup((ptr), sizeof(*(ptr)))) + +/*****************************************************************************/ + +static inline size_t _nl_addr_family_to_size(int addr_family) +{ + if (addr_family == AF_INET) + return sizeof(in_addr_t); + if (addr_family == AF_INET6) + return sizeof(struct in6_addr); + return 0; +} + +/*****************************************************************************/ + +typedef union { + in_addr_t addr4; + struct in_addr a4; + struct in6_addr a6; +} _NLIPAddr; + +static inline char *_nl_inet_ntop(int addr_family, const void *addr, char *buf) +{ + char *r; + + _nl_assert_addr_family(addr_family); + _nl_assert(addr); + + /* inet_ntop() is documented to fail, but if we pass a known address family + * and a suitably large buffer, it cannot. Assert for that. */ + + r = (char *)inet_ntop(addr_family, addr, buf, + (addr_family == AF_INET) ? INET_ADDRSTRLEN : + INET6_ADDRSTRLEN); + _nl_assert(r == buf); + _nl_assert(strlen(r) < ((addr_family == AF_INET) ? INET_ADDRSTRLEN : + INET6_ADDRSTRLEN)); + + return r; +} + +static inline char *_nl_inet_ntop_dup(int addr_family, const void *addr) +{ + return (char *)_nl_inet_ntop(addr_family, addr, + malloc((addr_family == AF_INET) ? + INET_ADDRSTRLEN : + INET6_ADDRSTRLEN)); +} + +/*****************************************************************************/ + +#define _NL_AUTO_DEFINE_FCN_VOID0(CastType, name, func) \ + static inline void name(void *v) \ + { \ + if (*((CastType *)v)) \ + func(*((CastType *)v)); \ + } \ + struct _nl_dummy_for_tailing_semicolon + +#define _NL_AUTO_DEFINE_FCN_STRUCT(CastType, name, func) \ + static inline void name(CastType *v) \ + { \ + if (v) \ + func(v); \ + } \ + struct _nl_dummy_for_tailing_semicolon + +#define _NL_AUTO_DEFINE_FCN_TYPED0(CastType, name, func) \ + static inline void name(CastType *v) \ + { \ + if (*v) \ + func(*v); \ + } \ + struct _nl_dummy_for_tailing_semicolon + +#define _NL_AUTO_DEFINE_FCN_INDIRECT0(CastType, name, func) \ + static inline void name(CastType *v) \ + { \ + if (*v) \ + func(v); \ + } \ + struct _nl_dummy_for_tailing_semicolon + +#define _nl_auto_free _nl_auto(_nl_auto_free_fcn) +_NL_AUTO_DEFINE_FCN_VOID0(void *, _nl_auto_free_fcn, free); + +/*****************************************************************************/ + +#define NSEC_PER_SEC 1000000000L + +struct trans_tbl { + uint64_t i; + const char *a; +}; + +#define __ADD(id, name) \ + { \ + .i = id, .a = #name \ + } + +#define BUG() \ + do { \ + fprintf(stderr, "BUG at file position %s:%d:%s\n", __FILE__, \ + __LINE__, __func__); \ + assert(0); \ + } while (0) + +#define BUG_ON(condition) \ + do { \ + if (condition) \ + BUG(); \ + } while (0) + +#define APPBUG(msg) \ + do { \ + fprintf(stderr, "APPLICATION BUG: %s:%d:%s: %s\n", __FILE__, \ + __LINE__, __func__, msg); \ + assert(0); \ + } while (0) + +/*****************************************************************************/ + +#ifndef DISABLE_PTHREADS +#define NL_LOCK(NAME) pthread_mutex_t(NAME) = PTHREAD_MUTEX_INITIALIZER +#define NL_RW_LOCK(NAME) pthread_rwlock_t(NAME) = PTHREAD_RWLOCK_INITIALIZER + +static inline void nl_lock(pthread_mutex_t *lock) +{ + pthread_mutex_lock(lock); +} + +static inline void nl_unlock(pthread_mutex_t *lock) +{ + pthread_mutex_unlock(lock); +} + +static inline void nl_read_lock(pthread_rwlock_t *lock) +{ + pthread_rwlock_rdlock(lock); +} + +static inline void nl_read_unlock(pthread_rwlock_t *lock) +{ + pthread_rwlock_unlock(lock); +} + +static inline void nl_write_lock(pthread_rwlock_t *lock) +{ + pthread_rwlock_wrlock(lock); +} + +static inline void nl_write_unlock(pthread_rwlock_t *lock) +{ + pthread_rwlock_unlock(lock); +} + +#else +#define NL_LOCK(NAME) int __unused_lock_##NAME __attribute__((unused)) +#define NL_RW_LOCK(NAME) int __unused_lock_##NAME __attribute__((unused)) + +#define nl_lock(LOCK) \ + do { \ + } while (0) +#define nl_unlock(LOCK) \ + do { \ + } while (0) +#define nl_read_lock(LOCK) \ + do { \ + } while (0) +#define nl_read_unlock(LOCK) \ + do { \ + } while (0) +#define nl_write_lock(LOCK) \ + do { \ + } while (0) +#define nl_write_unlock(LOCK) \ + do { \ + } while (0) +#endif + +#endif /* __NETLINK_BASE_NL_BASE_UTILS_H__ */ diff --git a/lib/defs.h.in b/include/config.h.in similarity index 70% rename from lib/defs.h.in rename to include/config.h.in index 62785cb..2855939 100644 --- a/lib/defs.h.in +++ b/include/config.h.in @@ -1,29 +1,37 @@ -/* lib/defs.h.in. Generated from configure.ac by autoheader. */ +/* include/config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 to disable pthreads */ #undef DISABLE_PTHREADS +/* Define to 1 if you have the declaration of `getprotobyname_r', and to 0 if + you don't. */ +#undef HAVE_DECL_GETPROTOBYNAME_R + +/* Define to 1 if you have the declaration of `getprotobynumber_r', and to 0 + if you don't. */ +#undef HAVE_DECL_GETPROTOBYNUMBER_R + /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H -/* Define to 1 if you have the `m' library (-lm). */ -#undef HAVE_LIBM - /* Define to 1 if you have the `pthread' library (-lpthread). */ #undef HAVE_LIBPTHREAD -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H +/* Define to 1 if you have the `strerror_l' function. */ +#undef HAVE_STRERROR_L + /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H @@ -39,16 +47,12 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ +/* Define to the sub-directory where libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Define to 1 to enable debugging */ #undef NL_DEBUG -/* Define to 1 if your C compiler doesn't accept -c and -o together. */ -#undef NO_MINUS_C_MINUS_O - /* Name of package */ #undef PACKAGE @@ -70,7 +74,9 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION -/* Define to 1 if you have the ANSI C header files. */ +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ #undef STDC_HEADERS /* Version number of package */ diff --git a/include/linux-private/linux/atm.h b/include/linux-private/linux/atm.h new file mode 100644 index 0000000..e33ff6b --- /dev/null +++ b/include/linux-private/linux/atm.h @@ -0,0 +1,242 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* atm.h - general ATM declarations */ + +/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ + + +/* + * WARNING: User-space programs should not #include directly. + * Instead, #include + */ + +#ifndef _LINUX_ATM_H +#define _LINUX_ATM_H + +/* + * BEGIN_xx and END_xx markers are used for automatic generation of + * documentation. Do not change them. + */ + + +#include +#include +#include +#include + + +/* general ATM constants */ +#define ATM_CELL_SIZE 53 /* ATM cell size incl. header */ +#define ATM_CELL_PAYLOAD 48 /* ATM payload size */ +#define ATM_AAL0_SDU 52 /* AAL0 SDU size */ +#define ATM_MAX_AAL34_PDU 65535 /* maximum AAL3/4 PDU payload */ +#define ATM_AAL5_TRAILER 8 /* AAL5 trailer size */ +#define ATM_MAX_AAL5_PDU 65535 /* maximum AAL5 PDU payload */ +#define ATM_MAX_CDV 9999 /* maximum (default) CDV */ +#define ATM_NOT_RSV_VCI 32 /* first non-reserved VCI value */ + +#define ATM_MAX_VPI 255 /* maximum VPI at the UNI */ +#define ATM_MAX_VPI_NNI 4096 /* maximum VPI at the NNI */ +#define ATM_MAX_VCI 65535 /* maximum VCI */ + + +/* "protcol" values for the socket system call */ +#define ATM_NO_AAL 0 /* AAL not specified */ +#define ATM_AAL0 13 /* "raw" ATM cells */ +#define ATM_AAL1 1 /* AAL1 (CBR) */ +#define ATM_AAL2 2 /* AAL2 (VBR) */ +#define ATM_AAL34 3 /* AAL3/4 (data) */ +#define ATM_AAL5 5 /* AAL5 (data) */ + +/* + * socket option name coding functions + * + * Note that __SO_ENCODE and __SO_LEVEL are somewhat a hack since the + * << 22 only reserves 9 bits for the level. On some architectures + * SOL_SOCKET is 0xFFFF, so that's a bit of a problem + */ + +#define __SO_ENCODE(l,n,t) ((((l) & 0x1FF) << 22) | ((n) << 16) | \ + sizeof(t)) +#define __SO_LEVEL_MATCH(c,m) (((c) >> 22) == ((m) & 0x1FF)) +#define __SO_NUMBER(c) (((c) >> 16) & 0x3f) +#define __SO_SIZE(c) ((c) & 0x3fff) + +/* + * ATM layer + */ + +#define SO_SETCLP __SO_ENCODE(SOL_ATM,0,int) + /* set CLP bit value - TODO */ +#define SO_CIRANGE __SO_ENCODE(SOL_ATM,1,struct atm_cirange) + /* connection identifier range; socket must be + bound or connected */ +#define SO_ATMQOS __SO_ENCODE(SOL_ATM,2,struct atm_qos) + /* Quality of Service setting */ +#define SO_ATMSAP __SO_ENCODE(SOL_ATM,3,struct atm_sap) + /* Service Access Point */ +#define SO_ATMPVC __SO_ENCODE(SOL_ATM,4,struct sockaddr_atmpvc) + /* "PVC" address (also for SVCs); get only */ +#define SO_MULTIPOINT __SO_ENCODE(SOL_ATM, 5, int) + /* make this vc a p2mp */ + + +/* + * Note @@@: since the socket layers don't really distinguish the control and + * the data plane but generally seems to be data plane-centric, any layer is + * about equally wrong for the SAP. If you have a better idea about this, + * please speak up ... + */ + + +/* ATM cell header (for AAL0) */ + +/* BEGIN_CH */ +#define ATM_HDR_GFC_MASK 0xf0000000 +#define ATM_HDR_GFC_SHIFT 28 +#define ATM_HDR_VPI_MASK 0x0ff00000 +#define ATM_HDR_VPI_SHIFT 20 +#define ATM_HDR_VCI_MASK 0x000ffff0 +#define ATM_HDR_VCI_SHIFT 4 +#define ATM_HDR_PTI_MASK 0x0000000e +#define ATM_HDR_PTI_SHIFT 1 +#define ATM_HDR_CLP 0x00000001 +/* END_CH */ + + +/* PTI codings */ + +/* BEGIN_PTI */ +#define ATM_PTI_US0 0 /* user data cell, congestion not exp, SDU-type 0 */ +#define ATM_PTI_US1 1 /* user data cell, congestion not exp, SDU-type 1 */ +#define ATM_PTI_UCES0 2 /* user data cell, cong. experienced, SDU-type 0 */ +#define ATM_PTI_UCES1 3 /* user data cell, cong. experienced, SDU-type 1 */ +#define ATM_PTI_SEGF5 4 /* segment OAM F5 flow related cell */ +#define ATM_PTI_E2EF5 5 /* end-to-end OAM F5 flow related cell */ +#define ATM_PTI_RSV_RM 6 /* reserved for traffic control/resource mgmt */ +#define ATM_PTI_RSV 7 /* reserved */ +/* END_PTI */ + + +/* + * The following items should stay in linux/atm.h, which should be linked to + * netatm/atm.h + */ + +/* Traffic description */ + +#define ATM_NONE 0 /* no traffic */ +#define ATM_UBR 1 +#define ATM_CBR 2 +#define ATM_VBR 3 +#define ATM_ABR 4 +#define ATM_ANYCLASS 5 /* compatible with everything */ + +#define ATM_MAX_PCR -1 /* maximum available PCR */ + +struct atm_trafprm { + unsigned char traffic_class; /* traffic class (ATM_UBR, ...) */ + int max_pcr; /* maximum PCR in cells per second */ + int pcr; /* desired PCR in cells per second */ + int min_pcr; /* minimum PCR in cells per second */ + int max_cdv; /* maximum CDV in microseconds */ + int max_sdu; /* maximum SDU in bytes */ + /* extra params for ABR */ + unsigned int icr; /* Initial Cell Rate (24-bit) */ + unsigned int tbe; /* Transient Buffer Exposure (24-bit) */ + unsigned int frtt : 24; /* Fixed Round Trip Time (24-bit) */ + unsigned int rif : 4; /* Rate Increment Factor (4-bit) */ + unsigned int rdf : 4; /* Rate Decrease Factor (4-bit) */ + unsigned int nrm_pres :1; /* nrm present bit */ + unsigned int trm_pres :1; /* rm present bit */ + unsigned int adtf_pres :1; /* adtf present bit */ + unsigned int cdf_pres :1; /* cdf present bit*/ + unsigned int nrm :3; /* Max # of Cells for each forward RM cell (3-bit) */ + unsigned int trm :3; /* Time between forward RM cells (3-bit) */ + unsigned int adtf :10; /* ACR Decrease Time Factor (10-bit) */ + unsigned int cdf :3; /* Cutoff Decrease Factor (3-bit) */ + unsigned int spare :9; /* spare bits */ +}; + +struct atm_qos { + struct atm_trafprm txtp; /* parameters in TX direction */ + struct atm_trafprm rxtp __ATM_API_ALIGN; + /* parameters in RX direction */ + unsigned char aal __ATM_API_ALIGN; +}; + +/* PVC addressing */ + +#define ATM_ITF_ANY -1 /* "magic" PVC address values */ +#define ATM_VPI_ANY -1 +#define ATM_VCI_ANY -1 +#define ATM_VPI_UNSPEC -2 +#define ATM_VCI_UNSPEC -2 + + +struct sockaddr_atmpvc { + unsigned short sap_family; /* address family, AF_ATMPVC */ + struct { /* PVC address */ + short itf; /* ATM interface */ + short vpi; /* VPI (only 8 bits at UNI) */ + int vci; /* VCI (only 16 bits at UNI) */ + } sap_addr __ATM_API_ALIGN; /* PVC address */ +}; + +/* SVC addressing */ + +#define ATM_ESA_LEN 20 /* ATM End System Address length */ +#define ATM_E164_LEN 12 /* maximum E.164 number length */ + +#define ATM_AFI_DCC 0x39 /* DCC ATM Format */ +#define ATM_AFI_ICD 0x47 /* ICD ATM Format */ +#define ATM_AFI_E164 0x45 /* E.164 ATM Format */ +#define ATM_AFI_LOCAL 0x49 /* Local ATM Format */ + +#define ATM_AFI_DCC_GROUP 0xBD /* DCC ATM Group Format */ +#define ATM_AFI_ICD_GROUP 0xC5 /* ICD ATM Group Format */ +#define ATM_AFI_E164_GROUP 0xC3 /* E.164 ATM Group Format */ +#define ATM_AFI_LOCAL_GROUP 0xC7 /* Local ATM Group Format */ + +#define ATM_LIJ_NONE 0 /* no leaf-initiated join */ +#define ATM_LIJ 1 /* request joining */ +#define ATM_LIJ_RPJ 2 /* set to root-prompted join */ +#define ATM_LIJ_NJ 3 /* set to network join */ + + +struct sockaddr_atmsvc { + unsigned short sas_family; /* address family, AF_ATMSVC */ + struct { /* SVC address */ + unsigned char prv[ATM_ESA_LEN];/* private ATM address */ + char pub[ATM_E164_LEN+1]; /* public address (E.164) */ + /* unused addresses must be bzero'ed */ + char lij_type; /* role in LIJ call; one of ATM_LIJ* */ + __u32 lij_id; /* LIJ call identifier */ + } sas_addr __ATM_API_ALIGN; /* SVC address */ +}; + + +static __inline__ int atmsvc_addr_in_use(struct sockaddr_atmsvc addr) +{ + return *addr.sas_addr.prv || *addr.sas_addr.pub; +} + + +static __inline__ int atmpvc_addr_in_use(struct sockaddr_atmpvc addr) +{ + return addr.sap_addr.itf || addr.sap_addr.vpi || addr.sap_addr.vci; +} + + +/* + * Some stuff for linux/sockios.h + */ + +struct atmif_sioc { + int number; + int length; + void *arg; +}; + + +typedef unsigned short atm_backend_t; +#endif /* _LINUX_ATM_H */ diff --git a/include/linux-private/linux/atmapi.h b/include/linux-private/linux/atmapi.h new file mode 100644 index 0000000..c9bf5c2 --- /dev/null +++ b/include/linux-private/linux/atmapi.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* atmapi.h - ATM API user space/kernel compatibility */ + +/* Written 1999,2000 by Werner Almesberger, EPFL ICA */ + + +#ifndef _LINUX_ATMAPI_H +#define _LINUX_ATMAPI_H + +#if defined(__sparc__) || defined(__ia64__) +/* such alignment is not required on 32 bit sparcs, but we can't + figure that we are on a sparc64 while compiling user-space programs. */ +#define __ATM_API_ALIGN __attribute__((aligned(8))) +#else +#define __ATM_API_ALIGN +#endif + + +/* + * Opaque type for kernel pointers. Note that _ is never accessed. We need + * the struct in order hide the array, so that we can make simple assignments + * instead of being forced to use memcpy. It also improves error reporting for + * code that still assumes that we're passing unsigned longs. + * + * Convention: NULL pointers are passed as a field of all zeroes. + */ + +typedef struct { unsigned char _[8]; } __ATM_API_ALIGN atm_kptr_t; + +#endif diff --git a/include/linux-private/linux/atmioc.h b/include/linux-private/linux/atmioc.h new file mode 100644 index 0000000..a9030bc --- /dev/null +++ b/include/linux-private/linux/atmioc.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* atmioc.h - ranges for ATM-related ioctl numbers */ + +/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */ + + +/* + * See https://icawww1.epfl.ch/linux-atm/magic.html for the complete list of + * "magic" ioctl numbers. + */ + + +#ifndef _LINUX_ATMIOC_H +#define _LINUX_ATMIOC_H + +#include + /* everybody including atmioc.h will also need _IO{,R,W,WR} */ + +#define ATMIOC_PHYCOM 0x00 /* PHY device common ioctls, globally unique */ +#define ATMIOC_PHYCOM_END 0x0f +#define ATMIOC_PHYTYP 0x10 /* PHY dev type ioctls, unique per PHY type */ +#define ATMIOC_PHYTYP_END 0x2f +#define ATMIOC_PHYPRV 0x30 /* PHY dev private ioctls, unique per driver */ +#define ATMIOC_PHYPRV_END 0x4f +#define ATMIOC_SARCOM 0x50 /* SAR device common ioctls, globally unique */ +#define ATMIOC_SARCOM_END 0x50 +#define ATMIOC_SARPRV 0x60 /* SAR dev private ioctls, unique per driver */ +#define ATMIOC_SARPRV_END 0x7f +#define ATMIOC_ITF 0x80 /* Interface ioctls, globally unique */ +#define ATMIOC_ITF_END 0x8f +#define ATMIOC_BACKEND 0x90 /* ATM generic backend ioctls, u. per backend */ +#define ATMIOC_BACKEND_END 0xaf +/* 0xb0-0xbf: Reserved for future use */ +#define ATMIOC_AREQUIPA 0xc0 /* Application requested IP over ATM, glob. u. */ +#define ATMIOC_LANE 0xd0 /* LAN Emulation, globally unique */ +#define ATMIOC_MPOA 0xd8 /* MPOA, globally unique */ +#define ATMIOC_CLIP 0xe0 /* Classical IP over ATM control, globally u. */ +#define ATMIOC_CLIP_END 0xef +#define ATMIOC_SPECIAL 0xf0 /* Special-purpose controls, globally unique */ +#define ATMIOC_SPECIAL_END 0xff + +#endif diff --git a/include/linux-private/linux/atmsap.h b/include/linux-private/linux/atmsap.h new file mode 100644 index 0000000..fc05248 --- /dev/null +++ b/include/linux-private/linux/atmsap.h @@ -0,0 +1,163 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* atmsap.h - ATM Service Access Point addressing definitions */ + +/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */ + + +#ifndef _LINUX_ATMSAP_H +#define _LINUX_ATMSAP_H + +#include + +/* + * BEGIN_xx and END_xx markers are used for automatic generation of + * documentation. Do not change them. + */ + + +/* + * Layer 2 protocol identifiers + */ + +/* BEGIN_L2 */ +#define ATM_L2_NONE 0 /* L2 not specified */ +#define ATM_L2_ISO1745 0x01 /* Basic mode ISO 1745 */ +#define ATM_L2_Q291 0x02 /* ITU-T Q.291 (Rec. I.441) */ +#define ATM_L2_X25_LL 0x06 /* ITU-T X.25, link layer */ +#define ATM_L2_X25_ML 0x07 /* ITU-T X.25, multilink */ +#define ATM_L2_LAPB 0x08 /* Extended LAPB, half-duplex (Rec. T.71) */ +#define ATM_L2_HDLC_ARM 0x09 /* HDLC ARM (ISO/IEC 4335) */ +#define ATM_L2_HDLC_NRM 0x0a /* HDLC NRM (ISO/IEC 4335) */ +#define ATM_L2_HDLC_ABM 0x0b /* HDLC ABM (ISO/IEC 4335) */ +#define ATM_L2_ISO8802 0x0c /* LAN LLC (ISO/IEC 8802/2) */ +#define ATM_L2_X75 0x0d /* ITU-T X.75, SLP */ +#define ATM_L2_Q922 0x0e /* ITU-T Q.922 */ +#define ATM_L2_USER 0x10 /* user-specified */ +#define ATM_L2_ISO7776 0x11 /* ISO 7776 DTE-DTE */ +/* END_L2 */ + + +/* + * Layer 3 protocol identifiers + */ + +/* BEGIN_L3 */ +#define ATM_L3_NONE 0 /* L3 not specified */ +#define ATM_L3_X25 0x06 /* ITU-T X.25, packet layer */ +#define ATM_L3_ISO8208 0x07 /* ISO/IEC 8208 */ +#define ATM_L3_X223 0x08 /* ITU-T X.223 | ISO/IEC 8878 */ +#define ATM_L3_ISO8473 0x09 /* ITU-T X.233 | ISO/IEC 8473 */ +#define ATM_L3_T70 0x0a /* ITU-T T.70 minimum network layer */ +#define ATM_L3_TR9577 0x0b /* ISO/IEC TR 9577 */ +#define ATM_L3_H310 0x0c /* ITU-T Recommendation H.310 */ +#define ATM_L3_H321 0x0d /* ITU-T Recommendation H.321 */ +#define ATM_L3_USER 0x10 /* user-specified */ +/* END_L3 */ + + +/* + * High layer identifiers + */ + +/* BEGIN_HL */ +#define ATM_HL_NONE 0 /* HL not specified */ +#define ATM_HL_ISO 0x01 /* ISO */ +#define ATM_HL_USER 0x02 /* user-specific */ +#define ATM_HL_HLP 0x03 /* high layer profile - UNI 3.0 only */ +#define ATM_HL_VENDOR 0x04 /* vendor-specific application identifier */ +/* END_HL */ + + +/* + * ITU-T coded mode of operation + */ + +/* BEGIN_IMD */ +#define ATM_IMD_NONE 0 /* mode not specified */ +#define ATM_IMD_NORMAL 1 /* normal mode of operation */ +#define ATM_IMD_EXTENDED 2 /* extended mode of operation */ +/* END_IMD */ + +/* + * H.310 code points + */ + +#define ATM_TT_NONE 0 /* terminal type not specified */ +#define ATM_TT_RX 1 /* receive only */ +#define ATM_TT_TX 2 /* send only */ +#define ATM_TT_RXTX 3 /* receive and send */ + +#define ATM_MC_NONE 0 /* no multiplexing */ +#define ATM_MC_TS 1 /* transport stream (TS) */ +#define ATM_MC_TS_FEC 2 /* transport stream with forward error corr. */ +#define ATM_MC_PS 3 /* program stream (PS) */ +#define ATM_MC_PS_FEC 4 /* program stream with forward error corr. */ +#define ATM_MC_H221 5 /* ITU-T Rec. H.221 */ + +/* + * SAP structures + */ + +#define ATM_MAX_HLI 8 /* maximum high-layer information length */ + + +struct atm_blli { + unsigned char l2_proto; /* layer 2 protocol */ + union { + struct { + unsigned char mode; /* mode of operation (ATM_IMD_xxx), 0 if */ + /* absent */ + unsigned char window; /* window size (k), 1-127 (0 to omit) */ + } itu; /* ITU-T encoding */ + unsigned char user; /* user-specified l2 information */ + } l2; + unsigned char l3_proto; /* layer 3 protocol */ + union { + struct { + unsigned char mode; /* mode of operation (ATM_IMD_xxx), 0 if */ + /* absent */ + unsigned char def_size; /* default packet size (log2), 4-12 (0 to */ + /* omit) */ + unsigned char window;/* packet window size, 1-127 (0 to omit) */ + } itu; /* ITU-T encoding */ + unsigned char user; /* user specified l3 information */ + struct { /* if l3_proto = ATM_L3_H310 */ + unsigned char term_type; /* terminal type */ + unsigned char fw_mpx_cap; /* forward multiplexing capability */ + /* only if term_type != ATM_TT_NONE */ + unsigned char bw_mpx_cap; /* backward multiplexing capability */ + /* only if term_type != ATM_TT_NONE */ + } h310; + struct { /* if l3_proto = ATM_L3_TR9577 */ + unsigned char ipi; /* initial protocol id */ + unsigned char snap[5];/* IEEE 802.1 SNAP identifier */ + /* (only if ipi == NLPID_IEEE802_1_SNAP) */ + } tr9577; + } l3; +} __ATM_API_ALIGN; + + +struct atm_bhli { + unsigned char hl_type; /* high layer information type */ + unsigned char hl_length; /* length (only if hl_type == ATM_HL_USER || */ + /* hl_type == ATM_HL_ISO) */ + unsigned char hl_info[ATM_MAX_HLI];/* high layer information */ +}; + + +#define ATM_MAX_BLLI 3 /* maximum number of BLLI elements */ + + +struct atm_sap { + struct atm_bhli bhli; /* local SAP, high-layer information */ + struct atm_blli blli[ATM_MAX_BLLI] __ATM_API_ALIGN; + /* local SAP, low-layer info */ +}; + + +static __inline__ int blli_in_use(struct atm_blli blli) +{ + return blli.l2_proto || blli.l3_proto; +} + +#endif diff --git a/include/linux-private/linux/byteorder/little_endian.h b/include/linux-private/linux/byteorder/little_endian.h new file mode 100644 index 0000000..ba6c199 --- /dev/null +++ b/include/linux-private/linux/byteorder/little_endian.h @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_BYTEORDER_LITTLE_ENDIAN_H +#define _LINUX_BYTEORDER_LITTLE_ENDIAN_H + +#ifndef __LITTLE_ENDIAN +#define __LITTLE_ENDIAN 1234 +#endif +#ifndef __LITTLE_ENDIAN_BITFIELD +#define __LITTLE_ENDIAN_BITFIELD +#endif + +#include +#include +#include + +#define __constant_htonl(x) ((__be32)___constant_swab32((x))) +#define __constant_ntohl(x) ___constant_swab32((__be32)(x)) +#define __constant_htons(x) ((__be16)___constant_swab16((x))) +#define __constant_ntohs(x) ___constant_swab16((__be16)(x)) +#define __constant_cpu_to_le64(x) ((__le64)(__u64)(x)) +#define __constant_le64_to_cpu(x) ((__u64)(__le64)(x)) +#define __constant_cpu_to_le32(x) ((__le32)(__u32)(x)) +#define __constant_le32_to_cpu(x) ((__u32)(__le32)(x)) +#define __constant_cpu_to_le16(x) ((__le16)(__u16)(x)) +#define __constant_le16_to_cpu(x) ((__u16)(__le16)(x)) +#define __constant_cpu_to_be64(x) ((__be64)___constant_swab64((x))) +#define __constant_be64_to_cpu(x) ___constant_swab64((__u64)(__be64)(x)) +#define __constant_cpu_to_be32(x) ((__be32)___constant_swab32((x))) +#define __constant_be32_to_cpu(x) ___constant_swab32((__u32)(__be32)(x)) +#define __constant_cpu_to_be16(x) ((__be16)___constant_swab16((x))) +#define __constant_be16_to_cpu(x) ___constant_swab16((__u16)(__be16)(x)) +#define __cpu_to_le64(x) ((__le64)(__u64)(x)) +#define __le64_to_cpu(x) ((__u64)(__le64)(x)) +#define __cpu_to_le32(x) ((__le32)(__u32)(x)) +#define __le32_to_cpu(x) ((__u32)(__le32)(x)) +#define __cpu_to_le16(x) ((__le16)(__u16)(x)) +#define __le16_to_cpu(x) ((__u16)(__le16)(x)) +#define __cpu_to_be64(x) ((__be64)__swab64((x))) +#define __be64_to_cpu(x) __swab64((__u64)(__be64)(x)) +#define __cpu_to_be32(x) ((__be32)__swab32((x))) +#define __be32_to_cpu(x) __swab32((__u32)(__be32)(x)) +#define __cpu_to_be16(x) ((__be16)__swab16((x))) +#define __be16_to_cpu(x) __swab16((__u16)(__be16)(x)) + +static __always_inline __le64 __cpu_to_le64p(const __u64 *p) +{ + return (__le64)*p; +} +static __always_inline __u64 __le64_to_cpup(const __le64 *p) +{ + return (__u64)*p; +} +static __always_inline __le32 __cpu_to_le32p(const __u32 *p) +{ + return (__le32)*p; +} +static __always_inline __u32 __le32_to_cpup(const __le32 *p) +{ + return (__u32)*p; +} +static __always_inline __le16 __cpu_to_le16p(const __u16 *p) +{ + return (__le16)*p; +} +static __always_inline __u16 __le16_to_cpup(const __le16 *p) +{ + return (__u16)*p; +} +static __always_inline __be64 __cpu_to_be64p(const __u64 *p) +{ + return (__be64)__swab64p(p); +} +static __always_inline __u64 __be64_to_cpup(const __be64 *p) +{ + return __swab64p((__u64 *)p); +} +static __always_inline __be32 __cpu_to_be32p(const __u32 *p) +{ + return (__be32)__swab32p(p); +} +static __always_inline __u32 __be32_to_cpup(const __be32 *p) +{ + return __swab32p((__u32 *)p); +} +static __always_inline __be16 __cpu_to_be16p(const __u16 *p) +{ + return (__be16)__swab16p(p); +} +static __always_inline __u16 __be16_to_cpup(const __be16 *p) +{ + return __swab16p((__u16 *)p); +} +#define __cpu_to_le64s(x) do { (void)(x); } while (0) +#define __le64_to_cpus(x) do { (void)(x); } while (0) +#define __cpu_to_le32s(x) do { (void)(x); } while (0) +#define __le32_to_cpus(x) do { (void)(x); } while (0) +#define __cpu_to_le16s(x) do { (void)(x); } while (0) +#define __le16_to_cpus(x) do { (void)(x); } while (0) +#define __cpu_to_be64s(x) __swab64s((x)) +#define __be64_to_cpus(x) __swab64s((x)) +#define __cpu_to_be32s(x) __swab32s((x)) +#define __be32_to_cpus(x) __swab32s((x)) +#define __cpu_to_be16s(x) __swab16s((x)) +#define __be16_to_cpus(x) __swab16s((x)) + + +#endif /* _LINUX_BYTEORDER_LITTLE_ENDIAN_H */ diff --git a/include/linux/can/netlink.h b/include/linux-private/linux/can/netlink.h similarity index 52% rename from include/linux/can/netlink.h rename to include/linux-private/linux/can/netlink.h index 14966dd..8ec98c2 100644 --- a/include/linux/can/netlink.h +++ b/include/linux-private/linux/can/netlink.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* * linux/can/netlink.h * @@ -5,10 +6,18 @@ * * Copyright (c) 2009 Wolfgang Grandegger * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the version 2 of the GNU General Public License + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. */ -#ifndef CAN_NETLINK_H -#define CAN_NETLINK_H +#ifndef _CAN_NETLINK_H +#define _CAN_NETLINK_H #include @@ -31,15 +40,15 @@ struct can_bittiming { }; /* - * CAN harware-dependent bit-timing constant + * CAN hardware-dependent bit-timing constant * * Used for calculating and checking bit-timing parameters */ struct can_bittiming_const { char name[16]; /* Name of the CAN controller hardware */ - __u32 tseg1_min; /* Time segement 1 = prop_seg + phase_seg1 */ + __u32 tseg1_min; /* Time segment 1 = prop_seg + phase_seg1 */ __u32 tseg1_max; - __u32 tseg2_min; /* Time segement 2 = phase_seg2 */ + __u32 tseg2_min; /* Time segment 2 = phase_seg2 */ __u32 tseg2_max; __u32 sjw_max; /* Synchronisation jump width */ __u32 brp_min; /* Bit-rate prescaler */ @@ -84,10 +93,16 @@ struct can_ctrlmode { }; #define CAN_CTRLMODE_LOOPBACK 0x01 /* Loopback mode */ -#define CAN_CTRLMODE_LISTENONLY 0x02 /* Listen-only mode */ +#define CAN_CTRLMODE_LISTENONLY 0x02 /* Listen-only mode */ #define CAN_CTRLMODE_3_SAMPLES 0x04 /* Triple sampling mode */ #define CAN_CTRLMODE_ONE_SHOT 0x08 /* One-Shot mode */ #define CAN_CTRLMODE_BERR_REPORTING 0x10 /* Bus-error reporting */ +#define CAN_CTRLMODE_FD 0x20 /* CAN FD mode */ +#define CAN_CTRLMODE_PRESUME_ACK 0x40 /* Ignore missing CAN ACKs */ +#define CAN_CTRLMODE_FD_NON_ISO 0x80 /* CAN FD in non-ISO mode */ +#define CAN_CTRLMODE_CC_LEN8_DLC 0x100 /* Classic CAN DLC option */ +#define CAN_CTRLMODE_TDC_AUTO 0x200 /* CAN transiver automatically calculates TDCV */ +#define CAN_CTRLMODE_TDC_MANUAL 0x400 /* TDCV is manually set up by user */ /* * CAN device statistics @@ -114,9 +129,57 @@ enum { IFLA_CAN_RESTART_MS, IFLA_CAN_RESTART, IFLA_CAN_BERR_COUNTER, - __IFLA_CAN_MAX + IFLA_CAN_DATA_BITTIMING, + IFLA_CAN_DATA_BITTIMING_CONST, + IFLA_CAN_TERMINATION, + IFLA_CAN_TERMINATION_CONST, + IFLA_CAN_BITRATE_CONST, + IFLA_CAN_DATA_BITRATE_CONST, + IFLA_CAN_BITRATE_MAX, + IFLA_CAN_TDC, + IFLA_CAN_CTRLMODE_EXT, + + /* add new constants above here */ + __IFLA_CAN_MAX, + IFLA_CAN_MAX = __IFLA_CAN_MAX - 1 +}; + +/* + * CAN FD Transmitter Delay Compensation (TDC) + * + * Please refer to struct can_tdc_const and can_tdc in + * include/linux/can/bittiming.h for further details. + */ +enum { + IFLA_CAN_TDC_UNSPEC, + IFLA_CAN_TDC_TDCV_MIN, /* u32 */ + IFLA_CAN_TDC_TDCV_MAX, /* u32 */ + IFLA_CAN_TDC_TDCO_MIN, /* u32 */ + IFLA_CAN_TDC_TDCO_MAX, /* u32 */ + IFLA_CAN_TDC_TDCF_MIN, /* u32 */ + IFLA_CAN_TDC_TDCF_MAX, /* u32 */ + IFLA_CAN_TDC_TDCV, /* u32 */ + IFLA_CAN_TDC_TDCO, /* u32 */ + IFLA_CAN_TDC_TDCF, /* u32 */ + + /* add new constants above here */ + __IFLA_CAN_TDC, + IFLA_CAN_TDC_MAX = __IFLA_CAN_TDC - 1 +}; + +/* + * IFLA_CAN_CTRLMODE_EXT nest: controller mode extended parameters + */ +enum { + IFLA_CAN_CTRLMODE_UNSPEC, + IFLA_CAN_CTRLMODE_SUPPORTED, /* u32 */ + + /* add new constants above here */ + __IFLA_CAN_CTRLMODE, + IFLA_CAN_CTRLMODE_MAX = __IFLA_CAN_CTRLMODE - 1 }; -#define IFLA_CAN_MAX (__IFLA_CAN_MAX - 1) +/* u16 termination range: 1..65535 Ohms */ +#define CAN_TERMINATION_DISABLED 0 -#endif /* CAN_NETLINK_H */ +#endif /* !_UAPI_CAN_NETLINK_H */ diff --git a/include/linux-private/linux/const.h b/include/linux-private/linux/const.h new file mode 100644 index 0000000..1eb84b5 --- /dev/null +++ b/include/linux-private/linux/const.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* const.h: Macros for dealing with constants. */ + +#ifndef _LINUX_CONST_H +#define _LINUX_CONST_H + +/* Some constant macros are used in both assembler and + * C code. Therefore we cannot annotate them always with + * 'UL' and other type specifiers unilaterally. We + * use the following macros to deal with this. + * + * Similarly, _AT() will cast an expression with a type in C, but + * leave it unchanged in asm. + */ + +#ifdef __ASSEMBLY__ +#define _AC(X,Y) X +#define _AT(T,X) X +#else +#define __AC(X,Y) (X##Y) +#define _AC(X,Y) __AC(X,Y) +#define _AT(T,X) ((T)(X)) +#endif + +#define _UL(x) (_AC(x, UL)) +#define _ULL(x) (_AC(x, ULL)) + +#define _BITUL(x) (_UL(1) << (x)) +#define _BITULL(x) (_ULL(1) << (x)) + +#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (__typeof__(x))(a) - 1) +#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) + +#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) + +#endif /* _LINUX_CONST_H */ diff --git a/include/linux-private/linux/errno.h b/include/linux-private/linux/errno.h new file mode 100644 index 0000000..70f2bd3 --- /dev/null +++ b/include/linux-private/linux/errno.h @@ -0,0 +1 @@ +#include diff --git a/include/linux-private/linux/ethtool.h b/include/linux-private/linux/ethtool.h new file mode 100644 index 0000000..1d0731b --- /dev/null +++ b/include/linux-private/linux/ethtool.h @@ -0,0 +1,2206 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * ethtool.h: Defines for Linux ethtool. + * + * Copyright (C) 1998 David S. Miller (davem@redhat.com) + * Copyright 2001 Jeff Garzik + * Portions Copyright 2001 Sun Microsystems (thockin@sun.com) + * Portions Copyright 2002 Intel (eli.kupermann@intel.com, + * christopher.leech@intel.com, + * scott.feldman@intel.com) + * Portions Copyright (C) Sun Microsystems 2008 + */ + +#ifndef _LINUX_ETHTOOL_H +#define _LINUX_ETHTOOL_H + +#include +#include +#include + +#include /* for INT_MAX */ + +/* All structures exposed to userland should be defined such that they + * have the same layout for 32-bit and 64-bit userland. + */ + +/* Note on reserved space. + * Reserved fields must not be accessed directly by user space because + * they may be replaced by a different field in the future. They must + * be initialized to zero before making the request, e.g. via memset + * of the entire structure or implicitly by not being set in a structure + * initializer. + */ + +/** + * struct ethtool_cmd - DEPRECATED, link control and status + * This structure is DEPRECATED, please use struct ethtool_link_settings. + * @cmd: Command number = %ETHTOOL_GSET or %ETHTOOL_SSET + * @supported: Bitmask of %SUPPORTED_* flags for the link modes, + * physical connectors and other link features for which the + * interface supports autonegotiation or auto-detection. + * Read-only. + * @advertising: Bitmask of %ADVERTISED_* flags for the link modes, + * physical connectors and other link features that are + * advertised through autonegotiation or enabled for + * auto-detection. + * @speed: Low bits of the speed, 1Mb units, 0 to INT_MAX or SPEED_UNKNOWN + * @duplex: Duplex mode; one of %DUPLEX_* + * @port: Physical connector type; one of %PORT_* + * @phy_address: MDIO address of PHY (transceiver); 0 or 255 if not + * applicable. For clause 45 PHYs this is the PRTAD. + * @transceiver: Historically used to distinguish different possible + * PHY types, but not in a consistent way. Deprecated. + * @autoneg: Enable/disable autonegotiation and auto-detection; + * either %AUTONEG_DISABLE or %AUTONEG_ENABLE + * @mdio_support: Bitmask of %ETH_MDIO_SUPPORTS_* flags for the MDIO + * protocols supported by the interface; 0 if unknown. + * Read-only. + * @maxtxpkt: Historically used to report TX IRQ coalescing; now + * obsoleted by &struct ethtool_coalesce. Read-only; deprecated. + * @maxrxpkt: Historically used to report RX IRQ coalescing; now + * obsoleted by &struct ethtool_coalesce. Read-only; deprecated. + * @speed_hi: High bits of the speed, 1Mb units, 0 to INT_MAX or SPEED_UNKNOWN + * @eth_tp_mdix: Ethernet twisted-pair MDI(-X) status; one of + * %ETH_TP_MDI_*. If the status is unknown or not applicable, the + * value will be %ETH_TP_MDI_INVALID. Read-only. + * @eth_tp_mdix_ctrl: Ethernet twisted pair MDI(-X) control; one of + * %ETH_TP_MDI_*. If MDI(-X) control is not implemented, reads + * yield %ETH_TP_MDI_INVALID and writes may be ignored or rejected. + * When written successfully, the link should be renegotiated if + * necessary. + * @lp_advertising: Bitmask of %ADVERTISED_* flags for the link modes + * and other link features that the link partner advertised + * through autonegotiation; 0 if unknown or not applicable. + * Read-only. + * @reserved: Reserved for future use; see the note on reserved space. + * + * The link speed in Mbps is split between @speed and @speed_hi. Use + * the ethtool_cmd_speed() and ethtool_cmd_speed_set() functions to + * access it. + * + * If autonegotiation is disabled, the speed and @duplex represent the + * fixed link mode and are writable if the driver supports multiple + * link modes. If it is enabled then they are read-only; if the link + * is up they represent the negotiated link mode; if the link is down, + * the speed is 0, %SPEED_UNKNOWN or the highest enabled speed and + * @duplex is %DUPLEX_UNKNOWN or the best enabled duplex mode. + * + * Some hardware interfaces may have multiple PHYs and/or physical + * connectors fitted or do not allow the driver to detect which are + * fitted. For these interfaces @port and/or @phy_address may be + * writable, possibly dependent on @autoneg being %AUTONEG_DISABLE. + * Otherwise, attempts to write different values may be ignored or + * rejected. + * + * Users should assume that all fields not marked read-only are + * writable and subject to validation by the driver. They should use + * %ETHTOOL_GSET to get the current values before making specific + * changes and then applying them with %ETHTOOL_SSET. + * + * Deprecated fields should be ignored by both users and drivers. + */ +struct ethtool_cmd { + __u32 cmd; + __u32 supported; + __u32 advertising; + __u16 speed; + __u8 duplex; + __u8 port; + __u8 phy_address; + __u8 transceiver; + __u8 autoneg; + __u8 mdio_support; + __u32 maxtxpkt; + __u32 maxrxpkt; + __u16 speed_hi; + __u8 eth_tp_mdix; + __u8 eth_tp_mdix_ctrl; + __u32 lp_advertising; + __u32 reserved[2]; +}; + +static __inline__ void ethtool_cmd_speed_set(struct ethtool_cmd *ep, + __u32 speed) +{ + ep->speed = (__u16)(speed & 0xFFFF); + ep->speed_hi = (__u16)(speed >> 16); +} + +static __inline__ __u32 ethtool_cmd_speed(const struct ethtool_cmd *ep) +{ + return (ep->speed_hi << 16) | ep->speed; +} + +/* Device supports clause 22 register access to PHY or peripherals + * using the interface defined in . This should not be + * set if there are known to be no such peripherals present or if + * the driver only emulates clause 22 registers for compatibility. + */ +#define ETH_MDIO_SUPPORTS_C22 1 + +/* Device supports clause 45 register access to PHY or peripherals + * using the interface defined in and . + * This should not be set if there are known to be no such peripherals + * present. + */ +#define ETH_MDIO_SUPPORTS_C45 2 + +#define ETHTOOL_FWVERS_LEN 32 +#define ETHTOOL_BUSINFO_LEN 32 +#define ETHTOOL_EROMVERS_LEN 32 + +/** + * struct ethtool_drvinfo - general driver and device information + * @cmd: Command number = %ETHTOOL_GDRVINFO + * @driver: Driver short name. This should normally match the name + * in its bus driver structure (e.g. pci_driver::name). Must + * not be an empty string. + * @version: Driver version string; may be an empty string + * @fw_version: Firmware version string; driver defined; may be an + * empty string + * @erom_version: Expansion ROM version string; driver defined; may be + * an empty string + * @bus_info: Device bus address. This should match the dev_name() + * string for the underlying bus device, if there is one. May be + * an empty string. + * @reserved2: Reserved for future use; see the note on reserved space. + * @n_priv_flags: Number of flags valid for %ETHTOOL_GPFLAGS and + * %ETHTOOL_SPFLAGS commands; also the number of strings in the + * %ETH_SS_PRIV_FLAGS set + * @n_stats: Number of u64 statistics returned by the %ETHTOOL_GSTATS + * command; also the number of strings in the %ETH_SS_STATS set + * @testinfo_len: Number of results returned by the %ETHTOOL_TEST + * command; also the number of strings in the %ETH_SS_TEST set + * @eedump_len: Size of EEPROM accessible through the %ETHTOOL_GEEPROM + * and %ETHTOOL_SEEPROM commands, in bytes + * @regdump_len: Size of register dump returned by the %ETHTOOL_GREGS + * command, in bytes + * + * Users can use the %ETHTOOL_GSSET_INFO command to get the number of + * strings in any string set (from Linux 2.6.34). + */ +struct ethtool_drvinfo { + __u32 cmd; + char driver[32]; + char version[32]; + char fw_version[ETHTOOL_FWVERS_LEN]; + char bus_info[ETHTOOL_BUSINFO_LEN]; + char erom_version[ETHTOOL_EROMVERS_LEN]; + char reserved2[12]; + __u32 n_priv_flags; + __u32 n_stats; + __u32 testinfo_len; + __u32 eedump_len; + __u32 regdump_len; +}; + +#define SOPASS_MAX 6 + +/** + * struct ethtool_wolinfo - Wake-On-Lan configuration + * @cmd: Command number = %ETHTOOL_GWOL or %ETHTOOL_SWOL + * @supported: Bitmask of %WAKE_* flags for supported Wake-On-Lan modes. + * Read-only. + * @wolopts: Bitmask of %WAKE_* flags for enabled Wake-On-Lan modes. + * @sopass: SecureOn(tm) password; meaningful only if %WAKE_MAGICSECURE + * is set in @wolopts. + */ +struct ethtool_wolinfo { + __u32 cmd; + __u32 supported; + __u32 wolopts; + __u8 sopass[SOPASS_MAX]; +}; + +/* for passing single values */ +struct ethtool_value { + __u32 cmd; + __u32 data; +}; + +#define PFC_STORM_PREVENTION_AUTO 0xffff +#define PFC_STORM_PREVENTION_DISABLE 0 + +enum tunable_id { + ETHTOOL_ID_UNSPEC, + ETHTOOL_RX_COPYBREAK, + ETHTOOL_TX_COPYBREAK, + ETHTOOL_PFC_PREVENTION_TOUT, /* timeout in msecs */ + ETHTOOL_TX_COPYBREAK_BUF_SIZE, + /* + * Add your fresh new tunable attribute above and remember to update + * tunable_strings[] in net/ethtool/common.c + */ + __ETHTOOL_TUNABLE_COUNT, +}; + +enum tunable_type_id { + ETHTOOL_TUNABLE_UNSPEC, + ETHTOOL_TUNABLE_U8, + ETHTOOL_TUNABLE_U16, + ETHTOOL_TUNABLE_U32, + ETHTOOL_TUNABLE_U64, + ETHTOOL_TUNABLE_STRING, + ETHTOOL_TUNABLE_S8, + ETHTOOL_TUNABLE_S16, + ETHTOOL_TUNABLE_S32, + ETHTOOL_TUNABLE_S64, +}; + +struct ethtool_tunable { + __u32 cmd; + __u32 id; + __u32 type_id; + __u32 len; + void *data[]; +}; + +#define DOWNSHIFT_DEV_DEFAULT_COUNT 0xff +#define DOWNSHIFT_DEV_DISABLE 0 + +/* Time in msecs after which link is reported as down + * 0 = lowest time supported by the PHY + * 0xff = off, link down detection according to standard + */ +#define ETHTOOL_PHY_FAST_LINK_DOWN_ON 0 +#define ETHTOOL_PHY_FAST_LINK_DOWN_OFF 0xff + +/* Energy Detect Power Down (EDPD) is a feature supported by some PHYs, where + * the PHY's RX & TX blocks are put into a low-power mode when there is no + * link detected (typically cable is un-plugged). For RX, only a minimal + * link-detection is available, and for TX the PHY wakes up to send link pulses + * to avoid any lock-ups in case the peer PHY may also be running in EDPD mode. + * + * Some PHYs may support configuration of the wake-up interval for TX pulses, + * and some PHYs may support only disabling TX pulses entirely. For the latter + * a special value is required (ETHTOOL_PHY_EDPD_NO_TX) so that this can be + * configured from userspace (should the user want it). + * + * The interval units for TX wake-up are in milliseconds, since this should + * cover a reasonable range of intervals: + * - from 1 millisecond, which does not sound like much of a power-saver + * - to ~65 seconds which is quite a lot to wait for a link to come up when + * plugging a cable + */ +#define ETHTOOL_PHY_EDPD_DFLT_TX_MSECS 0xffff +#define ETHTOOL_PHY_EDPD_NO_TX 0xfffe +#define ETHTOOL_PHY_EDPD_DISABLE 0 + +enum phy_tunable_id { + ETHTOOL_PHY_ID_UNSPEC, + ETHTOOL_PHY_DOWNSHIFT, + ETHTOOL_PHY_FAST_LINK_DOWN, + ETHTOOL_PHY_EDPD, + /* + * Add your fresh new phy tunable attribute above and remember to update + * phy_tunable_strings[] in net/ethtool/common.c + */ + __ETHTOOL_PHY_TUNABLE_COUNT, +}; + +/** + * struct ethtool_regs - hardware register dump + * @cmd: Command number = %ETHTOOL_GREGS + * @version: Dump format version. This is driver-specific and may + * distinguish different chips/revisions. Drivers must use new + * version numbers whenever the dump format changes in an + * incompatible way. + * @len: On entry, the real length of @data. On return, the number of + * bytes used. + * @data: Buffer for the register dump + * + * Users should use %ETHTOOL_GDRVINFO to find the maximum length of + * a register dump for the interface. They must allocate the buffer + * immediately following this structure. + */ +struct ethtool_regs { + __u32 cmd; + __u32 version; + __u32 len; + __u8 data[]; +}; + +/** + * struct ethtool_eeprom - EEPROM dump + * @cmd: Command number = %ETHTOOL_GEEPROM, %ETHTOOL_GMODULEEEPROM or + * %ETHTOOL_SEEPROM + * @magic: A 'magic cookie' value to guard against accidental changes. + * The value passed in to %ETHTOOL_SEEPROM must match the value + * returned by %ETHTOOL_GEEPROM for the same device. This is + * unused when @cmd is %ETHTOOL_GMODULEEEPROM. + * @offset: Offset within the EEPROM to begin reading/writing, in bytes + * @len: On entry, number of bytes to read/write. On successful + * return, number of bytes actually read/written. In case of + * error, this may indicate at what point the error occurred. + * @data: Buffer to read/write from + * + * Users may use %ETHTOOL_GDRVINFO or %ETHTOOL_GMODULEINFO to find + * the length of an on-board or module EEPROM, respectively. They + * must allocate the buffer immediately following this structure. + */ +struct ethtool_eeprom { + __u32 cmd; + __u32 magic; + __u32 offset; + __u32 len; + __u8 data[]; +}; + +/** + * struct ethtool_eee - Energy Efficient Ethernet information + * @cmd: ETHTOOL_{G,S}EEE + * @supported: Mask of %SUPPORTED_* flags for the speed/duplex combinations + * for which there is EEE support. + * @advertised: Mask of %ADVERTISED_* flags for the speed/duplex combinations + * advertised as eee capable. + * @lp_advertised: Mask of %ADVERTISED_* flags for the speed/duplex + * combinations advertised by the link partner as eee capable. + * @eee_active: Result of the eee auto negotiation. + * @eee_enabled: EEE configured mode (enabled/disabled). + * @tx_lpi_enabled: Whether the interface should assert its tx lpi, given + * that eee was negotiated. + * @tx_lpi_timer: Time in microseconds the interface delays prior to asserting + * its tx lpi (after reaching 'idle' state). Effective only when eee + * was negotiated and tx_lpi_enabled was set. + * @reserved: Reserved for future use; see the note on reserved space. + */ +struct ethtool_eee { + __u32 cmd; + __u32 supported; + __u32 advertised; + __u32 lp_advertised; + __u32 eee_active; + __u32 eee_enabled; + __u32 tx_lpi_enabled; + __u32 tx_lpi_timer; + __u32 reserved[2]; +}; + +/** + * struct ethtool_modinfo - plugin module eeprom information + * @cmd: %ETHTOOL_GMODULEINFO + * @type: Standard the module information conforms to %ETH_MODULE_SFF_xxxx + * @eeprom_len: Length of the eeprom + * @reserved: Reserved for future use; see the note on reserved space. + * + * This structure is used to return the information to + * properly size memory for a subsequent call to %ETHTOOL_GMODULEEEPROM. + * The type code indicates the eeprom data format + */ +struct ethtool_modinfo { + __u32 cmd; + __u32 type; + __u32 eeprom_len; + __u32 reserved[8]; +}; + +/** + * struct ethtool_coalesce - coalescing parameters for IRQs and stats updates + * @cmd: ETHTOOL_{G,S}COALESCE + * @rx_coalesce_usecs: How many usecs to delay an RX interrupt after + * a packet arrives. + * @rx_max_coalesced_frames: Maximum number of packets to receive + * before an RX interrupt. + * @rx_coalesce_usecs_irq: Same as @rx_coalesce_usecs, except that + * this value applies while an IRQ is being serviced by the host. + * @rx_max_coalesced_frames_irq: Same as @rx_max_coalesced_frames, + * except that this value applies while an IRQ is being serviced + * by the host. + * @tx_coalesce_usecs: How many usecs to delay a TX interrupt after + * a packet is sent. + * @tx_max_coalesced_frames: Maximum number of packets to be sent + * before a TX interrupt. + * @tx_coalesce_usecs_irq: Same as @tx_coalesce_usecs, except that + * this value applies while an IRQ is being serviced by the host. + * @tx_max_coalesced_frames_irq: Same as @tx_max_coalesced_frames, + * except that this value applies while an IRQ is being serviced + * by the host. + * @stats_block_coalesce_usecs: How many usecs to delay in-memory + * statistics block updates. Some drivers do not have an + * in-memory statistic block, and in such cases this value is + * ignored. This value must not be zero. + * @use_adaptive_rx_coalesce: Enable adaptive RX coalescing. + * @use_adaptive_tx_coalesce: Enable adaptive TX coalescing. + * @pkt_rate_low: Threshold for low packet rate (packets per second). + * @rx_coalesce_usecs_low: How many usecs to delay an RX interrupt after + * a packet arrives, when the packet rate is below @pkt_rate_low. + * @rx_max_coalesced_frames_low: Maximum number of packets to be received + * before an RX interrupt, when the packet rate is below @pkt_rate_low. + * @tx_coalesce_usecs_low: How many usecs to delay a TX interrupt after + * a packet is sent, when the packet rate is below @pkt_rate_low. + * @tx_max_coalesced_frames_low: Maximum nuumber of packets to be sent before + * a TX interrupt, when the packet rate is below @pkt_rate_low. + * @pkt_rate_high: Threshold for high packet rate (packets per second). + * @rx_coalesce_usecs_high: How many usecs to delay an RX interrupt after + * a packet arrives, when the packet rate is above @pkt_rate_high. + * @rx_max_coalesced_frames_high: Maximum number of packets to be received + * before an RX interrupt, when the packet rate is above @pkt_rate_high. + * @tx_coalesce_usecs_high: How many usecs to delay a TX interrupt after + * a packet is sent, when the packet rate is above @pkt_rate_high. + * @tx_max_coalesced_frames_high: Maximum number of packets to be sent before + * a TX interrupt, when the packet rate is above @pkt_rate_high. + * @rate_sample_interval: How often to do adaptive coalescing packet rate + * sampling, measured in seconds. Must not be zero. + * + * Each pair of (usecs, max_frames) fields specifies that interrupts + * should be coalesced until + * (usecs > 0 && time_since_first_completion >= usecs) || + * (max_frames > 0 && completed_frames >= max_frames) + * + * It is illegal to set both usecs and max_frames to zero as this + * would cause interrupts to never be generated. To disable + * coalescing, set usecs = 0 and max_frames = 1. + * + * Some implementations ignore the value of max_frames and use the + * condition time_since_first_completion >= usecs + * + * This is deprecated. Drivers for hardware that does not support + * counting completions should validate that max_frames == !rx_usecs. + * + * Adaptive RX/TX coalescing is an algorithm implemented by some + * drivers to improve latency under low packet rates and improve + * throughput under high packet rates. Some drivers only implement + * one of RX or TX adaptive coalescing. Anything not implemented by + * the driver causes these values to be silently ignored. + * + * When the packet rate is below @pkt_rate_high but above + * @pkt_rate_low (both measured in packets per second) the + * normal {rx,tx}_* coalescing parameters are used. + */ +struct ethtool_coalesce { + __u32 cmd; + __u32 rx_coalesce_usecs; + __u32 rx_max_coalesced_frames; + __u32 rx_coalesce_usecs_irq; + __u32 rx_max_coalesced_frames_irq; + __u32 tx_coalesce_usecs; + __u32 tx_max_coalesced_frames; + __u32 tx_coalesce_usecs_irq; + __u32 tx_max_coalesced_frames_irq; + __u32 stats_block_coalesce_usecs; + __u32 use_adaptive_rx_coalesce; + __u32 use_adaptive_tx_coalesce; + __u32 pkt_rate_low; + __u32 rx_coalesce_usecs_low; + __u32 rx_max_coalesced_frames_low; + __u32 tx_coalesce_usecs_low; + __u32 tx_max_coalesced_frames_low; + __u32 pkt_rate_high; + __u32 rx_coalesce_usecs_high; + __u32 rx_max_coalesced_frames_high; + __u32 tx_coalesce_usecs_high; + __u32 tx_max_coalesced_frames_high; + __u32 rate_sample_interval; +}; + +/** + * struct ethtool_ringparam - RX/TX ring parameters + * @cmd: Command number = %ETHTOOL_GRINGPARAM or %ETHTOOL_SRINGPARAM + * @rx_max_pending: Maximum supported number of pending entries per + * RX ring. Read-only. + * @rx_mini_max_pending: Maximum supported number of pending entries + * per RX mini ring. Read-only. + * @rx_jumbo_max_pending: Maximum supported number of pending entries + * per RX jumbo ring. Read-only. + * @tx_max_pending: Maximum supported number of pending entries per + * TX ring. Read-only. + * @rx_pending: Current maximum number of pending entries per RX ring + * @rx_mini_pending: Current maximum number of pending entries per RX + * mini ring + * @rx_jumbo_pending: Current maximum number of pending entries per RX + * jumbo ring + * @tx_pending: Current maximum supported number of pending entries + * per TX ring + * + * If the interface does not have separate RX mini and/or jumbo rings, + * @rx_mini_max_pending and/or @rx_jumbo_max_pending will be 0. + * + * There may also be driver-dependent minimum values for the number + * of entries per ring. + */ +struct ethtool_ringparam { + __u32 cmd; + __u32 rx_max_pending; + __u32 rx_mini_max_pending; + __u32 rx_jumbo_max_pending; + __u32 tx_max_pending; + __u32 rx_pending; + __u32 rx_mini_pending; + __u32 rx_jumbo_pending; + __u32 tx_pending; +}; + +/** + * struct ethtool_channels - configuring number of network channel + * @cmd: ETHTOOL_{G,S}CHANNELS + * @max_rx: Read only. Maximum number of receive channel the driver support. + * @max_tx: Read only. Maximum number of transmit channel the driver support. + * @max_other: Read only. Maximum number of other channel the driver support. + * @max_combined: Read only. Maximum number of combined channel the driver + * support. Set of queues RX, TX or other. + * @rx_count: Valid values are in the range 1 to the max_rx. + * @tx_count: Valid values are in the range 1 to the max_tx. + * @other_count: Valid values are in the range 1 to the max_other. + * @combined_count: Valid values are in the range 1 to the max_combined. + * + * This can be used to configure RX, TX and other channels. + */ + +struct ethtool_channels { + __u32 cmd; + __u32 max_rx; + __u32 max_tx; + __u32 max_other; + __u32 max_combined; + __u32 rx_count; + __u32 tx_count; + __u32 other_count; + __u32 combined_count; +}; + +/** + * struct ethtool_pauseparam - Ethernet pause (flow control) parameters + * @cmd: Command number = %ETHTOOL_GPAUSEPARAM or %ETHTOOL_SPAUSEPARAM + * @autoneg: Flag to enable autonegotiation of pause frame use + * @rx_pause: Flag to enable reception of pause frames + * @tx_pause: Flag to enable transmission of pause frames + * + * Drivers should reject a non-zero setting of @autoneg when + * autoneogotiation is disabled (or not supported) for the link. + * + * If the link is autonegotiated, drivers should use + * mii_advertise_flowctrl() or similar code to set the advertised + * pause frame capabilities based on the @rx_pause and @tx_pause flags, + * even if @autoneg is zero. They should also allow the advertised + * pause frame capabilities to be controlled directly through the + * advertising field of &struct ethtool_cmd. + * + * If @autoneg is non-zero, the MAC is configured to send and/or + * receive pause frames according to the result of autonegotiation. + * Otherwise, it is configured directly based on the @rx_pause and + * @tx_pause flags. + */ +struct ethtool_pauseparam { + __u32 cmd; + __u32 autoneg; + __u32 rx_pause; + __u32 tx_pause; +}; + +/* Link extended state */ +enum ethtool_link_ext_state { + ETHTOOL_LINK_EXT_STATE_AUTONEG, + ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE, + ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH, + ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY, + ETHTOOL_LINK_EXT_STATE_NO_CABLE, + ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE, + ETHTOOL_LINK_EXT_STATE_EEPROM_ISSUE, + ETHTOOL_LINK_EXT_STATE_CALIBRATION_FAILURE, + ETHTOOL_LINK_EXT_STATE_POWER_BUDGET_EXCEEDED, + ETHTOOL_LINK_EXT_STATE_OVERHEAT, + ETHTOOL_LINK_EXT_STATE_MODULE, +}; + +/* More information in addition to ETHTOOL_LINK_EXT_STATE_AUTONEG. */ +enum ethtool_link_ext_substate_autoneg { + ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED = 1, + ETHTOOL_LINK_EXT_SUBSTATE_AN_ACK_NOT_RECEIVED, + ETHTOOL_LINK_EXT_SUBSTATE_AN_NEXT_PAGE_EXCHANGE_FAILED, + ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED_FORCE_MODE, + ETHTOOL_LINK_EXT_SUBSTATE_AN_FEC_MISMATCH_DURING_OVERRIDE, + ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_HCD, +}; + +/* More information in addition to ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE. + */ +enum ethtool_link_ext_substate_link_training { + ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_FRAME_LOCK_NOT_ACQUIRED = 1, + ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_INHIBIT_TIMEOUT, + ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_PARTNER_DID_NOT_SET_RECEIVER_READY, + ETHTOOL_LINK_EXT_SUBSTATE_LT_REMOTE_FAULT, +}; + +/* More information in addition to ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH. + */ +enum ethtool_link_ext_substate_link_logical_mismatch { + ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_BLOCK_LOCK = 1, + ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_AM_LOCK, + ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_GET_ALIGN_STATUS, + ETHTOOL_LINK_EXT_SUBSTATE_LLM_FC_FEC_IS_NOT_LOCKED, + ETHTOOL_LINK_EXT_SUBSTATE_LLM_RS_FEC_IS_NOT_LOCKED, +}; + +/* More information in addition to ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY. + */ +enum ethtool_link_ext_substate_bad_signal_integrity { + ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS = 1, + ETHTOOL_LINK_EXT_SUBSTATE_BSI_UNSUPPORTED_RATE, + ETHTOOL_LINK_EXT_SUBSTATE_BSI_SERDES_REFERENCE_CLOCK_LOST, + ETHTOOL_LINK_EXT_SUBSTATE_BSI_SERDES_ALOS, +}; + +/* More information in addition to ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE. */ +enum ethtool_link_ext_substate_cable_issue { + ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE = 1, + ETHTOOL_LINK_EXT_SUBSTATE_CI_CABLE_TEST_FAILURE, +}; + +/* More information in addition to ETHTOOL_LINK_EXT_STATE_MODULE. */ +enum ethtool_link_ext_substate_module { + ETHTOOL_LINK_EXT_SUBSTATE_MODULE_CMIS_NOT_READY = 1, +}; + +#define ETH_GSTRING_LEN 32 + +/** + * enum ethtool_stringset - string set ID + * @ETH_SS_TEST: Self-test result names, for use with %ETHTOOL_TEST + * @ETH_SS_STATS: Statistic names, for use with %ETHTOOL_GSTATS + * @ETH_SS_PRIV_FLAGS: Driver private flag names, for use with + * %ETHTOOL_GPFLAGS and %ETHTOOL_SPFLAGS + * @ETH_SS_NTUPLE_FILTERS: Previously used with %ETHTOOL_GRXNTUPLE; + * now deprecated + * @ETH_SS_FEATURES: Device feature names + * @ETH_SS_RSS_HASH_FUNCS: RSS hush function names + * @ETH_SS_TUNABLES: tunable names + * @ETH_SS_PHY_STATS: Statistic names, for use with %ETHTOOL_GPHYSTATS + * @ETH_SS_PHY_TUNABLES: PHY tunable names + * @ETH_SS_LINK_MODES: link mode names + * @ETH_SS_MSG_CLASSES: debug message class names + * @ETH_SS_WOL_MODES: wake-on-lan modes + * @ETH_SS_SOF_TIMESTAMPING: SOF_TIMESTAMPING_* flags + * @ETH_SS_TS_TX_TYPES: timestamping Tx types + * @ETH_SS_TS_RX_FILTERS: timestamping Rx filters + * @ETH_SS_UDP_TUNNEL_TYPES: UDP tunnel types + * @ETH_SS_STATS_STD: standardized stats + * @ETH_SS_STATS_ETH_PHY: names of IEEE 802.3 PHY statistics + * @ETH_SS_STATS_ETH_MAC: names of IEEE 802.3 MAC statistics + * @ETH_SS_STATS_ETH_CTRL: names of IEEE 802.3 MAC Control statistics + * @ETH_SS_STATS_RMON: names of RMON statistics + * + * @ETH_SS_COUNT: number of defined string sets + */ +enum ethtool_stringset { + ETH_SS_TEST = 0, + ETH_SS_STATS, + ETH_SS_PRIV_FLAGS, + ETH_SS_NTUPLE_FILTERS, + ETH_SS_FEATURES, + ETH_SS_RSS_HASH_FUNCS, + ETH_SS_TUNABLES, + ETH_SS_PHY_STATS, + ETH_SS_PHY_TUNABLES, + ETH_SS_LINK_MODES, + ETH_SS_MSG_CLASSES, + ETH_SS_WOL_MODES, + ETH_SS_SOF_TIMESTAMPING, + ETH_SS_TS_TX_TYPES, + ETH_SS_TS_RX_FILTERS, + ETH_SS_UDP_TUNNEL_TYPES, + ETH_SS_STATS_STD, + ETH_SS_STATS_ETH_PHY, + ETH_SS_STATS_ETH_MAC, + ETH_SS_STATS_ETH_CTRL, + ETH_SS_STATS_RMON, + + /* add new constants above here */ + ETH_SS_COUNT +}; + +/** + * enum ethtool_mac_stats_src - source of ethtool MAC statistics + * @ETHTOOL_MAC_STATS_SRC_AGGREGATE: + * if device supports a MAC merge layer, this retrieves the aggregate + * statistics of the eMAC and pMAC. Otherwise, it retrieves just the + * statistics of the single (express) MAC. + * @ETHTOOL_MAC_STATS_SRC_EMAC: + * if device supports a MM layer, this retrieves the eMAC statistics. + * Otherwise, it retrieves the statistics of the single (express) MAC. + * @ETHTOOL_MAC_STATS_SRC_PMAC: + * if device supports a MM layer, this retrieves the pMAC statistics. + */ +enum ethtool_mac_stats_src { + ETHTOOL_MAC_STATS_SRC_AGGREGATE, + ETHTOOL_MAC_STATS_SRC_EMAC, + ETHTOOL_MAC_STATS_SRC_PMAC, +}; + +/** + * enum ethtool_module_power_mode_policy - plug-in module power mode policy + * @ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH: Module is always in high power mode. + * @ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO: Module is transitioned by the host + * to high power mode when the first port using it is put administratively + * up and to low power mode when the last port using it is put + * administratively down. + */ +enum ethtool_module_power_mode_policy { + ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH = 1, + ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO, +}; + +/** + * enum ethtool_module_power_mode - plug-in module power mode + * @ETHTOOL_MODULE_POWER_MODE_LOW: Module is in low power mode. + * @ETHTOOL_MODULE_POWER_MODE_HIGH: Module is in high power mode. + */ +enum ethtool_module_power_mode { + ETHTOOL_MODULE_POWER_MODE_LOW = 1, + ETHTOOL_MODULE_POWER_MODE_HIGH, +}; + +/** + * enum ethtool_podl_pse_admin_state - operational state of the PoDL PSE + * functions. IEEE 802.3-2018 30.15.1.1.2 aPoDLPSEAdminState + * @ETHTOOL_PODL_PSE_ADMIN_STATE_UNKNOWN: state of PoDL PSE functions are + * unknown + * @ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED: PoDL PSE functions are disabled + * @ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED: PoDL PSE functions are enabled + */ +enum ethtool_podl_pse_admin_state { + ETHTOOL_PODL_PSE_ADMIN_STATE_UNKNOWN = 1, + ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED, + ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED, +}; + +/** + * enum ethtool_podl_pse_pw_d_status - power detection status of the PoDL PSE. + * IEEE 802.3-2018 30.15.1.1.3 aPoDLPSEPowerDetectionStatus: + * @ETHTOOL_PODL_PSE_PW_D_STATUS_UNKNOWN: PoDL PSE + * @ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED: "The enumeration “disabled” is + * asserted true when the PoDL PSE state diagram variable mr_pse_enable is + * false" + * @ETHTOOL_PODL_PSE_PW_D_STATUS_SEARCHING: "The enumeration “searching” is + * asserted true when either of the PSE state diagram variables + * pi_detecting or pi_classifying is true." + * @ETHTOOL_PODL_PSE_PW_D_STATUS_DELIVERING: "The enumeration “deliveringPower” + * is asserted true when the PoDL PSE state diagram variable pi_powered is + * true." + * @ETHTOOL_PODL_PSE_PW_D_STATUS_SLEEP: "The enumeration “sleep” is asserted + * true when the PoDL PSE state diagram variable pi_sleeping is true." + * @ETHTOOL_PODL_PSE_PW_D_STATUS_IDLE: "The enumeration “idle” is asserted true + * when the logical combination of the PoDL PSE state diagram variables + * pi_prebiased*!pi_sleeping is true." + * @ETHTOOL_PODL_PSE_PW_D_STATUS_ERROR: "The enumeration “error” is asserted + * true when the PoDL PSE state diagram variable overload_held is true." + */ +enum ethtool_podl_pse_pw_d_status { + ETHTOOL_PODL_PSE_PW_D_STATUS_UNKNOWN = 1, + ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED, + ETHTOOL_PODL_PSE_PW_D_STATUS_SEARCHING, + ETHTOOL_PODL_PSE_PW_D_STATUS_DELIVERING, + ETHTOOL_PODL_PSE_PW_D_STATUS_SLEEP, + ETHTOOL_PODL_PSE_PW_D_STATUS_IDLE, + ETHTOOL_PODL_PSE_PW_D_STATUS_ERROR, +}; + +/** + * enum ethtool_mm_verify_status - status of MAC Merge Verify function + * @ETHTOOL_MM_VERIFY_STATUS_UNKNOWN: + * verification status is unknown + * @ETHTOOL_MM_VERIFY_STATUS_INITIAL: + * the 802.3 Verify State diagram is in the state INIT_VERIFICATION + * @ETHTOOL_MM_VERIFY_STATUS_VERIFYING: + * the Verify State diagram is in the state VERIFICATION_IDLE, + * SEND_VERIFY or WAIT_FOR_RESPONSE + * @ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED: + * indicates that the Verify State diagram is in the state VERIFIED + * @ETHTOOL_MM_VERIFY_STATUS_FAILED: + * the Verify State diagram is in the state VERIFY_FAIL + * @ETHTOOL_MM_VERIFY_STATUS_DISABLED: + * verification of preemption operation is disabled + */ +enum ethtool_mm_verify_status { + ETHTOOL_MM_VERIFY_STATUS_UNKNOWN, + ETHTOOL_MM_VERIFY_STATUS_INITIAL, + ETHTOOL_MM_VERIFY_STATUS_VERIFYING, + ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED, + ETHTOOL_MM_VERIFY_STATUS_FAILED, + ETHTOOL_MM_VERIFY_STATUS_DISABLED, +}; + +/** + * struct ethtool_gstrings - string set for data tagging + * @cmd: Command number = %ETHTOOL_GSTRINGS + * @string_set: String set ID; one of &enum ethtool_stringset + * @len: On return, the number of strings in the string set + * @data: Buffer for strings. Each string is null-padded to a size of + * %ETH_GSTRING_LEN. + * + * Users must use %ETHTOOL_GSSET_INFO to find the number of strings in + * the string set. They must allocate a buffer of the appropriate + * size immediately following this structure. + */ +struct ethtool_gstrings { + __u32 cmd; + __u32 string_set; + __u32 len; + __u8 data[]; +}; + +/** + * struct ethtool_sset_info - string set information + * @cmd: Command number = %ETHTOOL_GSSET_INFO + * @reserved: Reserved for future use; see the note on reserved space. + * @sset_mask: On entry, a bitmask of string sets to query, with bits + * numbered according to &enum ethtool_stringset. On return, a + * bitmask of those string sets queried that are supported. + * @data: Buffer for string set sizes. On return, this contains the + * size of each string set that was queried and supported, in + * order of ID. + * + * Example: The user passes in @sset_mask = 0x7 (sets 0, 1, 2) and on + * return @sset_mask == 0x6 (sets 1, 2). Then @data[0] contains the + * size of set 1 and @data[1] contains the size of set 2. + * + * Users must allocate a buffer of the appropriate size (4 * number of + * sets queried) immediately following this structure. + */ +struct ethtool_sset_info { + __u32 cmd; + __u32 reserved; + __u64 sset_mask; + __u32 data[]; +}; + +/** + * enum ethtool_test_flags - flags definition of ethtool_test + * @ETH_TEST_FL_OFFLINE: if set perform online and offline tests, otherwise + * only online tests. + * @ETH_TEST_FL_FAILED: Driver set this flag if test fails. + * @ETH_TEST_FL_EXTERNAL_LB: Application request to perform external loopback + * test. + * @ETH_TEST_FL_EXTERNAL_LB_DONE: Driver performed the external loopback test + */ + +enum ethtool_test_flags { + ETH_TEST_FL_OFFLINE = (1 << 0), + ETH_TEST_FL_FAILED = (1 << 1), + ETH_TEST_FL_EXTERNAL_LB = (1 << 2), + ETH_TEST_FL_EXTERNAL_LB_DONE = (1 << 3), +}; + +/** + * struct ethtool_test - device self-test invocation + * @cmd: Command number = %ETHTOOL_TEST + * @flags: A bitmask of flags from &enum ethtool_test_flags. Some + * flags may be set by the user on entry; others may be set by + * the driver on return. + * @reserved: Reserved for future use; see the note on reserved space. + * @len: On return, the number of test results + * @data: Array of test results + * + * Users must use %ETHTOOL_GSSET_INFO or %ETHTOOL_GDRVINFO to find the + * number of test results that will be returned. They must allocate a + * buffer of the appropriate size (8 * number of results) immediately + * following this structure. + */ +struct ethtool_test { + __u32 cmd; + __u32 flags; + __u32 reserved; + __u32 len; + __u64 data[]; +}; + +/** + * struct ethtool_stats - device-specific statistics + * @cmd: Command number = %ETHTOOL_GSTATS + * @n_stats: On return, the number of statistics + * @data: Array of statistics + * + * Users must use %ETHTOOL_GSSET_INFO or %ETHTOOL_GDRVINFO to find the + * number of statistics that will be returned. They must allocate a + * buffer of the appropriate size (8 * number of statistics) + * immediately following this structure. + */ +struct ethtool_stats { + __u32 cmd; + __u32 n_stats; + __u64 data[]; +}; + +/** + * struct ethtool_perm_addr - permanent hardware address + * @cmd: Command number = %ETHTOOL_GPERMADDR + * @size: On entry, the size of the buffer. On return, the size of the + * address. The command fails if the buffer is too small. + * @data: Buffer for the address + * + * Users must allocate the buffer immediately following this structure. + * A buffer size of %MAX_ADDR_LEN should be sufficient for any address + * type. + */ +struct ethtool_perm_addr { + __u32 cmd; + __u32 size; + __u8 data[]; +}; + +/* boolean flags controlling per-interface behavior characteristics. + * When reading, the flag indicates whether or not a certain behavior + * is enabled/present. When writing, the flag indicates whether + * or not the driver should turn on (set) or off (clear) a behavior. + * + * Some behaviors may read-only (unconditionally absent or present). + * If such is the case, return EINVAL in the set-flags operation if the + * flag differs from the read-only value. + */ +enum ethtool_flags { + ETH_FLAG_TXVLAN = (1 << 7), /* TX VLAN offload enabled */ + ETH_FLAG_RXVLAN = (1 << 8), /* RX VLAN offload enabled */ + ETH_FLAG_LRO = (1 << 15), /* LRO is enabled */ + ETH_FLAG_NTUPLE = (1 << 27), /* N-tuple filters enabled */ + ETH_FLAG_RXHASH = (1 << 28), +}; + +/* The following structures are for supporting RX network flow + * classification and RX n-tuple configuration. Note, all multibyte + * fields, e.g., ip4src, ip4dst, psrc, pdst, spi, etc. are expected to + * be in network byte order. + */ + +/** + * struct ethtool_tcpip4_spec - flow specification for TCP/IPv4 etc. + * @ip4src: Source host + * @ip4dst: Destination host + * @psrc: Source port + * @pdst: Destination port + * @tos: Type-of-service + * + * This can be used to specify a TCP/IPv4, UDP/IPv4 or SCTP/IPv4 flow. + */ +struct ethtool_tcpip4_spec { + __be32 ip4src; + __be32 ip4dst; + __be16 psrc; + __be16 pdst; + __u8 tos; +}; + +/** + * struct ethtool_ah_espip4_spec - flow specification for IPsec/IPv4 + * @ip4src: Source host + * @ip4dst: Destination host + * @spi: Security parameters index + * @tos: Type-of-service + * + * This can be used to specify an IPsec transport or tunnel over IPv4. + */ +struct ethtool_ah_espip4_spec { + __be32 ip4src; + __be32 ip4dst; + __be32 spi; + __u8 tos; +}; + +#define ETH_RX_NFC_IP4 1 + +/** + * struct ethtool_usrip4_spec - general flow specification for IPv4 + * @ip4src: Source host + * @ip4dst: Destination host + * @l4_4_bytes: First 4 bytes of transport (layer 4) header + * @tos: Type-of-service + * @ip_ver: Value must be %ETH_RX_NFC_IP4; mask must be 0 + * @proto: Transport protocol number; mask must be 0 + */ +struct ethtool_usrip4_spec { + __be32 ip4src; + __be32 ip4dst; + __be32 l4_4_bytes; + __u8 tos; + __u8 ip_ver; + __u8 proto; +}; + +/** + * struct ethtool_tcpip6_spec - flow specification for TCP/IPv6 etc. + * @ip6src: Source host + * @ip6dst: Destination host + * @psrc: Source port + * @pdst: Destination port + * @tclass: Traffic Class + * + * This can be used to specify a TCP/IPv6, UDP/IPv6 or SCTP/IPv6 flow. + */ +struct ethtool_tcpip6_spec { + __be32 ip6src[4]; + __be32 ip6dst[4]; + __be16 psrc; + __be16 pdst; + __u8 tclass; +}; + +/** + * struct ethtool_ah_espip6_spec - flow specification for IPsec/IPv6 + * @ip6src: Source host + * @ip6dst: Destination host + * @spi: Security parameters index + * @tclass: Traffic Class + * + * This can be used to specify an IPsec transport or tunnel over IPv6. + */ +struct ethtool_ah_espip6_spec { + __be32 ip6src[4]; + __be32 ip6dst[4]; + __be32 spi; + __u8 tclass; +}; + +/** + * struct ethtool_usrip6_spec - general flow specification for IPv6 + * @ip6src: Source host + * @ip6dst: Destination host + * @l4_4_bytes: First 4 bytes of transport (layer 4) header + * @tclass: Traffic Class + * @l4_proto: Transport protocol number (nexthdr after any Extension Headers) + */ +struct ethtool_usrip6_spec { + __be32 ip6src[4]; + __be32 ip6dst[4]; + __be32 l4_4_bytes; + __u8 tclass; + __u8 l4_proto; +}; + +union ethtool_flow_union { + struct ethtool_tcpip4_spec tcp_ip4_spec; + struct ethtool_tcpip4_spec udp_ip4_spec; + struct ethtool_tcpip4_spec sctp_ip4_spec; + struct ethtool_ah_espip4_spec ah_ip4_spec; + struct ethtool_ah_espip4_spec esp_ip4_spec; + struct ethtool_usrip4_spec usr_ip4_spec; + struct ethtool_tcpip6_spec tcp_ip6_spec; + struct ethtool_tcpip6_spec udp_ip6_spec; + struct ethtool_tcpip6_spec sctp_ip6_spec; + struct ethtool_ah_espip6_spec ah_ip6_spec; + struct ethtool_ah_espip6_spec esp_ip6_spec; + struct ethtool_usrip6_spec usr_ip6_spec; + struct ethhdr ether_spec; + __u8 hdata[52]; +}; + +/** + * struct ethtool_flow_ext - additional RX flow fields + * @h_dest: destination MAC address + * @vlan_etype: VLAN EtherType + * @vlan_tci: VLAN tag control information + * @data: user defined data + * @padding: Reserved for future use; see the note on reserved space. + * + * Note, @vlan_etype, @vlan_tci, and @data are only valid if %FLOW_EXT + * is set in &struct ethtool_rx_flow_spec @flow_type. + * @h_dest is valid if %FLOW_MAC_EXT is set. + */ +struct ethtool_flow_ext { + __u8 padding[2]; + unsigned char h_dest[ETH_ALEN]; + __be16 vlan_etype; + __be16 vlan_tci; + __be32 data[2]; +}; + +/** + * struct ethtool_rx_flow_spec - classification rule for RX flows + * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW + * @h_u: Flow fields to match (dependent on @flow_type) + * @h_ext: Additional fields to match + * @m_u: Masks for flow field bits to be matched + * @m_ext: Masks for additional field bits to be matched + * Note, all additional fields must be ignored unless @flow_type + * includes the %FLOW_EXT or %FLOW_MAC_EXT flag + * (see &struct ethtool_flow_ext description). + * @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC + * if packets should be discarded, or %RX_CLS_FLOW_WAKE if the + * packets should be used for Wake-on-LAN with %WAKE_FILTER + * @location: Location of rule in the table. Locations must be + * numbered such that a flow matching multiple rules will be + * classified according to the first (lowest numbered) rule. + */ +struct ethtool_rx_flow_spec { + __u32 flow_type; + union ethtool_flow_union h_u; + struct ethtool_flow_ext h_ext; + union ethtool_flow_union m_u; + struct ethtool_flow_ext m_ext; + __u64 ring_cookie; + __u32 location; +}; + +/* How rings are laid out when accessing virtual functions or + * offloaded queues is device specific. To allow users to do flow + * steering and specify these queues the ring cookie is partitioned + * into a 32bit queue index with an 8 bit virtual function id. + * This also leaves the 3bytes for further specifiers. It is possible + * future devices may support more than 256 virtual functions if + * devices start supporting PCIe w/ARI. However at the moment I + * do not know of any devices that support this so I do not reserve + * space for this at this time. If a future patch consumes the next + * byte it should be aware of this possibility. + */ +#define ETHTOOL_RX_FLOW_SPEC_RING 0x00000000FFFFFFFFLL +#define ETHTOOL_RX_FLOW_SPEC_RING_VF 0x000000FF00000000LL +#define ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF 32 +static __inline__ __u64 ethtool_get_flow_spec_ring(__u64 ring_cookie) +{ + return ETHTOOL_RX_FLOW_SPEC_RING & ring_cookie; +} + +static __inline__ __u64 ethtool_get_flow_spec_ring_vf(__u64 ring_cookie) +{ + return (ETHTOOL_RX_FLOW_SPEC_RING_VF & ring_cookie) >> + ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF; +} + +/** + * struct ethtool_rxnfc - command to get or set RX flow classification rules + * @cmd: Specific command number - %ETHTOOL_GRXFH, %ETHTOOL_SRXFH, + * %ETHTOOL_GRXRINGS, %ETHTOOL_GRXCLSRLCNT, %ETHTOOL_GRXCLSRULE, + * %ETHTOOL_GRXCLSRLALL, %ETHTOOL_SRXCLSRLDEL or %ETHTOOL_SRXCLSRLINS + * @flow_type: Type of flow to be affected, e.g. %TCP_V4_FLOW + * @data: Command-dependent value + * @fs: Flow classification rule + * @rss_context: RSS context to be affected + * @rule_cnt: Number of rules to be affected + * @rule_locs: Array of used rule locations + * + * For %ETHTOOL_GRXFH and %ETHTOOL_SRXFH, @data is a bitmask indicating + * the fields included in the flow hash, e.g. %RXH_IP_SRC. The following + * structure fields must not be used, except that if @flow_type includes + * the %FLOW_RSS flag, then @rss_context determines which RSS context to + * act on. + * + * For %ETHTOOL_GRXRINGS, @data is set to the number of RX rings/queues + * on return. + * + * For %ETHTOOL_GRXCLSRLCNT, @rule_cnt is set to the number of defined + * rules on return. If @data is non-zero on return then it is the + * size of the rule table, plus the flag %RX_CLS_LOC_SPECIAL if the + * driver supports any special location values. If that flag is not + * set in @data then special location values should not be used. + * + * For %ETHTOOL_GRXCLSRULE, @fs.@location specifies the location of an + * existing rule on entry and @fs contains the rule on return; if + * @fs.@flow_type includes the %FLOW_RSS flag, then @rss_context is + * filled with the RSS context ID associated with the rule. + * + * For %ETHTOOL_GRXCLSRLALL, @rule_cnt specifies the array size of the + * user buffer for @rule_locs on entry. On return, @data is the size + * of the rule table, @rule_cnt is the number of defined rules, and + * @rule_locs contains the locations of the defined rules. Drivers + * must use the second parameter to get_rxnfc() instead of @rule_locs. + * + * For %ETHTOOL_SRXCLSRLINS, @fs specifies the rule to add or update. + * @fs.@location either specifies the location to use or is a special + * location value with %RX_CLS_LOC_SPECIAL flag set. On return, + * @fs.@location is the actual rule location. If @fs.@flow_type + * includes the %FLOW_RSS flag, @rss_context is the RSS context ID to + * use for flow spreading traffic which matches this rule. The value + * from the rxfh indirection table will be added to @fs.@ring_cookie + * to choose which ring to deliver to. + * + * For %ETHTOOL_SRXCLSRLDEL, @fs.@location specifies the location of an + * existing rule on entry. + * + * A driver supporting the special location values for + * %ETHTOOL_SRXCLSRLINS may add the rule at any suitable unused + * location, and may remove a rule at a later location (lower + * priority) that matches exactly the same set of flows. The special + * values are %RX_CLS_LOC_ANY, selecting any location; + * %RX_CLS_LOC_FIRST, selecting the first suitable location (maximum + * priority); and %RX_CLS_LOC_LAST, selecting the last suitable + * location (minimum priority). Additional special values may be + * defined in future and drivers must return -%EINVAL for any + * unrecognised value. + */ +struct ethtool_rxnfc { + __u32 cmd; + __u32 flow_type; + __u64 data; + struct ethtool_rx_flow_spec fs; + union { + __u32 rule_cnt; + __u32 rss_context; + }; + __u32 rule_locs[]; +}; + + +/** + * struct ethtool_rxfh_indir - command to get or set RX flow hash indirection + * @cmd: Specific command number - %ETHTOOL_GRXFHINDIR or %ETHTOOL_SRXFHINDIR + * @size: On entry, the array size of the user buffer, which may be zero. + * On return from %ETHTOOL_GRXFHINDIR, the array size of the hardware + * indirection table. + * @ring_index: RX ring/queue index for each hash value + * + * For %ETHTOOL_GRXFHINDIR, a @size of zero means that only the size + * should be returned. For %ETHTOOL_SRXFHINDIR, a @size of zero means + * the table should be reset to default values. This last feature + * is not supported by the original implementations. + */ +struct ethtool_rxfh_indir { + __u32 cmd; + __u32 size; + __u32 ring_index[]; +}; + +/** + * struct ethtool_rxfh - command to get/set RX flow hash indir or/and hash key. + * @cmd: Specific command number - %ETHTOOL_GRSSH or %ETHTOOL_SRSSH + * @rss_context: RSS context identifier. Context 0 is the default for normal + * traffic; other contexts can be referenced as the destination for RX flow + * classification rules. %ETH_RXFH_CONTEXT_ALLOC is used with command + * %ETHTOOL_SRSSH to allocate a new RSS context; on return this field will + * contain the ID of the newly allocated context. + * @indir_size: On entry, the array size of the user buffer for the + * indirection table, which may be zero, or (for %ETHTOOL_SRSSH), + * %ETH_RXFH_INDIR_NO_CHANGE. On return from %ETHTOOL_GRSSH, + * the array size of the hardware indirection table. + * @key_size: On entry, the array size of the user buffer for the hash key, + * which may be zero. On return from %ETHTOOL_GRSSH, the size of the + * hardware hash key. + * @hfunc: Defines the current RSS hash function used by HW (or to be set to). + * Valid values are one of the %ETH_RSS_HASH_*. + * @rsvd8: Reserved for future use; see the note on reserved space. + * @rsvd32: Reserved for future use; see the note on reserved space. + * @rss_config: RX ring/queue index for each hash value i.e., indirection table + * of @indir_size __u32 elements, followed by hash key of @key_size + * bytes. + * + * For %ETHTOOL_GRSSH, a @indir_size and key_size of zero means that only the + * size should be returned. For %ETHTOOL_SRSSH, an @indir_size of + * %ETH_RXFH_INDIR_NO_CHANGE means that indir table setting is not requested + * and a @indir_size of zero means the indir table should be reset to default + * values (if @rss_context == 0) or that the RSS context should be deleted. + * An hfunc of zero means that hash function setting is not requested. + */ +struct ethtool_rxfh { + __u32 cmd; + __u32 rss_context; + __u32 indir_size; + __u32 key_size; + __u8 hfunc; + __u8 rsvd8[3]; + __u32 rsvd32; + __u32 rss_config[]; +}; +#define ETH_RXFH_CONTEXT_ALLOC 0xffffffff +#define ETH_RXFH_INDIR_NO_CHANGE 0xffffffff + +/** + * struct ethtool_rx_ntuple_flow_spec - specification for RX flow filter + * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW + * @h_u: Flow field values to match (dependent on @flow_type) + * @m_u: Masks for flow field value bits to be ignored + * @vlan_tag: VLAN tag to match + * @vlan_tag_mask: Mask for VLAN tag bits to be ignored + * @data: Driver-dependent data to match + * @data_mask: Mask for driver-dependent data bits to be ignored + * @action: RX ring/queue index to deliver to (non-negative) or other action + * (negative, e.g. %ETHTOOL_RXNTUPLE_ACTION_DROP) + * + * For flow types %TCP_V4_FLOW, %UDP_V4_FLOW and %SCTP_V4_FLOW, where + * a field value and mask are both zero this is treated as if all mask + * bits are set i.e. the field is ignored. + */ +struct ethtool_rx_ntuple_flow_spec { + __u32 flow_type; + union { + struct ethtool_tcpip4_spec tcp_ip4_spec; + struct ethtool_tcpip4_spec udp_ip4_spec; + struct ethtool_tcpip4_spec sctp_ip4_spec; + struct ethtool_ah_espip4_spec ah_ip4_spec; + struct ethtool_ah_espip4_spec esp_ip4_spec; + struct ethtool_usrip4_spec usr_ip4_spec; + struct ethhdr ether_spec; + __u8 hdata[72]; + } h_u, m_u; + + __u16 vlan_tag; + __u16 vlan_tag_mask; + __u64 data; + __u64 data_mask; + + __s32 action; +#define ETHTOOL_RXNTUPLE_ACTION_DROP (-1) /* drop packet */ +#define ETHTOOL_RXNTUPLE_ACTION_CLEAR (-2) /* clear filter */ +}; + +/** + * struct ethtool_rx_ntuple - command to set or clear RX flow filter + * @cmd: Command number - %ETHTOOL_SRXNTUPLE + * @fs: Flow filter specification + */ +struct ethtool_rx_ntuple { + __u32 cmd; + struct ethtool_rx_ntuple_flow_spec fs; +}; + +#define ETHTOOL_FLASH_MAX_FILENAME 128 +enum ethtool_flash_op_type { + ETHTOOL_FLASH_ALL_REGIONS = 0, +}; + +/* for passing firmware flashing related parameters */ +struct ethtool_flash { + __u32 cmd; + __u32 region; + char data[ETHTOOL_FLASH_MAX_FILENAME]; +}; + +/** + * struct ethtool_dump - used for retrieving, setting device dump + * @cmd: Command number - %ETHTOOL_GET_DUMP_FLAG, %ETHTOOL_GET_DUMP_DATA, or + * %ETHTOOL_SET_DUMP + * @version: FW version of the dump, filled in by driver + * @flag: driver dependent flag for dump setting, filled in by driver during + * get and filled in by ethtool for set operation. + * flag must be initialized by macro ETH_FW_DUMP_DISABLE value when + * firmware dump is disabled. + * @len: length of dump data, used as the length of the user buffer on entry to + * %ETHTOOL_GET_DUMP_DATA and this is returned as dump length by driver + * for %ETHTOOL_GET_DUMP_FLAG command + * @data: data collected for get dump data operation + */ +struct ethtool_dump { + __u32 cmd; + __u32 version; + __u32 flag; + __u32 len; + __u8 data[]; +}; + +#define ETH_FW_DUMP_DISABLE 0 + +/* for returning and changing feature sets */ + +/** + * struct ethtool_get_features_block - block with state of 32 features + * @available: mask of changeable features + * @requested: mask of features requested to be enabled if possible + * @active: mask of currently enabled features + * @never_changed: mask of features not changeable for any device + */ +struct ethtool_get_features_block { + __u32 available; + __u32 requested; + __u32 active; + __u32 never_changed; +}; + +/** + * struct ethtool_gfeatures - command to get state of device's features + * @cmd: command number = %ETHTOOL_GFEATURES + * @size: On entry, the number of elements in the features[] array; + * on return, the number of elements in features[] needed to hold + * all features + * @features: state of features + */ +struct ethtool_gfeatures { + __u32 cmd; + __u32 size; + struct ethtool_get_features_block features[]; +}; + +/** + * struct ethtool_set_features_block - block with request for 32 features + * @valid: mask of features to be changed + * @requested: values of features to be changed + */ +struct ethtool_set_features_block { + __u32 valid; + __u32 requested; +}; + +/** + * struct ethtool_sfeatures - command to request change in device's features + * @cmd: command number = %ETHTOOL_SFEATURES + * @size: array size of the features[] array + * @features: feature change masks + */ +struct ethtool_sfeatures { + __u32 cmd; + __u32 size; + struct ethtool_set_features_block features[]; +}; + +/** + * struct ethtool_ts_info - holds a device's timestamping and PHC association + * @cmd: command number = %ETHTOOL_GET_TS_INFO + * @so_timestamping: bit mask of the sum of the supported SO_TIMESTAMPING flags + * @phc_index: device index of the associated PHC, or -1 if there is none + * @tx_types: bit mask of the supported hwtstamp_tx_types enumeration values + * @tx_reserved: Reserved for future use; see the note on reserved space. + * @rx_filters: bit mask of the supported hwtstamp_rx_filters enumeration values + * @rx_reserved: Reserved for future use; see the note on reserved space. + * + * The bits in the 'tx_types' and 'rx_filters' fields correspond to + * the 'hwtstamp_tx_types' and 'hwtstamp_rx_filters' enumeration values, + * respectively. For example, if the device supports HWTSTAMP_TX_ON, + * then (1 << HWTSTAMP_TX_ON) in 'tx_types' will be set. + * + * Drivers should only report the filters they actually support without + * upscaling in the SIOCSHWTSTAMP ioctl. If the SIOCSHWSTAMP request for + * HWTSTAMP_FILTER_V1_SYNC is supported by HWTSTAMP_FILTER_V1_EVENT, then the + * driver should only report HWTSTAMP_FILTER_V1_EVENT in this op. + */ +struct ethtool_ts_info { + __u32 cmd; + __u32 so_timestamping; + __s32 phc_index; + __u32 tx_types; + __u32 tx_reserved[3]; + __u32 rx_filters; + __u32 rx_reserved[3]; +}; + +/* + * %ETHTOOL_SFEATURES changes features present in features[].valid to the + * values of corresponding bits in features[].requested. Bits in .requested + * not set in .valid or not changeable are ignored. + * + * Returns %EINVAL when .valid contains undefined or never-changeable bits + * or size is not equal to required number of features words (32-bit blocks). + * Returns >= 0 if request was completed; bits set in the value mean: + * %ETHTOOL_F_UNSUPPORTED - there were bits set in .valid that are not + * changeable (not present in %ETHTOOL_GFEATURES' features[].available) + * those bits were ignored. + * %ETHTOOL_F_WISH - some or all changes requested were recorded but the + * resulting state of bits masked by .valid is not equal to .requested. + * Probably there are other device-specific constraints on some features + * in the set. When %ETHTOOL_F_UNSUPPORTED is set, .valid is considered + * here as though ignored bits were cleared. + * %ETHTOOL_F_COMPAT - some or all changes requested were made by calling + * compatibility functions. Requested offload state cannot be properly + * managed by kernel. + * + * Meaning of bits in the masks are obtained by %ETHTOOL_GSSET_INFO (number of + * bits in the arrays - always multiple of 32) and %ETHTOOL_GSTRINGS commands + * for ETH_SS_FEATURES string set. First entry in the table corresponds to least + * significant bit in features[0] fields. Empty strings mark undefined features. + */ +enum ethtool_sfeatures_retval_bits { + ETHTOOL_F_UNSUPPORTED__BIT, + ETHTOOL_F_WISH__BIT, + ETHTOOL_F_COMPAT__BIT, +}; + +#define ETHTOOL_F_UNSUPPORTED (1 << ETHTOOL_F_UNSUPPORTED__BIT) +#define ETHTOOL_F_WISH (1 << ETHTOOL_F_WISH__BIT) +#define ETHTOOL_F_COMPAT (1 << ETHTOOL_F_COMPAT__BIT) + +#define MAX_NUM_QUEUE 4096 + +/** + * struct ethtool_per_queue_op - apply sub command to the queues in mask. + * @cmd: ETHTOOL_PERQUEUE + * @sub_command: the sub command which apply to each queues + * @queue_mask: Bitmap of the queues which sub command apply to + * @data: A complete command structure following for each of the queues addressed + */ +struct ethtool_per_queue_op { + __u32 cmd; + __u32 sub_command; + __u32 queue_mask[__KERNEL_DIV_ROUND_UP(MAX_NUM_QUEUE, 32)]; + char data[]; +}; + +/** + * struct ethtool_fecparam - Ethernet Forward Error Correction parameters + * @cmd: Command number = %ETHTOOL_GFECPARAM or %ETHTOOL_SFECPARAM + * @active_fec: FEC mode which is active on the port, single bit set, GET only. + * @fec: Bitmask of configured FEC modes. + * @reserved: Reserved for future extensions, ignore on GET, write 0 for SET. + * + * Note that @reserved was never validated on input and ethtool user space + * left it uninitialized when calling SET. Hence going forward it can only be + * used to return a value to userspace with GET. + * + * FEC modes supported by the device can be read via %ETHTOOL_GLINKSETTINGS. + * FEC settings are configured by link autonegotiation whenever it's enabled. + * With autoneg on %ETHTOOL_GFECPARAM can be used to read the current mode. + * + * When autoneg is disabled %ETHTOOL_SFECPARAM controls the FEC settings. + * It is recommended that drivers only accept a single bit set in @fec. + * When multiple bits are set in @fec drivers may pick mode in an implementation + * dependent way. Drivers should reject mixing %ETHTOOL_FEC_AUTO_BIT with other + * FEC modes, because it's unclear whether in this case other modes constrain + * AUTO or are independent choices. + * Drivers must reject SET requests if they support none of the requested modes. + * + * If device does not support FEC drivers may use %ETHTOOL_FEC_NONE instead + * of returning %EOPNOTSUPP from %ETHTOOL_GFECPARAM. + * + * See enum ethtool_fec_config_bits for definition of valid bits for both + * @fec and @active_fec. + */ +struct ethtool_fecparam { + __u32 cmd; + /* bitmask of FEC modes */ + __u32 active_fec; + __u32 fec; + __u32 reserved; +}; + +/** + * enum ethtool_fec_config_bits - flags definition of ethtool_fec_configuration + * @ETHTOOL_FEC_NONE_BIT: FEC mode configuration is not supported. Should not + * be used together with other bits. GET only. + * @ETHTOOL_FEC_AUTO_BIT: Select default/best FEC mode automatically, usually + * based link mode and SFP parameters read from module's + * EEPROM. This bit does _not_ mean autonegotiation. + * @ETHTOOL_FEC_OFF_BIT: No FEC Mode + * @ETHTOOL_FEC_RS_BIT: Reed-Solomon FEC Mode + * @ETHTOOL_FEC_BASER_BIT: Base-R/Reed-Solomon FEC Mode + * @ETHTOOL_FEC_LLRS_BIT: Low Latency Reed Solomon FEC Mode (25G/50G Ethernet + * Consortium) + */ +enum ethtool_fec_config_bits { + ETHTOOL_FEC_NONE_BIT, + ETHTOOL_FEC_AUTO_BIT, + ETHTOOL_FEC_OFF_BIT, + ETHTOOL_FEC_RS_BIT, + ETHTOOL_FEC_BASER_BIT, + ETHTOOL_FEC_LLRS_BIT, +}; + +#define ETHTOOL_FEC_NONE (1 << ETHTOOL_FEC_NONE_BIT) +#define ETHTOOL_FEC_AUTO (1 << ETHTOOL_FEC_AUTO_BIT) +#define ETHTOOL_FEC_OFF (1 << ETHTOOL_FEC_OFF_BIT) +#define ETHTOOL_FEC_RS (1 << ETHTOOL_FEC_RS_BIT) +#define ETHTOOL_FEC_BASER (1 << ETHTOOL_FEC_BASER_BIT) +#define ETHTOOL_FEC_LLRS (1 << ETHTOOL_FEC_LLRS_BIT) + +/* CMDs currently supported */ +#define ETHTOOL_GSET 0x00000001 /* DEPRECATED, Get settings. + * Please use ETHTOOL_GLINKSETTINGS + */ +#define ETHTOOL_SSET 0x00000002 /* DEPRECATED, Set settings. + * Please use ETHTOOL_SLINKSETTINGS + */ +#define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */ +#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers. */ +#define ETHTOOL_GWOL 0x00000005 /* Get wake-on-lan options. */ +#define ETHTOOL_SWOL 0x00000006 /* Set wake-on-lan options. */ +#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ +#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level. */ +#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation. */ +/* Get link status for host, i.e. whether the interface *and* the + * physical port (if there is one) are up (ethtool_value). */ +#define ETHTOOL_GLINK 0x0000000a +#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ +#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data. */ +#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ +#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ +#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ +#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters. */ +#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ +#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ +#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ +#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ +#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ +#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ +#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable + * (ethtool_value) */ +#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable + * (ethtool_value). */ +#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test. */ +#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ +#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ +#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ +#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ +#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ +#define ETHTOOL_GPERMADDR 0x00000020 /* Get permanent hardware address */ +#define ETHTOOL_GUFO 0x00000021 /* Get UFO enable (ethtool_value) */ +#define ETHTOOL_SUFO 0x00000022 /* Set UFO enable (ethtool_value) */ +#define ETHTOOL_GGSO 0x00000023 /* Get GSO enable (ethtool_value) */ +#define ETHTOOL_SGSO 0x00000024 /* Set GSO enable (ethtool_value) */ +#define ETHTOOL_GFLAGS 0x00000025 /* Get flags bitmap(ethtool_value) */ +#define ETHTOOL_SFLAGS 0x00000026 /* Set flags bitmap(ethtool_value) */ +#define ETHTOOL_GPFLAGS 0x00000027 /* Get driver-private flags bitmap */ +#define ETHTOOL_SPFLAGS 0x00000028 /* Set driver-private flags bitmap */ + +#define ETHTOOL_GRXFH 0x00000029 /* Get RX flow hash configuration */ +#define ETHTOOL_SRXFH 0x0000002a /* Set RX flow hash configuration */ +#define ETHTOOL_GGRO 0x0000002b /* Get GRO enable (ethtool_value) */ +#define ETHTOOL_SGRO 0x0000002c /* Set GRO enable (ethtool_value) */ +#define ETHTOOL_GRXRINGS 0x0000002d /* Get RX rings available for LB */ +#define ETHTOOL_GRXCLSRLCNT 0x0000002e /* Get RX class rule count */ +#define ETHTOOL_GRXCLSRULE 0x0000002f /* Get RX classification rule */ +#define ETHTOOL_GRXCLSRLALL 0x00000030 /* Get all RX classification rule */ +#define ETHTOOL_SRXCLSRLDEL 0x00000031 /* Delete RX classification rule */ +#define ETHTOOL_SRXCLSRLINS 0x00000032 /* Insert RX classification rule */ +#define ETHTOOL_FLASHDEV 0x00000033 /* Flash firmware to device */ +#define ETHTOOL_RESET 0x00000034 /* Reset hardware */ +#define ETHTOOL_SRXNTUPLE 0x00000035 /* Add an n-tuple filter to device */ +#define ETHTOOL_GRXNTUPLE 0x00000036 /* deprecated */ +#define ETHTOOL_GSSET_INFO 0x00000037 /* Get string set info */ +#define ETHTOOL_GRXFHINDIR 0x00000038 /* Get RX flow hash indir'n table */ +#define ETHTOOL_SRXFHINDIR 0x00000039 /* Set RX flow hash indir'n table */ + +#define ETHTOOL_GFEATURES 0x0000003a /* Get device offload settings */ +#define ETHTOOL_SFEATURES 0x0000003b /* Change device offload settings */ +#define ETHTOOL_GCHANNELS 0x0000003c /* Get no of channels */ +#define ETHTOOL_SCHANNELS 0x0000003d /* Set no of channels */ +#define ETHTOOL_SET_DUMP 0x0000003e /* Set dump settings */ +#define ETHTOOL_GET_DUMP_FLAG 0x0000003f /* Get dump settings */ +#define ETHTOOL_GET_DUMP_DATA 0x00000040 /* Get dump data */ +#define ETHTOOL_GET_TS_INFO 0x00000041 /* Get time stamping and PHC info */ +#define ETHTOOL_GMODULEINFO 0x00000042 /* Get plug-in module information */ +#define ETHTOOL_GMODULEEEPROM 0x00000043 /* Get plug-in module eeprom */ +#define ETHTOOL_GEEE 0x00000044 /* Get EEE settings */ +#define ETHTOOL_SEEE 0x00000045 /* Set EEE settings */ + +#define ETHTOOL_GRSSH 0x00000046 /* Get RX flow hash configuration */ +#define ETHTOOL_SRSSH 0x00000047 /* Set RX flow hash configuration */ +#define ETHTOOL_GTUNABLE 0x00000048 /* Get tunable configuration */ +#define ETHTOOL_STUNABLE 0x00000049 /* Set tunable configuration */ +#define ETHTOOL_GPHYSTATS 0x0000004a /* get PHY-specific statistics */ + +#define ETHTOOL_PERQUEUE 0x0000004b /* Set per queue options */ + +#define ETHTOOL_GLINKSETTINGS 0x0000004c /* Get ethtool_link_settings */ +#define ETHTOOL_SLINKSETTINGS 0x0000004d /* Set ethtool_link_settings */ +#define ETHTOOL_PHY_GTUNABLE 0x0000004e /* Get PHY tunable configuration */ +#define ETHTOOL_PHY_STUNABLE 0x0000004f /* Set PHY tunable configuration */ +#define ETHTOOL_GFECPARAM 0x00000050 /* Get FEC settings */ +#define ETHTOOL_SFECPARAM 0x00000051 /* Set FEC settings */ + +/* compatibility with older code */ +#define SPARC_ETH_GSET ETHTOOL_GSET +#define SPARC_ETH_SSET ETHTOOL_SSET + +/* Link mode bit indices */ +enum ethtool_link_mode_bit_indices { + ETHTOOL_LINK_MODE_10baseT_Half_BIT = 0, + ETHTOOL_LINK_MODE_10baseT_Full_BIT = 1, + ETHTOOL_LINK_MODE_100baseT_Half_BIT = 2, + ETHTOOL_LINK_MODE_100baseT_Full_BIT = 3, + ETHTOOL_LINK_MODE_1000baseT_Half_BIT = 4, + ETHTOOL_LINK_MODE_1000baseT_Full_BIT = 5, + ETHTOOL_LINK_MODE_Autoneg_BIT = 6, + ETHTOOL_LINK_MODE_TP_BIT = 7, + ETHTOOL_LINK_MODE_AUI_BIT = 8, + ETHTOOL_LINK_MODE_MII_BIT = 9, + ETHTOOL_LINK_MODE_FIBRE_BIT = 10, + ETHTOOL_LINK_MODE_BNC_BIT = 11, + ETHTOOL_LINK_MODE_10000baseT_Full_BIT = 12, + ETHTOOL_LINK_MODE_Pause_BIT = 13, + ETHTOOL_LINK_MODE_Asym_Pause_BIT = 14, + ETHTOOL_LINK_MODE_2500baseX_Full_BIT = 15, + ETHTOOL_LINK_MODE_Backplane_BIT = 16, + ETHTOOL_LINK_MODE_1000baseKX_Full_BIT = 17, + ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT = 18, + ETHTOOL_LINK_MODE_10000baseKR_Full_BIT = 19, + ETHTOOL_LINK_MODE_10000baseR_FEC_BIT = 20, + ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT = 21, + ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT = 22, + ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT = 23, + ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT = 24, + ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT = 25, + ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT = 26, + ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT = 27, + ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT = 28, + ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT = 29, + ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT = 30, + ETHTOOL_LINK_MODE_25000baseCR_Full_BIT = 31, + + /* Last allowed bit for __ETHTOOL_LINK_MODE_LEGACY_MASK is bit + * 31. Please do NOT define any SUPPORTED_* or ADVERTISED_* + * macro for bits > 31. The only way to use indices > 31 is to + * use the new ETHTOOL_GLINKSETTINGS/ETHTOOL_SLINKSETTINGS API. + */ + + ETHTOOL_LINK_MODE_25000baseKR_Full_BIT = 32, + ETHTOOL_LINK_MODE_25000baseSR_Full_BIT = 33, + ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT = 34, + ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT = 35, + ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT = 36, + ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT = 37, + ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT = 38, + ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT = 39, + ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT = 40, + ETHTOOL_LINK_MODE_1000baseX_Full_BIT = 41, + ETHTOOL_LINK_MODE_10000baseCR_Full_BIT = 42, + ETHTOOL_LINK_MODE_10000baseSR_Full_BIT = 43, + ETHTOOL_LINK_MODE_10000baseLR_Full_BIT = 44, + ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT = 45, + ETHTOOL_LINK_MODE_10000baseER_Full_BIT = 46, + ETHTOOL_LINK_MODE_2500baseT_Full_BIT = 47, + ETHTOOL_LINK_MODE_5000baseT_Full_BIT = 48, + + ETHTOOL_LINK_MODE_FEC_NONE_BIT = 49, + ETHTOOL_LINK_MODE_FEC_RS_BIT = 50, + ETHTOOL_LINK_MODE_FEC_BASER_BIT = 51, + ETHTOOL_LINK_MODE_50000baseKR_Full_BIT = 52, + ETHTOOL_LINK_MODE_50000baseSR_Full_BIT = 53, + ETHTOOL_LINK_MODE_50000baseCR_Full_BIT = 54, + ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT = 55, + ETHTOOL_LINK_MODE_50000baseDR_Full_BIT = 56, + ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT = 57, + ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT = 58, + ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT = 59, + ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT = 60, + ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT = 61, + ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT = 62, + ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT = 63, + ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT = 64, + ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT = 65, + ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT = 66, + ETHTOOL_LINK_MODE_100baseT1_Full_BIT = 67, + ETHTOOL_LINK_MODE_1000baseT1_Full_BIT = 68, + ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT = 69, + ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT = 70, + ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT = 71, + ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT = 72, + ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT = 73, + ETHTOOL_LINK_MODE_FEC_LLRS_BIT = 74, + ETHTOOL_LINK_MODE_100000baseKR_Full_BIT = 75, + ETHTOOL_LINK_MODE_100000baseSR_Full_BIT = 76, + ETHTOOL_LINK_MODE_100000baseLR_ER_FR_Full_BIT = 77, + ETHTOOL_LINK_MODE_100000baseCR_Full_BIT = 78, + ETHTOOL_LINK_MODE_100000baseDR_Full_BIT = 79, + ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT = 80, + ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT = 81, + ETHTOOL_LINK_MODE_200000baseLR2_ER2_FR2_Full_BIT = 82, + ETHTOOL_LINK_MODE_200000baseDR2_Full_BIT = 83, + ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT = 84, + ETHTOOL_LINK_MODE_400000baseKR4_Full_BIT = 85, + ETHTOOL_LINK_MODE_400000baseSR4_Full_BIT = 86, + ETHTOOL_LINK_MODE_400000baseLR4_ER4_FR4_Full_BIT = 87, + ETHTOOL_LINK_MODE_400000baseDR4_Full_BIT = 88, + ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT = 89, + ETHTOOL_LINK_MODE_100baseFX_Half_BIT = 90, + ETHTOOL_LINK_MODE_100baseFX_Full_BIT = 91, + ETHTOOL_LINK_MODE_10baseT1L_Full_BIT = 92, + ETHTOOL_LINK_MODE_800000baseCR8_Full_BIT = 93, + ETHTOOL_LINK_MODE_800000baseKR8_Full_BIT = 94, + ETHTOOL_LINK_MODE_800000baseDR8_Full_BIT = 95, + ETHTOOL_LINK_MODE_800000baseDR8_2_Full_BIT = 96, + ETHTOOL_LINK_MODE_800000baseSR8_Full_BIT = 97, + ETHTOOL_LINK_MODE_800000baseVR8_Full_BIT = 98, + ETHTOOL_LINK_MODE_10baseT1S_Full_BIT = 99, + ETHTOOL_LINK_MODE_10baseT1S_Half_BIT = 100, + ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half_BIT = 101, + + /* must be last entry */ + __ETHTOOL_LINK_MODE_MASK_NBITS +}; + +#define __ETHTOOL_LINK_MODE_LEGACY_MASK(base_name) \ + (1UL << (ETHTOOL_LINK_MODE_ ## base_name ## _BIT)) + +/* DEPRECATED macros. Please migrate to + * ETHTOOL_GLINKSETTINGS/ETHTOOL_SLINKSETTINGS API. Please do NOT + * define any new SUPPORTED_* macro for bits > 31. + */ +#define SUPPORTED_10baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Half) +#define SUPPORTED_10baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Full) +#define SUPPORTED_100baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Half) +#define SUPPORTED_100baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Full) +#define SUPPORTED_1000baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Half) +#define SUPPORTED_1000baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Full) +#define SUPPORTED_Autoneg __ETHTOOL_LINK_MODE_LEGACY_MASK(Autoneg) +#define SUPPORTED_TP __ETHTOOL_LINK_MODE_LEGACY_MASK(TP) +#define SUPPORTED_AUI __ETHTOOL_LINK_MODE_LEGACY_MASK(AUI) +#define SUPPORTED_MII __ETHTOOL_LINK_MODE_LEGACY_MASK(MII) +#define SUPPORTED_FIBRE __ETHTOOL_LINK_MODE_LEGACY_MASK(FIBRE) +#define SUPPORTED_BNC __ETHTOOL_LINK_MODE_LEGACY_MASK(BNC) +#define SUPPORTED_10000baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseT_Full) +#define SUPPORTED_Pause __ETHTOOL_LINK_MODE_LEGACY_MASK(Pause) +#define SUPPORTED_Asym_Pause __ETHTOOL_LINK_MODE_LEGACY_MASK(Asym_Pause) +#define SUPPORTED_2500baseX_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(2500baseX_Full) +#define SUPPORTED_Backplane __ETHTOOL_LINK_MODE_LEGACY_MASK(Backplane) +#define SUPPORTED_1000baseKX_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseKX_Full) +#define SUPPORTED_10000baseKX4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKX4_Full) +#define SUPPORTED_10000baseKR_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKR_Full) +#define SUPPORTED_10000baseR_FEC __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseR_FEC) +#define SUPPORTED_20000baseMLD2_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseMLD2_Full) +#define SUPPORTED_20000baseKR2_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseKR2_Full) +#define SUPPORTED_40000baseKR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseKR4_Full) +#define SUPPORTED_40000baseCR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseCR4_Full) +#define SUPPORTED_40000baseSR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseSR4_Full) +#define SUPPORTED_40000baseLR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseLR4_Full) +#define SUPPORTED_56000baseKR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseKR4_Full) +#define SUPPORTED_56000baseCR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseCR4_Full) +#define SUPPORTED_56000baseSR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseSR4_Full) +#define SUPPORTED_56000baseLR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseLR4_Full) +/* Please do not define any new SUPPORTED_* macro for bits > 31, see + * notice above. + */ + +/* + * DEPRECATED macros. Please migrate to + * ETHTOOL_GLINKSETTINGS/ETHTOOL_SLINKSETTINGS API. Please do NOT + * define any new ADERTISE_* macro for bits > 31. + */ +#define ADVERTISED_10baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Half) +#define ADVERTISED_10baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Full) +#define ADVERTISED_100baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Half) +#define ADVERTISED_100baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Full) +#define ADVERTISED_1000baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Half) +#define ADVERTISED_1000baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Full) +#define ADVERTISED_Autoneg __ETHTOOL_LINK_MODE_LEGACY_MASK(Autoneg) +#define ADVERTISED_TP __ETHTOOL_LINK_MODE_LEGACY_MASK(TP) +#define ADVERTISED_AUI __ETHTOOL_LINK_MODE_LEGACY_MASK(AUI) +#define ADVERTISED_MII __ETHTOOL_LINK_MODE_LEGACY_MASK(MII) +#define ADVERTISED_FIBRE __ETHTOOL_LINK_MODE_LEGACY_MASK(FIBRE) +#define ADVERTISED_BNC __ETHTOOL_LINK_MODE_LEGACY_MASK(BNC) +#define ADVERTISED_10000baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseT_Full) +#define ADVERTISED_Pause __ETHTOOL_LINK_MODE_LEGACY_MASK(Pause) +#define ADVERTISED_Asym_Pause __ETHTOOL_LINK_MODE_LEGACY_MASK(Asym_Pause) +#define ADVERTISED_2500baseX_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(2500baseX_Full) +#define ADVERTISED_Backplane __ETHTOOL_LINK_MODE_LEGACY_MASK(Backplane) +#define ADVERTISED_1000baseKX_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseKX_Full) +#define ADVERTISED_10000baseKX4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKX4_Full) +#define ADVERTISED_10000baseKR_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKR_Full) +#define ADVERTISED_10000baseR_FEC __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseR_FEC) +#define ADVERTISED_20000baseMLD2_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseMLD2_Full) +#define ADVERTISED_20000baseKR2_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseKR2_Full) +#define ADVERTISED_40000baseKR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseKR4_Full) +#define ADVERTISED_40000baseCR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseCR4_Full) +#define ADVERTISED_40000baseSR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseSR4_Full) +#define ADVERTISED_40000baseLR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseLR4_Full) +#define ADVERTISED_56000baseKR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseKR4_Full) +#define ADVERTISED_56000baseCR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseCR4_Full) +#define ADVERTISED_56000baseSR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseSR4_Full) +#define ADVERTISED_56000baseLR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseLR4_Full) +/* Please do not define any new ADVERTISED_* macro for bits > 31, see + * notice above. + */ + +/* The following are all involved in forcing a particular link + * mode for the device for setting things. When getting the + * devices settings, these indicate the current mode and whether + * it was forced up into this mode or autonegotiated. + */ + +/* The forced speed, in units of 1Mb. All values 0 to INT_MAX are legal. + * Update drivers/net/phy/phy.c:phy_speed_to_str() and + * drivers/net/bonding/bond_3ad.c:__get_link_speed() when adding new values. + */ +#define SPEED_10 10 +#define SPEED_100 100 +#define SPEED_1000 1000 +#define SPEED_2500 2500 +#define SPEED_5000 5000 +#define SPEED_10000 10000 +#define SPEED_14000 14000 +#define SPEED_20000 20000 +#define SPEED_25000 25000 +#define SPEED_40000 40000 +#define SPEED_50000 50000 +#define SPEED_56000 56000 +#define SPEED_100000 100000 +#define SPEED_200000 200000 +#define SPEED_400000 400000 +#define SPEED_800000 800000 + +#define SPEED_UNKNOWN -1 + +static __inline__ int ethtool_validate_speed(__u32 speed) +{ + return speed <= INT_MAX || speed == (__u32)SPEED_UNKNOWN; +} + +/* Duplex, half or full. */ +#define DUPLEX_HALF 0x00 +#define DUPLEX_FULL 0x01 +#define DUPLEX_UNKNOWN 0xff + +static __inline__ int ethtool_validate_duplex(__u8 duplex) +{ + switch (duplex) { + case DUPLEX_HALF: + case DUPLEX_FULL: + case DUPLEX_UNKNOWN: + return 1; + } + + return 0; +} + +#define MASTER_SLAVE_CFG_UNSUPPORTED 0 +#define MASTER_SLAVE_CFG_UNKNOWN 1 +#define MASTER_SLAVE_CFG_MASTER_PREFERRED 2 +#define MASTER_SLAVE_CFG_SLAVE_PREFERRED 3 +#define MASTER_SLAVE_CFG_MASTER_FORCE 4 +#define MASTER_SLAVE_CFG_SLAVE_FORCE 5 +#define MASTER_SLAVE_STATE_UNSUPPORTED 0 +#define MASTER_SLAVE_STATE_UNKNOWN 1 +#define MASTER_SLAVE_STATE_MASTER 2 +#define MASTER_SLAVE_STATE_SLAVE 3 +#define MASTER_SLAVE_STATE_ERR 4 + +/* These are used to throttle the rate of data on the phy interface when the + * native speed of the interface is higher than the link speed. These should + * not be used for phy interfaces which natively support multiple speeds (e.g. + * MII or SGMII). + */ +/* No rate matching performed. */ +#define RATE_MATCH_NONE 0 +/* The phy sends pause frames to throttle the MAC. */ +#define RATE_MATCH_PAUSE 1 +/* The phy asserts CRS to prevent the MAC from transmitting. */ +#define RATE_MATCH_CRS 2 +/* The MAC is programmed with a sufficiently-large IPG. */ +#define RATE_MATCH_OPEN_LOOP 3 + +/* Which connector port. */ +#define PORT_TP 0x00 +#define PORT_AUI 0x01 +#define PORT_MII 0x02 +#define PORT_FIBRE 0x03 +#define PORT_BNC 0x04 +#define PORT_DA 0x05 +#define PORT_NONE 0xef +#define PORT_OTHER 0xff + +/* Which transceiver to use. */ +#define XCVR_INTERNAL 0x00 /* PHY and MAC are in the same package */ +#define XCVR_EXTERNAL 0x01 /* PHY and MAC are in different packages */ +#define XCVR_DUMMY1 0x02 +#define XCVR_DUMMY2 0x03 +#define XCVR_DUMMY3 0x04 + +/* Enable or disable autonegotiation. */ +#define AUTONEG_DISABLE 0x00 +#define AUTONEG_ENABLE 0x01 + +/* MDI or MDI-X status/control - if MDI/MDI_X/AUTO is set then + * the driver is required to renegotiate link + */ +#define ETH_TP_MDI_INVALID 0x00 /* status: unknown; control: unsupported */ +#define ETH_TP_MDI 0x01 /* status: MDI; control: force MDI */ +#define ETH_TP_MDI_X 0x02 /* status: MDI-X; control: force MDI-X */ +#define ETH_TP_MDI_AUTO 0x03 /* control: auto-select */ + +/* Wake-On-Lan options. */ +#define WAKE_PHY (1 << 0) +#define WAKE_UCAST (1 << 1) +#define WAKE_MCAST (1 << 2) +#define WAKE_BCAST (1 << 3) +#define WAKE_ARP (1 << 4) +#define WAKE_MAGIC (1 << 5) +#define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */ +#define WAKE_FILTER (1 << 7) + +#define WOL_MODE_COUNT 8 + +/* L2-L4 network traffic flow types */ +#define TCP_V4_FLOW 0x01 /* hash or spec (tcp_ip4_spec) */ +#define UDP_V4_FLOW 0x02 /* hash or spec (udp_ip4_spec) */ +#define SCTP_V4_FLOW 0x03 /* hash or spec (sctp_ip4_spec) */ +#define AH_ESP_V4_FLOW 0x04 /* hash only */ +#define TCP_V6_FLOW 0x05 /* hash or spec (tcp_ip6_spec; nfc only) */ +#define UDP_V6_FLOW 0x06 /* hash or spec (udp_ip6_spec; nfc only) */ +#define SCTP_V6_FLOW 0x07 /* hash or spec (sctp_ip6_spec; nfc only) */ +#define AH_ESP_V6_FLOW 0x08 /* hash only */ +#define AH_V4_FLOW 0x09 /* hash or spec (ah_ip4_spec) */ +#define ESP_V4_FLOW 0x0a /* hash or spec (esp_ip4_spec) */ +#define AH_V6_FLOW 0x0b /* hash or spec (ah_ip6_spec; nfc only) */ +#define ESP_V6_FLOW 0x0c /* hash or spec (esp_ip6_spec; nfc only) */ +#define IPV4_USER_FLOW 0x0d /* spec only (usr_ip4_spec) */ +#define IP_USER_FLOW IPV4_USER_FLOW +#define IPV6_USER_FLOW 0x0e /* spec only (usr_ip6_spec; nfc only) */ +#define IPV4_FLOW 0x10 /* hash only */ +#define IPV6_FLOW 0x11 /* hash only */ +#define ETHER_FLOW 0x12 /* spec only (ether_spec) */ +/* Flag to enable additional fields in struct ethtool_rx_flow_spec */ +#define FLOW_EXT 0x80000000 +#define FLOW_MAC_EXT 0x40000000 +/* Flag to enable RSS spreading of traffic matching rule (nfc only) */ +#define FLOW_RSS 0x20000000 + +/* L3-L4 network traffic flow hash options */ +#define RXH_L2DA (1 << 1) +#define RXH_VLAN (1 << 2) +#define RXH_L3_PROTO (1 << 3) +#define RXH_IP_SRC (1 << 4) +#define RXH_IP_DST (1 << 5) +#define RXH_L4_B_0_1 (1 << 6) /* src port in case of TCP/UDP/SCTP */ +#define RXH_L4_B_2_3 (1 << 7) /* dst port in case of TCP/UDP/SCTP */ +#define RXH_DISCARD (1 << 31) + +#define RX_CLS_FLOW_DISC 0xffffffffffffffffULL +#define RX_CLS_FLOW_WAKE 0xfffffffffffffffeULL + +/* Special RX classification rule insert location values */ +#define RX_CLS_LOC_SPECIAL 0x80000000 /* flag */ +#define RX_CLS_LOC_ANY 0xffffffff +#define RX_CLS_LOC_FIRST 0xfffffffe +#define RX_CLS_LOC_LAST 0xfffffffd + +/* EEPROM Standards for plug in modules */ +#define ETH_MODULE_SFF_8079 0x1 +#define ETH_MODULE_SFF_8079_LEN 256 +#define ETH_MODULE_SFF_8472 0x2 +#define ETH_MODULE_SFF_8472_LEN 512 +#define ETH_MODULE_SFF_8636 0x3 +#define ETH_MODULE_SFF_8636_LEN 256 +#define ETH_MODULE_SFF_8436 0x4 +#define ETH_MODULE_SFF_8436_LEN 256 + +#define ETH_MODULE_SFF_8636_MAX_LEN 640 +#define ETH_MODULE_SFF_8436_MAX_LEN 640 + +/* Reset flags */ +/* The reset() operation must clear the flags for the components which + * were actually reset. On successful return, the flags indicate the + * components which were not reset, either because they do not exist + * in the hardware or because they cannot be reset independently. The + * driver must never reset any components that were not requested. + */ +enum ethtool_reset_flags { + /* These flags represent components dedicated to the interface + * the command is addressed to. Shift any flag left by + * ETH_RESET_SHARED_SHIFT to reset a shared component of the + * same type. + */ + ETH_RESET_MGMT = 1 << 0, /* Management processor */ + ETH_RESET_IRQ = 1 << 1, /* Interrupt requester */ + ETH_RESET_DMA = 1 << 2, /* DMA engine */ + ETH_RESET_FILTER = 1 << 3, /* Filtering/flow direction */ + ETH_RESET_OFFLOAD = 1 << 4, /* Protocol offload */ + ETH_RESET_MAC = 1 << 5, /* Media access controller */ + ETH_RESET_PHY = 1 << 6, /* Transceiver/PHY */ + ETH_RESET_RAM = 1 << 7, /* RAM shared between + * multiple components */ + ETH_RESET_AP = 1 << 8, /* Application processor */ + + ETH_RESET_DEDICATED = 0x0000ffff, /* All components dedicated to + * this interface */ + ETH_RESET_ALL = 0xffffffff, /* All components used by this + * interface, even if shared */ +}; +#define ETH_RESET_SHARED_SHIFT 16 + + +/** + * struct ethtool_link_settings - link control and status + * + * IMPORTANT, Backward compatibility notice: When implementing new + * user-space tools, please first try %ETHTOOL_GLINKSETTINGS, and + * if it succeeds use %ETHTOOL_SLINKSETTINGS to change link + * settings; do not use %ETHTOOL_SSET if %ETHTOOL_GLINKSETTINGS + * succeeded: stick to %ETHTOOL_GLINKSETTINGS/%SLINKSETTINGS in + * that case. Conversely, if %ETHTOOL_GLINKSETTINGS fails, use + * %ETHTOOL_GSET to query and %ETHTOOL_SSET to change link + * settings; do not use %ETHTOOL_SLINKSETTINGS if + * %ETHTOOL_GLINKSETTINGS failed: stick to + * %ETHTOOL_GSET/%ETHTOOL_SSET in that case. + * + * @cmd: Command number = %ETHTOOL_GLINKSETTINGS or %ETHTOOL_SLINKSETTINGS + * @speed: Link speed (Mbps) + * @duplex: Duplex mode; one of %DUPLEX_* + * @port: Physical connector type; one of %PORT_* + * @phy_address: MDIO address of PHY (transceiver); 0 or 255 if not + * applicable. For clause 45 PHYs this is the PRTAD. + * @autoneg: Enable/disable autonegotiation and auto-detection; + * either %AUTONEG_DISABLE or %AUTONEG_ENABLE + * @mdio_support: Bitmask of %ETH_MDIO_SUPPORTS_* flags for the MDIO + * protocols supported by the interface; 0 if unknown. + * Read-only. + * @eth_tp_mdix: Ethernet twisted-pair MDI(-X) status; one of + * %ETH_TP_MDI_*. If the status is unknown or not applicable, the + * value will be %ETH_TP_MDI_INVALID. Read-only. + * @eth_tp_mdix_ctrl: Ethernet twisted pair MDI(-X) control; one of + * %ETH_TP_MDI_*. If MDI(-X) control is not implemented, reads + * yield %ETH_TP_MDI_INVALID and writes may be ignored or rejected. + * When written successfully, the link should be renegotiated if + * necessary. + * @link_mode_masks_nwords: Number of 32-bit words for each of the + * supported, advertising, lp_advertising link mode bitmaps. For + * %ETHTOOL_GLINKSETTINGS: on entry, number of words passed by user + * (>= 0); on return, if handshake in progress, negative if + * request size unsupported by kernel: absolute value indicates + * kernel expected size and all the other fields but cmd + * are 0; otherwise (handshake completed), strictly positive + * to indicate size used by kernel and cmd field stays + * %ETHTOOL_GLINKSETTINGS, all other fields populated by driver. For + * %ETHTOOL_SLINKSETTINGS: must be valid on entry, ie. a positive + * value returned previously by %ETHTOOL_GLINKSETTINGS, otherwise + * refused. For drivers: ignore this field (use kernel's + * __ETHTOOL_LINK_MODE_MASK_NBITS instead), any change to it will + * be overwritten by kernel. + * @supported: Bitmap with each bit meaning given by + * %ethtool_link_mode_bit_indices for the link modes, physical + * connectors and other link features for which the interface + * supports autonegotiation or auto-detection. Read-only. + * @advertising: Bitmap with each bit meaning given by + * %ethtool_link_mode_bit_indices for the link modes, physical + * connectors and other link features that are advertised through + * autonegotiation or enabled for auto-detection. + * @lp_advertising: Bitmap with each bit meaning given by + * %ethtool_link_mode_bit_indices for the link modes, and other + * link features that the link partner advertised through + * autonegotiation; 0 if unknown or not applicable. Read-only. + * @transceiver: Used to distinguish different possible PHY types, + * reported consistently by PHYLIB. Read-only. + * @master_slave_cfg: Master/slave port mode. + * @master_slave_state: Master/slave port state. + * @rate_matching: Rate adaptation performed by the PHY + * @reserved: Reserved for future use; see the note on reserved space. + * @link_mode_masks: Variable length bitmaps. + * + * If autonegotiation is disabled, the speed and @duplex represent the + * fixed link mode and are writable if the driver supports multiple + * link modes. If it is enabled then they are read-only; if the link + * is up they represent the negotiated link mode; if the link is down, + * the speed is 0, %SPEED_UNKNOWN or the highest enabled speed and + * @duplex is %DUPLEX_UNKNOWN or the best enabled duplex mode. + * + * Some hardware interfaces may have multiple PHYs and/or physical + * connectors fitted or do not allow the driver to detect which are + * fitted. For these interfaces @port and/or @phy_address may be + * writable, possibly dependent on @autoneg being %AUTONEG_DISABLE. + * Otherwise, attempts to write different values may be ignored or + * rejected. + * + * Deprecated %ethtool_cmd fields transceiver, maxtxpkt and maxrxpkt + * are not available in %ethtool_link_settings. These fields will be + * always set to zero in %ETHTOOL_GSET reply and %ETHTOOL_SSET will + * fail if any of them is set to non-zero value. + * + * Users should assume that all fields not marked read-only are + * writable and subject to validation by the driver. They should use + * %ETHTOOL_GLINKSETTINGS to get the current values before making specific + * changes and then applying them with %ETHTOOL_SLINKSETTINGS. + * + * Drivers that implement %get_link_ksettings and/or + * %set_link_ksettings should ignore the @cmd + * and @link_mode_masks_nwords fields (any change to them overwritten + * by kernel), and rely only on kernel's internal + * %__ETHTOOL_LINK_MODE_MASK_NBITS and + * %ethtool_link_mode_mask_t. Drivers that implement + * %set_link_ksettings() should validate all fields other than @cmd + * and @link_mode_masks_nwords that are not described as read-only or + * deprecated, and must ignore all fields described as read-only. + */ +struct ethtool_link_settings { + __u32 cmd; + __u32 speed; + __u8 duplex; + __u8 port; + __u8 phy_address; + __u8 autoneg; + __u8 mdio_support; + __u8 eth_tp_mdix; + __u8 eth_tp_mdix_ctrl; + __s8 link_mode_masks_nwords; + __u8 transceiver; + __u8 master_slave_cfg; + __u8 master_slave_state; + __u8 rate_matching; + __u32 reserved[7]; + __u32 link_mode_masks[]; + /* layout of link_mode_masks fields: + * __u32 map_supported[link_mode_masks_nwords]; + * __u32 map_advertising[link_mode_masks_nwords]; + * __u32 map_lp_advertising[link_mode_masks_nwords]; + */ +}; +#endif /* _LINUX_ETHTOOL_H */ diff --git a/include/linux-private/linux/falloc.h b/include/linux-private/linux/falloc.h new file mode 100644 index 0000000..ca3904d --- /dev/null +++ b/include/linux-private/linux/falloc.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _FALLOC_H_ +#define _FALLOC_H_ + +#define FALLOC_FL_KEEP_SIZE 0x01 /* default is extend size */ +#define FALLOC_FL_PUNCH_HOLE 0x02 /* de-allocates range */ +#define FALLOC_FL_NO_HIDE_STALE 0x04 /* reserved codepoint */ + +/* + * FALLOC_FL_COLLAPSE_RANGE is used to remove a range of a file + * without leaving a hole in the file. The contents of the file beyond + * the range being removed is appended to the start offset of the range + * being removed (i.e. the hole that was punched is "collapsed"), + * resulting in a file layout that looks like the range that was + * removed never existed. As such collapsing a range of a file changes + * the size of the file, reducing it by the same length of the range + * that has been removed by the operation. + * + * Different filesystems may implement different limitations on the + * granularity of the operation. Most will limit operations to + * filesystem block size boundaries, but this boundary may be larger or + * smaller depending on the filesystem and/or the configuration of the + * filesystem or file. + * + * Attempting to collapse a range that crosses the end of the file is + * considered an illegal operation - just use ftruncate(2) if you need + * to collapse a range that crosses EOF. + */ +#define FALLOC_FL_COLLAPSE_RANGE 0x08 + +/* + * FALLOC_FL_ZERO_RANGE is used to convert a range of file to zeros preferably + * without issuing data IO. Blocks should be preallocated for the regions that + * span holes in the file, and the entire range is preferable converted to + * unwritten extents - even though file system may choose to zero out the + * extent or do whatever which will result in reading zeros from the range + * while the range remains allocated for the file. + * + * This can be also used to preallocate blocks past EOF in the same way as + * with fallocate. Flag FALLOC_FL_KEEP_SIZE should cause the inode + * size to remain the same. + */ +#define FALLOC_FL_ZERO_RANGE 0x10 + +/* + * FALLOC_FL_INSERT_RANGE is use to insert space within the file size without + * overwriting any existing data. The contents of the file beyond offset are + * shifted towards right by len bytes to create a hole. As such, this + * operation will increase the size of the file by len bytes. + * + * Different filesystems may implement different limitations on the granularity + * of the operation. Most will limit operations to filesystem block size + * boundaries, but this boundary may be larger or smaller depending on + * the filesystem and/or the configuration of the filesystem or file. + * + * Attempting to insert space using this flag at OR beyond the end of + * the file is considered an illegal operation - just use ftruncate(2) or + * fallocate(2) with mode 0 for such type of operations. + */ +#define FALLOC_FL_INSERT_RANGE 0x20 + +/* + * FALLOC_FL_UNSHARE_RANGE is used to unshare shared blocks within the + * file size without overwriting any existing data. The purpose of this + * call is to preemptively reallocate any blocks that are subject to + * copy-on-write. + * + * Different filesystems may implement different limitations on the + * granularity of the operation. Most will limit operations to filesystem + * block size boundaries, but this boundary may be larger or smaller + * depending on the filesystem and/or the configuration of the filesystem + * or file. + * + * This flag can only be used with allocate-mode fallocate, which is + * to say that it cannot be used with the punch, zero, collapse, or + * insert range modes. + */ +#define FALLOC_FL_UNSHARE_RANGE 0x40 + +#endif /* _FALLOC_H_ */ diff --git a/include/linux/fib_rules.h b/include/linux-private/linux/fib_rules.h similarity index 72% rename from include/linux/fib_rules.h rename to include/linux-private/linux/fib_rules.h index ed4504a..232df14 100644 --- a/include/linux/fib_rules.h +++ b/include/linux-private/linux/fib_rules.h @@ -1,6 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef __LINUX_FIB_RULES_H #define __LINUX_FIB_RULES_H +#include +#include + /* rule is permanent, and cannot be deleted */ #define FIB_RULE_PERMANENT 0x00000001 #define FIB_RULE_INVERT 0x00000002 @@ -19,13 +23,23 @@ struct fib_rule_hdr { __u8 tos; __u8 table; - __u8 res1; /* reserved */ + __u8 res1; /* reserved */ __u8 res2; /* reserved */ __u8 action; __u32 flags; }; +struct fib_rule_uid_range { + __u32 start; + __u32 end; +}; + +struct fib_rule_port_range { + __u16 start; + __u16 end; +}; + enum { FRA_UNSPEC, FRA_DST, /* destination address */ @@ -40,12 +54,19 @@ enum { FRA_UNUSED5, FRA_FWMARK, /* mark */ FRA_FLOW, /* flow/class id */ - FRA_UNUSED6, - FRA_UNUSED7, - FRA_UNUSED8, + FRA_TUN_ID, + FRA_SUPPRESS_IFGROUP, + FRA_SUPPRESS_PREFIXLEN, FRA_TABLE, /* Extended table id */ FRA_FWMASK, /* mask for netfilter mark */ FRA_OIFNAME, + FRA_PAD, + FRA_L3MDEV, /* iif or oif is l3mdev goto its table */ + FRA_UID_RANGE, /* UID range */ + FRA_PROTOCOL, /* Originator of the rule */ + FRA_IP_PROTO, /* ip proto */ + FRA_SPORT_RANGE, /* sport */ + FRA_DPORT_RANGE, /* dport */ __FRA_MAX }; diff --git a/include/linux/gen_stats.h b/include/linux-private/linux/gen_stats.h similarity index 79% rename from include/linux/gen_stats.h rename to include/linux-private/linux/gen_stats.h index 552c8a0..852f234 100644 --- a/include/linux/gen_stats.h +++ b/include/linux-private/linux/gen_stats.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef __LINUX_GEN_STATS_H #define __LINUX_GEN_STATS_H @@ -9,6 +10,10 @@ enum { TCA_STATS_RATE_EST, TCA_STATS_QUEUE, TCA_STATS_APP, + TCA_STATS_RATE_EST64, + TCA_STATS_PAD, + TCA_STATS_BASIC_HW, + TCA_STATS_PKT64, __TCA_STATS_MAX, }; #define TCA_STATS_MAX (__TCA_STATS_MAX - 1) @@ -22,10 +27,6 @@ struct gnet_stats_basic { __u64 bytes; __u32 packets; }; -struct gnet_stats_basic_packed { - __u64 bytes; - __u32 packets; -} __attribute__ ((packed)); /** * struct gnet_stats_rate_est - rate estimator @@ -38,6 +39,16 @@ struct gnet_stats_rate_est { }; /** + * struct gnet_stats_rate_est64 - rate estimator + * @bps: current byte rate + * @pps: current packet rate + */ +struct gnet_stats_rate_est64 { + __u64 bps; + __u64 pps; +}; + +/** * struct gnet_stats_queue - queuing statistics * @qlen: queue length * @backlog: backlog size of queue diff --git a/include/linux/genetlink.h b/include/linux-private/linux/genetlink.h similarity index 72% rename from include/linux/genetlink.h rename to include/linux-private/linux/genetlink.h index b834ef6..e9b8117 100644 --- a/include/linux/genetlink.h +++ b/include/linux-private/linux/genetlink.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef __LINUX_GENERIC_NETLINK_H #define __LINUX_GENERIC_NETLINK_H @@ -21,12 +22,16 @@ struct genlmsghdr { #define GENL_CMD_CAP_DO 0x02 #define GENL_CMD_CAP_DUMP 0x04 #define GENL_CMD_CAP_HASPOL 0x08 +#define GENL_UNS_ADMIN_PERM 0x10 /* * List of reserved static generic netlink identifiers: */ -#define GENL_ID_GENERATE 0 #define GENL_ID_CTRL NLMSG_MIN_TYPE +#define GENL_ID_VFS_DQUOT (NLMSG_MIN_TYPE + 1) +#define GENL_ID_PMCRAID (NLMSG_MIN_TYPE + 2) +/* must be last reserved + 1 */ +#define GENL_START_ALLOC (NLMSG_MIN_TYPE + 3) /************************************************************************** * Controller @@ -43,6 +48,7 @@ enum { CTRL_CMD_NEWMCAST_GRP, CTRL_CMD_DELMCAST_GRP, CTRL_CMD_GETMCAST_GRP, /* unused */ + CTRL_CMD_GETPOLICY, __CTRL_CMD_MAX, }; @@ -57,6 +63,9 @@ enum { CTRL_ATTR_MAXATTR, CTRL_ATTR_OPS, CTRL_ATTR_MCAST_GROUPS, + CTRL_ATTR_POLICY, + CTRL_ATTR_OP_POLICY, + CTRL_ATTR_OP, __CTRL_ATTR_MAX, }; @@ -80,4 +89,15 @@ enum { #define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1) -#endif /* __LINUX_GENERIC_NETLINK_H */ +enum { + CTRL_ATTR_POLICY_UNSPEC, + CTRL_ATTR_POLICY_DO, + CTRL_ATTR_POLICY_DUMP, + + __CTRL_ATTR_POLICY_DUMP_MAX, + CTRL_ATTR_POLICY_DUMP_MAX = __CTRL_ATTR_POLICY_DUMP_MAX - 1 +}; + +#define CTRL_ATTR_POLICY_MAX (__CTRL_ATTR_POLICY_DUMP_MAX - 1) + +#endif /* __LINUX_GENERIC_NETLINK_H */ diff --git a/include/linux-private/linux/hdlc/ioctl.h b/include/linux-private/linux/hdlc/ioctl.h new file mode 100644 index 0000000..b06341a --- /dev/null +++ b/include/linux-private/linux/hdlc/ioctl.h @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __HDLC_IOCTL_H__ +#define __HDLC_IOCTL_H__ + + +#define GENERIC_HDLC_VERSION 4 /* For synchronization with sethdlc utility */ + +#define CLOCK_DEFAULT 0 /* Default setting */ +#define CLOCK_EXT 1 /* External TX and RX clock - DTE */ +#define CLOCK_INT 2 /* Internal TX and RX clock - DCE */ +#define CLOCK_TXINT 3 /* Internal TX and external RX clock */ +#define CLOCK_TXFROMRX 4 /* TX clock derived from external RX clock */ + + +#define ENCODING_DEFAULT 0 /* Default setting */ +#define ENCODING_NRZ 1 +#define ENCODING_NRZI 2 +#define ENCODING_FM_MARK 3 +#define ENCODING_FM_SPACE 4 +#define ENCODING_MANCHESTER 5 + + +#define PARITY_DEFAULT 0 /* Default setting */ +#define PARITY_NONE 1 /* No parity */ +#define PARITY_CRC16_PR0 2 /* CRC16, initial value 0x0000 */ +#define PARITY_CRC16_PR1 3 /* CRC16, initial value 0xFFFF */ +#define PARITY_CRC16_PR0_CCITT 4 /* CRC16, initial 0x0000, ITU-T version */ +#define PARITY_CRC16_PR1_CCITT 5 /* CRC16, initial 0xFFFF, ITU-T version */ +#define PARITY_CRC32_PR0_CCITT 6 /* CRC32, initial value 0x00000000 */ +#define PARITY_CRC32_PR1_CCITT 7 /* CRC32, initial value 0xFFFFFFFF */ + +#define LMI_DEFAULT 0 /* Default setting */ +#define LMI_NONE 1 /* No LMI, all PVCs are static */ +#define LMI_ANSI 2 /* ANSI Annex D */ +#define LMI_CCITT 3 /* ITU-T Annex A */ +#define LMI_CISCO 4 /* The "original" LMI, aka Gang of Four */ + +#ifndef __ASSEMBLY__ + +typedef struct { + unsigned int clock_rate; /* bits per second */ + unsigned int clock_type; /* internal, external, TX-internal etc. */ + unsigned short loopback; +} sync_serial_settings; /* V.35, V.24, X.21 */ + +typedef struct { + unsigned int clock_rate; /* bits per second */ + unsigned int clock_type; /* internal, external, TX-internal etc. */ + unsigned short loopback; + unsigned int slot_map; +} te1_settings; /* T1, E1 */ + +typedef struct { + unsigned short encoding; + unsigned short parity; +} raw_hdlc_proto; + +typedef struct { + unsigned int t391; + unsigned int t392; + unsigned int n391; + unsigned int n392; + unsigned int n393; + unsigned short lmi; + unsigned short dce; /* 1 for DCE (network side) operation */ +} fr_proto; + +typedef struct { + unsigned int dlci; +} fr_proto_pvc; /* for creating/deleting FR PVCs */ + +typedef struct { + unsigned int dlci; + char master[IFNAMSIZ]; /* Name of master FRAD device */ +}fr_proto_pvc_info; /* for returning PVC information only */ + +typedef struct { + unsigned int interval; + unsigned int timeout; +} cisco_proto; + +typedef struct { + unsigned short dce; /* 1 for DCE (network side) operation */ + unsigned int modulo; /* modulo (8 = basic / 128 = extended) */ + unsigned int window; /* frame window size */ + unsigned int t1; /* timeout t1 */ + unsigned int t2; /* timeout t2 */ + unsigned int n2; /* frame retry counter */ +} x25_hdlc_proto; + +/* PPP doesn't need any info now - supply length = 0 to ioctl */ + +#endif /* __ASSEMBLY__ */ +#endif /* __HDLC_IOCTL_H__ */ diff --git a/include/linux-private/linux/if.h b/include/linux-private/linux/if.h new file mode 100644 index 0000000..b287b2a --- /dev/null +++ b/include/linux-private/linux/if.h @@ -0,0 +1,296 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Global definitions for the INET interface module. + * + * Version: @(#)if.h 1.0.2 04/18/93 + * + * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988 + * Ross Biro + * Fred N. van Kempen, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _LINUX_IF_H +#define _LINUX_IF_H + +#include /* for compatibility with glibc */ +#include /* for "__kernel_caddr_t" et al */ +#include /* for "struct sockaddr" et al */ + /* for "__user" et al */ + +#include /* for struct sockaddr. */ + +#if __UAPI_DEF_IF_IFNAMSIZ +#define IFNAMSIZ 16 +#endif /* __UAPI_DEF_IF_IFNAMSIZ */ +#define IFALIASZ 256 +#define ALTIFNAMSIZ 128 +#include + +/* For glibc compatibility. An empty enum does not compile. */ +#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO != 0 || \ + __UAPI_DEF_IF_NET_DEVICE_FLAGS != 0 +/** + * enum net_device_flags - &struct net_device flags + * + * These are the &struct net_device flags, they can be set by drivers, the + * kernel and some can be triggered by userspace. Userspace can query and + * set these flags using userspace utilities but there is also a sysfs + * entry available for all dev flags which can be queried and set. These flags + * are shared for all types of net_devices. The sysfs entries are available + * via /sys/class/net//flags. Flags which can be toggled through sysfs + * are annotated below, note that only a few flags can be toggled and some + * other flags are always preserved from the original net_device flags + * even if you try to set them via sysfs. Flags which are always preserved + * are kept under the flag grouping @IFF_VOLATILE. Flags which are __volatile__ + * are annotated below as such. + * + * You should have a pretty good reason to be extending these flags. + * + * @IFF_UP: interface is up. Can be toggled through sysfs. + * @IFF_BROADCAST: broadcast address valid. Volatile. + * @IFF_DEBUG: turn on debugging. Can be toggled through sysfs. + * @IFF_LOOPBACK: is a loopback net. Volatile. + * @IFF_POINTOPOINT: interface is has p-p link. Volatile. + * @IFF_NOTRAILERS: avoid use of trailers. Can be toggled through sysfs. + * Volatile. + * @IFF_RUNNING: interface RFC2863 OPER_UP. Volatile. + * @IFF_NOARP: no ARP protocol. Can be toggled through sysfs. Volatile. + * @IFF_PROMISC: receive all packets. Can be toggled through sysfs. + * @IFF_ALLMULTI: receive all multicast packets. Can be toggled through + * sysfs. + * @IFF_MASTER: master of a load balancer. Volatile. + * @IFF_SLAVE: slave of a load balancer. Volatile. + * @IFF_MULTICAST: Supports multicast. Can be toggled through sysfs. + * @IFF_PORTSEL: can set media type. Can be toggled through sysfs. + * @IFF_AUTOMEDIA: auto media select active. Can be toggled through sysfs. + * @IFF_DYNAMIC: dialup device with changing addresses. Can be toggled + * through sysfs. + * @IFF_LOWER_UP: driver signals L1 up. Volatile. + * @IFF_DORMANT: driver signals dormant. Volatile. + * @IFF_ECHO: echo sent packets. Volatile. + */ +enum net_device_flags { +/* for compatibility with glibc net/if.h */ +#if __UAPI_DEF_IF_NET_DEVICE_FLAGS + IFF_UP = 1<<0, /* sysfs */ + IFF_BROADCAST = 1<<1, /* __volatile__ */ + IFF_DEBUG = 1<<2, /* sysfs */ + IFF_LOOPBACK = 1<<3, /* __volatile__ */ + IFF_POINTOPOINT = 1<<4, /* __volatile__ */ + IFF_NOTRAILERS = 1<<5, /* sysfs */ + IFF_RUNNING = 1<<6, /* __volatile__ */ + IFF_NOARP = 1<<7, /* sysfs */ + IFF_PROMISC = 1<<8, /* sysfs */ + IFF_ALLMULTI = 1<<9, /* sysfs */ + IFF_MASTER = 1<<10, /* __volatile__ */ + IFF_SLAVE = 1<<11, /* __volatile__ */ + IFF_MULTICAST = 1<<12, /* sysfs */ + IFF_PORTSEL = 1<<13, /* sysfs */ + IFF_AUTOMEDIA = 1<<14, /* sysfs */ + IFF_DYNAMIC = 1<<15, /* sysfs */ +#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */ +#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO + IFF_LOWER_UP = 1<<16, /* __volatile__ */ + IFF_DORMANT = 1<<17, /* __volatile__ */ + IFF_ECHO = 1<<18, /* __volatile__ */ +#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */ +}; +#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO != 0 || __UAPI_DEF_IF_NET_DEVICE_FLAGS != 0 */ + +/* for compatibility with glibc net/if.h */ +#if __UAPI_DEF_IF_NET_DEVICE_FLAGS +#define IFF_UP IFF_UP +#define IFF_BROADCAST IFF_BROADCAST +#define IFF_DEBUG IFF_DEBUG +#define IFF_LOOPBACK IFF_LOOPBACK +#define IFF_POINTOPOINT IFF_POINTOPOINT +#define IFF_NOTRAILERS IFF_NOTRAILERS +#define IFF_RUNNING IFF_RUNNING +#define IFF_NOARP IFF_NOARP +#define IFF_PROMISC IFF_PROMISC +#define IFF_ALLMULTI IFF_ALLMULTI +#define IFF_MASTER IFF_MASTER +#define IFF_SLAVE IFF_SLAVE +#define IFF_MULTICAST IFF_MULTICAST +#define IFF_PORTSEL IFF_PORTSEL +#define IFF_AUTOMEDIA IFF_AUTOMEDIA +#define IFF_DYNAMIC IFF_DYNAMIC +#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */ + +#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO +#define IFF_LOWER_UP IFF_LOWER_UP +#define IFF_DORMANT IFF_DORMANT +#define IFF_ECHO IFF_ECHO +#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */ + +#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\ + IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT) + +#define IF_GET_IFACE 0x0001 /* for querying only */ +#define IF_GET_PROTO 0x0002 + +/* For definitions see hdlc.h */ +#define IF_IFACE_V35 0x1000 /* V.35 serial interface */ +#define IF_IFACE_V24 0x1001 /* V.24 serial interface */ +#define IF_IFACE_X21 0x1002 /* X.21 serial interface */ +#define IF_IFACE_T1 0x1003 /* T1 telco serial interface */ +#define IF_IFACE_E1 0x1004 /* E1 telco serial interface */ +#define IF_IFACE_SYNC_SERIAL 0x1005 /* can't be set by software */ +#define IF_IFACE_X21D 0x1006 /* X.21 Dual Clocking (FarSite) */ + +/* For definitions see hdlc.h */ +#define IF_PROTO_HDLC 0x2000 /* raw HDLC protocol */ +#define IF_PROTO_PPP 0x2001 /* PPP protocol */ +#define IF_PROTO_CISCO 0x2002 /* Cisco HDLC protocol */ +#define IF_PROTO_FR 0x2003 /* Frame Relay protocol */ +#define IF_PROTO_FR_ADD_PVC 0x2004 /* Create FR PVC */ +#define IF_PROTO_FR_DEL_PVC 0x2005 /* Delete FR PVC */ +#define IF_PROTO_X25 0x2006 /* X.25 */ +#define IF_PROTO_HDLC_ETH 0x2007 /* raw HDLC, Ethernet emulation */ +#define IF_PROTO_FR_ADD_ETH_PVC 0x2008 /* Create FR Ethernet-bridged PVC */ +#define IF_PROTO_FR_DEL_ETH_PVC 0x2009 /* Delete FR Ethernet-bridged PVC */ +#define IF_PROTO_FR_PVC 0x200A /* for reading PVC status */ +#define IF_PROTO_FR_ETH_PVC 0x200B +#define IF_PROTO_RAW 0x200C /* RAW Socket */ + +/* RFC 2863 operational status */ +enum { + IF_OPER_UNKNOWN, + IF_OPER_NOTPRESENT, + IF_OPER_DOWN, + IF_OPER_LOWERLAYERDOWN, + IF_OPER_TESTING, + IF_OPER_DORMANT, + IF_OPER_UP, +}; + +/* link modes */ +enum { + IF_LINK_MODE_DEFAULT, + IF_LINK_MODE_DORMANT, /* limit upward transition to dormant */ + IF_LINK_MODE_TESTING, /* limit upward transition to testing */ +}; + +/* + * Device mapping structure. I'd just gone off and designed a + * beautiful scheme using only loadable modules with arguments + * for driver options and along come the PCMCIA people 8) + * + * Ah well. The get() side of this is good for WDSETUP, and it'll + * be handy for debugging things. The set side is fine for now and + * being very small might be worth keeping for clean configuration. + */ + +/* for compatibility with glibc net/if.h */ +#if __UAPI_DEF_IF_IFMAP +struct ifmap { + unsigned long mem_start; + unsigned long mem_end; + unsigned short base_addr; + unsigned char irq; + unsigned char dma; + unsigned char port; + /* 3 bytes spare */ +}; +#endif /* __UAPI_DEF_IF_IFMAP */ + +struct if_settings { + unsigned int type; /* Type of physical device or protocol */ + unsigned int size; /* Size of the data allocated by the caller */ + union { + /* {atm/eth/dsl}_settings anyone ? */ + raw_hdlc_proto *raw_hdlc; + cisco_proto *cisco; + fr_proto *fr; + fr_proto_pvc *fr_pvc; + fr_proto_pvc_info *fr_pvc_info; + x25_hdlc_proto *x25; + + /* interface settings */ + sync_serial_settings *sync; + te1_settings *te1; + } ifs_ifsu; +}; + +/* + * Interface request structure used for socket + * ioctl's. All interface ioctl's must have parameter + * definitions which begin with ifr_name. The + * remainder may be interface specific. + */ + +/* for compatibility with glibc net/if.h */ +#if __UAPI_DEF_IF_IFREQ +struct ifreq { +#define IFHWADDRLEN 6 + union + { + char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + } ifr_ifrn; + + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; + short ifru_flags; + int ifru_ivalue; + int ifru_mtu; + struct ifmap ifru_map; + char ifru_slave[IFNAMSIZ]; /* Just fits the size */ + char ifru_newname[IFNAMSIZ]; + void * ifru_data; + struct if_settings ifru_settings; + } ifr_ifru; +}; +#endif /* __UAPI_DEF_IF_IFREQ */ + +#define ifr_name ifr_ifrn.ifrn_name /* interface name */ +#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ +#define ifr_addr ifr_ifru.ifru_addr /* address */ +#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */ +#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ +#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ +#define ifr_flags ifr_ifru.ifru_flags /* flags */ +#define ifr_metric ifr_ifru.ifru_ivalue /* metric */ +#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ +#define ifr_map ifr_ifru.ifru_map /* device map */ +#define ifr_slave ifr_ifru.ifru_slave /* slave device */ +#define ifr_data ifr_ifru.ifru_data /* for use by interface */ +#define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */ +#define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */ +#define ifr_qlen ifr_ifru.ifru_ivalue /* Queue length */ +#define ifr_newname ifr_ifru.ifru_newname /* New name */ +#define ifr_settings ifr_ifru.ifru_settings /* Device/proto settings*/ + +/* + * Structure used in SIOCGIFCONF request. + * Used to retrieve interface configuration + * for machine (useful for programs which + * must know all networks accessible). + */ + +/* for compatibility with glibc net/if.h */ +#if __UAPI_DEF_IF_IFCONF +struct ifconf { + int ifc_len; /* size of buffer */ + union { + char *ifcu_buf; + struct ifreq *ifcu_req; + } ifc_ifcu; +}; +#endif /* __UAPI_DEF_IF_IFCONF */ + +#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ +#define ifc_req ifc_ifcu.ifcu_req /* array of structures */ + +#endif /* _LINUX_IF_H */ diff --git a/include/linux/if_addr.h b/include/linux-private/linux/if_addr.h similarity index 58% rename from include/linux/if_addr.h rename to include/linux-private/linux/if_addr.h index c355522..d6db3ff 100644 --- a/include/linux/if_addr.h +++ b/include/linux-private/linux/if_addr.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef __LINUX_IF_ADDR_H #define __LINUX_IF_ADDR_H @@ -18,6 +19,9 @@ struct ifaddrmsg { * It makes no difference for normally configured broadcast interfaces, * but for point-to-point IFA_ADDRESS is DESTINATION address, * local address is supplied in IFA_LOCAL attribute. + * + * IFA_FLAGS is a u32 attribute that extends the u8 field ifa_flags. + * If present, the value from struct ifaddrmsg will be ignored. */ enum { IFA_UNSPEC, @@ -28,6 +32,10 @@ enum { IFA_ANYCAST, IFA_CACHEINFO, IFA_MULTICAST, + IFA_FLAGS, + IFA_RT_PRIORITY, /* u32, priority/metric for prefix route */ + IFA_TARGET_NETNSID, + IFA_PROTO, /* u8, address protocol */ __IFA_MAX, }; @@ -44,6 +52,10 @@ enum { #define IFA_F_DEPRECATED 0x20 #define IFA_F_TENTATIVE 0x40 #define IFA_F_PERMANENT 0x80 +#define IFA_F_MANAGETEMPADDR 0x100 +#define IFA_F_NOPREFIXROUTE 0x200 +#define IFA_F_MCAUTOJOIN 0x400 +#define IFA_F_STABLE_PRIVACY 0x800 struct ifa_cacheinfo { __u32 ifa_prefered; @@ -52,4 +64,14 @@ struct ifa_cacheinfo { __u32 tstamp; /* updated timestamp, hundredths of seconds */ }; +/* backwards compatibility for userspace */ +#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg)))) +#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg)) + +/* ifa_proto */ +#define IFAPROT_UNSPEC 0 +#define IFAPROT_KERNEL_LO 1 /* loopback */ +#define IFAPROT_KERNEL_RA 2 /* set by kernel from router announcement */ +#define IFAPROT_KERNEL_LL 3 /* link-local set by kernel */ + #endif diff --git a/include/linux/if_arp.h b/include/linux-private/linux/if_arp.h similarity index 86% rename from include/linux/if_arp.h rename to include/linux-private/linux/if_arp.h index e04cd2c..12d06bb 100644 --- a/include/linux/if_arp.h +++ b/include/linux-private/linux/if_arp.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ /* * INET An implementation of the TCP/IP protocol suite for the LINUX * operating system. INET is implemented using the BSD Socket @@ -53,12 +54,14 @@ #define ARPHRD_X25 271 /* CCITT X.25 */ #define ARPHRD_HWX25 272 /* Boards with X.25 in firmware */ #define ARPHRD_CAN 280 /* Controller Area Network */ +#define ARPHRD_MCTP 290 #define ARPHRD_PPP 512 #define ARPHRD_CISCO 513 /* Cisco HDLC */ #define ARPHRD_HDLC ARPHRD_CISCO #define ARPHRD_LAPB 516 /* LAPB */ #define ARPHRD_DDCMP 517 /* Digital's DDCMP protocol */ #define ARPHRD_RAWHDLC 518 /* Raw HDLC */ +#define ARPHRD_RAWIP 519 /* Raw IP */ #define ARPHRD_TUNNEL 768 /* IPIP tunnel */ #define ARPHRD_TUNNEL6 769 /* IP6IP6 tunnel */ @@ -87,10 +90,15 @@ #define ARPHRD_IEEE80211_PRISM 802 /* IEEE 802.11 + Prism2 header */ #define ARPHRD_IEEE80211_RADIOTAP 803 /* IEEE 802.11 + radiotap header */ #define ARPHRD_IEEE802154 804 +#define ARPHRD_IEEE802154_MONITOR 805 /* IEEE 802.15.4 network monitor */ #define ARPHRD_PHONET 820 /* PhoNet media type */ #define ARPHRD_PHONET_PIPE 821 /* PhoNet pipe header */ #define ARPHRD_CAIF 822 /* CAIF media type */ +#define ARPHRD_IP6GRE 823 /* GRE over IPv6 */ +#define ARPHRD_NETLINK 824 /* Netlink header */ +#define ARPHRD_6LOWPAN 825 /* IPv6 over LoWPAN */ +#define ARPHRD_VSOCKMON 826 /* Vsock monitor header */ #define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */ #define ARPHRD_NONE 0xFFFE /* zero header length */ @@ -107,18 +115,18 @@ /* ARP ioctl request. */ struct arpreq { - struct sockaddr arp_pa; /* protocol address */ - struct sockaddr arp_ha; /* hardware address */ - int arp_flags; /* flags */ - struct sockaddr arp_netmask; /* netmask (only for proxy arps) */ - char arp_dev[16]; + struct sockaddr arp_pa; /* protocol address */ + struct sockaddr arp_ha; /* hardware address */ + int arp_flags; /* flags */ + struct sockaddr arp_netmask; /* netmask (only for proxy arps) */ + char arp_dev[IFNAMSIZ]; }; struct arpreq_old { - struct sockaddr arp_pa; /* protocol address */ - struct sockaddr arp_ha; /* hardware address */ - int arp_flags; /* flags */ - struct sockaddr arp_netmask; /* netmask (only for proxy arps) */ + struct sockaddr arp_pa; /* protocol address */ + struct sockaddr arp_ha; /* hardware address */ + int arp_flags; /* flags */ + struct sockaddr arp_netmask; /* netmask (only for proxy arps) */ }; /* ARP Flag values. */ @@ -153,4 +161,5 @@ struct arphdr { }; -#endif /* _LINUX_IF_ARP_H */ + +#endif /* _LINUX_IF_ARP_H */ diff --git a/include/linux-private/linux/if_bridge.h b/include/linux-private/linux/if_bridge.h new file mode 100644 index 0000000..e3d55b1 --- /dev/null +++ b/include/linux-private/linux/if_bridge.h @@ -0,0 +1,839 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * Linux ethernet bridge + * + * Authors: + * Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _LINUX_IF_BRIDGE_H +#define _LINUX_IF_BRIDGE_H + +#include +#include +#include + +#define SYSFS_BRIDGE_ATTR "bridge" +#define SYSFS_BRIDGE_FDB "brforward" +#define SYSFS_BRIDGE_PORT_SUBDIR "brif" +#define SYSFS_BRIDGE_PORT_ATTR "brport" +#define SYSFS_BRIDGE_PORT_LINK "bridge" + +#define BRCTL_VERSION 1 + +#define BRCTL_GET_VERSION 0 +#define BRCTL_GET_BRIDGES 1 +#define BRCTL_ADD_BRIDGE 2 +#define BRCTL_DEL_BRIDGE 3 +#define BRCTL_ADD_IF 4 +#define BRCTL_DEL_IF 5 +#define BRCTL_GET_BRIDGE_INFO 6 +#define BRCTL_GET_PORT_LIST 7 +#define BRCTL_SET_BRIDGE_FORWARD_DELAY 8 +#define BRCTL_SET_BRIDGE_HELLO_TIME 9 +#define BRCTL_SET_BRIDGE_MAX_AGE 10 +#define BRCTL_SET_AGEING_TIME 11 +#define BRCTL_SET_GC_INTERVAL 12 +#define BRCTL_GET_PORT_INFO 13 +#define BRCTL_SET_BRIDGE_STP_STATE 14 +#define BRCTL_SET_BRIDGE_PRIORITY 15 +#define BRCTL_SET_PORT_PRIORITY 16 +#define BRCTL_SET_PATH_COST 17 +#define BRCTL_GET_FDB_ENTRIES 18 + +#define BR_STATE_DISABLED 0 +#define BR_STATE_LISTENING 1 +#define BR_STATE_LEARNING 2 +#define BR_STATE_FORWARDING 3 +#define BR_STATE_BLOCKING 4 + +struct __bridge_info { + __u64 designated_root; + __u64 bridge_id; + __u32 root_path_cost; + __u32 max_age; + __u32 hello_time; + __u32 forward_delay; + __u32 bridge_max_age; + __u32 bridge_hello_time; + __u32 bridge_forward_delay; + __u8 topology_change; + __u8 topology_change_detected; + __u8 root_port; + __u8 stp_enabled; + __u32 ageing_time; + __u32 gc_interval; + __u32 hello_timer_value; + __u32 tcn_timer_value; + __u32 topology_change_timer_value; + __u32 gc_timer_value; +}; + +struct __port_info { + __u64 designated_root; + __u64 designated_bridge; + __u16 port_id; + __u16 designated_port; + __u32 path_cost; + __u32 designated_cost; + __u8 state; + __u8 top_change_ack; + __u8 config_pending; + __u8 unused0; + __u32 message_age_timer_value; + __u32 forward_delay_timer_value; + __u32 hold_timer_value; +}; + +struct __fdb_entry { + __u8 mac_addr[ETH_ALEN]; + __u8 port_no; + __u8 is_local; + __u32 ageing_timer_value; + __u8 port_hi; + __u8 pad0; + __u16 unused; +}; + +/* Bridge Flags */ +#define BRIDGE_FLAGS_MASTER 1 /* Bridge command to/from master */ +#define BRIDGE_FLAGS_SELF 2 /* Bridge command to/from lowerdev */ + +#define BRIDGE_MODE_VEB 0 /* Default loopback mode */ +#define BRIDGE_MODE_VEPA 1 /* 802.1Qbg defined VEPA mode */ +#define BRIDGE_MODE_UNDEF 0xFFFF /* mode undefined */ + +/* Bridge management nested attributes + * [IFLA_AF_SPEC] = { + * [IFLA_BRIDGE_FLAGS] + * [IFLA_BRIDGE_MODE] + * [IFLA_BRIDGE_VLAN_INFO] + * } + */ +enum { + IFLA_BRIDGE_FLAGS, + IFLA_BRIDGE_MODE, + IFLA_BRIDGE_VLAN_INFO, + IFLA_BRIDGE_VLAN_TUNNEL_INFO, + IFLA_BRIDGE_MRP, + IFLA_BRIDGE_CFM, + IFLA_BRIDGE_MST, + __IFLA_BRIDGE_MAX, +}; +#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1) + +#define BRIDGE_VLAN_INFO_MASTER (1<<0) /* Operate on Bridge device as well */ +#define BRIDGE_VLAN_INFO_PVID (1<<1) /* VLAN is PVID, ingress untagged */ +#define BRIDGE_VLAN_INFO_UNTAGGED (1<<2) /* VLAN egresses untagged */ +#define BRIDGE_VLAN_INFO_RANGE_BEGIN (1<<3) /* VLAN is start of vlan range */ +#define BRIDGE_VLAN_INFO_RANGE_END (1<<4) /* VLAN is end of vlan range */ +#define BRIDGE_VLAN_INFO_BRENTRY (1<<5) /* Global bridge VLAN entry */ +#define BRIDGE_VLAN_INFO_ONLY_OPTS (1<<6) /* Skip create/delete/flags */ + +struct bridge_vlan_info { + __u16 flags; + __u16 vid; +}; + +enum { + IFLA_BRIDGE_VLAN_TUNNEL_UNSPEC, + IFLA_BRIDGE_VLAN_TUNNEL_ID, + IFLA_BRIDGE_VLAN_TUNNEL_VID, + IFLA_BRIDGE_VLAN_TUNNEL_FLAGS, + __IFLA_BRIDGE_VLAN_TUNNEL_MAX, +}; + +#define IFLA_BRIDGE_VLAN_TUNNEL_MAX (__IFLA_BRIDGE_VLAN_TUNNEL_MAX - 1) + +struct bridge_vlan_xstats { + __u64 rx_bytes; + __u64 rx_packets; + __u64 tx_bytes; + __u64 tx_packets; + __u16 vid; + __u16 flags; + __u32 pad2; +}; + +enum { + IFLA_BRIDGE_MRP_UNSPEC, + IFLA_BRIDGE_MRP_INSTANCE, + IFLA_BRIDGE_MRP_PORT_STATE, + IFLA_BRIDGE_MRP_PORT_ROLE, + IFLA_BRIDGE_MRP_RING_STATE, + IFLA_BRIDGE_MRP_RING_ROLE, + IFLA_BRIDGE_MRP_START_TEST, + IFLA_BRIDGE_MRP_INFO, + IFLA_BRIDGE_MRP_IN_ROLE, + IFLA_BRIDGE_MRP_IN_STATE, + IFLA_BRIDGE_MRP_START_IN_TEST, + __IFLA_BRIDGE_MRP_MAX, +}; + +#define IFLA_BRIDGE_MRP_MAX (__IFLA_BRIDGE_MRP_MAX - 1) + +enum { + IFLA_BRIDGE_MRP_INSTANCE_UNSPEC, + IFLA_BRIDGE_MRP_INSTANCE_RING_ID, + IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX, + IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX, + IFLA_BRIDGE_MRP_INSTANCE_PRIO, + __IFLA_BRIDGE_MRP_INSTANCE_MAX, +}; + +#define IFLA_BRIDGE_MRP_INSTANCE_MAX (__IFLA_BRIDGE_MRP_INSTANCE_MAX - 1) + +enum { + IFLA_BRIDGE_MRP_PORT_STATE_UNSPEC, + IFLA_BRIDGE_MRP_PORT_STATE_STATE, + __IFLA_BRIDGE_MRP_PORT_STATE_MAX, +}; + +#define IFLA_BRIDGE_MRP_PORT_STATE_MAX (__IFLA_BRIDGE_MRP_PORT_STATE_MAX - 1) + +enum { + IFLA_BRIDGE_MRP_PORT_ROLE_UNSPEC, + IFLA_BRIDGE_MRP_PORT_ROLE_ROLE, + __IFLA_BRIDGE_MRP_PORT_ROLE_MAX, +}; + +#define IFLA_BRIDGE_MRP_PORT_ROLE_MAX (__IFLA_BRIDGE_MRP_PORT_ROLE_MAX - 1) + +enum { + IFLA_BRIDGE_MRP_RING_STATE_UNSPEC, + IFLA_BRIDGE_MRP_RING_STATE_RING_ID, + IFLA_BRIDGE_MRP_RING_STATE_STATE, + __IFLA_BRIDGE_MRP_RING_STATE_MAX, +}; + +#define IFLA_BRIDGE_MRP_RING_STATE_MAX (__IFLA_BRIDGE_MRP_RING_STATE_MAX - 1) + +enum { + IFLA_BRIDGE_MRP_RING_ROLE_UNSPEC, + IFLA_BRIDGE_MRP_RING_ROLE_RING_ID, + IFLA_BRIDGE_MRP_RING_ROLE_ROLE, + __IFLA_BRIDGE_MRP_RING_ROLE_MAX, +}; + +#define IFLA_BRIDGE_MRP_RING_ROLE_MAX (__IFLA_BRIDGE_MRP_RING_ROLE_MAX - 1) + +enum { + IFLA_BRIDGE_MRP_START_TEST_UNSPEC, + IFLA_BRIDGE_MRP_START_TEST_RING_ID, + IFLA_BRIDGE_MRP_START_TEST_INTERVAL, + IFLA_BRIDGE_MRP_START_TEST_MAX_MISS, + IFLA_BRIDGE_MRP_START_TEST_PERIOD, + IFLA_BRIDGE_MRP_START_TEST_MONITOR, + __IFLA_BRIDGE_MRP_START_TEST_MAX, +}; + +#define IFLA_BRIDGE_MRP_START_TEST_MAX (__IFLA_BRIDGE_MRP_START_TEST_MAX - 1) + +enum { + IFLA_BRIDGE_MRP_INFO_UNSPEC, + IFLA_BRIDGE_MRP_INFO_RING_ID, + IFLA_BRIDGE_MRP_INFO_P_IFINDEX, + IFLA_BRIDGE_MRP_INFO_S_IFINDEX, + IFLA_BRIDGE_MRP_INFO_PRIO, + IFLA_BRIDGE_MRP_INFO_RING_STATE, + IFLA_BRIDGE_MRP_INFO_RING_ROLE, + IFLA_BRIDGE_MRP_INFO_TEST_INTERVAL, + IFLA_BRIDGE_MRP_INFO_TEST_MAX_MISS, + IFLA_BRIDGE_MRP_INFO_TEST_MONITOR, + IFLA_BRIDGE_MRP_INFO_I_IFINDEX, + IFLA_BRIDGE_MRP_INFO_IN_STATE, + IFLA_BRIDGE_MRP_INFO_IN_ROLE, + IFLA_BRIDGE_MRP_INFO_IN_TEST_INTERVAL, + IFLA_BRIDGE_MRP_INFO_IN_TEST_MAX_MISS, + __IFLA_BRIDGE_MRP_INFO_MAX, +}; + +#define IFLA_BRIDGE_MRP_INFO_MAX (__IFLA_BRIDGE_MRP_INFO_MAX - 1) + +enum { + IFLA_BRIDGE_MRP_IN_STATE_UNSPEC, + IFLA_BRIDGE_MRP_IN_STATE_IN_ID, + IFLA_BRIDGE_MRP_IN_STATE_STATE, + __IFLA_BRIDGE_MRP_IN_STATE_MAX, +}; + +#define IFLA_BRIDGE_MRP_IN_STATE_MAX (__IFLA_BRIDGE_MRP_IN_STATE_MAX - 1) + +enum { + IFLA_BRIDGE_MRP_IN_ROLE_UNSPEC, + IFLA_BRIDGE_MRP_IN_ROLE_RING_ID, + IFLA_BRIDGE_MRP_IN_ROLE_IN_ID, + IFLA_BRIDGE_MRP_IN_ROLE_ROLE, + IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX, + __IFLA_BRIDGE_MRP_IN_ROLE_MAX, +}; + +#define IFLA_BRIDGE_MRP_IN_ROLE_MAX (__IFLA_BRIDGE_MRP_IN_ROLE_MAX - 1) + +enum { + IFLA_BRIDGE_MRP_START_IN_TEST_UNSPEC, + IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID, + IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL, + IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS, + IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD, + __IFLA_BRIDGE_MRP_START_IN_TEST_MAX, +}; + +#define IFLA_BRIDGE_MRP_START_IN_TEST_MAX (__IFLA_BRIDGE_MRP_START_IN_TEST_MAX - 1) + +struct br_mrp_instance { + __u32 ring_id; + __u32 p_ifindex; + __u32 s_ifindex; + __u16 prio; +}; + +struct br_mrp_ring_state { + __u32 ring_id; + __u32 ring_state; +}; + +struct br_mrp_ring_role { + __u32 ring_id; + __u32 ring_role; +}; + +struct br_mrp_start_test { + __u32 ring_id; + __u32 interval; + __u32 max_miss; + __u32 period; + __u32 monitor; +}; + +struct br_mrp_in_state { + __u32 in_state; + __u16 in_id; +}; + +struct br_mrp_in_role { + __u32 ring_id; + __u32 in_role; + __u32 i_ifindex; + __u16 in_id; +}; + +struct br_mrp_start_in_test { + __u32 interval; + __u32 max_miss; + __u32 period; + __u16 in_id; +}; + +enum { + IFLA_BRIDGE_CFM_UNSPEC, + IFLA_BRIDGE_CFM_MEP_CREATE, + IFLA_BRIDGE_CFM_MEP_DELETE, + IFLA_BRIDGE_CFM_MEP_CONFIG, + IFLA_BRIDGE_CFM_CC_CONFIG, + IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD, + IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE, + IFLA_BRIDGE_CFM_CC_RDI, + IFLA_BRIDGE_CFM_CC_CCM_TX, + IFLA_BRIDGE_CFM_MEP_CREATE_INFO, + IFLA_BRIDGE_CFM_MEP_CONFIG_INFO, + IFLA_BRIDGE_CFM_CC_CONFIG_INFO, + IFLA_BRIDGE_CFM_CC_RDI_INFO, + IFLA_BRIDGE_CFM_CC_CCM_TX_INFO, + IFLA_BRIDGE_CFM_CC_PEER_MEP_INFO, + IFLA_BRIDGE_CFM_MEP_STATUS_INFO, + IFLA_BRIDGE_CFM_CC_PEER_STATUS_INFO, + __IFLA_BRIDGE_CFM_MAX, +}; + +#define IFLA_BRIDGE_CFM_MAX (__IFLA_BRIDGE_CFM_MAX - 1) + +enum { + IFLA_BRIDGE_CFM_MEP_CREATE_UNSPEC, + IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE, + IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN, + IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION, + IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX, + __IFLA_BRIDGE_CFM_MEP_CREATE_MAX, +}; + +#define IFLA_BRIDGE_CFM_MEP_CREATE_MAX (__IFLA_BRIDGE_CFM_MEP_CREATE_MAX - 1) + +enum { + IFLA_BRIDGE_CFM_MEP_DELETE_UNSPEC, + IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE, + __IFLA_BRIDGE_CFM_MEP_DELETE_MAX, +}; + +#define IFLA_BRIDGE_CFM_MEP_DELETE_MAX (__IFLA_BRIDGE_CFM_MEP_DELETE_MAX - 1) + +enum { + IFLA_BRIDGE_CFM_MEP_CONFIG_UNSPEC, + IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE, + IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC, + IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL, + IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID, + __IFLA_BRIDGE_CFM_MEP_CONFIG_MAX, +}; + +#define IFLA_BRIDGE_CFM_MEP_CONFIG_MAX (__IFLA_BRIDGE_CFM_MEP_CONFIG_MAX - 1) + +enum { + IFLA_BRIDGE_CFM_CC_CONFIG_UNSPEC, + IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE, + IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE, + IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL, + IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID, + __IFLA_BRIDGE_CFM_CC_CONFIG_MAX, +}; + +#define IFLA_BRIDGE_CFM_CC_CONFIG_MAX (__IFLA_BRIDGE_CFM_CC_CONFIG_MAX - 1) + +enum { + IFLA_BRIDGE_CFM_CC_PEER_MEP_UNSPEC, + IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE, + IFLA_BRIDGE_CFM_CC_PEER_MEPID, + __IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX, +}; + +#define IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX (__IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX - 1) + +enum { + IFLA_BRIDGE_CFM_CC_RDI_UNSPEC, + IFLA_BRIDGE_CFM_CC_RDI_INSTANCE, + IFLA_BRIDGE_CFM_CC_RDI_RDI, + __IFLA_BRIDGE_CFM_CC_RDI_MAX, +}; + +#define IFLA_BRIDGE_CFM_CC_RDI_MAX (__IFLA_BRIDGE_CFM_CC_RDI_MAX - 1) + +enum { + IFLA_BRIDGE_CFM_CC_CCM_TX_UNSPEC, + IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE, + IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC, + IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE, + IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD, + IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV, + IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE, + IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV, + IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE, + __IFLA_BRIDGE_CFM_CC_CCM_TX_MAX, +}; + +#define IFLA_BRIDGE_CFM_CC_CCM_TX_MAX (__IFLA_BRIDGE_CFM_CC_CCM_TX_MAX - 1) + +enum { + IFLA_BRIDGE_CFM_MEP_STATUS_UNSPEC, + IFLA_BRIDGE_CFM_MEP_STATUS_INSTANCE, + IFLA_BRIDGE_CFM_MEP_STATUS_OPCODE_UNEXP_SEEN, + IFLA_BRIDGE_CFM_MEP_STATUS_VERSION_UNEXP_SEEN, + IFLA_BRIDGE_CFM_MEP_STATUS_RX_LEVEL_LOW_SEEN, + __IFLA_BRIDGE_CFM_MEP_STATUS_MAX, +}; + +#define IFLA_BRIDGE_CFM_MEP_STATUS_MAX (__IFLA_BRIDGE_CFM_MEP_STATUS_MAX - 1) + +enum { + IFLA_BRIDGE_CFM_CC_PEER_STATUS_UNSPEC, + IFLA_BRIDGE_CFM_CC_PEER_STATUS_INSTANCE, + IFLA_BRIDGE_CFM_CC_PEER_STATUS_PEER_MEPID, + IFLA_BRIDGE_CFM_CC_PEER_STATUS_CCM_DEFECT, + IFLA_BRIDGE_CFM_CC_PEER_STATUS_RDI, + IFLA_BRIDGE_CFM_CC_PEER_STATUS_PORT_TLV_VALUE, + IFLA_BRIDGE_CFM_CC_PEER_STATUS_IF_TLV_VALUE, + IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEEN, + IFLA_BRIDGE_CFM_CC_PEER_STATUS_TLV_SEEN, + IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEQ_UNEXP_SEEN, + __IFLA_BRIDGE_CFM_CC_PEER_STATUS_MAX, +}; + +#define IFLA_BRIDGE_CFM_CC_PEER_STATUS_MAX (__IFLA_BRIDGE_CFM_CC_PEER_STATUS_MAX - 1) + +enum { + IFLA_BRIDGE_MST_UNSPEC, + IFLA_BRIDGE_MST_ENTRY, + __IFLA_BRIDGE_MST_MAX, +}; +#define IFLA_BRIDGE_MST_MAX (__IFLA_BRIDGE_MST_MAX - 1) + +enum { + IFLA_BRIDGE_MST_ENTRY_UNSPEC, + IFLA_BRIDGE_MST_ENTRY_MSTI, + IFLA_BRIDGE_MST_ENTRY_STATE, + __IFLA_BRIDGE_MST_ENTRY_MAX, +}; +#define IFLA_BRIDGE_MST_ENTRY_MAX (__IFLA_BRIDGE_MST_ENTRY_MAX - 1) + +struct bridge_stp_xstats { + __u64 transition_blk; + __u64 transition_fwd; + __u64 rx_bpdu; + __u64 tx_bpdu; + __u64 rx_tcn; + __u64 tx_tcn; +}; + +/* Bridge vlan RTM header */ +struct br_vlan_msg { + __u8 family; + __u8 reserved1; + __u16 reserved2; + __u32 ifindex; +}; + +enum { + BRIDGE_VLANDB_DUMP_UNSPEC, + BRIDGE_VLANDB_DUMP_FLAGS, + __BRIDGE_VLANDB_DUMP_MAX, +}; +#define BRIDGE_VLANDB_DUMP_MAX (__BRIDGE_VLANDB_DUMP_MAX - 1) + +/* flags used in BRIDGE_VLANDB_DUMP_FLAGS attribute to affect dumps */ +#define BRIDGE_VLANDB_DUMPF_STATS (1 << 0) /* Include stats in the dump */ +#define BRIDGE_VLANDB_DUMPF_GLOBAL (1 << 1) /* Dump global vlan options only */ + +/* Bridge vlan RTM attributes + * [BRIDGE_VLANDB_ENTRY] = { + * [BRIDGE_VLANDB_ENTRY_INFO] + * ... + * } + * [BRIDGE_VLANDB_GLOBAL_OPTIONS] = { + * [BRIDGE_VLANDB_GOPTS_ID] + * ... + * } + */ +enum { + BRIDGE_VLANDB_UNSPEC, + BRIDGE_VLANDB_ENTRY, + BRIDGE_VLANDB_GLOBAL_OPTIONS, + __BRIDGE_VLANDB_MAX, +}; +#define BRIDGE_VLANDB_MAX (__BRIDGE_VLANDB_MAX - 1) + +enum { + BRIDGE_VLANDB_ENTRY_UNSPEC, + BRIDGE_VLANDB_ENTRY_INFO, + BRIDGE_VLANDB_ENTRY_RANGE, + BRIDGE_VLANDB_ENTRY_STATE, + BRIDGE_VLANDB_ENTRY_TUNNEL_INFO, + BRIDGE_VLANDB_ENTRY_STATS, + BRIDGE_VLANDB_ENTRY_MCAST_ROUTER, + BRIDGE_VLANDB_ENTRY_MCAST_N_GROUPS, + BRIDGE_VLANDB_ENTRY_MCAST_MAX_GROUPS, + BRIDGE_VLANDB_ENTRY_NEIGH_SUPPRESS, + __BRIDGE_VLANDB_ENTRY_MAX, +}; +#define BRIDGE_VLANDB_ENTRY_MAX (__BRIDGE_VLANDB_ENTRY_MAX - 1) + +/* [BRIDGE_VLANDB_ENTRY] = { + * [BRIDGE_VLANDB_ENTRY_TUNNEL_INFO] = { + * [BRIDGE_VLANDB_TINFO_ID] + * ... + * } + * } + */ +enum { + BRIDGE_VLANDB_TINFO_UNSPEC, + BRIDGE_VLANDB_TINFO_ID, + BRIDGE_VLANDB_TINFO_CMD, + __BRIDGE_VLANDB_TINFO_MAX, +}; +#define BRIDGE_VLANDB_TINFO_MAX (__BRIDGE_VLANDB_TINFO_MAX - 1) + +/* [BRIDGE_VLANDB_ENTRY] = { + * [BRIDGE_VLANDB_ENTRY_STATS] = { + * [BRIDGE_VLANDB_STATS_RX_BYTES] + * ... + * } + * ... + * } + */ +enum { + BRIDGE_VLANDB_STATS_UNSPEC, + BRIDGE_VLANDB_STATS_RX_BYTES, + BRIDGE_VLANDB_STATS_RX_PACKETS, + BRIDGE_VLANDB_STATS_TX_BYTES, + BRIDGE_VLANDB_STATS_TX_PACKETS, + BRIDGE_VLANDB_STATS_PAD, + __BRIDGE_VLANDB_STATS_MAX, +}; +#define BRIDGE_VLANDB_STATS_MAX (__BRIDGE_VLANDB_STATS_MAX - 1) + +enum { + BRIDGE_VLANDB_GOPTS_UNSPEC, + BRIDGE_VLANDB_GOPTS_ID, + BRIDGE_VLANDB_GOPTS_RANGE, + BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING, + BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION, + BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION, + BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT, + BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT, + BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL, + BRIDGE_VLANDB_GOPTS_PAD, + BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL, + BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL, + BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL, + BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL, + BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL, + BRIDGE_VLANDB_GOPTS_MCAST_QUERIER, + BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS, + BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_STATE, + BRIDGE_VLANDB_GOPTS_MSTI, + __BRIDGE_VLANDB_GOPTS_MAX +}; +#define BRIDGE_VLANDB_GOPTS_MAX (__BRIDGE_VLANDB_GOPTS_MAX - 1) + +/* Bridge multicast database attributes + * [MDBA_MDB] = { + * [MDBA_MDB_ENTRY] = { + * [MDBA_MDB_ENTRY_INFO] { + * struct br_mdb_entry + * [MDBA_MDB_EATTR attributes] + * } + * } + * } + * [MDBA_ROUTER] = { + * [MDBA_ROUTER_PORT] = { + * u32 ifindex + * [MDBA_ROUTER_PATTR attributes] + * } + * } + */ +enum { + MDBA_UNSPEC, + MDBA_MDB, + MDBA_ROUTER, + __MDBA_MAX, +}; +#define MDBA_MAX (__MDBA_MAX - 1) + +enum { + MDBA_MDB_UNSPEC, + MDBA_MDB_ENTRY, + __MDBA_MDB_MAX, +}; +#define MDBA_MDB_MAX (__MDBA_MDB_MAX - 1) + +enum { + MDBA_MDB_ENTRY_UNSPEC, + MDBA_MDB_ENTRY_INFO, + __MDBA_MDB_ENTRY_MAX, +}; +#define MDBA_MDB_ENTRY_MAX (__MDBA_MDB_ENTRY_MAX - 1) + +/* per mdb entry additional attributes */ +enum { + MDBA_MDB_EATTR_UNSPEC, + MDBA_MDB_EATTR_TIMER, + MDBA_MDB_EATTR_SRC_LIST, + MDBA_MDB_EATTR_GROUP_MODE, + MDBA_MDB_EATTR_SOURCE, + MDBA_MDB_EATTR_RTPROT, + MDBA_MDB_EATTR_DST, + MDBA_MDB_EATTR_DST_PORT, + MDBA_MDB_EATTR_VNI, + MDBA_MDB_EATTR_IFINDEX, + MDBA_MDB_EATTR_SRC_VNI, + __MDBA_MDB_EATTR_MAX +}; +#define MDBA_MDB_EATTR_MAX (__MDBA_MDB_EATTR_MAX - 1) + +/* per mdb entry source */ +enum { + MDBA_MDB_SRCLIST_UNSPEC, + MDBA_MDB_SRCLIST_ENTRY, + __MDBA_MDB_SRCLIST_MAX +}; +#define MDBA_MDB_SRCLIST_MAX (__MDBA_MDB_SRCLIST_MAX - 1) + +/* per mdb entry per source attributes + * these are embedded in MDBA_MDB_SRCLIST_ENTRY + */ +enum { + MDBA_MDB_SRCATTR_UNSPEC, + MDBA_MDB_SRCATTR_ADDRESS, + MDBA_MDB_SRCATTR_TIMER, + __MDBA_MDB_SRCATTR_MAX +}; +#define MDBA_MDB_SRCATTR_MAX (__MDBA_MDB_SRCATTR_MAX - 1) + +/* multicast router types */ +enum { + MDB_RTR_TYPE_DISABLED, + MDB_RTR_TYPE_TEMP_QUERY, + MDB_RTR_TYPE_PERM, + MDB_RTR_TYPE_TEMP +}; + +enum { + MDBA_ROUTER_UNSPEC, + MDBA_ROUTER_PORT, + __MDBA_ROUTER_MAX, +}; +#define MDBA_ROUTER_MAX (__MDBA_ROUTER_MAX - 1) + +/* router port attributes */ +enum { + MDBA_ROUTER_PATTR_UNSPEC, + MDBA_ROUTER_PATTR_TIMER, + MDBA_ROUTER_PATTR_TYPE, + MDBA_ROUTER_PATTR_INET_TIMER, + MDBA_ROUTER_PATTR_INET6_TIMER, + MDBA_ROUTER_PATTR_VID, + __MDBA_ROUTER_PATTR_MAX +}; +#define MDBA_ROUTER_PATTR_MAX (__MDBA_ROUTER_PATTR_MAX - 1) + +struct br_port_msg { + __u8 family; + __u32 ifindex; +}; + +struct br_mdb_entry { + __u32 ifindex; +#define MDB_TEMPORARY 0 +#define MDB_PERMANENT 1 + __u8 state; +#define MDB_FLAGS_OFFLOAD (1 << 0) +#define MDB_FLAGS_FAST_LEAVE (1 << 1) +#define MDB_FLAGS_STAR_EXCL (1 << 2) +#define MDB_FLAGS_BLOCKED (1 << 3) + __u8 flags; + __u16 vid; + struct { + union { + __be32 ip4; + struct in6_addr ip6; + unsigned char mac_addr[ETH_ALEN]; + } u; + __be16 proto; + } addr; +}; + +enum { + MDBA_SET_ENTRY_UNSPEC, + MDBA_SET_ENTRY, + MDBA_SET_ENTRY_ATTRS, + __MDBA_SET_ENTRY_MAX, +}; +#define MDBA_SET_ENTRY_MAX (__MDBA_SET_ENTRY_MAX - 1) + +/* [MDBA_SET_ENTRY_ATTRS] = { + * [MDBE_ATTR_xxx] + * ... + * } + */ +enum { + MDBE_ATTR_UNSPEC, + MDBE_ATTR_SOURCE, + MDBE_ATTR_SRC_LIST, + MDBE_ATTR_GROUP_MODE, + MDBE_ATTR_RTPROT, + MDBE_ATTR_DST, + MDBE_ATTR_DST_PORT, + MDBE_ATTR_VNI, + MDBE_ATTR_IFINDEX, + MDBE_ATTR_SRC_VNI, + __MDBE_ATTR_MAX, +}; +#define MDBE_ATTR_MAX (__MDBE_ATTR_MAX - 1) + +/* per mdb entry source */ +enum { + MDBE_SRC_LIST_UNSPEC, + MDBE_SRC_LIST_ENTRY, + __MDBE_SRC_LIST_MAX, +}; +#define MDBE_SRC_LIST_MAX (__MDBE_SRC_LIST_MAX - 1) + +/* per mdb entry per source attributes + * these are embedded in MDBE_SRC_LIST_ENTRY + */ +enum { + MDBE_SRCATTR_UNSPEC, + MDBE_SRCATTR_ADDRESS, + __MDBE_SRCATTR_MAX, +}; +#define MDBE_SRCATTR_MAX (__MDBE_SRCATTR_MAX - 1) + +/* Embedded inside LINK_XSTATS_TYPE_BRIDGE */ +enum { + BRIDGE_XSTATS_UNSPEC, + BRIDGE_XSTATS_VLAN, + BRIDGE_XSTATS_MCAST, + BRIDGE_XSTATS_PAD, + BRIDGE_XSTATS_STP, + __BRIDGE_XSTATS_MAX +}; +#define BRIDGE_XSTATS_MAX (__BRIDGE_XSTATS_MAX - 1) + +enum { + BR_MCAST_DIR_RX, + BR_MCAST_DIR_TX, + BR_MCAST_DIR_SIZE +}; + +/* IGMP/MLD statistics */ +struct br_mcast_stats { + __u64 igmp_v1queries[BR_MCAST_DIR_SIZE]; + __u64 igmp_v2queries[BR_MCAST_DIR_SIZE]; + __u64 igmp_v3queries[BR_MCAST_DIR_SIZE]; + __u64 igmp_leaves[BR_MCAST_DIR_SIZE]; + __u64 igmp_v1reports[BR_MCAST_DIR_SIZE]; + __u64 igmp_v2reports[BR_MCAST_DIR_SIZE]; + __u64 igmp_v3reports[BR_MCAST_DIR_SIZE]; + __u64 igmp_parse_errors; + + __u64 mld_v1queries[BR_MCAST_DIR_SIZE]; + __u64 mld_v2queries[BR_MCAST_DIR_SIZE]; + __u64 mld_leaves[BR_MCAST_DIR_SIZE]; + __u64 mld_v1reports[BR_MCAST_DIR_SIZE]; + __u64 mld_v2reports[BR_MCAST_DIR_SIZE]; + __u64 mld_parse_errors; + + __u64 mcast_bytes[BR_MCAST_DIR_SIZE]; + __u64 mcast_packets[BR_MCAST_DIR_SIZE]; +}; + +/* bridge boolean options + * BR_BOOLOPT_NO_LL_LEARN - disable learning from link-local packets + * BR_BOOLOPT_MCAST_VLAN_SNOOPING - control vlan multicast snooping + * + * IMPORTANT: if adding a new option do not forget to handle + * it in br_boolopt_toggle/get and bridge sysfs + */ +enum br_boolopt_id { + BR_BOOLOPT_NO_LL_LEARN, + BR_BOOLOPT_MCAST_VLAN_SNOOPING, + BR_BOOLOPT_MST_ENABLE, + BR_BOOLOPT_MAX +}; + +/* struct br_boolopt_multi - change multiple bridge boolean options + * + * @optval: new option values (bit per option) + * @optmask: options to change (bit per option) + */ +struct br_boolopt_multi { + __u32 optval; + __u32 optmask; +}; + +enum { + BRIDGE_QUERIER_UNSPEC, + BRIDGE_QUERIER_IP_ADDRESS, + BRIDGE_QUERIER_IP_PORT, + BRIDGE_QUERIER_IP_OTHER_TIMER, + BRIDGE_QUERIER_PAD, + BRIDGE_QUERIER_IPV6_ADDRESS, + BRIDGE_QUERIER_IPV6_PORT, + BRIDGE_QUERIER_IPV6_OTHER_TIMER, + __BRIDGE_QUERIER_MAX +}; +#define BRIDGE_QUERIER_MAX (__BRIDGE_QUERIER_MAX - 1) +#endif /* _LINUX_IF_BRIDGE_H */ diff --git a/include/linux/if_ether.h b/include/linux-private/linux/if_ether.h similarity index 64% rename from include/linux/if_ether.h rename to include/linux-private/linux/if_ether.h index a6af32d..a1aff8e 100644 --- a/include/linux/if_ether.h +++ b/include/linux-private/linux/if_ether.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ /* * INET An implementation of the TCP/IP protocol suite for the LINUX * operating system. INET is implemented using the BSD Socket @@ -29,12 +30,16 @@ */ #define ETH_ALEN 6 /* Octets in one ethernet addr */ +#define ETH_TLEN 2 /* Octets in ethernet type field */ #define ETH_HLEN 14 /* Total octets in header. */ #define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ #define ETH_DATA_LEN 1500 /* Max. octets in payload */ #define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */ #define ETH_FCS_LEN 4 /* Octets in the FCS */ +#define ETH_MIN_MTU 68 /* Min IPv4 MTU per RFC791 */ +#define ETH_MAX_MTU 0xFFFFU /* 65535, same as IP_MAX_MTU */ + /* * These are the defined Ethernet Protocol ID's. */ @@ -42,12 +47,15 @@ #define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */ #define ETH_P_PUP 0x0200 /* Xerox PUP packet */ #define ETH_P_PUPAT 0x0201 /* Xerox PUP Addr Trans packet */ +#define ETH_P_TSN 0x22F0 /* TSN (IEEE 1722) packet */ +#define ETH_P_ERSPAN2 0x22EB /* ERSPAN version 2 (type III) */ #define ETH_P_IP 0x0800 /* Internet Protocol packet */ #define ETH_P_X25 0x0805 /* CCITT X.25 */ #define ETH_P_ARP 0x0806 /* Address Resolution packet */ #define ETH_P_BPQ 0x08FF /* G8BPQ AX.25 Ethernet Packet [ NOT AN OFFICIALLY REGISTERED ID ] */ #define ETH_P_IEEEPUP 0x0a00 /* Xerox IEEE802.3 PUP packet */ #define ETH_P_IEEEPUPAT 0x0a01 /* Xerox IEEE802.3 PUP Addr Trans packet */ +#define ETH_P_BATMAN 0x4305 /* B.A.T.M.A.N.-Advanced packet [ NOT AN OFFICIALLY REGISTERED ID ] */ #define ETH_P_DEC 0x6000 /* DEC Assigned proto */ #define ETH_P_DNA_DL 0x6001 /* DEC DNA Dump/Load */ #define ETH_P_DNA_RC 0x6002 /* DEC DNA Remote Console */ @@ -61,28 +69,59 @@ #define ETH_P_ATALK 0x809B /* Appletalk DDP */ #define ETH_P_AARP 0x80F3 /* Appletalk AARP */ #define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */ +#define ETH_P_ERSPAN 0x88BE /* ERSPAN type II */ #define ETH_P_IPX 0x8137 /* IPX over DIX */ #define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ #define ETH_P_PAUSE 0x8808 /* IEEE Pause frames. See 802.3 31B */ #define ETH_P_SLOW 0x8809 /* Slow Protocol. See 802.3ad 43B */ #define ETH_P_WCCP 0x883E /* Web-cache coordination protocol * defined in draft-wilson-wrec-wccp-v2-00.txt */ -#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ -#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */ #define ETH_P_MPLS_UC 0x8847 /* MPLS Unicast traffic */ #define ETH_P_MPLS_MC 0x8848 /* MPLS Multicast traffic */ #define ETH_P_ATMMPOA 0x884c /* MultiProtocol Over ATM */ +#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ +#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */ #define ETH_P_LINK_CTL 0x886c /* HPNA, wlan link local tunnel */ #define ETH_P_ATMFATE 0x8884 /* Frame-based ATM Transport * over Ethernet */ #define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ +#define ETH_P_PROFINET 0x8892 /* PROFINET */ +#define ETH_P_REALTEK 0x8899 /* Multiple proprietary protocols */ #define ETH_P_AOE 0x88A2 /* ATA over Ethernet */ +#define ETH_P_ETHERCAT 0x88A4 /* EtherCAT */ +#define ETH_P_8021AD 0x88A8 /* 802.1ad Service VLAN */ +#define ETH_P_802_EX1 0x88B5 /* 802.1 Local Experimental 1. */ +#define ETH_P_PREAUTH 0x88C7 /* 802.11 Preauthentication */ #define ETH_P_TIPC 0x88CA /* TIPC */ +#define ETH_P_LLDP 0x88CC /* Link Layer Discovery Protocol */ +#define ETH_P_MRP 0x88E3 /* Media Redundancy Protocol */ +#define ETH_P_MACSEC 0x88E5 /* 802.1ae MACsec */ +#define ETH_P_8021AH 0x88E7 /* 802.1ah Backbone Service Tag */ +#define ETH_P_MVRP 0x88F5 /* 802.1Q MVRP */ #define ETH_P_1588 0x88F7 /* IEEE 1588 Timesync */ +#define ETH_P_NCSI 0x88F8 /* NCSI protocol */ +#define ETH_P_PRP 0x88FB /* IEC 62439-3 PRP/HSRv0 */ +#define ETH_P_CFM 0x8902 /* Connectivity Fault Management */ #define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */ +#define ETH_P_IBOE 0x8915 /* Infiniband over Ethernet */ +#define ETH_P_TDLS 0x890D /* TDLS */ #define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */ +#define ETH_P_80221 0x8917 /* IEEE 802.21 Media Independent Handover Protocol */ +#define ETH_P_HSR 0x892F /* IEC 62439-3 HSRv1 */ +#define ETH_P_NSH 0x894F /* Network Service Header */ +#define ETH_P_LOOPBACK 0x9000 /* Ethernet loopback packet, per IEEE 802.3 */ +#define ETH_P_QINQ1 0x9100 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_QINQ2 0x9200 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_QINQ3 0x9300 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */ #define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_DSA_8021Q 0xDADB /* Fake VLAN Header for DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_DSA_A5PSW 0xE001 /* A5PSW Tag Value [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_IFE 0xED3E /* ForCES inter-FE LFB type */ +#define ETH_P_AF_IUCV 0xFBFB /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */ + +#define ETH_P_802_3_MIN 0x0600 /* If the value in the ethernet type is more than this value + * then the frame is Ethernet II. Else it is 802.3 */ /* * Non DIX types. Won't clash for 1500 types. @@ -97,7 +136,9 @@ #define ETH_P_WAN_PPP 0x0007 /* Dummy type for WAN PPP frames*/ #define ETH_P_PPP_MP 0x0008 /* Dummy type for PPP MP frames */ #define ETH_P_LOCALTALK 0x0009 /* Localtalk pseudo type */ -#define ETH_P_CAN 0x000C /* Controller Area Network */ +#define ETH_P_CAN 0x000C /* CAN: Controller Area Network */ +#define ETH_P_CANFD 0x000D /* CANFD: CAN flexible data rate*/ +#define ETH_P_CANXL 0x000E /* CANXL: eXtended frame Length */ #define ETH_P_PPPTALK 0x0010 /* Dummy type for Atalk over PPP*/ #define ETH_P_TR_802_2 0x0011 /* 802.2 frames */ #define ETH_P_MOBITEX 0x0015 /* Mobitex (kaz@cafe.net) */ @@ -111,15 +152,30 @@ #define ETH_P_PHONET 0x00F5 /* Nokia Phonet frames */ #define ETH_P_IEEE802154 0x00F6 /* IEEE802.15.4 frame */ #define ETH_P_CAIF 0x00F7 /* ST-Ericsson CAIF protocol */ +#define ETH_P_XDSA 0x00F8 /* Multiplexed DSA protocol */ +#define ETH_P_MAP 0x00F9 /* Qualcomm multiplexing and + * aggregation protocol + */ +#define ETH_P_MCTP 0x00FA /* Management component transport + * protocol packets + */ /* * This is an Ethernet frame header. */ +/* allow libcs like musl to deactivate this, glibc does not implement this. */ +#ifndef __UAPI_DEF_ETHHDR +#define __UAPI_DEF_ETHHDR 1 +#endif + +#if __UAPI_DEF_ETHHDR struct ethhdr { unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ unsigned char h_source[ETH_ALEN]; /* source ether addr */ __be16 h_proto; /* packet type ID field */ } __attribute__((packed)); +#endif + -#endif /* _LINUX_IF_ETHER_H */ +#endif /* _LINUX_IF_ETHER_H */ diff --git a/include/linux-private/linux/if_link.h b/include/linux-private/linux/if_link.h new file mode 100644 index 0000000..94fb7ef --- /dev/null +++ b/include/linux-private/linux/if_link.h @@ -0,0 +1,1397 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_IF_LINK_H +#define _LINUX_IF_LINK_H + +#include +#include + +/* This struct should be in sync with struct rtnl_link_stats64 */ +struct rtnl_link_stats { + __u32 rx_packets; + __u32 tx_packets; + __u32 rx_bytes; + __u32 tx_bytes; + __u32 rx_errors; + __u32 tx_errors; + __u32 rx_dropped; + __u32 tx_dropped; + __u32 multicast; + __u32 collisions; + /* detailed rx_errors: */ + __u32 rx_length_errors; + __u32 rx_over_errors; + __u32 rx_crc_errors; + __u32 rx_frame_errors; + __u32 rx_fifo_errors; + __u32 rx_missed_errors; + + /* detailed tx_errors */ + __u32 tx_aborted_errors; + __u32 tx_carrier_errors; + __u32 tx_fifo_errors; + __u32 tx_heartbeat_errors; + __u32 tx_window_errors; + + /* for cslip etc */ + __u32 rx_compressed; + __u32 tx_compressed; + + __u32 rx_nohandler; +}; + +/** + * struct rtnl_link_stats64 - The main device statistics structure. + * + * @rx_packets: Number of good packets received by the interface. + * For hardware interfaces counts all good packets received from the device + * by the host, including packets which host had to drop at various stages + * of processing (even in the driver). + * + * @tx_packets: Number of packets successfully transmitted. + * For hardware interfaces counts packets which host was able to successfully + * hand over to the device, which does not necessarily mean that packets + * had been successfully transmitted out of the device, only that device + * acknowledged it copied them out of host memory. + * + * @rx_bytes: Number of good received bytes, corresponding to @rx_packets. + * + * For IEEE 802.3 devices should count the length of Ethernet Frames + * excluding the FCS. + * + * @tx_bytes: Number of good transmitted bytes, corresponding to @tx_packets. + * + * For IEEE 802.3 devices should count the length of Ethernet Frames + * excluding the FCS. + * + * @rx_errors: Total number of bad packets received on this network device. + * This counter must include events counted by @rx_length_errors, + * @rx_crc_errors, @rx_frame_errors and other errors not otherwise + * counted. + * + * @tx_errors: Total number of transmit problems. + * This counter must include events counter by @tx_aborted_errors, + * @tx_carrier_errors, @tx_fifo_errors, @tx_heartbeat_errors, + * @tx_window_errors and other errors not otherwise counted. + * + * @rx_dropped: Number of packets received but not processed, + * e.g. due to lack of resources or unsupported protocol. + * For hardware interfaces this counter may include packets discarded + * due to L2 address filtering but should not include packets dropped + * by the device due to buffer exhaustion which are counted separately in + * @rx_missed_errors (since procfs folds those two counters together). + * + * @tx_dropped: Number of packets dropped on their way to transmission, + * e.g. due to lack of resources. + * + * @multicast: Multicast packets received. + * For hardware interfaces this statistic is commonly calculated + * at the device level (unlike @rx_packets) and therefore may include + * packets which did not reach the host. + * + * For IEEE 802.3 devices this counter may be equivalent to: + * + * - 30.3.1.1.21 aMulticastFramesReceivedOK + * + * @collisions: Number of collisions during packet transmissions. + * + * @rx_length_errors: Number of packets dropped due to invalid length. + * Part of aggregate "frame" errors in `/proc/net/dev`. + * + * For IEEE 802.3 devices this counter should be equivalent to a sum + * of the following attributes: + * + * - 30.3.1.1.23 aInRangeLengthErrors + * - 30.3.1.1.24 aOutOfRangeLengthField + * - 30.3.1.1.25 aFrameTooLongErrors + * + * @rx_over_errors: Receiver FIFO overflow event counter. + * + * Historically the count of overflow events. Such events may be + * reported in the receive descriptors or via interrupts, and may + * not correspond one-to-one with dropped packets. + * + * The recommended interpretation for high speed interfaces is - + * number of packets dropped because they did not fit into buffers + * provided by the host, e.g. packets larger than MTU or next buffer + * in the ring was not available for a scatter transfer. + * + * Part of aggregate "frame" errors in `/proc/net/dev`. + * + * This statistics was historically used interchangeably with + * @rx_fifo_errors. + * + * This statistic corresponds to hardware events and is not commonly used + * on software devices. + * + * @rx_crc_errors: Number of packets received with a CRC error. + * Part of aggregate "frame" errors in `/proc/net/dev`. + * + * For IEEE 802.3 devices this counter must be equivalent to: + * + * - 30.3.1.1.6 aFrameCheckSequenceErrors + * + * @rx_frame_errors: Receiver frame alignment errors. + * Part of aggregate "frame" errors in `/proc/net/dev`. + * + * For IEEE 802.3 devices this counter should be equivalent to: + * + * - 30.3.1.1.7 aAlignmentErrors + * + * @rx_fifo_errors: Receiver FIFO error counter. + * + * Historically the count of overflow events. Those events may be + * reported in the receive descriptors or via interrupts, and may + * not correspond one-to-one with dropped packets. + * + * This statistics was used interchangeably with @rx_over_errors. + * Not recommended for use in drivers for high speed interfaces. + * + * This statistic is used on software devices, e.g. to count software + * packet queue overflow (can) or sequencing errors (GRE). + * + * @rx_missed_errors: Count of packets missed by the host. + * Folded into the "drop" counter in `/proc/net/dev`. + * + * Counts number of packets dropped by the device due to lack + * of buffer space. This usually indicates that the host interface + * is slower than the network interface, or host is not keeping up + * with the receive packet rate. + * + * This statistic corresponds to hardware events and is not used + * on software devices. + * + * @tx_aborted_errors: + * Part of aggregate "carrier" errors in `/proc/net/dev`. + * For IEEE 802.3 devices capable of half-duplex operation this counter + * must be equivalent to: + * + * - 30.3.1.1.11 aFramesAbortedDueToXSColls + * + * High speed interfaces may use this counter as a general device + * discard counter. + * + * @tx_carrier_errors: Number of frame transmission errors due to loss + * of carrier during transmission. + * Part of aggregate "carrier" errors in `/proc/net/dev`. + * + * For IEEE 802.3 devices this counter must be equivalent to: + * + * - 30.3.1.1.13 aCarrierSenseErrors + * + * @tx_fifo_errors: Number of frame transmission errors due to device + * FIFO underrun / underflow. This condition occurs when the device + * begins transmission of a frame but is unable to deliver the + * entire frame to the transmitter in time for transmission. + * Part of aggregate "carrier" errors in `/proc/net/dev`. + * + * @tx_heartbeat_errors: Number of Heartbeat / SQE Test errors for + * old half-duplex Ethernet. + * Part of aggregate "carrier" errors in `/proc/net/dev`. + * + * For IEEE 802.3 devices possibly equivalent to: + * + * - 30.3.2.1.4 aSQETestErrors + * + * @tx_window_errors: Number of frame transmission errors due + * to late collisions (for Ethernet - after the first 64B of transmission). + * Part of aggregate "carrier" errors in `/proc/net/dev`. + * + * For IEEE 802.3 devices this counter must be equivalent to: + * + * - 30.3.1.1.10 aLateCollisions + * + * @rx_compressed: Number of correctly received compressed packets. + * This counters is only meaningful for interfaces which support + * packet compression (e.g. CSLIP, PPP). + * + * @tx_compressed: Number of transmitted compressed packets. + * This counters is only meaningful for interfaces which support + * packet compression (e.g. CSLIP, PPP). + * + * @rx_nohandler: Number of packets received on the interface + * but dropped by the networking stack because the device is + * not designated to receive packets (e.g. backup link in a bond). + * + * @rx_otherhost_dropped: Number of packets dropped due to mismatch + * in destination MAC address. + */ +struct rtnl_link_stats64 { + __u64 rx_packets; + __u64 tx_packets; + __u64 rx_bytes; + __u64 tx_bytes; + __u64 rx_errors; + __u64 tx_errors; + __u64 rx_dropped; + __u64 tx_dropped; + __u64 multicast; + __u64 collisions; + + /* detailed rx_errors: */ + __u64 rx_length_errors; + __u64 rx_over_errors; + __u64 rx_crc_errors; + __u64 rx_frame_errors; + __u64 rx_fifo_errors; + __u64 rx_missed_errors; + + /* detailed tx_errors */ + __u64 tx_aborted_errors; + __u64 tx_carrier_errors; + __u64 tx_fifo_errors; + __u64 tx_heartbeat_errors; + __u64 tx_window_errors; + + /* for cslip etc */ + __u64 rx_compressed; + __u64 tx_compressed; + __u64 rx_nohandler; + + __u64 rx_otherhost_dropped; +}; + +/* Subset of link stats useful for in-HW collection. Meaning of the fields is as + * for struct rtnl_link_stats64. + */ +struct rtnl_hw_stats64 { + __u64 rx_packets; + __u64 tx_packets; + __u64 rx_bytes; + __u64 tx_bytes; + __u64 rx_errors; + __u64 tx_errors; + __u64 rx_dropped; + __u64 tx_dropped; + __u64 multicast; +}; + +/* The struct should be in sync with struct ifmap */ +struct rtnl_link_ifmap { + __u64 mem_start; + __u64 mem_end; + __u64 base_addr; + __u16 irq; + __u8 dma; + __u8 port; +}; + +/* + * IFLA_AF_SPEC + * Contains nested attributes for address family specific attributes. + * Each address family may create a attribute with the address family + * number as type and create its own attribute structure in it. + * + * Example: + * [IFLA_AF_SPEC] = { + * [AF_INET] = { + * [IFLA_INET_CONF] = ..., + * }, + * [AF_INET6] = { + * [IFLA_INET6_FLAGS] = ..., + * [IFLA_INET6_CONF] = ..., + * } + * } + */ + +enum { + IFLA_UNSPEC, + IFLA_ADDRESS, + IFLA_BROADCAST, + IFLA_IFNAME, + IFLA_MTU, + IFLA_LINK, + IFLA_QDISC, + IFLA_STATS, + IFLA_COST, +#define IFLA_COST IFLA_COST + IFLA_PRIORITY, +#define IFLA_PRIORITY IFLA_PRIORITY + IFLA_MASTER, +#define IFLA_MASTER IFLA_MASTER + IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */ +#define IFLA_WIRELESS IFLA_WIRELESS + IFLA_PROTINFO, /* Protocol specific information for a link */ +#define IFLA_PROTINFO IFLA_PROTINFO + IFLA_TXQLEN, +#define IFLA_TXQLEN IFLA_TXQLEN + IFLA_MAP, +#define IFLA_MAP IFLA_MAP + IFLA_WEIGHT, +#define IFLA_WEIGHT IFLA_WEIGHT + IFLA_OPERSTATE, + IFLA_LINKMODE, + IFLA_LINKINFO, +#define IFLA_LINKINFO IFLA_LINKINFO + IFLA_NET_NS_PID, + IFLA_IFALIAS, + IFLA_NUM_VF, /* Number of VFs if device is SR-IOV PF */ + IFLA_VFINFO_LIST, + IFLA_STATS64, + IFLA_VF_PORTS, + IFLA_PORT_SELF, + IFLA_AF_SPEC, + IFLA_GROUP, /* Group the device belongs to */ + IFLA_NET_NS_FD, + IFLA_EXT_MASK, /* Extended info mask, VFs, etc */ + IFLA_PROMISCUITY, /* Promiscuity count: > 0 means acts PROMISC */ +#define IFLA_PROMISCUITY IFLA_PROMISCUITY + IFLA_NUM_TX_QUEUES, + IFLA_NUM_RX_QUEUES, + IFLA_CARRIER, + IFLA_PHYS_PORT_ID, + IFLA_CARRIER_CHANGES, + IFLA_PHYS_SWITCH_ID, + IFLA_LINK_NETNSID, + IFLA_PHYS_PORT_NAME, + IFLA_PROTO_DOWN, + IFLA_GSO_MAX_SEGS, + IFLA_GSO_MAX_SIZE, + IFLA_PAD, + IFLA_XDP, + IFLA_EVENT, + IFLA_NEW_NETNSID, + IFLA_IF_NETNSID, + IFLA_TARGET_NETNSID = IFLA_IF_NETNSID, /* new alias */ + IFLA_CARRIER_UP_COUNT, + IFLA_CARRIER_DOWN_COUNT, + IFLA_NEW_IFINDEX, + IFLA_MIN_MTU, + IFLA_MAX_MTU, + IFLA_PROP_LIST, + IFLA_ALT_IFNAME, /* Alternative ifname */ + IFLA_PERM_ADDRESS, + IFLA_PROTO_DOWN_REASON, + + /* device (sysfs) name as parent, used instead + * of IFLA_LINK where there's no parent netdev + */ + IFLA_PARENT_DEV_NAME, + IFLA_PARENT_DEV_BUS_NAME, + IFLA_GRO_MAX_SIZE, + IFLA_TSO_MAX_SIZE, + IFLA_TSO_MAX_SEGS, + IFLA_ALLMULTI, /* Allmulti count: > 0 means acts ALLMULTI */ + + IFLA_DEVLINK_PORT, + + IFLA_GSO_IPV4_MAX_SIZE, + IFLA_GRO_IPV4_MAX_SIZE, + + __IFLA_MAX +}; + + +#define IFLA_MAX (__IFLA_MAX - 1) + +enum { + IFLA_PROTO_DOWN_REASON_UNSPEC, + IFLA_PROTO_DOWN_REASON_MASK, /* u32, mask for reason bits */ + IFLA_PROTO_DOWN_REASON_VALUE, /* u32, reason bit value */ + + __IFLA_PROTO_DOWN_REASON_CNT, + IFLA_PROTO_DOWN_REASON_MAX = __IFLA_PROTO_DOWN_REASON_CNT - 1 +}; + +/* backwards compatibility for userspace */ +#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg)))) +#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg)) + +enum { + IFLA_INET_UNSPEC, + IFLA_INET_CONF, + __IFLA_INET_MAX, +}; + +#define IFLA_INET_MAX (__IFLA_INET_MAX - 1) + +/* ifi_flags. + + IFF_* flags. + + The only change is: + IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are + more not changeable by user. They describe link media + characteristics and set by device driver. + + Comments: + - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid + - If neither of these three flags are set; + the interface is NBMA. + + - IFF_MULTICAST does not mean anything special: + multicasts can be used on all not-NBMA links. + IFF_MULTICAST means that this media uses special encapsulation + for multicast frames. Apparently, all IFF_POINTOPOINT and + IFF_BROADCAST devices are able to use multicasts too. + */ + +/* IFLA_LINK. + For usual devices it is equal ifi_index. + If it is a "virtual interface" (f.e. tunnel), ifi_link + can point to real physical interface (f.e. for bandwidth calculations), + or maybe 0, what means, that real media is unknown (usual + for IPIP tunnels, when route to endpoint is allowed to change) + */ + +/* Subtype attributes for IFLA_PROTINFO */ +enum { + IFLA_INET6_UNSPEC, + IFLA_INET6_FLAGS, /* link flags */ + IFLA_INET6_CONF, /* sysctl parameters */ + IFLA_INET6_STATS, /* statistics */ + IFLA_INET6_MCAST, /* MC things. What of them? */ + IFLA_INET6_CACHEINFO, /* time values and max reasm size */ + IFLA_INET6_ICMP6STATS, /* statistics (icmpv6) */ + IFLA_INET6_TOKEN, /* device token */ + IFLA_INET6_ADDR_GEN_MODE, /* implicit address generator mode */ + IFLA_INET6_RA_MTU, /* mtu carried in the RA message */ + __IFLA_INET6_MAX +}; + +#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) + +enum in6_addr_gen_mode { + IN6_ADDR_GEN_MODE_EUI64, + IN6_ADDR_GEN_MODE_NONE, + IN6_ADDR_GEN_MODE_STABLE_PRIVACY, + IN6_ADDR_GEN_MODE_RANDOM, +}; + +/* Bridge section */ + +enum { + IFLA_BR_UNSPEC, + IFLA_BR_FORWARD_DELAY, + IFLA_BR_HELLO_TIME, + IFLA_BR_MAX_AGE, + IFLA_BR_AGEING_TIME, + IFLA_BR_STP_STATE, + IFLA_BR_PRIORITY, + IFLA_BR_VLAN_FILTERING, + IFLA_BR_VLAN_PROTOCOL, + IFLA_BR_GROUP_FWD_MASK, + IFLA_BR_ROOT_ID, + IFLA_BR_BRIDGE_ID, + IFLA_BR_ROOT_PORT, + IFLA_BR_ROOT_PATH_COST, + IFLA_BR_TOPOLOGY_CHANGE, + IFLA_BR_TOPOLOGY_CHANGE_DETECTED, + IFLA_BR_HELLO_TIMER, + IFLA_BR_TCN_TIMER, + IFLA_BR_TOPOLOGY_CHANGE_TIMER, + IFLA_BR_GC_TIMER, + IFLA_BR_GROUP_ADDR, + IFLA_BR_FDB_FLUSH, + IFLA_BR_MCAST_ROUTER, + IFLA_BR_MCAST_SNOOPING, + IFLA_BR_MCAST_QUERY_USE_IFADDR, + IFLA_BR_MCAST_QUERIER, + IFLA_BR_MCAST_HASH_ELASTICITY, + IFLA_BR_MCAST_HASH_MAX, + IFLA_BR_MCAST_LAST_MEMBER_CNT, + IFLA_BR_MCAST_STARTUP_QUERY_CNT, + IFLA_BR_MCAST_LAST_MEMBER_INTVL, + IFLA_BR_MCAST_MEMBERSHIP_INTVL, + IFLA_BR_MCAST_QUERIER_INTVL, + IFLA_BR_MCAST_QUERY_INTVL, + IFLA_BR_MCAST_QUERY_RESPONSE_INTVL, + IFLA_BR_MCAST_STARTUP_QUERY_INTVL, + IFLA_BR_NF_CALL_IPTABLES, + IFLA_BR_NF_CALL_IP6TABLES, + IFLA_BR_NF_CALL_ARPTABLES, + IFLA_BR_VLAN_DEFAULT_PVID, + IFLA_BR_PAD, + IFLA_BR_VLAN_STATS_ENABLED, + IFLA_BR_MCAST_STATS_ENABLED, + IFLA_BR_MCAST_IGMP_VERSION, + IFLA_BR_MCAST_MLD_VERSION, + IFLA_BR_VLAN_STATS_PER_PORT, + IFLA_BR_MULTI_BOOLOPT, + IFLA_BR_MCAST_QUERIER_STATE, + __IFLA_BR_MAX, +}; + +#define IFLA_BR_MAX (__IFLA_BR_MAX - 1) + +struct ifla_bridge_id { + __u8 prio[2]; + __u8 addr[6]; /* ETH_ALEN */ +}; + +enum { + BRIDGE_MODE_UNSPEC, + BRIDGE_MODE_HAIRPIN, +}; + +enum { + IFLA_BRPORT_UNSPEC, + IFLA_BRPORT_STATE, /* Spanning tree state */ + IFLA_BRPORT_PRIORITY, /* " priority */ + IFLA_BRPORT_COST, /* " cost */ + IFLA_BRPORT_MODE, /* mode (hairpin) */ + IFLA_BRPORT_GUARD, /* bpdu guard */ + IFLA_BRPORT_PROTECT, /* root port protection */ + IFLA_BRPORT_FAST_LEAVE, /* multicast fast leave */ + IFLA_BRPORT_LEARNING, /* mac learning */ + IFLA_BRPORT_UNICAST_FLOOD, /* flood unicast traffic */ + IFLA_BRPORT_PROXYARP, /* proxy ARP */ + IFLA_BRPORT_LEARNING_SYNC, /* mac learning sync from device */ + IFLA_BRPORT_PROXYARP_WIFI, /* proxy ARP for Wi-Fi */ + IFLA_BRPORT_ROOT_ID, /* designated root */ + IFLA_BRPORT_BRIDGE_ID, /* designated bridge */ + IFLA_BRPORT_DESIGNATED_PORT, + IFLA_BRPORT_DESIGNATED_COST, + IFLA_BRPORT_ID, + IFLA_BRPORT_NO, + IFLA_BRPORT_TOPOLOGY_CHANGE_ACK, + IFLA_BRPORT_CONFIG_PENDING, + IFLA_BRPORT_MESSAGE_AGE_TIMER, + IFLA_BRPORT_FORWARD_DELAY_TIMER, + IFLA_BRPORT_HOLD_TIMER, + IFLA_BRPORT_FLUSH, + IFLA_BRPORT_MULTICAST_ROUTER, + IFLA_BRPORT_PAD, + IFLA_BRPORT_MCAST_FLOOD, + IFLA_BRPORT_MCAST_TO_UCAST, + IFLA_BRPORT_VLAN_TUNNEL, + IFLA_BRPORT_BCAST_FLOOD, + IFLA_BRPORT_GROUP_FWD_MASK, + IFLA_BRPORT_NEIGH_SUPPRESS, + IFLA_BRPORT_ISOLATED, + IFLA_BRPORT_BACKUP_PORT, + IFLA_BRPORT_MRP_RING_OPEN, + IFLA_BRPORT_MRP_IN_OPEN, + IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT, + IFLA_BRPORT_MCAST_EHT_HOSTS_CNT, + IFLA_BRPORT_LOCKED, + IFLA_BRPORT_MAB, + IFLA_BRPORT_MCAST_N_GROUPS, + IFLA_BRPORT_MCAST_MAX_GROUPS, + IFLA_BRPORT_NEIGH_VLAN_SUPPRESS, + __IFLA_BRPORT_MAX +}; +#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) + +struct ifla_cacheinfo { + __u32 max_reasm_len; + __u32 tstamp; /* ipv6InterfaceTable updated timestamp */ + __u32 reachable_time; + __u32 retrans_time; +}; + +enum { + IFLA_INFO_UNSPEC, + IFLA_INFO_KIND, + IFLA_INFO_DATA, + IFLA_INFO_XSTATS, + IFLA_INFO_SLAVE_KIND, + IFLA_INFO_SLAVE_DATA, + __IFLA_INFO_MAX, +}; + +#define IFLA_INFO_MAX (__IFLA_INFO_MAX - 1) + +/* VLAN section */ + +enum { + IFLA_VLAN_UNSPEC, + IFLA_VLAN_ID, + IFLA_VLAN_FLAGS, + IFLA_VLAN_EGRESS_QOS, + IFLA_VLAN_INGRESS_QOS, + IFLA_VLAN_PROTOCOL, + __IFLA_VLAN_MAX, +}; + +#define IFLA_VLAN_MAX (__IFLA_VLAN_MAX - 1) + +struct ifla_vlan_flags { + __u32 flags; + __u32 mask; +}; + +enum { + IFLA_VLAN_QOS_UNSPEC, + IFLA_VLAN_QOS_MAPPING, + __IFLA_VLAN_QOS_MAX +}; + +#define IFLA_VLAN_QOS_MAX (__IFLA_VLAN_QOS_MAX - 1) + +struct ifla_vlan_qos_mapping { + __u32 from; + __u32 to; +}; + +/* MACVLAN section */ +enum { + IFLA_MACVLAN_UNSPEC, + IFLA_MACVLAN_MODE, + IFLA_MACVLAN_FLAGS, + IFLA_MACVLAN_MACADDR_MODE, + IFLA_MACVLAN_MACADDR, + IFLA_MACVLAN_MACADDR_DATA, + IFLA_MACVLAN_MACADDR_COUNT, + IFLA_MACVLAN_BC_QUEUE_LEN, + IFLA_MACVLAN_BC_QUEUE_LEN_USED, + IFLA_MACVLAN_BC_CUTOFF, + __IFLA_MACVLAN_MAX, +}; + +#define IFLA_MACVLAN_MAX (__IFLA_MACVLAN_MAX - 1) + +enum macvlan_mode { + MACVLAN_MODE_PRIVATE = 1, /* don't talk to other macvlans */ + MACVLAN_MODE_VEPA = 2, /* talk to other ports through ext bridge */ + MACVLAN_MODE_BRIDGE = 4, /* talk to bridge ports directly */ + MACVLAN_MODE_PASSTHRU = 8,/* take over the underlying device */ + MACVLAN_MODE_SOURCE = 16,/* use source MAC address list to assign */ +}; + +enum macvlan_macaddr_mode { + MACVLAN_MACADDR_ADD, + MACVLAN_MACADDR_DEL, + MACVLAN_MACADDR_FLUSH, + MACVLAN_MACADDR_SET, +}; + +#define MACVLAN_FLAG_NOPROMISC 1 +#define MACVLAN_FLAG_NODST 2 /* skip dst macvlan if matching src macvlan */ + +/* VRF section */ +enum { + IFLA_VRF_UNSPEC, + IFLA_VRF_TABLE, + __IFLA_VRF_MAX +}; + +#define IFLA_VRF_MAX (__IFLA_VRF_MAX - 1) + +enum { + IFLA_VRF_PORT_UNSPEC, + IFLA_VRF_PORT_TABLE, + __IFLA_VRF_PORT_MAX +}; + +#define IFLA_VRF_PORT_MAX (__IFLA_VRF_PORT_MAX - 1) + +/* MACSEC section */ +enum { + IFLA_MACSEC_UNSPEC, + IFLA_MACSEC_SCI, + IFLA_MACSEC_PORT, + IFLA_MACSEC_ICV_LEN, + IFLA_MACSEC_CIPHER_SUITE, + IFLA_MACSEC_WINDOW, + IFLA_MACSEC_ENCODING_SA, + IFLA_MACSEC_ENCRYPT, + IFLA_MACSEC_PROTECT, + IFLA_MACSEC_INC_SCI, + IFLA_MACSEC_ES, + IFLA_MACSEC_SCB, + IFLA_MACSEC_REPLAY_PROTECT, + IFLA_MACSEC_VALIDATION, + IFLA_MACSEC_PAD, + IFLA_MACSEC_OFFLOAD, + __IFLA_MACSEC_MAX, +}; + +#define IFLA_MACSEC_MAX (__IFLA_MACSEC_MAX - 1) + +/* XFRM section */ +enum { + IFLA_XFRM_UNSPEC, + IFLA_XFRM_LINK, + IFLA_XFRM_IF_ID, + IFLA_XFRM_COLLECT_METADATA, + __IFLA_XFRM_MAX +}; + +#define IFLA_XFRM_MAX (__IFLA_XFRM_MAX - 1) + +enum macsec_validation_type { + MACSEC_VALIDATE_DISABLED = 0, + MACSEC_VALIDATE_CHECK = 1, + MACSEC_VALIDATE_STRICT = 2, + __MACSEC_VALIDATE_END, + MACSEC_VALIDATE_MAX = __MACSEC_VALIDATE_END - 1, +}; + +enum macsec_offload { + MACSEC_OFFLOAD_OFF = 0, + MACSEC_OFFLOAD_PHY = 1, + MACSEC_OFFLOAD_MAC = 2, + __MACSEC_OFFLOAD_END, + MACSEC_OFFLOAD_MAX = __MACSEC_OFFLOAD_END - 1, +}; + +/* IPVLAN section */ +enum { + IFLA_IPVLAN_UNSPEC, + IFLA_IPVLAN_MODE, + IFLA_IPVLAN_FLAGS, + __IFLA_IPVLAN_MAX +}; + +#define IFLA_IPVLAN_MAX (__IFLA_IPVLAN_MAX - 1) + +enum ipvlan_mode { + IPVLAN_MODE_L2 = 0, + IPVLAN_MODE_L3, + IPVLAN_MODE_L3S, + IPVLAN_MODE_MAX +}; + +#define IPVLAN_F_PRIVATE 0x01 +#define IPVLAN_F_VEPA 0x02 + +/* Tunnel RTM header */ +struct tunnel_msg { + __u8 family; + __u8 flags; + __u16 reserved2; + __u32 ifindex; +}; + +/* VXLAN section */ + +/* include statistics in the dump */ +#define TUNNEL_MSG_FLAG_STATS 0x01 + +#define TUNNEL_MSG_VALID_USER_FLAGS TUNNEL_MSG_FLAG_STATS + +/* Embedded inside VXLAN_VNIFILTER_ENTRY_STATS */ +enum { + VNIFILTER_ENTRY_STATS_UNSPEC, + VNIFILTER_ENTRY_STATS_RX_BYTES, + VNIFILTER_ENTRY_STATS_RX_PKTS, + VNIFILTER_ENTRY_STATS_RX_DROPS, + VNIFILTER_ENTRY_STATS_RX_ERRORS, + VNIFILTER_ENTRY_STATS_TX_BYTES, + VNIFILTER_ENTRY_STATS_TX_PKTS, + VNIFILTER_ENTRY_STATS_TX_DROPS, + VNIFILTER_ENTRY_STATS_TX_ERRORS, + VNIFILTER_ENTRY_STATS_PAD, + __VNIFILTER_ENTRY_STATS_MAX +}; +#define VNIFILTER_ENTRY_STATS_MAX (__VNIFILTER_ENTRY_STATS_MAX - 1) + +enum { + VXLAN_VNIFILTER_ENTRY_UNSPEC, + VXLAN_VNIFILTER_ENTRY_START, + VXLAN_VNIFILTER_ENTRY_END, + VXLAN_VNIFILTER_ENTRY_GROUP, + VXLAN_VNIFILTER_ENTRY_GROUP6, + VXLAN_VNIFILTER_ENTRY_STATS, + __VXLAN_VNIFILTER_ENTRY_MAX +}; +#define VXLAN_VNIFILTER_ENTRY_MAX (__VXLAN_VNIFILTER_ENTRY_MAX - 1) + +enum { + VXLAN_VNIFILTER_UNSPEC, + VXLAN_VNIFILTER_ENTRY, + __VXLAN_VNIFILTER_MAX +}; +#define VXLAN_VNIFILTER_MAX (__VXLAN_VNIFILTER_MAX - 1) + +enum { + IFLA_VXLAN_UNSPEC, + IFLA_VXLAN_ID, + IFLA_VXLAN_GROUP, /* group or remote address */ + IFLA_VXLAN_LINK, + IFLA_VXLAN_LOCAL, + IFLA_VXLAN_TTL, + IFLA_VXLAN_TOS, + IFLA_VXLAN_LEARNING, + IFLA_VXLAN_AGEING, + IFLA_VXLAN_LIMIT, + IFLA_VXLAN_PORT_RANGE, /* source port */ + IFLA_VXLAN_PROXY, + IFLA_VXLAN_RSC, + IFLA_VXLAN_L2MISS, + IFLA_VXLAN_L3MISS, + IFLA_VXLAN_PORT, /* destination port */ + IFLA_VXLAN_GROUP6, + IFLA_VXLAN_LOCAL6, + IFLA_VXLAN_UDP_CSUM, + IFLA_VXLAN_UDP_ZERO_CSUM6_TX, + IFLA_VXLAN_UDP_ZERO_CSUM6_RX, + IFLA_VXLAN_REMCSUM_TX, + IFLA_VXLAN_REMCSUM_RX, + IFLA_VXLAN_GBP, + IFLA_VXLAN_REMCSUM_NOPARTIAL, + IFLA_VXLAN_COLLECT_METADATA, + IFLA_VXLAN_LABEL, + IFLA_VXLAN_GPE, + IFLA_VXLAN_TTL_INHERIT, + IFLA_VXLAN_DF, + IFLA_VXLAN_VNIFILTER, /* only applicable with COLLECT_METADATA mode */ + __IFLA_VXLAN_MAX +}; +#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) + +struct ifla_vxlan_port_range { + __be16 low; + __be16 high; +}; + +enum ifla_vxlan_df { + VXLAN_DF_UNSET = 0, + VXLAN_DF_SET, + VXLAN_DF_INHERIT, + __VXLAN_DF_END, + VXLAN_DF_MAX = __VXLAN_DF_END - 1, +}; + +/* GENEVE section */ +enum { + IFLA_GENEVE_UNSPEC, + IFLA_GENEVE_ID, + IFLA_GENEVE_REMOTE, + IFLA_GENEVE_TTL, + IFLA_GENEVE_TOS, + IFLA_GENEVE_PORT, /* destination port */ + IFLA_GENEVE_COLLECT_METADATA, + IFLA_GENEVE_REMOTE6, + IFLA_GENEVE_UDP_CSUM, + IFLA_GENEVE_UDP_ZERO_CSUM6_TX, + IFLA_GENEVE_UDP_ZERO_CSUM6_RX, + IFLA_GENEVE_LABEL, + IFLA_GENEVE_TTL_INHERIT, + IFLA_GENEVE_DF, + IFLA_GENEVE_INNER_PROTO_INHERIT, + __IFLA_GENEVE_MAX +}; +#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) + +enum ifla_geneve_df { + GENEVE_DF_UNSET = 0, + GENEVE_DF_SET, + GENEVE_DF_INHERIT, + __GENEVE_DF_END, + GENEVE_DF_MAX = __GENEVE_DF_END - 1, +}; + +/* Bareudp section */ +enum { + IFLA_BAREUDP_UNSPEC, + IFLA_BAREUDP_PORT, + IFLA_BAREUDP_ETHERTYPE, + IFLA_BAREUDP_SRCPORT_MIN, + IFLA_BAREUDP_MULTIPROTO_MODE, + __IFLA_BAREUDP_MAX +}; + +#define IFLA_BAREUDP_MAX (__IFLA_BAREUDP_MAX - 1) + +/* PPP section */ +enum { + IFLA_PPP_UNSPEC, + IFLA_PPP_DEV_FD, + __IFLA_PPP_MAX +}; +#define IFLA_PPP_MAX (__IFLA_PPP_MAX - 1) + +/* GTP section */ + +enum ifla_gtp_role { + GTP_ROLE_GGSN = 0, + GTP_ROLE_SGSN, +}; + +enum { + IFLA_GTP_UNSPEC, + IFLA_GTP_FD0, + IFLA_GTP_FD1, + IFLA_GTP_PDP_HASHSIZE, + IFLA_GTP_ROLE, + IFLA_GTP_CREATE_SOCKETS, + IFLA_GTP_RESTART_COUNT, + __IFLA_GTP_MAX, +}; +#define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1) + +/* Bonding section */ + +enum { + IFLA_BOND_UNSPEC, + IFLA_BOND_MODE, + IFLA_BOND_ACTIVE_SLAVE, + IFLA_BOND_MIIMON, + IFLA_BOND_UPDELAY, + IFLA_BOND_DOWNDELAY, + IFLA_BOND_USE_CARRIER, + IFLA_BOND_ARP_INTERVAL, + IFLA_BOND_ARP_IP_TARGET, + IFLA_BOND_ARP_VALIDATE, + IFLA_BOND_ARP_ALL_TARGETS, + IFLA_BOND_PRIMARY, + IFLA_BOND_PRIMARY_RESELECT, + IFLA_BOND_FAIL_OVER_MAC, + IFLA_BOND_XMIT_HASH_POLICY, + IFLA_BOND_RESEND_IGMP, + IFLA_BOND_NUM_PEER_NOTIF, + IFLA_BOND_ALL_SLAVES_ACTIVE, + IFLA_BOND_MIN_LINKS, + IFLA_BOND_LP_INTERVAL, + IFLA_BOND_PACKETS_PER_SLAVE, + IFLA_BOND_AD_LACP_RATE, + IFLA_BOND_AD_SELECT, + IFLA_BOND_AD_INFO, + IFLA_BOND_AD_ACTOR_SYS_PRIO, + IFLA_BOND_AD_USER_PORT_KEY, + IFLA_BOND_AD_ACTOR_SYSTEM, + IFLA_BOND_TLB_DYNAMIC_LB, + IFLA_BOND_PEER_NOTIF_DELAY, + IFLA_BOND_AD_LACP_ACTIVE, + IFLA_BOND_MISSED_MAX, + IFLA_BOND_NS_IP6_TARGET, + __IFLA_BOND_MAX, +}; + +#define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1) + +enum { + IFLA_BOND_AD_INFO_UNSPEC, + IFLA_BOND_AD_INFO_AGGREGATOR, + IFLA_BOND_AD_INFO_NUM_PORTS, + IFLA_BOND_AD_INFO_ACTOR_KEY, + IFLA_BOND_AD_INFO_PARTNER_KEY, + IFLA_BOND_AD_INFO_PARTNER_MAC, + __IFLA_BOND_AD_INFO_MAX, +}; + +#define IFLA_BOND_AD_INFO_MAX (__IFLA_BOND_AD_INFO_MAX - 1) + +enum { + IFLA_BOND_SLAVE_UNSPEC, + IFLA_BOND_SLAVE_STATE, + IFLA_BOND_SLAVE_MII_STATUS, + IFLA_BOND_SLAVE_LINK_FAILURE_COUNT, + IFLA_BOND_SLAVE_PERM_HWADDR, + IFLA_BOND_SLAVE_QUEUE_ID, + IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, + IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE, + IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE, + IFLA_BOND_SLAVE_PRIO, + __IFLA_BOND_SLAVE_MAX, +}; + +#define IFLA_BOND_SLAVE_MAX (__IFLA_BOND_SLAVE_MAX - 1) + +/* SR-IOV virtual function management section */ + +enum { + IFLA_VF_INFO_UNSPEC, + IFLA_VF_INFO, + __IFLA_VF_INFO_MAX, +}; + +#define IFLA_VF_INFO_MAX (__IFLA_VF_INFO_MAX - 1) + +enum { + IFLA_VF_UNSPEC, + IFLA_VF_MAC, /* Hardware queue specific attributes */ + IFLA_VF_VLAN, /* VLAN ID and QoS */ + IFLA_VF_TX_RATE, /* Max TX Bandwidth Allocation */ + IFLA_VF_SPOOFCHK, /* Spoof Checking on/off switch */ + IFLA_VF_LINK_STATE, /* link state enable/disable/auto switch */ + IFLA_VF_RATE, /* Min and Max TX Bandwidth Allocation */ + IFLA_VF_RSS_QUERY_EN, /* RSS Redirection Table and Hash Key query + * on/off switch + */ + IFLA_VF_STATS, /* network device statistics */ + IFLA_VF_TRUST, /* Trust VF */ + IFLA_VF_IB_NODE_GUID, /* VF Infiniband node GUID */ + IFLA_VF_IB_PORT_GUID, /* VF Infiniband port GUID */ + IFLA_VF_VLAN_LIST, /* nested list of vlans, option for QinQ */ + IFLA_VF_BROADCAST, /* VF broadcast */ + __IFLA_VF_MAX, +}; + +#define IFLA_VF_MAX (__IFLA_VF_MAX - 1) + +struct ifla_vf_mac { + __u32 vf; + __u8 mac[32]; /* MAX_ADDR_LEN */ +}; + +struct ifla_vf_broadcast { + __u8 broadcast[32]; +}; + +struct ifla_vf_vlan { + __u32 vf; + __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */ + __u32 qos; +}; + +enum { + IFLA_VF_VLAN_INFO_UNSPEC, + IFLA_VF_VLAN_INFO, /* VLAN ID, QoS and VLAN protocol */ + __IFLA_VF_VLAN_INFO_MAX, +}; + +#define IFLA_VF_VLAN_INFO_MAX (__IFLA_VF_VLAN_INFO_MAX - 1) +#define MAX_VLAN_LIST_LEN 1 + +struct ifla_vf_vlan_info { + __u32 vf; + __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */ + __u32 qos; + __be16 vlan_proto; /* VLAN protocol either 802.1Q or 802.1ad */ +}; + +struct ifla_vf_tx_rate { + __u32 vf; + __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */ +}; + +struct ifla_vf_rate { + __u32 vf; + __u32 min_tx_rate; /* Min Bandwidth in Mbps */ + __u32 max_tx_rate; /* Max Bandwidth in Mbps */ +}; + +struct ifla_vf_spoofchk { + __u32 vf; + __u32 setting; +}; + +struct ifla_vf_guid { + __u32 vf; + __u64 guid; +}; + +enum { + IFLA_VF_LINK_STATE_AUTO, /* link state of the uplink */ + IFLA_VF_LINK_STATE_ENABLE, /* link always up */ + IFLA_VF_LINK_STATE_DISABLE, /* link always down */ + __IFLA_VF_LINK_STATE_MAX, +}; + +struct ifla_vf_link_state { + __u32 vf; + __u32 link_state; +}; + +struct ifla_vf_rss_query_en { + __u32 vf; + __u32 setting; +}; + +enum { + IFLA_VF_STATS_RX_PACKETS, + IFLA_VF_STATS_TX_PACKETS, + IFLA_VF_STATS_RX_BYTES, + IFLA_VF_STATS_TX_BYTES, + IFLA_VF_STATS_BROADCAST, + IFLA_VF_STATS_MULTICAST, + IFLA_VF_STATS_PAD, + IFLA_VF_STATS_RX_DROPPED, + IFLA_VF_STATS_TX_DROPPED, + __IFLA_VF_STATS_MAX, +}; + +#define IFLA_VF_STATS_MAX (__IFLA_VF_STATS_MAX - 1) + +struct ifla_vf_trust { + __u32 vf; + __u32 setting; +}; + +/* VF ports management section + * + * Nested layout of set/get msg is: + * + * [IFLA_NUM_VF] + * [IFLA_VF_PORTS] + * [IFLA_VF_PORT] + * [IFLA_PORT_*], ... + * [IFLA_VF_PORT] + * [IFLA_PORT_*], ... + * ... + * [IFLA_PORT_SELF] + * [IFLA_PORT_*], ... + */ + +enum { + IFLA_VF_PORT_UNSPEC, + IFLA_VF_PORT, /* nest */ + __IFLA_VF_PORT_MAX, +}; + +#define IFLA_VF_PORT_MAX (__IFLA_VF_PORT_MAX - 1) + +enum { + IFLA_PORT_UNSPEC, + IFLA_PORT_VF, /* __u32 */ + IFLA_PORT_PROFILE, /* string */ + IFLA_PORT_VSI_TYPE, /* 802.1Qbg (pre-)standard VDP */ + IFLA_PORT_INSTANCE_UUID, /* binary UUID */ + IFLA_PORT_HOST_UUID, /* binary UUID */ + IFLA_PORT_REQUEST, /* __u8 */ + IFLA_PORT_RESPONSE, /* __u16, output only */ + __IFLA_PORT_MAX, +}; + +#define IFLA_PORT_MAX (__IFLA_PORT_MAX - 1) + +#define PORT_PROFILE_MAX 40 +#define PORT_UUID_MAX 16 +#define PORT_SELF_VF -1 + +enum { + PORT_REQUEST_PREASSOCIATE = 0, + PORT_REQUEST_PREASSOCIATE_RR, + PORT_REQUEST_ASSOCIATE, + PORT_REQUEST_DISASSOCIATE, +}; + +enum { + PORT_VDP_RESPONSE_SUCCESS = 0, + PORT_VDP_RESPONSE_INVALID_FORMAT, + PORT_VDP_RESPONSE_INSUFFICIENT_RESOURCES, + PORT_VDP_RESPONSE_UNUSED_VTID, + PORT_VDP_RESPONSE_VTID_VIOLATION, + PORT_VDP_RESPONSE_VTID_VERSION_VIOALTION, + PORT_VDP_RESPONSE_OUT_OF_SYNC, + /* 0x08-0xFF reserved for future VDP use */ + PORT_PROFILE_RESPONSE_SUCCESS = 0x100, + PORT_PROFILE_RESPONSE_INPROGRESS, + PORT_PROFILE_RESPONSE_INVALID, + PORT_PROFILE_RESPONSE_BADSTATE, + PORT_PROFILE_RESPONSE_INSUFFICIENT_RESOURCES, + PORT_PROFILE_RESPONSE_ERROR, +}; + +struct ifla_port_vsi { + __u8 vsi_mgr_id; + __u8 vsi_type_id[3]; + __u8 vsi_type_version; + __u8 pad[3]; +}; + + +/* IPoIB section */ + +enum { + IFLA_IPOIB_UNSPEC, + IFLA_IPOIB_PKEY, + IFLA_IPOIB_MODE, + IFLA_IPOIB_UMCAST, + __IFLA_IPOIB_MAX +}; + +enum { + IPOIB_MODE_DATAGRAM = 0, /* using unreliable datagram QPs */ + IPOIB_MODE_CONNECTED = 1, /* using connected QPs */ +}; + +#define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1) + + +/* HSR/PRP section, both uses same interface */ + +/* Different redundancy protocols for hsr device */ +enum { + HSR_PROTOCOL_HSR, + HSR_PROTOCOL_PRP, + HSR_PROTOCOL_MAX, +}; + +enum { + IFLA_HSR_UNSPEC, + IFLA_HSR_SLAVE1, + IFLA_HSR_SLAVE2, + IFLA_HSR_MULTICAST_SPEC, /* Last byte of supervision addr */ + IFLA_HSR_SUPERVISION_ADDR, /* Supervision frame multicast addr */ + IFLA_HSR_SEQ_NR, + IFLA_HSR_VERSION, /* HSR version */ + IFLA_HSR_PROTOCOL, /* Indicate different protocol than + * HSR. For example PRP. + */ + __IFLA_HSR_MAX, +}; + +#define IFLA_HSR_MAX (__IFLA_HSR_MAX - 1) + +/* STATS section */ + +struct if_stats_msg { + __u8 family; + __u8 pad1; + __u16 pad2; + __u32 ifindex; + __u32 filter_mask; +}; + +/* A stats attribute can be netdev specific or a global stat. + * For netdev stats, lets use the prefix IFLA_STATS_LINK_* + */ +enum { + IFLA_STATS_UNSPEC, /* also used as 64bit pad attribute */ + IFLA_STATS_LINK_64, + IFLA_STATS_LINK_XSTATS, + IFLA_STATS_LINK_XSTATS_SLAVE, + IFLA_STATS_LINK_OFFLOAD_XSTATS, + IFLA_STATS_AF_SPEC, + __IFLA_STATS_MAX, +}; + +#define IFLA_STATS_MAX (__IFLA_STATS_MAX - 1) + +#define IFLA_STATS_FILTER_BIT(ATTR) (1 << (ATTR - 1)) + +enum { + IFLA_STATS_GETSET_UNSPEC, + IFLA_STATS_GET_FILTERS, /* Nest of IFLA_STATS_LINK_xxx, each a u32 with + * a filter mask for the corresponding group. + */ + IFLA_STATS_SET_OFFLOAD_XSTATS_L3_STATS, /* 0 or 1 as u8 */ + __IFLA_STATS_GETSET_MAX, +}; + +#define IFLA_STATS_GETSET_MAX (__IFLA_STATS_GETSET_MAX - 1) + +/* These are embedded into IFLA_STATS_LINK_XSTATS: + * [IFLA_STATS_LINK_XSTATS] + * -> [LINK_XSTATS_TYPE_xxx] + * -> [rtnl link type specific attributes] + */ +enum { + LINK_XSTATS_TYPE_UNSPEC, + LINK_XSTATS_TYPE_BRIDGE, + LINK_XSTATS_TYPE_BOND, + __LINK_XSTATS_TYPE_MAX +}; +#define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1) + +/* These are stats embedded into IFLA_STATS_LINK_OFFLOAD_XSTATS */ +enum { + IFLA_OFFLOAD_XSTATS_UNSPEC, + IFLA_OFFLOAD_XSTATS_CPU_HIT, /* struct rtnl_link_stats64 */ + IFLA_OFFLOAD_XSTATS_HW_S_INFO, /* HW stats info. A nest */ + IFLA_OFFLOAD_XSTATS_L3_STATS, /* struct rtnl_hw_stats64 */ + __IFLA_OFFLOAD_XSTATS_MAX +}; +#define IFLA_OFFLOAD_XSTATS_MAX (__IFLA_OFFLOAD_XSTATS_MAX - 1) + +enum { + IFLA_OFFLOAD_XSTATS_HW_S_INFO_UNSPEC, + IFLA_OFFLOAD_XSTATS_HW_S_INFO_REQUEST, /* u8 */ + IFLA_OFFLOAD_XSTATS_HW_S_INFO_USED, /* u8 */ + __IFLA_OFFLOAD_XSTATS_HW_S_INFO_MAX, +}; +#define IFLA_OFFLOAD_XSTATS_HW_S_INFO_MAX \ + (__IFLA_OFFLOAD_XSTATS_HW_S_INFO_MAX - 1) + +/* XDP section */ + +#define XDP_FLAGS_UPDATE_IF_NOEXIST (1U << 0) +#define XDP_FLAGS_SKB_MODE (1U << 1) +#define XDP_FLAGS_DRV_MODE (1U << 2) +#define XDP_FLAGS_HW_MODE (1U << 3) +#define XDP_FLAGS_REPLACE (1U << 4) +#define XDP_FLAGS_MODES (XDP_FLAGS_SKB_MODE | \ + XDP_FLAGS_DRV_MODE | \ + XDP_FLAGS_HW_MODE) +#define XDP_FLAGS_MASK (XDP_FLAGS_UPDATE_IF_NOEXIST | \ + XDP_FLAGS_MODES | XDP_FLAGS_REPLACE) + +/* These are stored into IFLA_XDP_ATTACHED on dump. */ +enum { + XDP_ATTACHED_NONE = 0, + XDP_ATTACHED_DRV, + XDP_ATTACHED_SKB, + XDP_ATTACHED_HW, + XDP_ATTACHED_MULTI, +}; + +enum { + IFLA_XDP_UNSPEC, + IFLA_XDP_FD, + IFLA_XDP_ATTACHED, + IFLA_XDP_FLAGS, + IFLA_XDP_PROG_ID, + IFLA_XDP_DRV_PROG_ID, + IFLA_XDP_SKB_PROG_ID, + IFLA_XDP_HW_PROG_ID, + IFLA_XDP_EXPECTED_FD, + __IFLA_XDP_MAX, +}; + +#define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1) + +enum { + IFLA_EVENT_NONE, + IFLA_EVENT_REBOOT, /* internal reset / reboot */ + IFLA_EVENT_FEATURES, /* change in offload features */ + IFLA_EVENT_BONDING_FAILOVER, /* change in active slave */ + IFLA_EVENT_NOTIFY_PEERS, /* re-sent grat. arp/ndisc */ + IFLA_EVENT_IGMP_RESEND, /* re-sent IGMP JOIN */ + IFLA_EVENT_BONDING_OPTIONS, /* change in bonding options */ +}; + +/* tun section */ + +enum { + IFLA_TUN_UNSPEC, + IFLA_TUN_OWNER, + IFLA_TUN_GROUP, + IFLA_TUN_TYPE, + IFLA_TUN_PI, + IFLA_TUN_VNET_HDR, + IFLA_TUN_PERSIST, + IFLA_TUN_MULTI_QUEUE, + IFLA_TUN_NUM_QUEUES, + IFLA_TUN_NUM_DISABLED_QUEUES, + __IFLA_TUN_MAX, +}; + +#define IFLA_TUN_MAX (__IFLA_TUN_MAX - 1) + +/* rmnet section */ + +#define RMNET_FLAGS_INGRESS_DEAGGREGATION (1U << 0) +#define RMNET_FLAGS_INGRESS_MAP_COMMANDS (1U << 1) +#define RMNET_FLAGS_INGRESS_MAP_CKSUMV4 (1U << 2) +#define RMNET_FLAGS_EGRESS_MAP_CKSUMV4 (1U << 3) +#define RMNET_FLAGS_INGRESS_MAP_CKSUMV5 (1U << 4) +#define RMNET_FLAGS_EGRESS_MAP_CKSUMV5 (1U << 5) + +enum { + IFLA_RMNET_UNSPEC, + IFLA_RMNET_MUX_ID, + IFLA_RMNET_FLAGS, + __IFLA_RMNET_MAX, +}; + +#define IFLA_RMNET_MAX (__IFLA_RMNET_MAX - 1) + +struct ifla_rmnet_flags { + __u32 flags; + __u32 mask; +}; + +/* MCTP section */ + +enum { + IFLA_MCTP_UNSPEC, + IFLA_MCTP_NET, + __IFLA_MCTP_MAX, +}; + +#define IFLA_MCTP_MAX (__IFLA_MCTP_MAX - 1) + +/* DSA section */ + +enum { + IFLA_DSA_UNSPEC, + IFLA_DSA_MASTER, + __IFLA_DSA_MAX, +}; + +#define IFLA_DSA_MAX (__IFLA_DSA_MAX - 1) + +#endif /* _LINUX_IF_LINK_H */ diff --git a/include/linux-private/linux/if_macsec.h b/include/linux-private/linux/if_macsec.h new file mode 100644 index 0000000..6edfea0 --- /dev/null +++ b/include/linux-private/linux/if_macsec.h @@ -0,0 +1,194 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * include/uapi/linux/if_macsec.h - MACsec device + * + * Copyright (c) 2015 Sabrina Dubroca + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _MACSEC_H +#define _MACSEC_H + +#include + +#define MACSEC_GENL_NAME "macsec" +#define MACSEC_GENL_VERSION 1 + +#define MACSEC_MAX_KEY_LEN 128 + +#define MACSEC_KEYID_LEN 16 + +#define MACSEC_SALT_LEN 12 + +/* cipher IDs as per IEEE802.1AE-2018 (Table 14-1) */ +#define MACSEC_CIPHER_ID_GCM_AES_128 0x0080C20001000001ULL +#define MACSEC_CIPHER_ID_GCM_AES_256 0x0080C20001000002ULL +#define MACSEC_CIPHER_ID_GCM_AES_XPN_128 0x0080C20001000003ULL +#define MACSEC_CIPHER_ID_GCM_AES_XPN_256 0x0080C20001000004ULL + +/* deprecated cipher ID for GCM-AES-128 */ +#define MACSEC_DEFAULT_CIPHER_ID 0x0080020001000001ULL +#define MACSEC_DEFAULT_CIPHER_ALT MACSEC_CIPHER_ID_GCM_AES_128 + +#define MACSEC_MIN_ICV_LEN 8 +#define MACSEC_MAX_ICV_LEN 32 +/* upper limit for ICV length as recommended by IEEE802.1AE-2006 */ +#define MACSEC_STD_ICV_LEN 16 + +enum macsec_attrs { + MACSEC_ATTR_UNSPEC, + MACSEC_ATTR_IFINDEX, /* u32, ifindex of the MACsec netdevice */ + MACSEC_ATTR_RXSC_CONFIG, /* config, nested macsec_rxsc_attrs */ + MACSEC_ATTR_SA_CONFIG, /* config, nested macsec_sa_attrs */ + MACSEC_ATTR_SECY, /* dump, nested macsec_secy_attrs */ + MACSEC_ATTR_TXSA_LIST, /* dump, nested, macsec_sa_attrs for each TXSA */ + MACSEC_ATTR_RXSC_LIST, /* dump, nested, macsec_rxsc_attrs for each RXSC */ + MACSEC_ATTR_TXSC_STATS, /* dump, nested, macsec_txsc_stats_attr */ + MACSEC_ATTR_SECY_STATS, /* dump, nested, macsec_secy_stats_attr */ + MACSEC_ATTR_OFFLOAD, /* config, nested, macsec_offload_attrs */ + __MACSEC_ATTR_END, + NUM_MACSEC_ATTR = __MACSEC_ATTR_END, + MACSEC_ATTR_MAX = __MACSEC_ATTR_END - 1, +}; + +enum macsec_secy_attrs { + MACSEC_SECY_ATTR_UNSPEC, + MACSEC_SECY_ATTR_SCI, + MACSEC_SECY_ATTR_ENCODING_SA, + MACSEC_SECY_ATTR_WINDOW, + MACSEC_SECY_ATTR_CIPHER_SUITE, + MACSEC_SECY_ATTR_ICV_LEN, + MACSEC_SECY_ATTR_PROTECT, + MACSEC_SECY_ATTR_REPLAY, + MACSEC_SECY_ATTR_OPER, + MACSEC_SECY_ATTR_VALIDATE, + MACSEC_SECY_ATTR_ENCRYPT, + MACSEC_SECY_ATTR_INC_SCI, + MACSEC_SECY_ATTR_ES, + MACSEC_SECY_ATTR_SCB, + MACSEC_SECY_ATTR_PAD, + __MACSEC_SECY_ATTR_END, + NUM_MACSEC_SECY_ATTR = __MACSEC_SECY_ATTR_END, + MACSEC_SECY_ATTR_MAX = __MACSEC_SECY_ATTR_END - 1, +}; + +enum macsec_rxsc_attrs { + MACSEC_RXSC_ATTR_UNSPEC, + MACSEC_RXSC_ATTR_SCI, /* config/dump, u64 */ + MACSEC_RXSC_ATTR_ACTIVE, /* config/dump, u8 0..1 */ + MACSEC_RXSC_ATTR_SA_LIST, /* dump, nested */ + MACSEC_RXSC_ATTR_STATS, /* dump, nested, macsec_rxsc_stats_attr */ + MACSEC_RXSC_ATTR_PAD, + __MACSEC_RXSC_ATTR_END, + NUM_MACSEC_RXSC_ATTR = __MACSEC_RXSC_ATTR_END, + MACSEC_RXSC_ATTR_MAX = __MACSEC_RXSC_ATTR_END - 1, +}; + +enum macsec_sa_attrs { + MACSEC_SA_ATTR_UNSPEC, + MACSEC_SA_ATTR_AN, /* config/dump, u8 0..3 */ + MACSEC_SA_ATTR_ACTIVE, /* config/dump, u8 0..1 */ + MACSEC_SA_ATTR_PN, /* config/dump, u32/u64 (u64 if XPN) */ + MACSEC_SA_ATTR_KEY, /* config, data */ + MACSEC_SA_ATTR_KEYID, /* config/dump, 128-bit */ + MACSEC_SA_ATTR_STATS, /* dump, nested, macsec_sa_stats_attr */ + MACSEC_SA_ATTR_PAD, + MACSEC_SA_ATTR_SSCI, /* config/dump, u32 - XPN only */ + MACSEC_SA_ATTR_SALT, /* config, 96-bit - XPN only */ + __MACSEC_SA_ATTR_END, + NUM_MACSEC_SA_ATTR = __MACSEC_SA_ATTR_END, + MACSEC_SA_ATTR_MAX = __MACSEC_SA_ATTR_END - 1, +}; + +enum macsec_offload_attrs { + MACSEC_OFFLOAD_ATTR_UNSPEC, + MACSEC_OFFLOAD_ATTR_TYPE, /* config/dump, u8 0..2 */ + MACSEC_OFFLOAD_ATTR_PAD, + __MACSEC_OFFLOAD_ATTR_END, + NUM_MACSEC_OFFLOAD_ATTR = __MACSEC_OFFLOAD_ATTR_END, + MACSEC_OFFLOAD_ATTR_MAX = __MACSEC_OFFLOAD_ATTR_END - 1, +}; + +enum macsec_nl_commands { + MACSEC_CMD_GET_TXSC, + MACSEC_CMD_ADD_RXSC, + MACSEC_CMD_DEL_RXSC, + MACSEC_CMD_UPD_RXSC, + MACSEC_CMD_ADD_TXSA, + MACSEC_CMD_DEL_TXSA, + MACSEC_CMD_UPD_TXSA, + MACSEC_CMD_ADD_RXSA, + MACSEC_CMD_DEL_RXSA, + MACSEC_CMD_UPD_RXSA, + MACSEC_CMD_UPD_OFFLOAD, +}; + +/* u64 per-RXSC stats */ +enum macsec_rxsc_stats_attr { + MACSEC_RXSC_STATS_ATTR_UNSPEC, + MACSEC_RXSC_STATS_ATTR_IN_OCTETS_VALIDATED, + MACSEC_RXSC_STATS_ATTR_IN_OCTETS_DECRYPTED, + MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNCHECKED, + MACSEC_RXSC_STATS_ATTR_IN_PKTS_DELAYED, + MACSEC_RXSC_STATS_ATTR_IN_PKTS_OK, + MACSEC_RXSC_STATS_ATTR_IN_PKTS_INVALID, + MACSEC_RXSC_STATS_ATTR_IN_PKTS_LATE, + MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_VALID, + MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_USING_SA, + MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNUSED_SA, + MACSEC_RXSC_STATS_ATTR_PAD, + __MACSEC_RXSC_STATS_ATTR_END, + NUM_MACSEC_RXSC_STATS_ATTR = __MACSEC_RXSC_STATS_ATTR_END, + MACSEC_RXSC_STATS_ATTR_MAX = __MACSEC_RXSC_STATS_ATTR_END - 1, +}; + +/* u32 per-{RX,TX}SA stats */ +enum macsec_sa_stats_attr { + MACSEC_SA_STATS_ATTR_UNSPEC, + MACSEC_SA_STATS_ATTR_IN_PKTS_OK, + MACSEC_SA_STATS_ATTR_IN_PKTS_INVALID, + MACSEC_SA_STATS_ATTR_IN_PKTS_NOT_VALID, + MACSEC_SA_STATS_ATTR_IN_PKTS_NOT_USING_SA, + MACSEC_SA_STATS_ATTR_IN_PKTS_UNUSED_SA, + MACSEC_SA_STATS_ATTR_OUT_PKTS_PROTECTED, + MACSEC_SA_STATS_ATTR_OUT_PKTS_ENCRYPTED, + __MACSEC_SA_STATS_ATTR_END, + NUM_MACSEC_SA_STATS_ATTR = __MACSEC_SA_STATS_ATTR_END, + MACSEC_SA_STATS_ATTR_MAX = __MACSEC_SA_STATS_ATTR_END - 1, +}; + +/* u64 per-TXSC stats */ +enum macsec_txsc_stats_attr { + MACSEC_TXSC_STATS_ATTR_UNSPEC, + MACSEC_TXSC_STATS_ATTR_OUT_PKTS_PROTECTED, + MACSEC_TXSC_STATS_ATTR_OUT_PKTS_ENCRYPTED, + MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_PROTECTED, + MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_ENCRYPTED, + MACSEC_TXSC_STATS_ATTR_PAD, + __MACSEC_TXSC_STATS_ATTR_END, + NUM_MACSEC_TXSC_STATS_ATTR = __MACSEC_TXSC_STATS_ATTR_END, + MACSEC_TXSC_STATS_ATTR_MAX = __MACSEC_TXSC_STATS_ATTR_END - 1, +}; + +/* u64 per-SecY stats */ +enum macsec_secy_stats_attr { + MACSEC_SECY_STATS_ATTR_UNSPEC, + MACSEC_SECY_STATS_ATTR_OUT_PKTS_UNTAGGED, + MACSEC_SECY_STATS_ATTR_IN_PKTS_UNTAGGED, + MACSEC_SECY_STATS_ATTR_OUT_PKTS_TOO_LONG, + MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_TAG, + MACSEC_SECY_STATS_ATTR_IN_PKTS_BAD_TAG, + MACSEC_SECY_STATS_ATTR_IN_PKTS_UNKNOWN_SCI, + MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_SCI, + MACSEC_SECY_STATS_ATTR_IN_PKTS_OVERRUN, + MACSEC_SECY_STATS_ATTR_PAD, + __MACSEC_SECY_STATS_ATTR_END, + NUM_MACSEC_SECY_STATS_ATTR = __MACSEC_SECY_STATS_ATTR_END, + MACSEC_SECY_STATS_ATTR_MAX = __MACSEC_SECY_STATS_ATTR_END - 1, +}; + +#endif /* _MACSEC_H */ diff --git a/include/linux-private/linux/if_packet.h b/include/linux-private/linux/if_packet.h new file mode 100644 index 0000000..9efc423 --- /dev/null +++ b/include/linux-private/linux/if_packet.h @@ -0,0 +1,319 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __LINUX_IF_PACKET_H +#define __LINUX_IF_PACKET_H + +#include +#include + +struct sockaddr_pkt { + unsigned short spkt_family; + unsigned char spkt_device[14]; + __be16 spkt_protocol; +}; + +struct sockaddr_ll { + unsigned short sll_family; + __be16 sll_protocol; + int sll_ifindex; + unsigned short sll_hatype; + unsigned char sll_pkttype; + unsigned char sll_halen; + unsigned char sll_addr[8]; +}; + +/* Packet types */ + +#define PACKET_HOST 0 /* To us */ +#define PACKET_BROADCAST 1 /* To all */ +#define PACKET_MULTICAST 2 /* To group */ +#define PACKET_OTHERHOST 3 /* To someone else */ +#define PACKET_OUTGOING 4 /* Outgoing of any type */ +#define PACKET_LOOPBACK 5 /* MC/BRD frame looped back */ +#define PACKET_USER 6 /* To user space */ +#define PACKET_KERNEL 7 /* To kernel space */ +/* Unused, PACKET_FASTROUTE and PACKET_LOOPBACK are invisible to user space */ +#define PACKET_FASTROUTE 6 /* Fastrouted frame */ + +/* Packet socket options */ + +#define PACKET_ADD_MEMBERSHIP 1 +#define PACKET_DROP_MEMBERSHIP 2 +#define PACKET_RECV_OUTPUT 3 +/* Value 4 is still used by obsolete turbo-packet. */ +#define PACKET_RX_RING 5 +#define PACKET_STATISTICS 6 +#define PACKET_COPY_THRESH 7 +#define PACKET_AUXDATA 8 +#define PACKET_ORIGDEV 9 +#define PACKET_VERSION 10 +#define PACKET_HDRLEN 11 +#define PACKET_RESERVE 12 +#define PACKET_TX_RING 13 +#define PACKET_LOSS 14 +#define PACKET_VNET_HDR 15 +#define PACKET_TX_TIMESTAMP 16 +#define PACKET_TIMESTAMP 17 +#define PACKET_FANOUT 18 +#define PACKET_TX_HAS_OFF 19 +#define PACKET_QDISC_BYPASS 20 +#define PACKET_ROLLOVER_STATS 21 +#define PACKET_FANOUT_DATA 22 +#define PACKET_IGNORE_OUTGOING 23 +#define PACKET_VNET_HDR_SZ 24 + +#define PACKET_FANOUT_HASH 0 +#define PACKET_FANOUT_LB 1 +#define PACKET_FANOUT_CPU 2 +#define PACKET_FANOUT_ROLLOVER 3 +#define PACKET_FANOUT_RND 4 +#define PACKET_FANOUT_QM 5 +#define PACKET_FANOUT_CBPF 6 +#define PACKET_FANOUT_EBPF 7 +#define PACKET_FANOUT_FLAG_ROLLOVER 0x1000 +#define PACKET_FANOUT_FLAG_UNIQUEID 0x2000 +#define PACKET_FANOUT_FLAG_IGNORE_OUTGOING 0x4000 +#define PACKET_FANOUT_FLAG_DEFRAG 0x8000 + +struct tpacket_stats { + unsigned int tp_packets; + unsigned int tp_drops; +}; + +struct tpacket_stats_v3 { + unsigned int tp_packets; + unsigned int tp_drops; + unsigned int tp_freeze_q_cnt; +}; + +struct tpacket_rollover_stats { + __aligned_u64 tp_all; + __aligned_u64 tp_huge; + __aligned_u64 tp_failed; +}; + +union tpacket_stats_u { + struct tpacket_stats stats1; + struct tpacket_stats_v3 stats3; +}; + +struct tpacket_auxdata { + __u32 tp_status; + __u32 tp_len; + __u32 tp_snaplen; + __u16 tp_mac; + __u16 tp_net; + __u16 tp_vlan_tci; + __u16 tp_vlan_tpid; +}; + +/* Rx ring - header status */ +#define TP_STATUS_KERNEL 0 +#define TP_STATUS_USER (1 << 0) +#define TP_STATUS_COPY (1 << 1) +#define TP_STATUS_LOSING (1 << 2) +#define TP_STATUS_CSUMNOTREADY (1 << 3) +#define TP_STATUS_VLAN_VALID (1 << 4) /* auxdata has valid tp_vlan_tci */ +#define TP_STATUS_BLK_TMO (1 << 5) +#define TP_STATUS_VLAN_TPID_VALID (1 << 6) /* auxdata has valid tp_vlan_tpid */ +#define TP_STATUS_CSUM_VALID (1 << 7) +#define TP_STATUS_GSO_TCP (1 << 8) + +/* Tx ring - header status */ +#define TP_STATUS_AVAILABLE 0 +#define TP_STATUS_SEND_REQUEST (1 << 0) +#define TP_STATUS_SENDING (1 << 1) +#define TP_STATUS_WRONG_FORMAT (1 << 2) + +/* Rx and Tx ring - header status */ +#define TP_STATUS_TS_SOFTWARE (1 << 29) +#define TP_STATUS_TS_SYS_HARDWARE (1 << 30) /* deprecated, never set */ +#define TP_STATUS_TS_RAW_HARDWARE (1U << 31) + +/* Rx ring - feature request bits */ +#define TP_FT_REQ_FILL_RXHASH 0x1 + +struct tpacket_hdr { + unsigned long tp_status; + unsigned int tp_len; + unsigned int tp_snaplen; + unsigned short tp_mac; + unsigned short tp_net; + unsigned int tp_sec; + unsigned int tp_usec; +}; + +#define TPACKET_ALIGNMENT 16 +#define TPACKET_ALIGN(x) (((x)+TPACKET_ALIGNMENT-1)&~(TPACKET_ALIGNMENT-1)) +#define TPACKET_HDRLEN (TPACKET_ALIGN(sizeof(struct tpacket_hdr)) + sizeof(struct sockaddr_ll)) + +struct tpacket2_hdr { + __u32 tp_status; + __u32 tp_len; + __u32 tp_snaplen; + __u16 tp_mac; + __u16 tp_net; + __u32 tp_sec; + __u32 tp_nsec; + __u16 tp_vlan_tci; + __u16 tp_vlan_tpid; + __u8 tp_padding[4]; +}; + +struct tpacket_hdr_variant1 { + __u32 tp_rxhash; + __u32 tp_vlan_tci; + __u16 tp_vlan_tpid; + __u16 tp_padding; +}; + +struct tpacket3_hdr { + __u32 tp_next_offset; + __u32 tp_sec; + __u32 tp_nsec; + __u32 tp_snaplen; + __u32 tp_len; + __u32 tp_status; + __u16 tp_mac; + __u16 tp_net; + /* pkt_hdr variants */ + union { + struct tpacket_hdr_variant1 hv1; + }; + __u8 tp_padding[8]; +}; + +struct tpacket_bd_ts { + unsigned int ts_sec; + union { + unsigned int ts_usec; + unsigned int ts_nsec; + }; +}; + +struct tpacket_hdr_v1 { + __u32 block_status; + __u32 num_pkts; + __u32 offset_to_first_pkt; + + /* Number of valid bytes (including padding) + * blk_len <= tp_block_size + */ + __u32 blk_len; + + /* + * Quite a few uses of sequence number: + * 1. Make sure cache flush etc worked. + * Well, one can argue - why not use the increasing ts below? + * But look at 2. below first. + * 2. When you pass around blocks to other user space decoders, + * you can see which blk[s] is[are] outstanding etc. + * 3. Validate kernel code. + */ + __aligned_u64 seq_num; + + /* + * ts_last_pkt: + * + * Case 1. Block has 'N'(N >=1) packets and TMO'd(timed out) + * ts_last_pkt == 'time-stamp of last packet' and NOT the + * time when the timer fired and the block was closed. + * By providing the ts of the last packet we can absolutely + * guarantee that time-stamp wise, the first packet in the + * next block will never precede the last packet of the + * previous block. + * Case 2. Block has zero packets and TMO'd + * ts_last_pkt = time when the timer fired and the block + * was closed. + * Case 3. Block has 'N' packets and NO TMO. + * ts_last_pkt = time-stamp of the last pkt in the block. + * + * ts_first_pkt: + * Is always the time-stamp when the block was opened. + * Case a) ZERO packets + * No packets to deal with but atleast you know the + * time-interval of this block. + * Case b) Non-zero packets + * Use the ts of the first packet in the block. + * + */ + struct tpacket_bd_ts ts_first_pkt, ts_last_pkt; +}; + +union tpacket_bd_header_u { + struct tpacket_hdr_v1 bh1; +}; + +struct tpacket_block_desc { + __u32 version; + __u32 offset_to_priv; + union tpacket_bd_header_u hdr; +}; + +#define TPACKET2_HDRLEN (TPACKET_ALIGN(sizeof(struct tpacket2_hdr)) + sizeof(struct sockaddr_ll)) +#define TPACKET3_HDRLEN (TPACKET_ALIGN(sizeof(struct tpacket3_hdr)) + sizeof(struct sockaddr_ll)) + +enum tpacket_versions { + TPACKET_V1, + TPACKET_V2, + TPACKET_V3 +}; + +/* + Frame structure: + + - Start. Frame must be aligned to TPACKET_ALIGNMENT=16 + - struct tpacket_hdr + - pad to TPACKET_ALIGNMENT=16 + - struct sockaddr_ll + - Gap, chosen so that packet data (Start+tp_net) alignes to TPACKET_ALIGNMENT=16 + - Start+tp_mac: [ Optional MAC header ] + - Start+tp_net: Packet data, aligned to TPACKET_ALIGNMENT=16. + - Pad to align to TPACKET_ALIGNMENT=16 + */ + +struct tpacket_req { + unsigned int tp_block_size; /* Minimal size of contiguous block */ + unsigned int tp_block_nr; /* Number of blocks */ + unsigned int tp_frame_size; /* Size of frame */ + unsigned int tp_frame_nr; /* Total number of frames */ +}; + +struct tpacket_req3 { + unsigned int tp_block_size; /* Minimal size of contiguous block */ + unsigned int tp_block_nr; /* Number of blocks */ + unsigned int tp_frame_size; /* Size of frame */ + unsigned int tp_frame_nr; /* Total number of frames */ + unsigned int tp_retire_blk_tov; /* timeout in msecs */ + unsigned int tp_sizeof_priv; /* offset to private data area */ + unsigned int tp_feature_req_word; +}; + +union tpacket_req_u { + struct tpacket_req req; + struct tpacket_req3 req3; +}; + +struct packet_mreq { + int mr_ifindex; + unsigned short mr_type; + unsigned short mr_alen; + unsigned char mr_address[8]; +}; + +struct fanout_args { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u16 id; + __u16 type_flags; +#else + __u16 type_flags; + __u16 id; +#endif + __u32 max_num_members; +}; + +#define PACKET_MR_MULTICAST 0 +#define PACKET_MR_PROMISC 1 +#define PACKET_MR_ALLMULTI 2 +#define PACKET_MR_UNICAST 3 + +#endif diff --git a/include/linux-private/linux/if_tunnel.h b/include/linux-private/linux/if_tunnel.h new file mode 100644 index 0000000..edaea41 --- /dev/null +++ b/include/linux-private/linux/if_tunnel.h @@ -0,0 +1,185 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _IF_TUNNEL_H_ +#define _IF_TUNNEL_H_ + +#include +#include +#include +#include +#include + + +#define SIOCGETTUNNEL (SIOCDEVPRIVATE + 0) +#define SIOCADDTUNNEL (SIOCDEVPRIVATE + 1) +#define SIOCDELTUNNEL (SIOCDEVPRIVATE + 2) +#define SIOCCHGTUNNEL (SIOCDEVPRIVATE + 3) +#define SIOCGETPRL (SIOCDEVPRIVATE + 4) +#define SIOCADDPRL (SIOCDEVPRIVATE + 5) +#define SIOCDELPRL (SIOCDEVPRIVATE + 6) +#define SIOCCHGPRL (SIOCDEVPRIVATE + 7) +#define SIOCGET6RD (SIOCDEVPRIVATE + 8) +#define SIOCADD6RD (SIOCDEVPRIVATE + 9) +#define SIOCDEL6RD (SIOCDEVPRIVATE + 10) +#define SIOCCHG6RD (SIOCDEVPRIVATE + 11) + +#define GRE_CSUM __cpu_to_be16(0x8000) +#define GRE_ROUTING __cpu_to_be16(0x4000) +#define GRE_KEY __cpu_to_be16(0x2000) +#define GRE_SEQ __cpu_to_be16(0x1000) +#define GRE_STRICT __cpu_to_be16(0x0800) +#define GRE_REC __cpu_to_be16(0x0700) +#define GRE_ACK __cpu_to_be16(0x0080) +#define GRE_FLAGS __cpu_to_be16(0x0078) +#define GRE_VERSION __cpu_to_be16(0x0007) + +#define GRE_IS_CSUM(f) ((f) & GRE_CSUM) +#define GRE_IS_ROUTING(f) ((f) & GRE_ROUTING) +#define GRE_IS_KEY(f) ((f) & GRE_KEY) +#define GRE_IS_SEQ(f) ((f) & GRE_SEQ) +#define GRE_IS_STRICT(f) ((f) & GRE_STRICT) +#define GRE_IS_REC(f) ((f) & GRE_REC) +#define GRE_IS_ACK(f) ((f) & GRE_ACK) + +#define GRE_VERSION_0 __cpu_to_be16(0x0000) +#define GRE_VERSION_1 __cpu_to_be16(0x0001) +#define GRE_PROTO_PPP __cpu_to_be16(0x880b) +#define GRE_PPTP_KEY_MASK __cpu_to_be32(0xffff) + +struct ip_tunnel_parm { + char name[IFNAMSIZ]; + int link; + __be16 i_flags; + __be16 o_flags; + __be32 i_key; + __be32 o_key; + struct iphdr iph; +}; + +enum { + IFLA_IPTUN_UNSPEC, + IFLA_IPTUN_LINK, + IFLA_IPTUN_LOCAL, + IFLA_IPTUN_REMOTE, + IFLA_IPTUN_TTL, + IFLA_IPTUN_TOS, + IFLA_IPTUN_ENCAP_LIMIT, + IFLA_IPTUN_FLOWINFO, + IFLA_IPTUN_FLAGS, + IFLA_IPTUN_PROTO, + IFLA_IPTUN_PMTUDISC, + IFLA_IPTUN_6RD_PREFIX, + IFLA_IPTUN_6RD_RELAY_PREFIX, + IFLA_IPTUN_6RD_PREFIXLEN, + IFLA_IPTUN_6RD_RELAY_PREFIXLEN, + IFLA_IPTUN_ENCAP_TYPE, + IFLA_IPTUN_ENCAP_FLAGS, + IFLA_IPTUN_ENCAP_SPORT, + IFLA_IPTUN_ENCAP_DPORT, + IFLA_IPTUN_COLLECT_METADATA, + IFLA_IPTUN_FWMARK, + __IFLA_IPTUN_MAX, +}; +#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1) + +enum tunnel_encap_types { + TUNNEL_ENCAP_NONE, + TUNNEL_ENCAP_FOU, + TUNNEL_ENCAP_GUE, + TUNNEL_ENCAP_MPLS, +}; + +#define TUNNEL_ENCAP_FLAG_CSUM (1<<0) +#define TUNNEL_ENCAP_FLAG_CSUM6 (1<<1) +#define TUNNEL_ENCAP_FLAG_REMCSUM (1<<2) + +/* SIT-mode i_flags */ +#define SIT_ISATAP 0x0001 + +struct ip_tunnel_prl { + __be32 addr; + __u16 flags; + __u16 __reserved; + __u32 datalen; + __u32 __reserved2; + /* data follows */ +}; + +/* PRL flags */ +#define PRL_DEFAULT 0x0001 + +struct ip_tunnel_6rd { + struct in6_addr prefix; + __be32 relay_prefix; + __u16 prefixlen; + __u16 relay_prefixlen; +}; + +enum { + IFLA_GRE_UNSPEC, + IFLA_GRE_LINK, + IFLA_GRE_IFLAGS, + IFLA_GRE_OFLAGS, + IFLA_GRE_IKEY, + IFLA_GRE_OKEY, + IFLA_GRE_LOCAL, + IFLA_GRE_REMOTE, + IFLA_GRE_TTL, + IFLA_GRE_TOS, + IFLA_GRE_PMTUDISC, + IFLA_GRE_ENCAP_LIMIT, + IFLA_GRE_FLOWINFO, + IFLA_GRE_FLAGS, + IFLA_GRE_ENCAP_TYPE, + IFLA_GRE_ENCAP_FLAGS, + IFLA_GRE_ENCAP_SPORT, + IFLA_GRE_ENCAP_DPORT, + IFLA_GRE_COLLECT_METADATA, + IFLA_GRE_IGNORE_DF, + IFLA_GRE_FWMARK, + IFLA_GRE_ERSPAN_INDEX, + IFLA_GRE_ERSPAN_VER, + IFLA_GRE_ERSPAN_DIR, + IFLA_GRE_ERSPAN_HWID, + __IFLA_GRE_MAX, +}; + +#define IFLA_GRE_MAX (__IFLA_GRE_MAX - 1) + +/* VTI-mode i_flags */ +#define VTI_ISVTI ((__be16)0x0001) + +enum { + IFLA_VTI_UNSPEC, + IFLA_VTI_LINK, + IFLA_VTI_IKEY, + IFLA_VTI_OKEY, + IFLA_VTI_LOCAL, + IFLA_VTI_REMOTE, + IFLA_VTI_FWMARK, + __IFLA_VTI_MAX, +}; + +#define IFLA_VTI_MAX (__IFLA_VTI_MAX - 1) + +#define TUNNEL_CSUM __cpu_to_be16(0x01) +#define TUNNEL_ROUTING __cpu_to_be16(0x02) +#define TUNNEL_KEY __cpu_to_be16(0x04) +#define TUNNEL_SEQ __cpu_to_be16(0x08) +#define TUNNEL_STRICT __cpu_to_be16(0x10) +#define TUNNEL_REC __cpu_to_be16(0x20) +#define TUNNEL_VERSION __cpu_to_be16(0x40) +#define TUNNEL_NO_KEY __cpu_to_be16(0x80) +#define TUNNEL_DONT_FRAGMENT __cpu_to_be16(0x0100) +#define TUNNEL_OAM __cpu_to_be16(0x0200) +#define TUNNEL_CRIT_OPT __cpu_to_be16(0x0400) +#define TUNNEL_GENEVE_OPT __cpu_to_be16(0x0800) +#define TUNNEL_VXLAN_OPT __cpu_to_be16(0x1000) +#define TUNNEL_NOCACHE __cpu_to_be16(0x2000) +#define TUNNEL_ERSPAN_OPT __cpu_to_be16(0x4000) +#define TUNNEL_GTP_OPT __cpu_to_be16(0x8000) + +#define TUNNEL_OPTIONS_PRESENT \ + (TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT | TUNNEL_ERSPAN_OPT | \ + TUNNEL_GTP_OPT) + +#endif /* _IF_TUNNEL_H_ */ diff --git a/include/linux/if_vlan.h b/include/linux-private/linux/if_vlan.h similarity index 83% rename from include/linux/if_vlan.h rename to include/linux-private/linux/if_vlan.h index 67affd1..04bca79 100644 --- a/include/linux/if_vlan.h +++ b/include/linux-private/linux/if_vlan.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ /* * VLAN An implementation of 802.1Q VLAN tagging. * @@ -13,6 +14,7 @@ #ifndef _LINUX_IF_VLAN_H_ #define _LINUX_IF_VLAN_H_ + /* VLAN IOCTLs are found in sockios.h */ /* Passed in vlan_ioctl_args structure to determine behaviour. */ @@ -30,9 +32,11 @@ enum vlan_ioctl_cmds { }; enum vlan_flags { - VLAN_FLAG_REORDER_HDR = 0x1, - VLAN_FLAG_GVRP = 0x2, - VLAN_FLAG_LOOSE_BINDING = 0x4, + VLAN_FLAG_REORDER_HDR = 0x1, + VLAN_FLAG_GVRP = 0x2, + VLAN_FLAG_LOOSE_BINDING = 0x4, + VLAN_FLAG_MVRP = 0x8, + VLAN_FLAG_BRIDGE_BINDING = 0x10, }; enum vlan_name_types { @@ -53,10 +57,10 @@ struct vlan_ioctl_args { unsigned int skb_priority; unsigned int name_type; unsigned int bind_type; - unsigned int flag; /* Matches vlan_dev_info flags */ + unsigned int flag; /* Matches vlan_dev_priv flags */ } u; short vlan_qos; }; -#endif /* !(_LINUX_IF_VLAN_H_) */ +#endif /* _LINUX_IF_VLAN_H_ */ diff --git a/include/linux-private/linux/in.h b/include/linux-private/linux/in.h new file mode 100644 index 0000000..7bdd684 --- /dev/null +++ b/include/linux-private/linux/in.h @@ -0,0 +1,333 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Definitions of the Internet Protocol. + * + * Version: @(#)in.h 1.0.1 04/21/93 + * + * Authors: Original taken from the GNU Project file. + * Fred N. van Kempen, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _LINUX_IN_H +#define _LINUX_IN_H + +#include +#include +#include +#include + +#if __UAPI_DEF_IN_IPPROTO +/* Standard well-defined IP protocols. */ +enum { + IPPROTO_IP = 0, /* Dummy protocol for TCP */ +#define IPPROTO_IP IPPROTO_IP + IPPROTO_ICMP = 1, /* Internet Control Message Protocol */ +#define IPPROTO_ICMP IPPROTO_ICMP + IPPROTO_IGMP = 2, /* Internet Group Management Protocol */ +#define IPPROTO_IGMP IPPROTO_IGMP + IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94) */ +#define IPPROTO_IPIP IPPROTO_IPIP + IPPROTO_TCP = 6, /* Transmission Control Protocol */ +#define IPPROTO_TCP IPPROTO_TCP + IPPROTO_EGP = 8, /* Exterior Gateway Protocol */ +#define IPPROTO_EGP IPPROTO_EGP + IPPROTO_PUP = 12, /* PUP protocol */ +#define IPPROTO_PUP IPPROTO_PUP + IPPROTO_UDP = 17, /* User Datagram Protocol */ +#define IPPROTO_UDP IPPROTO_UDP + IPPROTO_IDP = 22, /* XNS IDP protocol */ +#define IPPROTO_IDP IPPROTO_IDP + IPPROTO_TP = 29, /* SO Transport Protocol Class 4 */ +#define IPPROTO_TP IPPROTO_TP + IPPROTO_DCCP = 33, /* Datagram Congestion Control Protocol */ +#define IPPROTO_DCCP IPPROTO_DCCP + IPPROTO_IPV6 = 41, /* IPv6-in-IPv4 tunnelling */ +#define IPPROTO_IPV6 IPPROTO_IPV6 + IPPROTO_RSVP = 46, /* RSVP Protocol */ +#define IPPROTO_RSVP IPPROTO_RSVP + IPPROTO_GRE = 47, /* Cisco GRE tunnels (rfc 1701,1702) */ +#define IPPROTO_GRE IPPROTO_GRE + IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */ +#define IPPROTO_ESP IPPROTO_ESP + IPPROTO_AH = 51, /* Authentication Header protocol */ +#define IPPROTO_AH IPPROTO_AH + IPPROTO_MTP = 92, /* Multicast Transport Protocol */ +#define IPPROTO_MTP IPPROTO_MTP + IPPROTO_BEETPH = 94, /* IP option pseudo header for BEET */ +#define IPPROTO_BEETPH IPPROTO_BEETPH + IPPROTO_ENCAP = 98, /* Encapsulation Header */ +#define IPPROTO_ENCAP IPPROTO_ENCAP + IPPROTO_PIM = 103, /* Protocol Independent Multicast */ +#define IPPROTO_PIM IPPROTO_PIM + IPPROTO_COMP = 108, /* Compression Header Protocol */ +#define IPPROTO_COMP IPPROTO_COMP + IPPROTO_L2TP = 115, /* Layer 2 Tunnelling Protocol */ +#define IPPROTO_L2TP IPPROTO_L2TP + IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */ +#define IPPROTO_SCTP IPPROTO_SCTP + IPPROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828) */ +#define IPPROTO_UDPLITE IPPROTO_UDPLITE + IPPROTO_MPLS = 137, /* MPLS in IP (RFC 4023) */ +#define IPPROTO_MPLS IPPROTO_MPLS + IPPROTO_ETHERNET = 143, /* Ethernet-within-IPv6 Encapsulation */ +#define IPPROTO_ETHERNET IPPROTO_ETHERNET + IPPROTO_RAW = 255, /* Raw IP packets */ +#define IPPROTO_RAW IPPROTO_RAW + IPPROTO_MPTCP = 262, /* Multipath TCP connection */ +#define IPPROTO_MPTCP IPPROTO_MPTCP + IPPROTO_MAX +}; +#endif + +#if __UAPI_DEF_IN_ADDR +/* Internet address. */ +struct in_addr { + __be32 s_addr; +}; +#endif + +#define IP_TOS 1 +#define IP_TTL 2 +#define IP_HDRINCL 3 +#define IP_OPTIONS 4 +#define IP_ROUTER_ALERT 5 +#define IP_RECVOPTS 6 +#define IP_RETOPTS 7 +#define IP_PKTINFO 8 +#define IP_PKTOPTIONS 9 +#define IP_MTU_DISCOVER 10 +#define IP_RECVERR 11 +#define IP_RECVTTL 12 +#define IP_RECVTOS 13 +#define IP_MTU 14 +#define IP_FREEBIND 15 +#define IP_IPSEC_POLICY 16 +#define IP_XFRM_POLICY 17 +#define IP_PASSSEC 18 +#define IP_TRANSPARENT 19 + +/* BSD compatibility */ +#define IP_RECVRETOPTS IP_RETOPTS + +/* TProxy original addresses */ +#define IP_ORIGDSTADDR 20 +#define IP_RECVORIGDSTADDR IP_ORIGDSTADDR + +#define IP_MINTTL 21 +#define IP_NODEFRAG 22 +#define IP_CHECKSUM 23 +#define IP_BIND_ADDRESS_NO_PORT 24 +#define IP_RECVFRAGSIZE 25 +#define IP_RECVERR_RFC4884 26 + +/* IP_MTU_DISCOVER values */ +#define IP_PMTUDISC_DONT 0 /* Never send DF frames */ +#define IP_PMTUDISC_WANT 1 /* Use per route hints */ +#define IP_PMTUDISC_DO 2 /* Always DF */ +#define IP_PMTUDISC_PROBE 3 /* Ignore dst pmtu */ +/* Always use interface mtu (ignores dst pmtu) but don't set DF flag. + * Also incoming ICMP frag_needed notifications will be ignored on + * this socket to prevent accepting spoofed ones. + */ +#define IP_PMTUDISC_INTERFACE 4 +/* weaker version of IP_PMTUDISC_INTERFACE, which allows packets to get + * fragmented if they exeed the interface mtu + */ +#define IP_PMTUDISC_OMIT 5 + +#define IP_MULTICAST_IF 32 +#define IP_MULTICAST_TTL 33 +#define IP_MULTICAST_LOOP 34 +#define IP_ADD_MEMBERSHIP 35 +#define IP_DROP_MEMBERSHIP 36 +#define IP_UNBLOCK_SOURCE 37 +#define IP_BLOCK_SOURCE 38 +#define IP_ADD_SOURCE_MEMBERSHIP 39 +#define IP_DROP_SOURCE_MEMBERSHIP 40 +#define IP_MSFILTER 41 +#define MCAST_JOIN_GROUP 42 +#define MCAST_BLOCK_SOURCE 43 +#define MCAST_UNBLOCK_SOURCE 44 +#define MCAST_LEAVE_GROUP 45 +#define MCAST_JOIN_SOURCE_GROUP 46 +#define MCAST_LEAVE_SOURCE_GROUP 47 +#define MCAST_MSFILTER 48 +#define IP_MULTICAST_ALL 49 +#define IP_UNICAST_IF 50 +#define IP_LOCAL_PORT_RANGE 51 +#define IP_PROTOCOL 52 + +#define MCAST_EXCLUDE 0 +#define MCAST_INCLUDE 1 + +/* These need to appear somewhere around here */ +#define IP_DEFAULT_MULTICAST_TTL 1 +#define IP_DEFAULT_MULTICAST_LOOP 1 + +/* Request struct for multicast socket ops */ + +#if __UAPI_DEF_IP_MREQ +struct ip_mreq { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_interface; /* local IP address of interface */ +}; + +struct ip_mreqn { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_address; /* local IP address of interface */ + int imr_ifindex; /* Interface index */ +}; + +struct ip_mreq_source { + __be32 imr_multiaddr; + __be32 imr_interface; + __be32 imr_sourceaddr; +}; + +struct ip_msfilter { + __be32 imsf_multiaddr; + __be32 imsf_interface; + __u32 imsf_fmode; + __u32 imsf_numsrc; + union { + __be32 imsf_slist[1]; + __DECLARE_FLEX_ARRAY(__be32, imsf_slist_flex); + }; +}; + +#define IP_MSFILTER_SIZE(numsrc) \ + (sizeof(struct ip_msfilter) - sizeof(__u32) \ + + (numsrc) * sizeof(__u32)) + +struct group_req { + __u32 gr_interface; /* interface index */ + struct __kernel_sockaddr_storage gr_group; /* group address */ +}; + +struct group_source_req { + __u32 gsr_interface; /* interface index */ + struct __kernel_sockaddr_storage gsr_group; /* group address */ + struct __kernel_sockaddr_storage gsr_source; /* source address */ +}; + +struct group_filter { + union { + struct { + __u32 gf_interface_aux; /* interface index */ + struct __kernel_sockaddr_storage gf_group_aux; /* multicast address */ + __u32 gf_fmode_aux; /* filter mode */ + __u32 gf_numsrc_aux; /* number of sources */ + struct __kernel_sockaddr_storage gf_slist[1]; /* interface index */ + }; + struct { + __u32 gf_interface; /* interface index */ + struct __kernel_sockaddr_storage gf_group; /* multicast address */ + __u32 gf_fmode; /* filter mode */ + __u32 gf_numsrc; /* number of sources */ + struct __kernel_sockaddr_storage gf_slist_flex[]; /* interface index */ + }; + }; +}; + +#define GROUP_FILTER_SIZE(numsrc) \ + (sizeof(struct group_filter) - sizeof(struct __kernel_sockaddr_storage) \ + + (numsrc) * sizeof(struct __kernel_sockaddr_storage)) +#endif + +#if __UAPI_DEF_IN_PKTINFO +struct in_pktinfo { + int ipi_ifindex; + struct in_addr ipi_spec_dst; + struct in_addr ipi_addr; +}; +#endif + +/* Structure describing an Internet (IP) socket address. */ +#if __UAPI_DEF_SOCKADDR_IN +#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ +struct sockaddr_in { + __kernel_sa_family_t sin_family; /* Address family */ + __be16 sin_port; /* Port number */ + struct in_addr sin_addr; /* Internet address */ + + /* Pad to size of `struct sockaddr'. */ + unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) - + sizeof(unsigned short int) - sizeof(struct in_addr)]; +}; +#define sin_zero __pad /* for BSD UNIX comp. -FvK */ +#endif + +#if __UAPI_DEF_IN_CLASS +/* + * Definitions of the bits in an Internet address integer. + * On subnets, host and network parts are found according + * to the subnet mask, not these masks. + */ +#define IN_CLASSA(a) ((((long int) (a)) & 0x80000000) == 0) +#define IN_CLASSA_NET 0xff000000 +#define IN_CLASSA_NSHIFT 24 +#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET) +#define IN_CLASSA_MAX 128 + +#define IN_CLASSB(a) ((((long int) (a)) & 0xc0000000) == 0x80000000) +#define IN_CLASSB_NET 0xffff0000 +#define IN_CLASSB_NSHIFT 16 +#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET) +#define IN_CLASSB_MAX 65536 + +#define IN_CLASSC(a) ((((long int) (a)) & 0xe0000000) == 0xc0000000) +#define IN_CLASSC_NET 0xffffff00 +#define IN_CLASSC_NSHIFT 8 +#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET) + +#define IN_CLASSD(a) ((((long int) (a)) & 0xf0000000) == 0xe0000000) +#define IN_MULTICAST(a) IN_CLASSD(a) +#define IN_MULTICAST_NET 0xe0000000 + +#define IN_BADCLASS(a) (((long int) (a) ) == (long int)0xffffffff) +#define IN_EXPERIMENTAL(a) IN_BADCLASS((a)) + +#define IN_CLASSE(a) ((((long int) (a)) & 0xf0000000) == 0xf0000000) +#define IN_CLASSE_NET 0xffffffff +#define IN_CLASSE_NSHIFT 0 + +/* Address to accept any incoming messages. */ +#define INADDR_ANY ((unsigned long int) 0x00000000) + +/* Address to send to all hosts. */ +#define INADDR_BROADCAST ((unsigned long int) 0xffffffff) + +/* Address indicating an error return. */ +#define INADDR_NONE ((unsigned long int) 0xffffffff) + +/* Dummy address for src of ICMP replies if no real address is set (RFC7600). */ +#define INADDR_DUMMY ((unsigned long int) 0xc0000008) + +/* Network number for local host loopback. */ +#define IN_LOOPBACKNET 127 + +/* Address to loopback in software to local host. */ +#define INADDR_LOOPBACK 0x7f000001 /* 127.0.0.1 */ +#define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000) + +/* Defines for Multicast INADDR */ +#define INADDR_UNSPEC_GROUP 0xe0000000U /* 224.0.0.0 */ +#define INADDR_ALLHOSTS_GROUP 0xe0000001U /* 224.0.0.1 */ +#define INADDR_ALLRTRS_GROUP 0xe0000002U /* 224.0.0.2 */ +#define INADDR_ALLSNOOPERS_GROUP 0xe000006aU /* 224.0.0.106 */ +#define INADDR_MAX_LOCAL_GROUP 0xe00000ffU /* 224.0.0.255 */ +#endif + +/* contains the htonl type stuff.. */ +#include + + +#endif /* _LINUX_IN_H */ diff --git a/include/linux-private/linux/in6.h b/include/linux-private/linux/in6.h new file mode 100644 index 0000000..a17363e --- /dev/null +++ b/include/linux-private/linux/in6.h @@ -0,0 +1,302 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * Types and definitions for AF_INET6 + * Linux INET6 implementation + * + * Authors: + * Pedro Roque + * + * Sources: + * IPv6 Program Interfaces for BSD Systems + * + * + * Advanced Sockets API for IPv6 + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _LINUX_IN6_H +#define _LINUX_IN6_H + +#include +#include + +/* + * IPv6 address structure + */ + +#if __UAPI_DEF_IN6_ADDR +struct in6_addr { + union { + __u8 u6_addr8[16]; +#if __UAPI_DEF_IN6_ADDR_ALT + __be16 u6_addr16[8]; + __be32 u6_addr32[4]; +#endif + } in6_u; +#define s6_addr in6_u.u6_addr8 +#if __UAPI_DEF_IN6_ADDR_ALT +#define s6_addr16 in6_u.u6_addr16 +#define s6_addr32 in6_u.u6_addr32 +#endif +}; +#endif /* __UAPI_DEF_IN6_ADDR */ + +#if __UAPI_DEF_SOCKADDR_IN6 +struct sockaddr_in6 { + unsigned short int sin6_family; /* AF_INET6 */ + __be16 sin6_port; /* Transport layer port # */ + __be32 sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ + __u32 sin6_scope_id; /* scope id (new in RFC2553) */ +}; +#endif /* __UAPI_DEF_SOCKADDR_IN6 */ + +#if __UAPI_DEF_IPV6_MREQ +struct ipv6_mreq { + /* IPv6 multicast address of group */ + struct in6_addr ipv6mr_multiaddr; + + /* local IPv6 address of interface */ + int ipv6mr_ifindex; +}; +#endif /* __UAPI_DEF_IVP6_MREQ */ + +#define ipv6mr_acaddr ipv6mr_multiaddr + +struct in6_flowlabel_req { + struct in6_addr flr_dst; + __be32 flr_label; + __u8 flr_action; + __u8 flr_share; + __u16 flr_flags; + __u16 flr_expires; + __u16 flr_linger; + __u32 __flr_pad; + /* Options in format of IPV6_PKTOPTIONS */ +}; + +#define IPV6_FL_A_GET 0 +#define IPV6_FL_A_PUT 1 +#define IPV6_FL_A_RENEW 2 + +#define IPV6_FL_F_CREATE 1 +#define IPV6_FL_F_EXCL 2 +#define IPV6_FL_F_REFLECT 4 +#define IPV6_FL_F_REMOTE 8 + +#define IPV6_FL_S_NONE 0 +#define IPV6_FL_S_EXCL 1 +#define IPV6_FL_S_PROCESS 2 +#define IPV6_FL_S_USER 3 +#define IPV6_FL_S_ANY 255 + + +/* + * Bitmask constant declarations to help applications select out the + * flow label and priority fields. + * + * Note that this are in host byte order while the flowinfo field of + * sockaddr_in6 is in network byte order. + */ + +#define IPV6_FLOWINFO_FLOWLABEL 0x000fffff +#define IPV6_FLOWINFO_PRIORITY 0x0ff00000 + +/* These definitions are obsolete */ +#define IPV6_PRIORITY_UNCHARACTERIZED 0x0000 +#define IPV6_PRIORITY_FILLER 0x0100 +#define IPV6_PRIORITY_UNATTENDED 0x0200 +#define IPV6_PRIORITY_RESERVED1 0x0300 +#define IPV6_PRIORITY_BULK 0x0400 +#define IPV6_PRIORITY_RESERVED2 0x0500 +#define IPV6_PRIORITY_INTERACTIVE 0x0600 +#define IPV6_PRIORITY_CONTROL 0x0700 +#define IPV6_PRIORITY_8 0x0800 +#define IPV6_PRIORITY_9 0x0900 +#define IPV6_PRIORITY_10 0x0a00 +#define IPV6_PRIORITY_11 0x0b00 +#define IPV6_PRIORITY_12 0x0c00 +#define IPV6_PRIORITY_13 0x0d00 +#define IPV6_PRIORITY_14 0x0e00 +#define IPV6_PRIORITY_15 0x0f00 + +/* + * IPV6 extension headers + */ +#if __UAPI_DEF_IPPROTO_V6 +#define IPPROTO_HOPOPTS 0 /* IPv6 hop-by-hop options */ +#define IPPROTO_ROUTING 43 /* IPv6 routing header */ +#define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */ +#define IPPROTO_ICMPV6 58 /* ICMPv6 */ +#define IPPROTO_NONE 59 /* IPv6 no next header */ +#define IPPROTO_DSTOPTS 60 /* IPv6 destination options */ +#define IPPROTO_MH 135 /* IPv6 mobility header */ +#endif /* __UAPI_DEF_IPPROTO_V6 */ + +/* + * IPv6 TLV options. + */ +#define IPV6_TLV_PAD1 0 +#define IPV6_TLV_PADN 1 +#define IPV6_TLV_ROUTERALERT 5 +#define IPV6_TLV_CALIPSO 7 /* RFC 5570 */ +#define IPV6_TLV_IOAM 49 /* TEMPORARY IANA allocation for IOAM */ +#define IPV6_TLV_JUMBO 194 +#define IPV6_TLV_HAO 201 /* home address option */ + +/* + * IPV6 socket options + */ +#if __UAPI_DEF_IPV6_OPTIONS +#define IPV6_ADDRFORM 1 +#define IPV6_2292PKTINFO 2 +#define IPV6_2292HOPOPTS 3 +#define IPV6_2292DSTOPTS 4 +#define IPV6_2292RTHDR 5 +#define IPV6_2292PKTOPTIONS 6 +#define IPV6_CHECKSUM 7 +#define IPV6_2292HOPLIMIT 8 +#define IPV6_NEXTHOP 9 +#define IPV6_AUTHHDR 10 /* obsolete */ +#define IPV6_FLOWINFO 11 + +#define IPV6_UNICAST_HOPS 16 +#define IPV6_MULTICAST_IF 17 +#define IPV6_MULTICAST_HOPS 18 +#define IPV6_MULTICAST_LOOP 19 +#define IPV6_ADD_MEMBERSHIP 20 +#define IPV6_DROP_MEMBERSHIP 21 +#define IPV6_ROUTER_ALERT 22 +#define IPV6_MTU_DISCOVER 23 +#define IPV6_MTU 24 +#define IPV6_RECVERR 25 +#define IPV6_V6ONLY 26 +#define IPV6_JOIN_ANYCAST 27 +#define IPV6_LEAVE_ANYCAST 28 +#define IPV6_MULTICAST_ALL 29 +#define IPV6_ROUTER_ALERT_ISOLATE 30 +#define IPV6_RECVERR_RFC4884 31 + +/* IPV6_MTU_DISCOVER values */ +#define IPV6_PMTUDISC_DONT 0 +#define IPV6_PMTUDISC_WANT 1 +#define IPV6_PMTUDISC_DO 2 +#define IPV6_PMTUDISC_PROBE 3 +/* same as IPV6_PMTUDISC_PROBE, provided for symetry with IPv4 + * also see comments on IP_PMTUDISC_INTERFACE + */ +#define IPV6_PMTUDISC_INTERFACE 4 +/* weaker version of IPV6_PMTUDISC_INTERFACE, which allows packets to + * get fragmented if they exceed the interface mtu + */ +#define IPV6_PMTUDISC_OMIT 5 + +/* Flowlabel */ +#define IPV6_FLOWLABEL_MGR 32 +#define IPV6_FLOWINFO_SEND 33 + +#define IPV6_IPSEC_POLICY 34 +#define IPV6_XFRM_POLICY 35 +#define IPV6_HDRINCL 36 +#endif + +/* + * Multicast: + * Following socket options are shared between IPv4 and IPv6. + * + * MCAST_JOIN_GROUP 42 + * MCAST_BLOCK_SOURCE 43 + * MCAST_UNBLOCK_SOURCE 44 + * MCAST_LEAVE_GROUP 45 + * MCAST_JOIN_SOURCE_GROUP 46 + * MCAST_LEAVE_SOURCE_GROUP 47 + * MCAST_MSFILTER 48 + */ + +/* + * Advanced API (RFC3542) (1) + * + * Note: IPV6_RECVRTHDRDSTOPTS does not exist. see net/ipv6/datagram.c. + */ + +#define IPV6_RECVPKTINFO 49 +#define IPV6_PKTINFO 50 +#define IPV6_RECVHOPLIMIT 51 +#define IPV6_HOPLIMIT 52 +#define IPV6_RECVHOPOPTS 53 +#define IPV6_HOPOPTS 54 +#define IPV6_RTHDRDSTOPTS 55 +#define IPV6_RECVRTHDR 56 +#define IPV6_RTHDR 57 +#define IPV6_RECVDSTOPTS 58 +#define IPV6_DSTOPTS 59 +#define IPV6_RECVPATHMTU 60 +#define IPV6_PATHMTU 61 +#define IPV6_DONTFRAG 62 +#if 0 /* not yet */ +#define IPV6_USE_MIN_MTU 63 +#endif + +/* + * Netfilter (1) + * + * Following socket options are used in ip6_tables; + * see include/linux/netfilter_ipv6/ip6_tables.h. + * + * IP6T_SO_SET_REPLACE / IP6T_SO_GET_INFO 64 + * IP6T_SO_SET_ADD_COUNTERS / IP6T_SO_GET_ENTRIES 65 + */ + +/* + * Advanced API (RFC3542) (2) + */ +#define IPV6_RECVTCLASS 66 +#define IPV6_TCLASS 67 + +/* + * Netfilter (2) + * + * Following socket options are used in ip6_tables; + * see include/linux/netfilter_ipv6/ip6_tables.h. + * + * IP6T_SO_GET_REVISION_MATCH 68 + * IP6T_SO_GET_REVISION_TARGET 69 + * IP6T_SO_ORIGINAL_DST 80 + */ + +#define IPV6_AUTOFLOWLABEL 70 +/* RFC5014: Source address selection */ +#define IPV6_ADDR_PREFERENCES 72 + +#define IPV6_PREFER_SRC_TMP 0x0001 +#define IPV6_PREFER_SRC_PUBLIC 0x0002 +#define IPV6_PREFER_SRC_PUBTMP_DEFAULT 0x0100 +#define IPV6_PREFER_SRC_COA 0x0004 +#define IPV6_PREFER_SRC_HOME 0x0400 +#define IPV6_PREFER_SRC_CGA 0x0008 +#define IPV6_PREFER_SRC_NONCGA 0x0800 + +/* RFC5082: Generalized Ttl Security Mechanism */ +#define IPV6_MINHOPCOUNT 73 + +#define IPV6_ORIGDSTADDR 74 +#define IPV6_RECVORIGDSTADDR IPV6_ORIGDSTADDR +#define IPV6_TRANSPARENT 75 +#define IPV6_UNICAST_IF 76 +#define IPV6_RECVFRAGSIZE 77 +#define IPV6_FREEBIND 78 + +/* + * Multicast Routing: + * see include/uapi/linux/mroute6.h. + * + * MRT6_BASE 200 + * ... + * MRT6_MAX + */ +#endif /* _LINUX_IN6_H */ diff --git a/include/linux-private/linux/in_route.h b/include/linux-private/linux/in_route.h new file mode 100644 index 0000000..0cc2c23 --- /dev/null +++ b/include/linux-private/linux/in_route.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_IN_ROUTE_H +#define _LINUX_IN_ROUTE_H + +/* IPv4 routing cache flags */ + +#define RTCF_DEAD RTNH_F_DEAD +#define RTCF_ONLINK RTNH_F_ONLINK + +/* Obsolete flag. About to be deleted */ +#define RTCF_NOPMTUDISC RTM_F_NOPMTUDISC + +#define RTCF_NOTIFY 0x00010000 +#define RTCF_DIRECTDST 0x00020000 /* unused */ +#define RTCF_REDIRECTED 0x00040000 +#define RTCF_TPROXY 0x00080000 /* unused */ + +#define RTCF_FAST 0x00200000 /* unused */ +#define RTCF_MASQ 0x00400000 /* unused */ +#define RTCF_SNAT 0x00800000 /* unused */ +#define RTCF_DOREDIRECT 0x01000000 +#define RTCF_DIRECTSRC 0x04000000 +#define RTCF_DNAT 0x08000000 +#define RTCF_BROADCAST 0x10000000 +#define RTCF_MULTICAST 0x20000000 +#define RTCF_REJECT 0x40000000 /* unused */ +#define RTCF_LOCAL 0x80000000 + +#define RTCF_NAT (RTCF_DNAT|RTCF_SNAT) + +#define RT_TOS(tos) ((tos)&IPTOS_TOS_MASK) + +#endif /* _LINUX_IN_ROUTE_H */ diff --git a/include/linux-private/linux/inet_diag.h b/include/linux-private/linux/inet_diag.h new file mode 100644 index 0000000..d81cb69 --- /dev/null +++ b/include/linux-private/linux/inet_diag.h @@ -0,0 +1,239 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _INET_DIAG_H_ +#define _INET_DIAG_H_ + +#include + +/* Just some random number */ +#define TCPDIAG_GETSOCK 18 +#define DCCPDIAG_GETSOCK 19 + +#define INET_DIAG_GETSOCK_MAX 24 + +/* Socket identity */ +struct inet_diag_sockid { + __be16 idiag_sport; + __be16 idiag_dport; + __be32 idiag_src[4]; + __be32 idiag_dst[4]; + __u32 idiag_if; + __u32 idiag_cookie[2]; +#define INET_DIAG_NOCOOKIE (~0U) +}; + +/* Request structure */ + +struct inet_diag_req { + __u8 idiag_family; /* Family of addresses. */ + __u8 idiag_src_len; + __u8 idiag_dst_len; + __u8 idiag_ext; /* Query extended information */ + + struct inet_diag_sockid id; + + __u32 idiag_states; /* States to dump */ + __u32 idiag_dbs; /* Tables to dump (NI) */ +}; + +struct inet_diag_req_v2 { + __u8 sdiag_family; + __u8 sdiag_protocol; + __u8 idiag_ext; + __u8 pad; + __u32 idiag_states; + struct inet_diag_sockid id; +}; + +/* + * SOCK_RAW sockets require the underlied protocol to be + * additionally specified so we can use @pad member for + * this, but we can't rename it because userspace programs + * still may depend on this name. Instead lets use another + * structure definition as an alias for struct + * @inet_diag_req_v2. + */ +struct inet_diag_req_raw { + __u8 sdiag_family; + __u8 sdiag_protocol; + __u8 idiag_ext; + __u8 sdiag_raw_protocol; + __u32 idiag_states; + struct inet_diag_sockid id; +}; + +enum { + INET_DIAG_REQ_NONE, + INET_DIAG_REQ_BYTECODE, + INET_DIAG_REQ_SK_BPF_STORAGES, + INET_DIAG_REQ_PROTOCOL, + __INET_DIAG_REQ_MAX, +}; + +#define INET_DIAG_REQ_MAX (__INET_DIAG_REQ_MAX - 1) + +/* Bytecode is sequence of 4 byte commands followed by variable arguments. + * All the commands identified by "code" are conditional jumps forward: + * to offset cc+"yes" or to offset cc+"no". "yes" is supposed to be + * length of the command and its arguments. + */ + +struct inet_diag_bc_op { + unsigned char code; + unsigned char yes; + unsigned short no; +}; + +enum { + INET_DIAG_BC_NOP, + INET_DIAG_BC_JMP, + INET_DIAG_BC_S_GE, + INET_DIAG_BC_S_LE, + INET_DIAG_BC_D_GE, + INET_DIAG_BC_D_LE, + INET_DIAG_BC_AUTO, + INET_DIAG_BC_S_COND, + INET_DIAG_BC_D_COND, + INET_DIAG_BC_DEV_COND, /* u32 ifindex */ + INET_DIAG_BC_MARK_COND, + INET_DIAG_BC_S_EQ, + INET_DIAG_BC_D_EQ, + INET_DIAG_BC_CGROUP_COND, /* u64 cgroup v2 ID */ +}; + +struct inet_diag_hostcond { + __u8 family; + __u8 prefix_len; + int port; + __be32 addr[]; +}; + +struct inet_diag_markcond { + __u32 mark; + __u32 mask; +}; + +/* Base info structure. It contains socket identity (addrs/ports/cookie) + * and, alas, the information shown by netstat. */ +struct inet_diag_msg { + __u8 idiag_family; + __u8 idiag_state; + __u8 idiag_timer; + __u8 idiag_retrans; + + struct inet_diag_sockid id; + + __u32 idiag_expires; + __u32 idiag_rqueue; + __u32 idiag_wqueue; + __u32 idiag_uid; + __u32 idiag_inode; +}; + +/* Extensions */ + +enum { + INET_DIAG_NONE, + INET_DIAG_MEMINFO, + INET_DIAG_INFO, + INET_DIAG_VEGASINFO, + INET_DIAG_CONG, + INET_DIAG_TOS, + INET_DIAG_TCLASS, + INET_DIAG_SKMEMINFO, + INET_DIAG_SHUTDOWN, + + /* + * Next extenstions cannot be requested in struct inet_diag_req_v2: + * its field idiag_ext has only 8 bits. + */ + + INET_DIAG_DCTCPINFO, /* request as INET_DIAG_VEGASINFO */ + INET_DIAG_PROTOCOL, /* response attribute only */ + INET_DIAG_SKV6ONLY, + INET_DIAG_LOCALS, + INET_DIAG_PEERS, + INET_DIAG_PAD, + INET_DIAG_MARK, /* only with CAP_NET_ADMIN */ + INET_DIAG_BBRINFO, /* request as INET_DIAG_VEGASINFO */ + INET_DIAG_CLASS_ID, /* request as INET_DIAG_TCLASS */ + INET_DIAG_MD5SIG, + INET_DIAG_ULP_INFO, + INET_DIAG_SK_BPF_STORAGES, + INET_DIAG_CGROUP_ID, + INET_DIAG_SOCKOPT, + __INET_DIAG_MAX, +}; + +#define INET_DIAG_MAX (__INET_DIAG_MAX - 1) + +enum { + INET_ULP_INFO_UNSPEC, + INET_ULP_INFO_NAME, + INET_ULP_INFO_TLS, + INET_ULP_INFO_MPTCP, + __INET_ULP_INFO_MAX, +}; +#define INET_ULP_INFO_MAX (__INET_ULP_INFO_MAX - 1) + +/* INET_DIAG_MEM */ + +struct inet_diag_meminfo { + __u32 idiag_rmem; + __u32 idiag_wmem; + __u32 idiag_fmem; + __u32 idiag_tmem; +}; + +/* INET_DIAG_SOCKOPT */ + +struct inet_diag_sockopt { + __u8 recverr:1, + is_icsk:1, + freebind:1, + hdrincl:1, + mc_loop:1, + transparent:1, + mc_all:1, + nodefrag:1; + __u8 bind_address_no_port:1, + recverr_rfc4884:1, + defer_connect:1, + unused:5; +}; + +/* INET_DIAG_VEGASINFO */ + +struct tcpvegas_info { + __u32 tcpv_enabled; + __u32 tcpv_rttcnt; + __u32 tcpv_rtt; + __u32 tcpv_minrtt; +}; + +/* INET_DIAG_DCTCPINFO */ + +struct tcp_dctcp_info { + __u16 dctcp_enabled; + __u16 dctcp_ce_state; + __u32 dctcp_alpha; + __u32 dctcp_ab_ecn; + __u32 dctcp_ab_tot; +}; + +/* INET_DIAG_BBRINFO */ + +struct tcp_bbr_info { + /* u64 bw: max-filtered BW (app throughput) estimate in Byte per sec: */ + __u32 bbr_bw_lo; /* lower 32 bits of bw */ + __u32 bbr_bw_hi; /* upper 32 bits of bw */ + __u32 bbr_min_rtt; /* min-filtered RTT in uSec */ + __u32 bbr_pacing_gain; /* pacing gain shifted left 8 bits */ + __u32 bbr_cwnd_gain; /* cwnd gain shifted left 8 bits */ +}; + +union tcp_cc_info { + struct tcpvegas_info vegas; + struct tcp_dctcp_info dctcp; + struct tcp_bbr_info bbr; +}; +#endif /* _INET_DIAG_H_ */ diff --git a/include/linux-private/linux/ioctl.h b/include/linux-private/linux/ioctl.h new file mode 100644 index 0000000..b292e80 --- /dev/null +++ b/include/linux-private/linux/ioctl.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_IOCTL_H +#define _LINUX_IOCTL_H + +#include + +#endif /* _LINUX_IOCTL_H */ + diff --git a/include/linux-private/linux/ip.h b/include/linux-private/linux/ip.h new file mode 100644 index 0000000..9b4dd89 --- /dev/null +++ b/include/linux-private/linux/ip.h @@ -0,0 +1,181 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Definitions for the IP protocol. + * + * Version: @(#)ip.h 1.0.2 04/28/93 + * + * Authors: Fred N. van Kempen, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _LINUX_IP_H +#define _LINUX_IP_H +#include +#include +#include + +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_TOS(tos) ((tos)&IPTOS_TOS_MASK) +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_MINCOST 0x02 + +#define IPTOS_PREC_MASK 0xE0 +#define IPTOS_PREC(tos) ((tos)&IPTOS_PREC_MASK) +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_ROUTINE 0x00 + + +/* IP options */ +#define IPOPT_COPY 0x80 +#define IPOPT_CLASS_MASK 0x60 +#define IPOPT_NUMBER_MASK 0x1f + +#define IPOPT_COPIED(o) ((o)&IPOPT_COPY) +#define IPOPT_CLASS(o) ((o)&IPOPT_CLASS_MASK) +#define IPOPT_NUMBER(o) ((o)&IPOPT_NUMBER_MASK) + +#define IPOPT_CONTROL 0x00 +#define IPOPT_RESERVED1 0x20 +#define IPOPT_MEASUREMENT 0x40 +#define IPOPT_RESERVED2 0x60 + +#define IPOPT_END (0 |IPOPT_CONTROL) +#define IPOPT_NOOP (1 |IPOPT_CONTROL) +#define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY) +#define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY) +#define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT) +#define IPOPT_CIPSO (6 |IPOPT_CONTROL|IPOPT_COPY) +#define IPOPT_RR (7 |IPOPT_CONTROL) +#define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY) +#define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY) +#define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY) + +#define IPVERSION 4 +#define MAXTTL 255 +#define IPDEFTTL 64 + +#define IPOPT_OPTVAL 0 +#define IPOPT_OLEN 1 +#define IPOPT_OFFSET 2 +#define IPOPT_MINOFF 4 +#define MAX_IPOPTLEN 40 +#define IPOPT_NOP IPOPT_NOOP +#define IPOPT_EOL IPOPT_END +#define IPOPT_TS IPOPT_TIMESTAMP + +#define IPOPT_TS_TSONLY 0 /* timestamps only */ +#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */ +#define IPOPT_TS_PRESPEC 3 /* specified modules only */ + +#define IPV4_BEET_PHMAXLEN 8 + +struct iphdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 ihl:4, + version:4; +#elif defined (__BIG_ENDIAN_BITFIELD) + __u8 version:4, + ihl:4; +#else +#error "Please fix " +#endif + __u8 tos; + __be16 tot_len; + __be16 id; + __be16 frag_off; + __u8 ttl; + __u8 protocol; + __sum16 check; + __struct_group(/* no tag */, addrs, /* no attrs */, + __be32 saddr; + __be32 daddr; + ); + /*The options start here. */ +}; + + +struct ip_auth_hdr { + __u8 nexthdr; + __u8 hdrlen; /* This one is measured in 32 bit units! */ + __be16 reserved; + __be32 spi; + __be32 seq_no; /* Sequence number */ + __u8 auth_data[]; /* Variable len but >=4. Mind the 64 bit alignment! */ +}; + +struct ip_esp_hdr { + __be32 spi; + __be32 seq_no; /* Sequence number */ + __u8 enc_data[]; /* Variable len but >=8. Mind the 64 bit alignment! */ +}; + +struct ip_comp_hdr { + __u8 nexthdr; + __u8 flags; + __be16 cpi; +}; + +struct ip_beet_phdr { + __u8 nexthdr; + __u8 hdrlen; + __u8 padlen; + __u8 reserved; +}; + +/* index values for the variables in ipv4_devconf */ +enum +{ + IPV4_DEVCONF_FORWARDING=1, + IPV4_DEVCONF_MC_FORWARDING, + IPV4_DEVCONF_PROXY_ARP, + IPV4_DEVCONF_ACCEPT_REDIRECTS, + IPV4_DEVCONF_SECURE_REDIRECTS, + IPV4_DEVCONF_SEND_REDIRECTS, + IPV4_DEVCONF_SHARED_MEDIA, + IPV4_DEVCONF_RP_FILTER, + IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE, + IPV4_DEVCONF_BOOTP_RELAY, + IPV4_DEVCONF_LOG_MARTIANS, + IPV4_DEVCONF_TAG, + IPV4_DEVCONF_ARPFILTER, + IPV4_DEVCONF_MEDIUM_ID, + IPV4_DEVCONF_NOXFRM, + IPV4_DEVCONF_NOPOLICY, + IPV4_DEVCONF_FORCE_IGMP_VERSION, + IPV4_DEVCONF_ARP_ANNOUNCE, + IPV4_DEVCONF_ARP_IGNORE, + IPV4_DEVCONF_PROMOTE_SECONDARIES, + IPV4_DEVCONF_ARP_ACCEPT, + IPV4_DEVCONF_ARP_NOTIFY, + IPV4_DEVCONF_ACCEPT_LOCAL, + IPV4_DEVCONF_SRC_VMARK, + IPV4_DEVCONF_PROXY_ARP_PVLAN, + IPV4_DEVCONF_ROUTE_LOCALNET, + IPV4_DEVCONF_IGMPV2_UNSOLICITED_REPORT_INTERVAL, + IPV4_DEVCONF_IGMPV3_UNSOLICITED_REPORT_INTERVAL, + IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN, + IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST, + IPV4_DEVCONF_DROP_GRATUITOUS_ARP, + IPV4_DEVCONF_BC_FORWARDING, + IPV4_DEVCONF_ARP_EVICT_NOCARRIER, + __IPV4_DEVCONF_MAX +}; + +#define IPV4_DEVCONF_MAX (__IPV4_DEVCONF_MAX - 1) + +#endif /* _LINUX_IP_H */ diff --git a/include/linux/ipv6.h b/include/linux-private/linux/ipv6.h similarity index 60% rename from include/linux/ipv6.h rename to include/linux-private/linux/ipv6.h index f16349d..fcf05a6 100644 --- a/include/linux/ipv6.h +++ b/include/linux-private/linux/ipv6.h @@ -1,6 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef _IPV6_H #define _IPV6_H +#include +#include +#include +#include #include /* The latest drafts declared increase in minimal mtu up to 1280. */ @@ -13,10 +18,31 @@ * *under construction* */ +#if __UAPI_DEF_IN6_PKTINFO +struct in6_pktinfo { + struct in6_addr ipi6_addr; + int ipi6_ifindex; +}; +#endif + +#if __UAPI_DEF_IP6_MTUINFO +struct ip6_mtuinfo { + struct sockaddr_in6 ip6m_addr; + __u32 ip6m_mtu; +}; +#endif + +struct in6_ifreq { + struct in6_addr ifr6_addr; + __u32 ifr6_prefixlen; + int ifr6_ifindex; +}; #define IPV6_SRCRT_STRICT 0x01 /* Deprecated; will be removed */ #define IPV6_SRCRT_TYPE_0 0 /* Deprecated; will be removed */ #define IPV6_SRCRT_TYPE_2 2 /* IPv6 type 2 Routing Header */ +#define IPV6_SRCRT_TYPE_3 3 /* RPL Segment Routing with IPv6 */ +#define IPV6_SRCRT_TYPE_4 4 /* Segment Routing with IPv6 */ /* * routing header @@ -45,6 +71,8 @@ struct ipv6_opt_hdr { #define ipv6_destopt_hdr ipv6_opt_hdr #define ipv6_hopopt_hdr ipv6_opt_hdr +/* Router Alert option values (RFC2711) */ +#define IPV6_OPT_ROUTERALERT_MLD 0x0000 /* MLD(RFC2710) */ /* * routing header type 0 (used in cmsghdr struct) @@ -53,7 +81,7 @@ struct ipv6_opt_hdr { struct rt0_hdr { struct ipv6_rt_hdr rt_hdr; __u32 reserved; - struct in6_addr addr[0]; + struct in6_addr addr[]; #define rt0_type rt_hdr.type }; @@ -103,8 +131,10 @@ struct ipv6hdr { __u8 nexthdr; __u8 hop_limit; - struct in6_addr saddr; - struct in6_addr daddr; + __struct_group(/* no tag */, addrs, /* no attrs */, + struct in6_addr saddr; + struct in6_addr daddr; + ); }; @@ -139,6 +169,35 @@ enum { DEVCONF_DISABLE_IPV6, DEVCONF_ACCEPT_DAD, DEVCONF_FORCE_TLLAO, + DEVCONF_NDISC_NOTIFY, + DEVCONF_MLDV1_UNSOLICITED_REPORT_INTERVAL, + DEVCONF_MLDV2_UNSOLICITED_REPORT_INTERVAL, + DEVCONF_SUPPRESS_FRAG_NDISC, + DEVCONF_ACCEPT_RA_FROM_LOCAL, + DEVCONF_USE_OPTIMISTIC, + DEVCONF_ACCEPT_RA_MTU, + DEVCONF_STABLE_SECRET, + DEVCONF_USE_OIF_ADDRS_ONLY, + DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT, + DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN, + DEVCONF_DROP_UNICAST_IN_L2_MULTICAST, + DEVCONF_DROP_UNSOLICITED_NA, + DEVCONF_KEEP_ADDR_ON_DOWN, + DEVCONF_RTR_SOLICIT_MAX_INTERVAL, + DEVCONF_SEG6_ENABLED, + DEVCONF_SEG6_REQUIRE_HMAC, + DEVCONF_ENHANCED_DAD, + DEVCONF_ADDR_GEN_MODE, + DEVCONF_DISABLE_POLICY, + DEVCONF_ACCEPT_RA_RT_INFO_MIN_PLEN, + DEVCONF_NDISC_TCLASS, + DEVCONF_RPL_SEG_ENABLED, + DEVCONF_RA_DEFRTR_METRIC, + DEVCONF_IOAM6_ENABLED, + DEVCONF_IOAM6_ID, + DEVCONF_IOAM6_ID_WIDE, + DEVCONF_NDISC_EVICT_NOCARRIER, + DEVCONF_ACCEPT_UNTRACKED_NA, DEVCONF_MAX }; diff --git a/include/linux-private/linux/libc-compat.h b/include/linux-private/linux/libc-compat.h new file mode 100644 index 0000000..a159991 --- /dev/null +++ b/include/linux-private/linux/libc-compat.h @@ -0,0 +1,267 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Compatibility interface for userspace libc header coordination: + * + * Define compatibility macros that are used to control the inclusion or + * exclusion of UAPI structures and definitions in coordination with another + * userspace C library. + * + * This header is intended to solve the problem of UAPI definitions that + * conflict with userspace definitions. If a UAPI header has such conflicting + * definitions then the solution is as follows: + * + * * Synchronize the UAPI header and the libc headers so either one can be + * used and such that the ABI is preserved. If this is not possible then + * no simple compatibility interface exists (you need to write translating + * wrappers and rename things) and you can't use this interface. + * + * Then follow this process: + * + * (a) Include libc-compat.h in the UAPI header. + * e.g. #include + * This include must be as early as possible. + * + * (b) In libc-compat.h add enough code to detect that the comflicting + * userspace libc header has been included first. + * + * (c) If the userspace libc header has been included first define a set of + * guard macros of the form __UAPI_DEF_FOO and set their values to 1, else + * set their values to 0. + * + * (d) Back in the UAPI header with the conflicting definitions, guard the + * definitions with: + * #if __UAPI_DEF_FOO + * ... + * #endif + * + * This fixes the situation where the linux headers are included *after* the + * libc headers. To fix the problem with the inclusion in the other order the + * userspace libc headers must be fixed like this: + * + * * For all definitions that conflict with kernel definitions wrap those + * defines in the following: + * #if !__UAPI_DEF_FOO + * ... + * #endif + * + * This prevents the redefinition of a construct already defined by the kernel. + */ +#ifndef _LIBC_COMPAT_H +#define _LIBC_COMPAT_H + +/* We have included glibc headers... */ +#if defined(__GLIBC__) + +/* Coordinate with glibc net/if.h header. */ +#if defined(_NET_IF_H) && defined(__USE_MISC) + +/* GLIBC headers included first so don't define anything + * that would already be defined. */ + +#define __UAPI_DEF_IF_IFCONF 0 +#define __UAPI_DEF_IF_IFMAP 0 +#define __UAPI_DEF_IF_IFNAMSIZ 0 +#define __UAPI_DEF_IF_IFREQ 0 +/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */ +#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 0 +/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */ +#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO +#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1 +#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */ + +#else /* _NET_IF_H */ + +/* Linux headers included first, and we must define everything + * we need. The expectation is that glibc will check the + * __UAPI_DEF_* defines and adjust appropriately. */ + +#define __UAPI_DEF_IF_IFCONF 1 +#define __UAPI_DEF_IF_IFMAP 1 +#define __UAPI_DEF_IF_IFNAMSIZ 1 +#define __UAPI_DEF_IF_IFREQ 1 +/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */ +#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1 +/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */ +#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1 + +#endif /* _NET_IF_H */ + +/* Coordinate with glibc netinet/in.h header. */ +#if defined(_NETINET_IN_H) + +/* GLIBC headers included first so don't define anything + * that would already be defined. */ +#define __UAPI_DEF_IN_ADDR 0 +#define __UAPI_DEF_IN_IPPROTO 0 +#define __UAPI_DEF_IN_PKTINFO 0 +#define __UAPI_DEF_IP_MREQ 0 +#define __UAPI_DEF_SOCKADDR_IN 0 +#define __UAPI_DEF_IN_CLASS 0 + +#define __UAPI_DEF_IN6_ADDR 0 +/* The exception is the in6_addr macros which must be defined + * if the glibc code didn't define them. This guard matches + * the guard in glibc/inet/netinet/in.h which defines the + * additional in6_addr macros e.g. s6_addr16, and s6_addr32. */ +#if defined(__USE_MISC) || defined (__USE_GNU) +#define __UAPI_DEF_IN6_ADDR_ALT 0 +#else +#define __UAPI_DEF_IN6_ADDR_ALT 1 +#endif +#define __UAPI_DEF_SOCKADDR_IN6 0 +#define __UAPI_DEF_IPV6_MREQ 0 +#define __UAPI_DEF_IPPROTO_V6 0 +#define __UAPI_DEF_IPV6_OPTIONS 0 +#define __UAPI_DEF_IN6_PKTINFO 0 +#define __UAPI_DEF_IP6_MTUINFO 0 + +#else + +/* Linux headers included first, and we must define everything + * we need. The expectation is that glibc will check the + * __UAPI_DEF_* defines and adjust appropriately. */ +#define __UAPI_DEF_IN_ADDR 1 +#define __UAPI_DEF_IN_IPPROTO 1 +#define __UAPI_DEF_IN_PKTINFO 1 +#define __UAPI_DEF_IP_MREQ 1 +#define __UAPI_DEF_SOCKADDR_IN 1 +#define __UAPI_DEF_IN_CLASS 1 + +#define __UAPI_DEF_IN6_ADDR 1 +/* We unconditionally define the in6_addr macros and glibc must + * coordinate. */ +#define __UAPI_DEF_IN6_ADDR_ALT 1 +#define __UAPI_DEF_SOCKADDR_IN6 1 +#define __UAPI_DEF_IPV6_MREQ 1 +#define __UAPI_DEF_IPPROTO_V6 1 +#define __UAPI_DEF_IPV6_OPTIONS 1 +#define __UAPI_DEF_IN6_PKTINFO 1 +#define __UAPI_DEF_IP6_MTUINFO 1 + +#endif /* _NETINET_IN_H */ + +/* Coordinate with glibc netipx/ipx.h header. */ +#if defined(__NETIPX_IPX_H) + +#define __UAPI_DEF_SOCKADDR_IPX 0 +#define __UAPI_DEF_IPX_ROUTE_DEFINITION 0 +#define __UAPI_DEF_IPX_INTERFACE_DEFINITION 0 +#define __UAPI_DEF_IPX_CONFIG_DATA 0 +#define __UAPI_DEF_IPX_ROUTE_DEF 0 + +#else /* defined(__NETIPX_IPX_H) */ + +#define __UAPI_DEF_SOCKADDR_IPX 1 +#define __UAPI_DEF_IPX_ROUTE_DEFINITION 1 +#define __UAPI_DEF_IPX_INTERFACE_DEFINITION 1 +#define __UAPI_DEF_IPX_CONFIG_DATA 1 +#define __UAPI_DEF_IPX_ROUTE_DEF 1 + +#endif /* defined(__NETIPX_IPX_H) */ + +/* Definitions for xattr.h */ +#if defined(_SYS_XATTR_H) +#define __UAPI_DEF_XATTR 0 +#else +#define __UAPI_DEF_XATTR 1 +#endif + +/* If we did not see any headers from any supported C libraries, + * or we are being included in the kernel, then define everything + * that we need. Check for previous __UAPI_* definitions to give + * unsupported C libraries a way to opt out of any kernel definition. */ +#else /* !defined(__GLIBC__) */ + +/* Definitions for if.h */ +#ifndef __UAPI_DEF_IF_IFCONF +#define __UAPI_DEF_IF_IFCONF 1 +#endif +#ifndef __UAPI_DEF_IF_IFMAP +#define __UAPI_DEF_IF_IFMAP 1 +#endif +#ifndef __UAPI_DEF_IF_IFNAMSIZ +#define __UAPI_DEF_IF_IFNAMSIZ 1 +#endif +#ifndef __UAPI_DEF_IF_IFREQ +#define __UAPI_DEF_IF_IFREQ 1 +#endif +/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */ +#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS +#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1 +#endif +/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */ +#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO +#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1 +#endif + +/* Definitions for in.h */ +#ifndef __UAPI_DEF_IN_ADDR +#define __UAPI_DEF_IN_ADDR 1 +#endif +#ifndef __UAPI_DEF_IN_IPPROTO +#define __UAPI_DEF_IN_IPPROTO 1 +#endif +#ifndef __UAPI_DEF_IN_PKTINFO +#define __UAPI_DEF_IN_PKTINFO 1 +#endif +#ifndef __UAPI_DEF_IP_MREQ +#define __UAPI_DEF_IP_MREQ 1 +#endif +#ifndef __UAPI_DEF_SOCKADDR_IN +#define __UAPI_DEF_SOCKADDR_IN 1 +#endif +#ifndef __UAPI_DEF_IN_CLASS +#define __UAPI_DEF_IN_CLASS 1 +#endif + +/* Definitions for in6.h */ +#ifndef __UAPI_DEF_IN6_ADDR +#define __UAPI_DEF_IN6_ADDR 1 +#endif +#ifndef __UAPI_DEF_IN6_ADDR_ALT +#define __UAPI_DEF_IN6_ADDR_ALT 1 +#endif +#ifndef __UAPI_DEF_SOCKADDR_IN6 +#define __UAPI_DEF_SOCKADDR_IN6 1 +#endif +#ifndef __UAPI_DEF_IPV6_MREQ +#define __UAPI_DEF_IPV6_MREQ 1 +#endif +#ifndef __UAPI_DEF_IPPROTO_V6 +#define __UAPI_DEF_IPPROTO_V6 1 +#endif +#ifndef __UAPI_DEF_IPV6_OPTIONS +#define __UAPI_DEF_IPV6_OPTIONS 1 +#endif +#ifndef __UAPI_DEF_IN6_PKTINFO +#define __UAPI_DEF_IN6_PKTINFO 1 +#endif +#ifndef __UAPI_DEF_IP6_MTUINFO +#define __UAPI_DEF_IP6_MTUINFO 1 +#endif + +/* Definitions for ipx.h */ +#ifndef __UAPI_DEF_SOCKADDR_IPX +#define __UAPI_DEF_SOCKADDR_IPX 1 +#endif +#ifndef __UAPI_DEF_IPX_ROUTE_DEFINITION +#define __UAPI_DEF_IPX_ROUTE_DEFINITION 1 +#endif +#ifndef __UAPI_DEF_IPX_INTERFACE_DEFINITION +#define __UAPI_DEF_IPX_INTERFACE_DEFINITION 1 +#endif +#ifndef __UAPI_DEF_IPX_CONFIG_DATA +#define __UAPI_DEF_IPX_CONFIG_DATA 1 +#endif +#ifndef __UAPI_DEF_IPX_ROUTE_DEF +#define __UAPI_DEF_IPX_ROUTE_DEF 1 +#endif + +/* Definitions for xattr.h */ +#ifndef __UAPI_DEF_XATTR +#define __UAPI_DEF_XATTR 1 +#endif + +#endif /* __GLIBC__ */ + +#endif /* _LIBC_COMPAT_H */ diff --git a/include/linux-private/linux/limits.h b/include/linux-private/linux/limits.h new file mode 100644 index 0000000..c3547f0 --- /dev/null +++ b/include/linux-private/linux/limits.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_LIMITS_H +#define _LINUX_LIMITS_H + +#define NR_OPEN 1024 + +#define NGROUPS_MAX 65536 /* supplemental group IDs are available */ +#define ARG_MAX 131072 /* # bytes of args + environ for exec() */ +#define LINK_MAX 127 /* # links a file may have */ +#define MAX_CANON 255 /* size of the canonical input queue */ +#define MAX_INPUT 255 /* size of the type-ahead buffer */ +#define NAME_MAX 255 /* # chars in a file name */ +#define PATH_MAX 4096 /* # chars in a path name including nul */ +#define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */ +#define XATTR_NAME_MAX 255 /* # chars in an extended attribute name */ +#define XATTR_SIZE_MAX 65536 /* size of an extended attribute value (64k) */ +#define XATTR_LIST_MAX 65536 /* size of extended attribute namelist (64k) */ + +#define RTSIG_MAX 32 + +#endif diff --git a/include/linux-private/linux/lwtunnel.h b/include/linux-private/linux/lwtunnel.h new file mode 100644 index 0000000..9d22961 --- /dev/null +++ b/include/linux-private/linux/lwtunnel.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LWTUNNEL_H_ +#define _LWTUNNEL_H_ + +#include + +enum lwtunnel_encap_types { + LWTUNNEL_ENCAP_NONE, + LWTUNNEL_ENCAP_MPLS, + LWTUNNEL_ENCAP_IP, + LWTUNNEL_ENCAP_ILA, + LWTUNNEL_ENCAP_IP6, + LWTUNNEL_ENCAP_SEG6, + LWTUNNEL_ENCAP_BPF, + LWTUNNEL_ENCAP_SEG6_LOCAL, + LWTUNNEL_ENCAP_RPL, + LWTUNNEL_ENCAP_IOAM6, + LWTUNNEL_ENCAP_XFRM, + __LWTUNNEL_ENCAP_MAX, +}; + +#define LWTUNNEL_ENCAP_MAX (__LWTUNNEL_ENCAP_MAX - 1) + +enum lwtunnel_ip_t { + LWTUNNEL_IP_UNSPEC, + LWTUNNEL_IP_ID, + LWTUNNEL_IP_DST, + LWTUNNEL_IP_SRC, + LWTUNNEL_IP_TTL, + LWTUNNEL_IP_TOS, + LWTUNNEL_IP_FLAGS, + LWTUNNEL_IP_PAD, + LWTUNNEL_IP_OPTS, + __LWTUNNEL_IP_MAX, +}; + +#define LWTUNNEL_IP_MAX (__LWTUNNEL_IP_MAX - 1) + +enum lwtunnel_ip6_t { + LWTUNNEL_IP6_UNSPEC, + LWTUNNEL_IP6_ID, + LWTUNNEL_IP6_DST, + LWTUNNEL_IP6_SRC, + LWTUNNEL_IP6_HOPLIMIT, + LWTUNNEL_IP6_TC, + LWTUNNEL_IP6_FLAGS, + LWTUNNEL_IP6_PAD, + LWTUNNEL_IP6_OPTS, + __LWTUNNEL_IP6_MAX, +}; + +#define LWTUNNEL_IP6_MAX (__LWTUNNEL_IP6_MAX - 1) + +enum { + LWTUNNEL_IP_OPTS_UNSPEC, + LWTUNNEL_IP_OPTS_GENEVE, + LWTUNNEL_IP_OPTS_VXLAN, + LWTUNNEL_IP_OPTS_ERSPAN, + __LWTUNNEL_IP_OPTS_MAX, +}; + +#define LWTUNNEL_IP_OPTS_MAX (__LWTUNNEL_IP_OPTS_MAX - 1) + +enum { + LWTUNNEL_IP_OPT_GENEVE_UNSPEC, + LWTUNNEL_IP_OPT_GENEVE_CLASS, + LWTUNNEL_IP_OPT_GENEVE_TYPE, + LWTUNNEL_IP_OPT_GENEVE_DATA, + __LWTUNNEL_IP_OPT_GENEVE_MAX, +}; + +#define LWTUNNEL_IP_OPT_GENEVE_MAX (__LWTUNNEL_IP_OPT_GENEVE_MAX - 1) + +enum { + LWTUNNEL_IP_OPT_VXLAN_UNSPEC, + LWTUNNEL_IP_OPT_VXLAN_GBP, + __LWTUNNEL_IP_OPT_VXLAN_MAX, +}; + +#define LWTUNNEL_IP_OPT_VXLAN_MAX (__LWTUNNEL_IP_OPT_VXLAN_MAX - 1) + +enum { + LWTUNNEL_IP_OPT_ERSPAN_UNSPEC, + LWTUNNEL_IP_OPT_ERSPAN_VER, + LWTUNNEL_IP_OPT_ERSPAN_INDEX, + LWTUNNEL_IP_OPT_ERSPAN_DIR, + LWTUNNEL_IP_OPT_ERSPAN_HWID, + __LWTUNNEL_IP_OPT_ERSPAN_MAX, +}; + +#define LWTUNNEL_IP_OPT_ERSPAN_MAX (__LWTUNNEL_IP_OPT_ERSPAN_MAX - 1) + +enum { + LWT_BPF_PROG_UNSPEC, + LWT_BPF_PROG_FD, + LWT_BPF_PROG_NAME, + __LWT_BPF_PROG_MAX, +}; + +#define LWT_BPF_PROG_MAX (__LWT_BPF_PROG_MAX - 1) + +enum { + LWT_BPF_UNSPEC, + LWT_BPF_IN, + LWT_BPF_OUT, + LWT_BPF_XMIT, + LWT_BPF_XMIT_HEADROOM, + __LWT_BPF_MAX, +}; + +#define LWT_BPF_MAX (__LWT_BPF_MAX - 1) + +#define LWT_BPF_MAX_HEADROOM 256 + +enum { + LWT_XFRM_UNSPEC, + LWT_XFRM_IF_ID, + LWT_XFRM_LINK, + __LWT_XFRM_MAX, +}; + +#define LWT_XFRM_MAX (__LWT_XFRM_MAX - 1) + +#endif /* _LWTUNNEL_H_ */ diff --git a/include/linux-private/linux/mpls.h b/include/linux-private/linux/mpls.h new file mode 100644 index 0000000..9effbf9 --- /dev/null +++ b/include/linux-private/linux/mpls.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _MPLS_H +#define _MPLS_H + +#include +#include + +/* Reference: RFC 5462, RFC 3032 + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Label | TC |S| TTL | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Label: Label Value, 20 bits + * TC: Traffic Class field, 3 bits + * S: Bottom of Stack, 1 bit + * TTL: Time to Live, 8 bits + */ + +struct mpls_label { + __be32 entry; +}; + +#define MPLS_LS_LABEL_MASK 0xFFFFF000 +#define MPLS_LS_LABEL_SHIFT 12 +#define MPLS_LS_TC_MASK 0x00000E00 +#define MPLS_LS_TC_SHIFT 9 +#define MPLS_LS_S_MASK 0x00000100 +#define MPLS_LS_S_SHIFT 8 +#define MPLS_LS_TTL_MASK 0x000000FF +#define MPLS_LS_TTL_SHIFT 0 + +/* Reserved labels */ +#define MPLS_LABEL_IPV4NULL 0 /* RFC3032 */ +#define MPLS_LABEL_RTALERT 1 /* RFC3032 */ +#define MPLS_LABEL_IPV6NULL 2 /* RFC3032 */ +#define MPLS_LABEL_IMPLNULL 3 /* RFC3032 */ +#define MPLS_LABEL_ENTROPY 7 /* RFC6790 */ +#define MPLS_LABEL_GAL 13 /* RFC5586 */ +#define MPLS_LABEL_OAMALERT 14 /* RFC3429 */ +#define MPLS_LABEL_EXTENSION 15 /* RFC7274 */ + +#define MPLS_LABEL_FIRST_UNRESERVED 16 /* RFC3032 */ + +/* These are embedded into IFLA_STATS_AF_SPEC: + * [IFLA_STATS_AF_SPEC] + * -> [AF_MPLS] + * -> [MPLS_STATS_xxx] + * + * Attributes: + * [MPLS_STATS_LINK] = { + * struct mpls_link_stats + * } + */ +enum { + MPLS_STATS_UNSPEC, /* also used as 64bit pad attribute */ + MPLS_STATS_LINK, + __MPLS_STATS_MAX, +}; + +#define MPLS_STATS_MAX (__MPLS_STATS_MAX - 1) + +struct mpls_link_stats { + __u64 rx_packets; /* total packets received */ + __u64 tx_packets; /* total packets transmitted */ + __u64 rx_bytes; /* total bytes received */ + __u64 tx_bytes; /* total bytes transmitted */ + __u64 rx_errors; /* bad packets received */ + __u64 tx_errors; /* packet transmit problems */ + __u64 rx_dropped; /* packet dropped on receive */ + __u64 tx_dropped; /* packet dropped on transmit */ + __u64 rx_noroute; /* no route for packet dest */ +}; + +#endif /* _MPLS_H */ diff --git a/include/linux-private/linux/mpls_iptunnel.h b/include/linux-private/linux/mpls_iptunnel.h new file mode 100644 index 0000000..2c69b7d --- /dev/null +++ b/include/linux-private/linux/mpls_iptunnel.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * mpls tunnel api + * + * Authors: + * Roopa Prabhu + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _LINUX_MPLS_IPTUNNEL_H +#define _LINUX_MPLS_IPTUNNEL_H + +/* MPLS tunnel attributes + * [RTA_ENCAP] = { + * [MPLS_IPTUNNEL_DST] + * [MPLS_IPTUNNEL_TTL] + * } + */ +enum { + MPLS_IPTUNNEL_UNSPEC, + MPLS_IPTUNNEL_DST, + MPLS_IPTUNNEL_TTL, + __MPLS_IPTUNNEL_MAX, +}; +#define MPLS_IPTUNNEL_MAX (__MPLS_IPTUNNEL_MAX - 1) + +#endif /* _LINUX_MPLS_IPTUNNEL_H */ diff --git a/include/linux/neighbour.h b/include/linux-private/linux/neighbour.h similarity index 61% rename from include/linux/neighbour.h rename to include/linux-private/linux/neighbour.h index a7003b7..5e67a7e 100644 --- a/include/linux/neighbour.h +++ b/include/linux-private/linux/neighbour.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef __LINUX_NEIGHBOUR_H #define __LINUX_NEIGHBOUR_H @@ -20,6 +21,19 @@ enum { NDA_LLADDR, NDA_CACHEINFO, NDA_PROBES, + NDA_VLAN, + NDA_PORT, + NDA_VNI, + NDA_IFINDEX, + NDA_MASTER, + NDA_LINK_NETNSID, + NDA_SRC_VNI, + NDA_PROTOCOL, /* Originator of entry */ + NDA_NH_ID, + NDA_FDB_EXT_ATTRS, + NDA_FLAGS_EXT, + NDA_NDM_STATE_MASK, + NDA_NDM_FLAGS_MASK, __NDA_MAX }; @@ -29,9 +43,17 @@ enum { * Neighbor Cache Entry Flags */ -#define NTF_USE 0x01 -#define NTF_PROXY 0x08 /* == ATF_PUBL */ -#define NTF_ROUTER 0x80 +#define NTF_USE (1 << 0) +#define NTF_SELF (1 << 1) +#define NTF_MASTER (1 << 2) +#define NTF_PROXY (1 << 3) /* == ATF_PUBL */ +#define NTF_EXT_LEARNED (1 << 4) +#define NTF_OFFLOADED (1 << 5) +#define NTF_STICKY (1 << 6) +#define NTF_ROUTER (1 << 7) +/* Extended flags under NDA_FLAGS_EXT: */ +#define NTF_EXT_MANAGED (1 << 0) +#define NTF_EXT_LOCKED (1 << 1) /* * Neighbor Cache Entry States. @@ -49,9 +71,27 @@ enum { #define NUD_PERMANENT 0x80 #define NUD_NONE 0x00 -/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change - and make no address resolution or NUD. - NUD_PERMANENT is also cannot be deleted by garbage collectors. +/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change and make no + * address resolution or NUD. + * + * NUD_PERMANENT also cannot be deleted by garbage collectors. This holds true + * for dynamic entries with NTF_EXT_LEARNED flag as well. However, upon carrier + * down event, NUD_PERMANENT entries are not flushed whereas NTF_EXT_LEARNED + * flagged entries explicitly are (which is also consistent with the routing + * subsystem). + * + * When NTF_EXT_LEARNED is set for a bridge fdb entry the different cache entry + * states don't make sense and thus are ignored. Such entries don't age and + * can roam. + * + * NTF_EXT_MANAGED flagged neigbor entries are managed by the kernel on behalf + * of a user space control plane, and automatically refreshed so that (if + * possible) they remain in NUD_REACHABLE state. + * + * NTF_EXT_LOCKED flagged bridge FDB entries are entries generated by the + * bridge in response to a host trying to communicate via a locked bridge port + * with MAB enabled. Their purpose is to notify user space that a host requires + * authentication. */ struct nda_cacheinfo { @@ -97,6 +137,7 @@ struct ndt_stats { __u64 ndts_rcv_probes_ucast; __u64 ndts_periodic_gc_runs; __u64 ndts_forced_gc_runs; + __u64 ndts_table_fulls; }; enum { @@ -116,6 +157,10 @@ enum { NDTPA_PROXY_DELAY, /* u64, msecs */ NDTPA_PROXY_QLEN, /* u32 */ NDTPA_LOCKTIME, /* u64, msecs */ + NDTPA_QUEUE_LENBYTES, /* u32 */ + NDTPA_MCAST_REPROBES, /* u32 */ + NDTPA_PAD, + NDTPA_INTERVAL_PROBE_TIME_MS, /* u64, msecs */ __NDTPA_MAX }; #define NDTPA_MAX (__NDTPA_MAX - 1) @@ -148,8 +193,32 @@ enum { NDTA_PARMS, /* nested TLV NDTPA_* */ NDTA_STATS, /* struct ndt_stats, read-only */ NDTA_GC_INTERVAL, /* u64, msecs */ + NDTA_PAD, __NDTA_MAX }; #define NDTA_MAX (__NDTA_MAX - 1) + /* FDB activity notification bits used in NFEA_ACTIVITY_NOTIFY: + * - FDB_NOTIFY_BIT - notify on activity/expire for any entry + * - FDB_NOTIFY_INACTIVE_BIT - mark as inactive to avoid multiple notifications + */ +enum { + FDB_NOTIFY_BIT = (1 << 0), + FDB_NOTIFY_INACTIVE_BIT = (1 << 1) +}; + +/* embedded into NDA_FDB_EXT_ATTRS: + * [NDA_FDB_EXT_ATTRS] = { + * [NFEA_ACTIVITY_NOTIFY] + * ... + * } + */ +enum { + NFEA_UNSPEC, + NFEA_ACTIVITY_NOTIFY, + NFEA_DONT_REFRESH, + __NFEA_MAX +}; +#define NFEA_MAX (__NFEA_MAX - 1) + #endif diff --git a/include/linux-private/linux/netconf.h b/include/linux-private/linux/netconf.h new file mode 100644 index 0000000..229e885 --- /dev/null +++ b/include/linux-private/linux/netconf.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_NETCONF_H_ +#define _LINUX_NETCONF_H_ + +#include +#include + +struct netconfmsg { + __u8 ncm_family; +}; + +enum { + NETCONFA_UNSPEC, + NETCONFA_IFINDEX, + NETCONFA_FORWARDING, + NETCONFA_RP_FILTER, + NETCONFA_MC_FORWARDING, + NETCONFA_PROXY_NEIGH, + NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN, + NETCONFA_INPUT, + NETCONFA_BC_FORWARDING, + __NETCONFA_MAX +}; +#define NETCONFA_MAX (__NETCONFA_MAX - 1) +#define NETCONFA_ALL -1 + +#define NETCONFA_IFINDEX_ALL -1 +#define NETCONFA_IFINDEX_DEFAULT -2 + +#endif /* _LINUX_NETCONF_H_ */ diff --git a/include/linux-private/linux/netdevice.h b/include/linux-private/linux/netdevice.h new file mode 100644 index 0000000..86d961c --- /dev/null +++ b/include/linux-private/linux/netdevice.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Definitions for the Interfaces handler. + * + * Version: @(#)dev.h 1.0.10 08/12/93 + * + * Authors: Ross Biro + * Fred N. van Kempen, + * Corey Minyard + * Donald J. Becker, + * Alan Cox, + * Bjorn Ekwall. + * Pekka Riikonen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Moved to /usr/include/linux for NET3 + */ +#ifndef _LINUX_NETDEVICE_H +#define _LINUX_NETDEVICE_H + +#include +#include +#include +#include + + +#define MAX_ADDR_LEN 32 /* Largest hardware address length */ + +/* Initial net device group. All devices belong to group 0 by default. */ +#define INIT_NETDEV_GROUP 0 + + +/* interface name assignment types (sysfs name_assign_type attribute) */ +#define NET_NAME_UNKNOWN 0 /* unknown origin (not exposed to userspace) */ +#define NET_NAME_ENUM 1 /* enumerated by kernel */ +#define NET_NAME_PREDICTABLE 2 /* predictably named by the kernel */ +#define NET_NAME_USER 3 /* provided by user-space */ +#define NET_NAME_RENAMED 4 /* renamed by user-space */ + +/* Media selection options. */ +enum { + IF_PORT_UNKNOWN = 0, + IF_PORT_10BASE2, + IF_PORT_10BASET, + IF_PORT_AUI, + IF_PORT_100BASET, + IF_PORT_100BASETX, + IF_PORT_100BASEFX +}; + +/* hardware address assignment types */ +#define NET_ADDR_PERM 0 /* address is permanent (default) */ +#define NET_ADDR_RANDOM 1 /* address is generated randomly */ +#define NET_ADDR_STOLEN 2 /* address is stolen from other device */ +#define NET_ADDR_SET 3 /* address is set using + * dev_set_mac_address() */ + +#endif /* _LINUX_NETDEVICE_H */ diff --git a/include/linux-private/linux/netfilter.h b/include/linux-private/linux/netfilter.h new file mode 100644 index 0000000..30c045b --- /dev/null +++ b/include/linux-private/linux/netfilter.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __LINUX_NETFILTER_H +#define __LINUX_NETFILTER_H + +#include + +#include +#include + +/* Responses from hook functions. */ +#define NF_DROP 0 +#define NF_ACCEPT 1 +#define NF_STOLEN 2 +#define NF_QUEUE 3 +#define NF_REPEAT 4 +#define NF_STOP 5 /* Deprecated, for userspace nf_queue compatibility. */ +#define NF_MAX_VERDICT NF_STOP + +/* we overload the higher bits for encoding auxiliary data such as the queue + * number or errno values. Not nice, but better than additional function + * arguments. */ +#define NF_VERDICT_MASK 0x000000ff + +/* extra verdict flags have mask 0x0000ff00 */ +#define NF_VERDICT_FLAG_QUEUE_BYPASS 0x00008000 + +/* queue number (NF_QUEUE) or errno (NF_DROP) */ +#define NF_VERDICT_QMASK 0xffff0000 +#define NF_VERDICT_QBITS 16 + +#define NF_QUEUE_NR(x) ((((x) << 16) & NF_VERDICT_QMASK) | NF_QUEUE) + +#define NF_DROP_ERR(x) (((-x) << 16) | NF_DROP) + +/* only for userspace compatibility */ + +/* NF_VERDICT_BITS should be 8 now, but userspace might break if this changes */ +#define NF_VERDICT_BITS 16 + +enum nf_inet_hooks { + NF_INET_PRE_ROUTING, + NF_INET_LOCAL_IN, + NF_INET_FORWARD, + NF_INET_LOCAL_OUT, + NF_INET_POST_ROUTING, + NF_INET_NUMHOOKS, + NF_INET_INGRESS = NF_INET_NUMHOOKS, +}; + +enum nf_dev_hooks { + NF_NETDEV_INGRESS, + NF_NETDEV_EGRESS, + NF_NETDEV_NUMHOOKS +}; + +enum { + NFPROTO_UNSPEC = 0, + NFPROTO_INET = 1, + NFPROTO_IPV4 = 2, + NFPROTO_ARP = 3, + NFPROTO_NETDEV = 5, + NFPROTO_BRIDGE = 7, + NFPROTO_IPV6 = 10, + NFPROTO_DECNET = 12, + NFPROTO_NUMPROTO, +}; + +union nf_inet_addr { + __u32 all[4]; + __be32 ip; + __be32 ip6[4]; + struct in_addr in; + struct in6_addr in6; +}; + +#endif /* __LINUX_NETFILTER_H */ diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux-private/linux/netfilter/nf_conntrack_common.h similarity index 69% rename from include/linux/netfilter/nf_conntrack_common.h rename to include/linux-private/linux/netfilter/nf_conntrack_common.h index 1644cdd..3c99056 100644 --- a/include/linux/netfilter/nf_conntrack_common.h +++ b/include/linux-private/linux/netfilter/nf_conntrack_common.h @@ -1,5 +1,6 @@ -#ifndef _UAPI_NF_CONNTRACK_COMMON_H -#define _UAPI_NF_CONNTRACK_COMMON_H +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _NF_CONNTRACK_COMMON_H +#define _NF_CONNTRACK_COMMON_H /* Connection state tracking for netfilter. This is separated from, but required by, the NAT layer; it can also be used by an iptables extension. */ @@ -20,11 +21,19 @@ enum ip_conntrack_info { IP_CT_ESTABLISHED_REPLY = IP_CT_ESTABLISHED + IP_CT_IS_REPLY, IP_CT_RELATED_REPLY = IP_CT_RELATED + IP_CT_IS_REPLY, - IP_CT_NEW_REPLY = IP_CT_NEW + IP_CT_IS_REPLY, - /* Number of distinct IP_CT types (no NEW in reply dirn). */ - IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1 + /* No NEW in reply direction. */ + + /* Number of distinct IP_CT types. */ + IP_CT_NUMBER, + + /* only for userspace compatibility */ + IP_CT_NEW_REPLY = IP_CT_NUMBER, }; +#define NF_CT_STATE_INVALID_BIT (1 << 0) +#define NF_CT_STATE_BIT(ctinfo) (1 << ((ctinfo) % IP_CT_IS_REPLY + 1)) +#define NF_CT_STATE_UNTRACKED_BIT (1 << 6) + /* Bitset representing status of connection. */ enum ip_conntrack_status { /* It's an expected connection: bit 0 set. This bit never changed */ @@ -80,13 +89,32 @@ enum ip_conntrack_status { IPS_TEMPLATE_BIT = 11, IPS_TEMPLATE = (1 << IPS_TEMPLATE_BIT), - /* Conntrack is a fake untracked entry */ + /* Conntrack is a fake untracked entry. Obsolete and not used anymore */ IPS_UNTRACKED_BIT = 12, IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT), - /* Conntrack got a helper explicitly attached via CT target. */ + + /* Conntrack got a helper explicitly attached (ruleset, ctnetlink). */ IPS_HELPER_BIT = 13, IPS_HELPER = (1 << IPS_HELPER_BIT), + + /* Conntrack has been offloaded to flow table. */ + IPS_OFFLOAD_BIT = 14, + IPS_OFFLOAD = (1 << IPS_OFFLOAD_BIT), + + /* Conntrack has been offloaded to hardware. */ + IPS_HW_OFFLOAD_BIT = 15, + IPS_HW_OFFLOAD = (1 << IPS_HW_OFFLOAD_BIT), + + /* Be careful here, modifying these bits can make things messy, + * so don't let users modify them directly. + */ + IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK | + IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING | + IPS_SEQ_ADJUST | IPS_TEMPLATE | IPS_UNTRACKED | + IPS_OFFLOAD | IPS_HW_OFFLOAD), + + __IPS_MAX_BIT = 16, }; /* Connection tracking event types */ @@ -99,8 +127,11 @@ enum ip_conntrack_events { IPCT_PROTOINFO, /* protocol information has changed */ IPCT_HELPER, /* new helper has been set */ IPCT_MARK, /* new mark has been set */ - IPCT_NATSEQADJ, /* NAT is doing sequence adjustment */ + IPCT_SEQADJ, /* sequence adjustment has changed */ + IPCT_NATSEQADJ = IPCT_SEQADJ, IPCT_SECMARK, /* new security mark has been set */ + IPCT_LABEL, /* new connlabel has been set */ + IPCT_SYNPROXY, /* synproxy has been set */ }; enum ip_conntrack_expect_events { @@ -114,4 +145,4 @@ enum ip_conntrack_expect_events { #define NF_CT_EXPECT_USERSPACE 0x4 -#endif /* _UAPI_NF_CONNTRACK_COMMON_H */ +#endif /* _NF_CONNTRACK_COMMON_H */ diff --git a/include/linux-private/linux/netfilter/nf_conntrack_tcp.h b/include/linux-private/linux/netfilter/nf_conntrack_tcp.h new file mode 100644 index 0000000..a589dbc --- /dev/null +++ b/include/linux-private/linux/netfilter/nf_conntrack_tcp.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _NF_CONNTRACK_TCP_H +#define _NF_CONNTRACK_TCP_H +/* TCP tracking. */ + +#include + +/* This is exposed to userspace (ctnetlink) */ +enum tcp_conntrack { + TCP_CONNTRACK_NONE, + TCP_CONNTRACK_SYN_SENT, + TCP_CONNTRACK_SYN_RECV, + TCP_CONNTRACK_ESTABLISHED, + TCP_CONNTRACK_FIN_WAIT, + TCP_CONNTRACK_CLOSE_WAIT, + TCP_CONNTRACK_LAST_ACK, + TCP_CONNTRACK_TIME_WAIT, + TCP_CONNTRACK_CLOSE, + TCP_CONNTRACK_LISTEN, /* obsolete */ +#define TCP_CONNTRACK_SYN_SENT2 TCP_CONNTRACK_LISTEN + TCP_CONNTRACK_MAX, + TCP_CONNTRACK_IGNORE, + TCP_CONNTRACK_RETRANS, + TCP_CONNTRACK_UNACK, + TCP_CONNTRACK_TIMEOUT_MAX +}; + +/* Window scaling is advertised by the sender */ +#define IP_CT_TCP_FLAG_WINDOW_SCALE 0x01 + +/* SACK is permitted by the sender */ +#define IP_CT_TCP_FLAG_SACK_PERM 0x02 + +/* This sender sent FIN first */ +#define IP_CT_TCP_FLAG_CLOSE_INIT 0x04 + +/* Be liberal in window checking */ +#define IP_CT_TCP_FLAG_BE_LIBERAL 0x08 + +/* Has unacknowledged data */ +#define IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED 0x10 + +/* The field td_maxack has been set */ +#define IP_CT_TCP_FLAG_MAXACK_SET 0x20 + +/* Marks possibility for expected RFC5961 challenge ACK */ +#define IP_CT_EXP_CHALLENGE_ACK 0x40 + +/* Simultaneous open initialized */ +#define IP_CT_TCP_SIMULTANEOUS_OPEN 0x80 + +struct nf_ct_tcp_flags { + __u8 flags; + __u8 mask; +}; + + +#endif /* _NF_CONNTRACK_TCP_H */ diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux-private/linux/netfilter/nfnetlink.h similarity index 63% rename from include/linux/netfilter/nfnetlink.h rename to include/linux-private/linux/netfilter/nfnetlink.h index 4a4efaf..b89a3e6 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux-private/linux/netfilter/nfnetlink.h @@ -1,5 +1,6 @@ -#ifndef _UAPI_NFNETLINK_H -#define _UAPI_NFNETLINK_H +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _NFNETLINK_H +#define _NFNETLINK_H #include #include @@ -18,6 +19,12 @@ enum nfnetlink_groups { #define NFNLGRP_CONNTRACK_EXP_UPDATE NFNLGRP_CONNTRACK_EXP_UPDATE NFNLGRP_CONNTRACK_EXP_DESTROY, #define NFNLGRP_CONNTRACK_EXP_DESTROY NFNLGRP_CONNTRACK_EXP_DESTROY + NFNLGRP_NFTABLES, +#define NFNLGRP_NFTABLES NFNLGRP_NFTABLES + NFNLGRP_ACCT_QUOTA, +#define NFNLGRP_ACCT_QUOTA NFNLGRP_ACCT_QUOTA + NFNLGRP_NFTRACE, +#define NFNLGRP_NFTRACE NFNLGRP_NFTRACE __NFNLGRP_MAX, }; #define NFNLGRP_MAX (__NFNLGRP_MAX - 1) @@ -51,6 +58,25 @@ struct nfgenmsg { #define NFNL_SUBSYS_ACCT 7 #define NFNL_SUBSYS_CTNETLINK_TIMEOUT 8 #define NFNL_SUBSYS_CTHELPER 9 -#define NFNL_SUBSYS_COUNT 10 +#define NFNL_SUBSYS_NFTABLES 10 +#define NFNL_SUBSYS_NFT_COMPAT 11 +#define NFNL_SUBSYS_HOOK 12 +#define NFNL_SUBSYS_COUNT 13 -#endif /* _UAPI_NFNETLINK_H */ +/* Reserved control nfnetlink messages */ +#define NFNL_MSG_BATCH_BEGIN NLMSG_MIN_TYPE +#define NFNL_MSG_BATCH_END NLMSG_MIN_TYPE+1 + +/** + * enum nfnl_batch_attributes - nfnetlink batch netlink attributes + * + * @NFNL_BATCH_GENID: generation ID for this changeset (NLA_U32) + */ +enum nfnl_batch_attributes { + NFNL_BATCH_UNSPEC, + NFNL_BATCH_GENID, + __NFNL_BATCH_MAX +}; +#define NFNL_BATCH_MAX (__NFNL_BATCH_MAX - 1) + +#endif /* _NFNETLINK_H */ diff --git a/include/linux/netfilter/nfnetlink_compat.h b/include/linux-private/linux/netfilter/nfnetlink_compat.h similarity index 97% rename from include/linux/netfilter/nfnetlink_compat.h rename to include/linux-private/linux/netfilter/nfnetlink_compat.h index ffb9503..ead7161 100644 --- a/include/linux/netfilter/nfnetlink_compat.h +++ b/include/linux-private/linux/netfilter/nfnetlink_compat.h @@ -1,9 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef _NFNETLINK_COMPAT_H #define _NFNETLINK_COMPAT_H #include -#ifndef __KERNEL__ /* Old nfnetlink macros for userspace */ /* nfnetlink groups: Up to 32 maximum */ @@ -59,5 +59,4 @@ struct nfattr { + NLMSG_ALIGN(sizeof(struct nfgenmsg)))) #define NFM_PAYLOAD(n) NLMSG_PAYLOAD(n, sizeof(struct nfgenmsg)) -#endif /* ! __KERNEL__ */ #endif /* _NFNETLINK_COMPAT_H */ diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux-private/linux/netfilter/nfnetlink_conntrack.h similarity index 80% rename from include/linux/netfilter/nfnetlink_conntrack.h rename to include/linux-private/linux/netfilter/nfnetlink_conntrack.h index 43bfe3e..c2ac726 100644 --- a/include/linux/netfilter/nfnetlink_conntrack.h +++ b/include/linux-private/linux/netfilter/nfnetlink_conntrack.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef _IPCONNTRACK_NETLINK_H #define _IPCONNTRACK_NETLINK_H #include @@ -9,6 +10,8 @@ enum cntl_msg_types { IPCTNL_MSG_CT_GET_CTRZERO, IPCTNL_MSG_CT_GET_STATS_CPU, IPCTNL_MSG_CT_GET_STATS, + IPCTNL_MSG_CT_GET_DYING, + IPCTNL_MSG_CT_GET_UNCONFIRMED, IPCTNL_MSG_MAX }; @@ -40,13 +43,20 @@ enum ctattr_type { CTA_ID, CTA_NAT_DST, CTA_TUPLE_MASTER, - CTA_NAT_SEQ_ADJ_ORIG, - CTA_NAT_SEQ_ADJ_REPLY, + CTA_SEQ_ADJ_ORIG, + CTA_NAT_SEQ_ADJ_ORIG = CTA_SEQ_ADJ_ORIG, + CTA_SEQ_ADJ_REPLY, + CTA_NAT_SEQ_ADJ_REPLY = CTA_SEQ_ADJ_REPLY, CTA_SECMARK, /* obsolete */ CTA_ZONE, CTA_SECCTX, CTA_TIMESTAMP, CTA_MARK_MASK, + CTA_LABELS, + CTA_LABELS_MASK, + CTA_SYNPROXY, + CTA_FILTER, + CTA_STATUS_MASK, __CTA_MAX }; #define CTA_MAX (__CTA_MAX - 1) @@ -55,6 +65,7 @@ enum ctattr_tuple { CTA_TUPLE_UNSPEC, CTA_TUPLE_IP, CTA_TUPLE_PROTO, + CTA_TUPLE_ZONE, __CTA_TUPLE_MAX }; #define CTA_TUPLE_MAX (__CTA_TUPLE_MAX - 1) @@ -109,6 +120,7 @@ enum ctattr_protoinfo_dccp { CTA_PROTOINFO_DCCP_STATE, CTA_PROTOINFO_DCCP_ROLE, CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ, + CTA_PROTOINFO_DCCP_PAD, __CTA_PROTOINFO_DCCP_MAX, }; #define CTA_PROTOINFO_DCCP_MAX (__CTA_PROTOINFO_DCCP_MAX - 1) @@ -128,6 +140,7 @@ enum ctattr_counters { CTA_COUNTERS_BYTES, /* 64bit counters */ CTA_COUNTERS32_PACKETS, /* old 32bit counters, unused */ CTA_COUNTERS32_BYTES, /* old 32bit counters, unused */ + CTA_COUNTERS_PAD, __CTA_COUNTERS_MAX }; #define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1) @@ -136,6 +149,7 @@ enum ctattr_tstamp { CTA_TIMESTAMP_UNSPEC, CTA_TIMESTAMP_START, CTA_TIMESTAMP_STOP, + CTA_TIMESTAMP_PAD, __CTA_TIMESTAMP_MAX }; #define CTA_TIMESTAMP_MAX (__CTA_TIMESTAMP_MAX - 1) @@ -161,6 +175,15 @@ enum ctattr_protonat { }; #define CTA_PROTONAT_MAX (__CTA_PROTONAT_MAX - 1) +enum ctattr_seqadj { + CTA_SEQADJ_UNSPEC, + CTA_SEQADJ_CORRECTION_POS, + CTA_SEQADJ_OFFSET_BEFORE, + CTA_SEQADJ_OFFSET_AFTER, + __CTA_SEQADJ_MAX +}; +#define CTA_SEQADJ_MAX (__CTA_SEQADJ_MAX - 1) + enum ctattr_natseq { CTA_NAT_SEQ_UNSPEC, CTA_NAT_SEQ_CORRECTION_POS, @@ -170,6 +193,15 @@ enum ctattr_natseq { }; #define CTA_NAT_SEQ_MAX (__CTA_NAT_SEQ_MAX - 1) +enum ctattr_synproxy { + CTA_SYNPROXY_UNSPEC, + CTA_SYNPROXY_ISN, + CTA_SYNPROXY_ITS, + CTA_SYNPROXY_TSOFF, + __CTA_SYNPROXY_MAX, +}; +#define CTA_SYNPROXY_MAX (__CTA_SYNPROXY_MAX - 1) + enum ctattr_expect { CTA_EXPECT_UNSPEC, CTA_EXPECT_MASTER, @@ -212,19 +244,21 @@ enum ctattr_secctx { enum ctattr_stats_cpu { CTA_STATS_UNSPEC, - CTA_STATS_SEARCHED, + CTA_STATS_SEARCHED, /* no longer used */ CTA_STATS_FOUND, - CTA_STATS_NEW, + CTA_STATS_NEW, /* no longer used */ CTA_STATS_INVALID, - CTA_STATS_IGNORE, - CTA_STATS_DELETE, - CTA_STATS_DELETE_LIST, + CTA_STATS_IGNORE, /* no longer used */ + CTA_STATS_DELETE, /* no longer used */ + CTA_STATS_DELETE_LIST, /* no longer used */ CTA_STATS_INSERT, CTA_STATS_INSERT_FAILED, CTA_STATS_DROP, CTA_STATS_EARLY_DROP, CTA_STATS_ERROR, CTA_STATS_SEARCH_RESTART, + CTA_STATS_CLASH_RESOLVE, + CTA_STATS_CHAIN_TOOLONG, __CTA_STATS_MAX, }; #define CTA_STATS_MAX (__CTA_STATS_MAX - 1) @@ -232,6 +266,7 @@ enum ctattr_stats_cpu { enum ctattr_stats_global { CTA_STATS_GLOBAL_UNSPEC, CTA_STATS_GLOBAL_ENTRIES, + CTA_STATS_GLOBAL_MAX_ENTRIES, __CTA_STATS_GLOBAL_MAX, }; #define CTA_STATS_GLOBAL_MAX (__CTA_STATS_GLOBAL_MAX - 1) @@ -245,4 +280,12 @@ enum ctattr_expect_stats { }; #define CTA_STATS_EXP_MAX (__CTA_STATS_EXP_MAX - 1) +enum ctattr_filter { + CTA_FILTER_UNSPEC, + CTA_FILTER_ORIG_FLAGS, + CTA_FILTER_REPLY_FLAGS, + __CTA_FILTER_MAX +}; +#define CTA_FILTER_MAX (__CTA_FILTER_MAX - 1) + #endif /* _IPCONNTRACK_NETLINK_H */ diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux-private/linux/netfilter/nfnetlink_log.h similarity index 82% rename from include/linux/netfilter/nfnetlink_log.h rename to include/linux-private/linux/netfilter/nfnetlink_log.h index 2cfbf13..0af9c11 100644 --- a/include/linux/netfilter/nfnetlink_log.h +++ b/include/linux-private/linux/netfilter/nfnetlink_log.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef _NFNETLINK_LOG_H #define _NFNETLINK_LOG_H @@ -5,10 +6,6 @@ * and not any kind of function definitions. It is shared between kernel and * userspace. Don't put kernel specific stuff in here */ -#ifndef __aligned_be64 -#define __aligned_be64 u_int64_t __attribute__((aligned(8))) -#endif - #include #include @@ -36,6 +33,15 @@ struct nfulnl_msg_packet_timestamp { __aligned_be64 usec; }; +enum nfulnl_vlan_attr { + NFULA_VLAN_UNSPEC, + NFULA_VLAN_PROTO, /* __be16 skb vlan_proto */ + NFULA_VLAN_TCI, /* __be16 skb htons(vlan_tci) */ + __NFULA_VLAN_MAX, +}; + +#define NFULA_VLAN_MAX (__NFULA_VLAN_MAX + 1) + enum nfulnl_attr_type { NFULA_UNSPEC, NFULA_PACKET_HDR, @@ -55,6 +61,10 @@ enum nfulnl_attr_type { NFULA_HWTYPE, /* hardware type */ NFULA_HWHEADER, /* hardware header */ NFULA_HWLEN, /* hardware header length */ + NFULA_CT, /* nfnetlink_conntrack.h */ + NFULA_CT_INFO, /* enum ip_conntrack_info */ + NFULA_VLAN, /* nested attribute: packet vlan info */ + NFULA_L2HDR, /* full L2 header */ __NFULA_MAX }; @@ -97,5 +107,6 @@ enum nfulnl_attr_config { #define NFULNL_CFG_F_SEQ 0x0001 #define NFULNL_CFG_F_SEQ_GLOBAL 0x0002 +#define NFULNL_CFG_F_CONNTRACK 0x0004 #endif /* _NFNETLINK_LOG_H */ diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux-private/linux/netfilter/nfnetlink_queue.h similarity index 67% rename from include/linux/netfilter/nfnetlink_queue.h rename to include/linux-private/linux/netfilter/nfnetlink_queue.h index 95af967..efcb7c0 100644 --- a/include/linux/netfilter/nfnetlink_queue.h +++ b/include/linux-private/linux/netfilter/nfnetlink_queue.h @@ -1,13 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef _NFNETLINK_QUEUE_H #define _NFNETLINK_QUEUE_H #include #include -#ifndef __aligned_be64 -#define __aligned_be64 u_int64_t __attribute__((aligned(8))) -#endif - enum nfqnl_msg_types { NFQNL_MSG_PACKET, /* packet from kernel to userspace */ NFQNL_MSG_VERDICT, /* verdict from userspace to kernel */ @@ -34,6 +31,14 @@ struct nfqnl_msg_packet_timestamp { __aligned_be64 usec; }; +enum nfqnl_vlan_attr { + NFQA_VLAN_UNSPEC, + NFQA_VLAN_PROTO, /* __be16 skb vlan_proto */ + NFQA_VLAN_TCI, /* __be16 skb htons(vlan_tci) */ + __NFQA_VLAN_MAX, +}; +#define NFQA_VLAN_MAX (__NFQA_VLAN_MAX - 1) + enum nfqnl_attr_type { NFQA_UNSPEC, NFQA_PACKET_HDR, @@ -46,9 +51,18 @@ enum nfqnl_attr_type { NFQA_IFINDEX_PHYSOUTDEV, /* __u32 ifindex */ NFQA_HWADDR, /* nfqnl_msg_packet_hw */ NFQA_PAYLOAD, /* opaque data payload */ - NFQA_CT, /* nf_conntrack_netlink.h */ + NFQA_CT, /* nfnetlink_conntrack.h */ NFQA_CT_INFO, /* enum ip_conntrack_info */ NFQA_CAP_LEN, /* __u32 length of captured packet */ + NFQA_SKB_INFO, /* __u32 skb meta information */ + NFQA_EXP, /* nfnetlink_conntrack.h */ + NFQA_UID, /* __u32 sk uid */ + NFQA_GID, /* __u32 sk gid */ + NFQA_SECCTX, /* security context string */ + NFQA_VLAN, /* nested attribute: packet vlan info */ + NFQA_L2HDR, /* full L2 header */ + NFQA_PRIORITY, /* skb->priority */ + NFQA_CGROUP_CLASSID, /* __u32 cgroup classid */ __NFQA_MAX }; @@ -100,6 +114,17 @@ enum nfqnl_attr_config { /* Flags for NFQA_CFG_FLAGS */ #define NFQA_CFG_F_FAIL_OPEN (1 << 0) #define NFQA_CFG_F_CONNTRACK (1 << 1) -#define NFQA_CFG_F_MAX (1 << 2) +#define NFQA_CFG_F_GSO (1 << 2) +#define NFQA_CFG_F_UID_GID (1 << 3) +#define NFQA_CFG_F_SECCTX (1 << 4) +#define NFQA_CFG_F_MAX (1 << 5) + +/* flags for NFQA_SKB_INFO */ +/* packet appears to have wrong checksums, but they are ok */ +#define NFQA_SKB_CSUMNOTREADY (1 << 0) +/* packet is GSO (i.e., exceeds device mtu) */ +#define NFQA_SKB_GSO (1 << 1) +/* csum not validated (incoming device doesn't support hw checksum, etc.) */ +#define NFQA_SKB_CSUM_NOTVERIFIED (1 << 2) #endif /* _NFNETLINK_QUEUE_H */ diff --git a/include/linux-private/linux/netlink.h b/include/linux-private/linux/netlink.h new file mode 100644 index 0000000..47bac97 --- /dev/null +++ b/include/linux-private/linux/netlink.h @@ -0,0 +1,374 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __LINUX_NETLINK_H +#define __LINUX_NETLINK_H + +#include +#include /* for __kernel_sa_family_t */ +#include + +#define NETLINK_ROUTE 0 /* Routing/device hook */ +#define NETLINK_UNUSED 1 /* Unused number */ +#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */ +#define NETLINK_FIREWALL 3 /* Unused number, formerly ip_queue */ +#define NETLINK_SOCK_DIAG 4 /* socket monitoring */ +#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */ +#define NETLINK_XFRM 6 /* ipsec */ +#define NETLINK_SELINUX 7 /* SELinux event notifications */ +#define NETLINK_ISCSI 8 /* Open-iSCSI */ +#define NETLINK_AUDIT 9 /* auditing */ +#define NETLINK_FIB_LOOKUP 10 +#define NETLINK_CONNECTOR 11 +#define NETLINK_NETFILTER 12 /* netfilter subsystem */ +#define NETLINK_IP6_FW 13 +#define NETLINK_DNRTMSG 14 /* DECnet routing messages (obsolete) */ +#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */ +#define NETLINK_GENERIC 16 +/* leave room for NETLINK_DM (DM Events) */ +#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */ +#define NETLINK_ECRYPTFS 19 +#define NETLINK_RDMA 20 +#define NETLINK_CRYPTO 21 /* Crypto layer */ +#define NETLINK_SMC 22 /* SMC monitoring */ + +#define NETLINK_INET_DIAG NETLINK_SOCK_DIAG + +#define MAX_LINKS 32 + +struct sockaddr_nl { + __kernel_sa_family_t nl_family; /* AF_NETLINK */ + unsigned short nl_pad; /* zero */ + __u32 nl_pid; /* port ID */ + __u32 nl_groups; /* multicast groups mask */ +}; + +/** + * struct nlmsghdr - fixed format metadata header of Netlink messages + * @nlmsg_len: Length of message including header + * @nlmsg_type: Message content type + * @nlmsg_flags: Additional flags + * @nlmsg_seq: Sequence number + * @nlmsg_pid: Sending process port ID + */ +struct nlmsghdr { + __u32 nlmsg_len; + __u16 nlmsg_type; + __u16 nlmsg_flags; + __u32 nlmsg_seq; + __u32 nlmsg_pid; +}; + +/* Flags values */ + +#define NLM_F_REQUEST 0x01 /* It is request message. */ +#define NLM_F_MULTI 0x02 /* Multipart message, terminated by NLMSG_DONE */ +#define NLM_F_ACK 0x04 /* Reply with ack, with zero or error code */ +#define NLM_F_ECHO 0x08 /* Receive resulting notifications */ +#define NLM_F_DUMP_INTR 0x10 /* Dump was inconsistent due to sequence change */ +#define NLM_F_DUMP_FILTERED 0x20 /* Dump was filtered as requested */ + +/* Modifiers to GET request */ +#define NLM_F_ROOT 0x100 /* specify tree root */ +#define NLM_F_MATCH 0x200 /* return all matching */ +#define NLM_F_ATOMIC 0x400 /* atomic GET */ +#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH) + +/* Modifiers to NEW request */ +#define NLM_F_REPLACE 0x100 /* Override existing */ +#define NLM_F_EXCL 0x200 /* Do not touch, if it exists */ +#define NLM_F_CREATE 0x400 /* Create, if it does not exist */ +#define NLM_F_APPEND 0x800 /* Add to end of list */ + +/* Modifiers to DELETE request */ +#define NLM_F_NONREC 0x100 /* Do not delete recursively */ +#define NLM_F_BULK 0x200 /* Delete multiple objects */ + +/* Flags for ACK message */ +#define NLM_F_CAPPED 0x100 /* request was capped */ +#define NLM_F_ACK_TLVS 0x200 /* extended ACK TVLs were included */ + +/* + 4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL + 4.4BSD CHANGE NLM_F_REPLACE + + True CHANGE NLM_F_CREATE|NLM_F_REPLACE + Append NLM_F_CREATE + Check NLM_F_EXCL + */ + +#define NLMSG_ALIGNTO 4U +#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) ) +#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr))) +#define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN) +#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len)) +#define NLMSG_DATA(nlh) ((void *)(((char *)nlh) + NLMSG_HDRLEN)) +#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \ + (struct nlmsghdr *)(((char *)(nlh)) + \ + NLMSG_ALIGN((nlh)->nlmsg_len))) +#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \ + (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \ + (nlh)->nlmsg_len <= (len)) +#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len))) + +#define NLMSG_NOOP 0x1 /* Nothing. */ +#define NLMSG_ERROR 0x2 /* Error */ +#define NLMSG_DONE 0x3 /* End of a dump */ +#define NLMSG_OVERRUN 0x4 /* Data lost */ + +#define NLMSG_MIN_TYPE 0x10 /* < 0x10: reserved control messages */ + +struct nlmsgerr { + int error; + struct nlmsghdr msg; + /* + * followed by the message contents unless NETLINK_CAP_ACK was set + * or the ACK indicates success (error == 0) + * message length is aligned with NLMSG_ALIGN() + */ + /* + * followed by TLVs defined in enum nlmsgerr_attrs + * if NETLINK_EXT_ACK was set + */ +}; + +/** + * enum nlmsgerr_attrs - nlmsgerr attributes + * @NLMSGERR_ATTR_UNUSED: unused + * @NLMSGERR_ATTR_MSG: error message string (string) + * @NLMSGERR_ATTR_OFFS: offset of the invalid attribute in the original + * message, counting from the beginning of the header (u32) + * @NLMSGERR_ATTR_COOKIE: arbitrary subsystem specific cookie to + * be used - in the success case - to identify a created + * object or operation or similar (binary) + * @NLMSGERR_ATTR_POLICY: policy for a rejected attribute + * @NLMSGERR_ATTR_MISS_TYPE: type of a missing required attribute, + * %NLMSGERR_ATTR_MISS_NEST will not be present if the attribute was + * missing at the message level + * @NLMSGERR_ATTR_MISS_NEST: offset of the nest where attribute was missing + * @__NLMSGERR_ATTR_MAX: number of attributes + * @NLMSGERR_ATTR_MAX: highest attribute number + */ +enum nlmsgerr_attrs { + NLMSGERR_ATTR_UNUSED, + NLMSGERR_ATTR_MSG, + NLMSGERR_ATTR_OFFS, + NLMSGERR_ATTR_COOKIE, + NLMSGERR_ATTR_POLICY, + NLMSGERR_ATTR_MISS_TYPE, + NLMSGERR_ATTR_MISS_NEST, + + __NLMSGERR_ATTR_MAX, + NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1 +}; + +#define NETLINK_ADD_MEMBERSHIP 1 +#define NETLINK_DROP_MEMBERSHIP 2 +#define NETLINK_PKTINFO 3 +#define NETLINK_BROADCAST_ERROR 4 +#define NETLINK_NO_ENOBUFS 5 +#define NETLINK_RX_RING 6 +#define NETLINK_TX_RING 7 +#define NETLINK_LISTEN_ALL_NSID 8 +#define NETLINK_LIST_MEMBERSHIPS 9 +#define NETLINK_CAP_ACK 10 +#define NETLINK_EXT_ACK 11 +#define NETLINK_GET_STRICT_CHK 12 + +struct nl_pktinfo { + __u32 group; +}; + +struct nl_mmap_req { + unsigned int nm_block_size; + unsigned int nm_block_nr; + unsigned int nm_frame_size; + unsigned int nm_frame_nr; +}; + +struct nl_mmap_hdr { + unsigned int nm_status; + unsigned int nm_len; + __u32 nm_group; + /* credentials */ + __u32 nm_pid; + __u32 nm_uid; + __u32 nm_gid; +}; + +enum nl_mmap_status { + NL_MMAP_STATUS_UNUSED, + NL_MMAP_STATUS_RESERVED, + NL_MMAP_STATUS_VALID, + NL_MMAP_STATUS_COPY, + NL_MMAP_STATUS_SKIP, +}; + +#define NL_MMAP_MSG_ALIGNMENT NLMSG_ALIGNTO +#define NL_MMAP_MSG_ALIGN(sz) __ALIGN_KERNEL(sz, NL_MMAP_MSG_ALIGNMENT) +#define NL_MMAP_HDRLEN NL_MMAP_MSG_ALIGN(sizeof(struct nl_mmap_hdr)) + +#define NET_MAJOR 36 /* Major 36 is reserved for networking */ + +enum { + NETLINK_UNCONNECTED = 0, + NETLINK_CONNECTED, +}; + +/* + * <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)--> + * +---------------------+- - -+- - - - - - - - - -+- - -+ + * | Header | Pad | Payload | Pad | + * | (struct nlattr) | ing | | ing | + * +---------------------+- - -+- - - - - - - - - -+- - -+ + * <-------------- nlattr->nla_len --------------> + */ + +struct nlattr { + __u16 nla_len; + __u16 nla_type; +}; + +/* + * nla_type (16 bits) + * +---+---+-------------------------------+ + * | N | O | Attribute Type | + * +---+---+-------------------------------+ + * N := Carries nested attributes + * O := Payload stored in network byte order + * + * Note: The N and O flag are mutually exclusive. + */ +#define NLA_F_NESTED (1 << 15) +#define NLA_F_NET_BYTEORDER (1 << 14) +#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER) + +#define NLA_ALIGNTO 4 +#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1)) +#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr))) + +/* Generic 32 bitflags attribute content sent to the kernel. + * + * The value is a bitmap that defines the values being set + * The selector is a bitmask that defines which value is legit + * + * Examples: + * value = 0x0, and selector = 0x1 + * implies we are selecting bit 1 and we want to set its value to 0. + * + * value = 0x2, and selector = 0x2 + * implies we are selecting bit 2 and we want to set its value to 1. + * + */ +struct nla_bitfield32 { + __u32 value; + __u32 selector; +}; + +/* + * policy descriptions - it's specific to each family how this is used + * Normally, it should be retrieved via a dump inside another attribute + * specifying where it applies. + */ + +/** + * enum netlink_attribute_type - type of an attribute + * @NL_ATTR_TYPE_INVALID: unused + * @NL_ATTR_TYPE_FLAG: flag attribute (present/not present) + * @NL_ATTR_TYPE_U8: 8-bit unsigned attribute + * @NL_ATTR_TYPE_U16: 16-bit unsigned attribute + * @NL_ATTR_TYPE_U32: 32-bit unsigned attribute + * @NL_ATTR_TYPE_U64: 64-bit unsigned attribute + * @NL_ATTR_TYPE_S8: 8-bit signed attribute + * @NL_ATTR_TYPE_S16: 16-bit signed attribute + * @NL_ATTR_TYPE_S32: 32-bit signed attribute + * @NL_ATTR_TYPE_S64: 64-bit signed attribute + * @NL_ATTR_TYPE_BINARY: binary data, min/max length may be specified + * @NL_ATTR_TYPE_STRING: string, min/max length may be specified + * @NL_ATTR_TYPE_NUL_STRING: NUL-terminated string, + * min/max length may be specified + * @NL_ATTR_TYPE_NESTED: nested, i.e. the content of this attribute + * consists of sub-attributes. The nested policy and maxtype + * inside may be specified. + * @NL_ATTR_TYPE_NESTED_ARRAY: nested array, i.e. the content of this + * attribute contains sub-attributes whose type is irrelevant + * (just used to separate the array entries) and each such array + * entry has attributes again, the policy for those inner ones + * and the corresponding maxtype may be specified. + * @NL_ATTR_TYPE_BITFIELD32: &struct nla_bitfield32 attribute + */ +enum netlink_attribute_type { + NL_ATTR_TYPE_INVALID, + + NL_ATTR_TYPE_FLAG, + + NL_ATTR_TYPE_U8, + NL_ATTR_TYPE_U16, + NL_ATTR_TYPE_U32, + NL_ATTR_TYPE_U64, + + NL_ATTR_TYPE_S8, + NL_ATTR_TYPE_S16, + NL_ATTR_TYPE_S32, + NL_ATTR_TYPE_S64, + + NL_ATTR_TYPE_BINARY, + NL_ATTR_TYPE_STRING, + NL_ATTR_TYPE_NUL_STRING, + + NL_ATTR_TYPE_NESTED, + NL_ATTR_TYPE_NESTED_ARRAY, + + NL_ATTR_TYPE_BITFIELD32, +}; + +/** + * enum netlink_policy_type_attr - policy type attributes + * @NL_POLICY_TYPE_ATTR_UNSPEC: unused + * @NL_POLICY_TYPE_ATTR_TYPE: type of the attribute, + * &enum netlink_attribute_type (U32) + * @NL_POLICY_TYPE_ATTR_MIN_VALUE_S: minimum value for signed + * integers (S64) + * @NL_POLICY_TYPE_ATTR_MAX_VALUE_S: maximum value for signed + * integers (S64) + * @NL_POLICY_TYPE_ATTR_MIN_VALUE_U: minimum value for unsigned + * integers (U64) + * @NL_POLICY_TYPE_ATTR_MAX_VALUE_U: maximum value for unsigned + * integers (U64) + * @NL_POLICY_TYPE_ATTR_MIN_LENGTH: minimum length for binary + * attributes, no minimum if not given (U32) + * @NL_POLICY_TYPE_ATTR_MAX_LENGTH: maximum length for binary + * attributes, no maximum if not given (U32) + * @NL_POLICY_TYPE_ATTR_POLICY_IDX: sub policy for nested and + * nested array types (U32) + * @NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE: maximum sub policy + * attribute for nested and nested array types, this can + * in theory be < the size of the policy pointed to by + * the index, if limited inside the nesting (U32) + * @NL_POLICY_TYPE_ATTR_BITFIELD32_MASK: valid mask for the + * bitfield32 type (U32) + * @NL_POLICY_TYPE_ATTR_MASK: mask of valid bits for unsigned integers (U64) + * @NL_POLICY_TYPE_ATTR_PAD: pad attribute for 64-bit alignment + * + * @__NL_POLICY_TYPE_ATTR_MAX: number of attributes + * @NL_POLICY_TYPE_ATTR_MAX: highest attribute number + */ +enum netlink_policy_type_attr { + NL_POLICY_TYPE_ATTR_UNSPEC, + NL_POLICY_TYPE_ATTR_TYPE, + NL_POLICY_TYPE_ATTR_MIN_VALUE_S, + NL_POLICY_TYPE_ATTR_MAX_VALUE_S, + NL_POLICY_TYPE_ATTR_MIN_VALUE_U, + NL_POLICY_TYPE_ATTR_MAX_VALUE_U, + NL_POLICY_TYPE_ATTR_MIN_LENGTH, + NL_POLICY_TYPE_ATTR_MAX_LENGTH, + NL_POLICY_TYPE_ATTR_POLICY_IDX, + NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE, + NL_POLICY_TYPE_ATTR_BITFIELD32_MASK, + NL_POLICY_TYPE_ATTR_PAD, + NL_POLICY_TYPE_ATTR_MASK, + + /* keep last */ + __NL_POLICY_TYPE_ATTR_MAX, + NL_POLICY_TYPE_ATTR_MAX = __NL_POLICY_TYPE_ATTR_MAX - 1 +}; + +#endif /* __LINUX_NETLINK_H */ diff --git a/include/linux-private/linux/nexthop.h b/include/linux-private/linux/nexthop.h new file mode 100644 index 0000000..37b14b4 --- /dev/null +++ b/include/linux-private/linux/nexthop.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_NEXTHOP_H +#define _LINUX_NEXTHOP_H + +#include + +struct nhmsg { + unsigned char nh_family; + unsigned char nh_scope; /* return only */ + unsigned char nh_protocol; /* Routing protocol that installed nh */ + unsigned char resvd; + unsigned int nh_flags; /* RTNH_F flags */ +}; + +/* entry in a nexthop group */ +struct nexthop_grp { + __u32 id; /* nexthop id - must exist */ + __u8 weight; /* weight of this nexthop */ + __u8 resvd1; + __u16 resvd2; +}; + +enum { + NEXTHOP_GRP_TYPE_MPATH, /* hash-threshold nexthop group + * default type if not specified + */ + NEXTHOP_GRP_TYPE_RES, /* resilient nexthop group */ + __NEXTHOP_GRP_TYPE_MAX, +}; + +#define NEXTHOP_GRP_TYPE_MAX (__NEXTHOP_GRP_TYPE_MAX - 1) + +enum { + NHA_UNSPEC, + NHA_ID, /* u32; id for nexthop. id == 0 means auto-assign */ + + NHA_GROUP, /* array of nexthop_grp */ + NHA_GROUP_TYPE, /* u16 one of NEXTHOP_GRP_TYPE */ + /* if NHA_GROUP attribute is added, no other attributes can be set */ + + NHA_BLACKHOLE, /* flag; nexthop used to blackhole packets */ + /* if NHA_BLACKHOLE is added, OIF, GATEWAY, ENCAP can not be set */ + + NHA_OIF, /* u32; nexthop device */ + NHA_GATEWAY, /* be32 (IPv4) or in6_addr (IPv6) gw address */ + NHA_ENCAP_TYPE, /* u16; lwt encap type */ + NHA_ENCAP, /* lwt encap data */ + + /* NHA_OIF can be appended to dump request to return only + * nexthops using given device + */ + NHA_GROUPS, /* flag; only return nexthop groups in dump */ + NHA_MASTER, /* u32; only return nexthops with given master dev */ + + NHA_FDB, /* flag; nexthop belongs to a bridge fdb */ + /* if NHA_FDB is added, OIF, BLACKHOLE, ENCAP cannot be set */ + + /* nested; resilient nexthop group attributes */ + NHA_RES_GROUP, + /* nested; nexthop bucket attributes */ + NHA_RES_BUCKET, + + __NHA_MAX, +}; + +#define NHA_MAX (__NHA_MAX - 1) + +enum { + NHA_RES_GROUP_UNSPEC, + /* Pad attribute for 64-bit alignment. */ + NHA_RES_GROUP_PAD = NHA_RES_GROUP_UNSPEC, + + /* u16; number of nexthop buckets in a resilient nexthop group */ + NHA_RES_GROUP_BUCKETS, + /* clock_t as u32; nexthop bucket idle timer (per-group) */ + NHA_RES_GROUP_IDLE_TIMER, + /* clock_t as u32; nexthop unbalanced timer */ + NHA_RES_GROUP_UNBALANCED_TIMER, + /* clock_t as u64; nexthop unbalanced time */ + NHA_RES_GROUP_UNBALANCED_TIME, + + __NHA_RES_GROUP_MAX, +}; + +#define NHA_RES_GROUP_MAX (__NHA_RES_GROUP_MAX - 1) + +enum { + NHA_RES_BUCKET_UNSPEC, + /* Pad attribute for 64-bit alignment. */ + NHA_RES_BUCKET_PAD = NHA_RES_BUCKET_UNSPEC, + + /* u16; nexthop bucket index */ + NHA_RES_BUCKET_INDEX, + /* clock_t as u64; nexthop bucket idle time */ + NHA_RES_BUCKET_IDLE_TIME, + /* u32; nexthop id assigned to the nexthop bucket */ + NHA_RES_BUCKET_NH_ID, + + __NHA_RES_BUCKET_MAX, +}; + +#define NHA_RES_BUCKET_MAX (__NHA_RES_BUCKET_MAX - 1) + +#endif diff --git a/include/linux-private/linux/pkt_cls.h b/include/linux-private/linux/pkt_cls.h new file mode 100644 index 0000000..648a82f --- /dev/null +++ b/include/linux-private/linux/pkt_cls.h @@ -0,0 +1,804 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __LINUX_PKT_CLS_H +#define __LINUX_PKT_CLS_H + +#include +#include + +#define TC_COOKIE_MAX_SIZE 16 + +/* Action attributes */ +enum { + TCA_ACT_UNSPEC, + TCA_ACT_KIND, + TCA_ACT_OPTIONS, + TCA_ACT_INDEX, + TCA_ACT_STATS, + TCA_ACT_PAD, + TCA_ACT_COOKIE, + TCA_ACT_FLAGS, + TCA_ACT_HW_STATS, + TCA_ACT_USED_HW_STATS, + TCA_ACT_IN_HW_COUNT, + __TCA_ACT_MAX +}; + +/* See other TCA_ACT_FLAGS_ * flags in include/net/act_api.h. */ +#define TCA_ACT_FLAGS_NO_PERCPU_STATS (1 << 0) /* Don't use percpu allocator for + * actions stats. + */ +#define TCA_ACT_FLAGS_SKIP_HW (1 << 1) /* don't offload action to HW */ +#define TCA_ACT_FLAGS_SKIP_SW (1 << 2) /* don't use action in SW */ + +/* tca HW stats type + * When user does not pass the attribute, he does not care. + * It is the same as if he would pass the attribute with + * all supported bits set. + * In case no bits are set, user is not interested in getting any HW statistics. + */ +#define TCA_ACT_HW_STATS_IMMEDIATE (1 << 0) /* Means that in dump, user + * gets the current HW stats + * state from the device + * queried at the dump time. + */ +#define TCA_ACT_HW_STATS_DELAYED (1 << 1) /* Means that in dump, user gets + * HW stats that might be out of date + * for some time, maybe couple of + * seconds. This is the case when + * driver polls stats updates + * periodically or when it gets async + * stats update from the device. + */ + +#define TCA_ACT_MAX __TCA_ACT_MAX +#define TCA_OLD_COMPAT (TCA_ACT_MAX+1) +#define TCA_ACT_MAX_PRIO 32 +#define TCA_ACT_BIND 1 +#define TCA_ACT_NOBIND 0 +#define TCA_ACT_UNBIND 1 +#define TCA_ACT_NOUNBIND 0 +#define TCA_ACT_REPLACE 1 +#define TCA_ACT_NOREPLACE 0 + +#define TC_ACT_UNSPEC (-1) +#define TC_ACT_OK 0 +#define TC_ACT_RECLASSIFY 1 +#define TC_ACT_SHOT 2 +#define TC_ACT_PIPE 3 +#define TC_ACT_STOLEN 4 +#define TC_ACT_QUEUED 5 +#define TC_ACT_REPEAT 6 +#define TC_ACT_REDIRECT 7 +#define TC_ACT_TRAP 8 /* For hw path, this means "trap to cpu" + * and don't further process the frame + * in hardware. For sw path, this is + * equivalent of TC_ACT_STOLEN - drop + * the skb and act like everything + * is alright. + */ +#define TC_ACT_VALUE_MAX TC_ACT_TRAP + +/* There is a special kind of actions called "extended actions", + * which need a value parameter. These have a local opcode located in + * the highest nibble, starting from 1. The rest of the bits + * are used to carry the value. These two parts together make + * a combined opcode. + */ +#define __TC_ACT_EXT_SHIFT 28 +#define __TC_ACT_EXT(local) ((local) << __TC_ACT_EXT_SHIFT) +#define TC_ACT_EXT_VAL_MASK ((1 << __TC_ACT_EXT_SHIFT) - 1) +#define TC_ACT_EXT_OPCODE(combined) ((combined) & (~TC_ACT_EXT_VAL_MASK)) +#define TC_ACT_EXT_CMP(combined, opcode) (TC_ACT_EXT_OPCODE(combined) == opcode) + +#define TC_ACT_JUMP __TC_ACT_EXT(1) +#define TC_ACT_GOTO_CHAIN __TC_ACT_EXT(2) +#define TC_ACT_EXT_OPCODE_MAX TC_ACT_GOTO_CHAIN + +/* These macros are put here for binary compatibility with userspace apps that + * make use of them. For kernel code and new userspace apps, use the TCA_ID_* + * versions. + */ +#define TCA_ACT_GACT 5 +#define TCA_ACT_IPT 6 +#define TCA_ACT_PEDIT 7 +#define TCA_ACT_MIRRED 8 +#define TCA_ACT_NAT 9 +#define TCA_ACT_XT 10 +#define TCA_ACT_SKBEDIT 11 +#define TCA_ACT_VLAN 12 +#define TCA_ACT_BPF 13 +#define TCA_ACT_CONNMARK 14 +#define TCA_ACT_SKBMOD 15 +#define TCA_ACT_CSUM 16 +#define TCA_ACT_TUNNEL_KEY 17 +#define TCA_ACT_SIMP 22 +#define TCA_ACT_IFE 25 +#define TCA_ACT_SAMPLE 26 + +/* Action type identifiers*/ +enum tca_id { + TCA_ID_UNSPEC = 0, + TCA_ID_POLICE = 1, + TCA_ID_GACT = TCA_ACT_GACT, + TCA_ID_IPT = TCA_ACT_IPT, + TCA_ID_PEDIT = TCA_ACT_PEDIT, + TCA_ID_MIRRED = TCA_ACT_MIRRED, + TCA_ID_NAT = TCA_ACT_NAT, + TCA_ID_XT = TCA_ACT_XT, + TCA_ID_SKBEDIT = TCA_ACT_SKBEDIT, + TCA_ID_VLAN = TCA_ACT_VLAN, + TCA_ID_BPF = TCA_ACT_BPF, + TCA_ID_CONNMARK = TCA_ACT_CONNMARK, + TCA_ID_SKBMOD = TCA_ACT_SKBMOD, + TCA_ID_CSUM = TCA_ACT_CSUM, + TCA_ID_TUNNEL_KEY = TCA_ACT_TUNNEL_KEY, + TCA_ID_SIMP = TCA_ACT_SIMP, + TCA_ID_IFE = TCA_ACT_IFE, + TCA_ID_SAMPLE = TCA_ACT_SAMPLE, + TCA_ID_CTINFO, + TCA_ID_MPLS, + TCA_ID_CT, + TCA_ID_GATE, + /* other actions go here */ + __TCA_ID_MAX = 255 +}; + +#define TCA_ID_MAX __TCA_ID_MAX + +struct tc_police { + __u32 index; + int action; +#define TC_POLICE_UNSPEC TC_ACT_UNSPEC +#define TC_POLICE_OK TC_ACT_OK +#define TC_POLICE_RECLASSIFY TC_ACT_RECLASSIFY +#define TC_POLICE_SHOT TC_ACT_SHOT +#define TC_POLICE_PIPE TC_ACT_PIPE + + __u32 limit; + __u32 burst; + __u32 mtu; + struct tc_ratespec rate; + struct tc_ratespec peakrate; + int refcnt; + int bindcnt; + __u32 capab; +}; + +struct tcf_t { + __u64 install; + __u64 lastuse; + __u64 expires; + __u64 firstuse; +}; + +struct tc_cnt { + int refcnt; + int bindcnt; +}; + +#define tc_gen \ + __u32 index; \ + __u32 capab; \ + int action; \ + int refcnt; \ + int bindcnt + +enum { + TCA_POLICE_UNSPEC, + TCA_POLICE_TBF, + TCA_POLICE_RATE, + TCA_POLICE_PEAKRATE, + TCA_POLICE_AVRATE, + TCA_POLICE_RESULT, + TCA_POLICE_TM, + TCA_POLICE_PAD, + TCA_POLICE_RATE64, + TCA_POLICE_PEAKRATE64, + TCA_POLICE_PKTRATE64, + TCA_POLICE_PKTBURST64, + __TCA_POLICE_MAX +#define TCA_POLICE_RESULT TCA_POLICE_RESULT +}; + +#define TCA_POLICE_MAX (__TCA_POLICE_MAX - 1) + +/* tca flags definitions */ +#define TCA_CLS_FLAGS_SKIP_HW (1 << 0) /* don't offload filter to HW */ +#define TCA_CLS_FLAGS_SKIP_SW (1 << 1) /* don't use filter in SW */ +#define TCA_CLS_FLAGS_IN_HW (1 << 2) /* filter is offloaded to HW */ +#define TCA_CLS_FLAGS_NOT_IN_HW (1 << 3) /* filter isn't offloaded to HW */ +#define TCA_CLS_FLAGS_VERBOSE (1 << 4) /* verbose logging */ + +/* U32 filters */ + +#define TC_U32_HTID(h) ((h)&0xFFF00000) +#define TC_U32_USERHTID(h) (TC_U32_HTID(h)>>20) +#define TC_U32_HASH(h) (((h)>>12)&0xFF) +#define TC_U32_NODE(h) ((h)&0xFFF) +#define TC_U32_KEY(h) ((h)&0xFFFFF) +#define TC_U32_UNSPEC 0 +#define TC_U32_ROOT (0xFFF00000) + +enum { + TCA_U32_UNSPEC, + TCA_U32_CLASSID, + TCA_U32_HASH, + TCA_U32_LINK, + TCA_U32_DIVISOR, + TCA_U32_SEL, + TCA_U32_POLICE, + TCA_U32_ACT, + TCA_U32_INDEV, + TCA_U32_PCNT, + TCA_U32_MARK, + TCA_U32_FLAGS, + TCA_U32_PAD, + __TCA_U32_MAX +}; + +#define TCA_U32_MAX (__TCA_U32_MAX - 1) + +struct tc_u32_key { + __be32 mask; + __be32 val; + int off; + int offmask; +}; + +struct tc_u32_sel { + unsigned char flags; + unsigned char offshift; + unsigned char nkeys; + + __be16 offmask; + __u16 off; + short offoff; + + short hoff; + __be32 hmask; + struct tc_u32_key keys[]; +}; + +struct tc_u32_mark { + __u32 val; + __u32 mask; + __u32 success; +}; + +struct tc_u32_pcnt { + __u64 rcnt; + __u64 rhit; + __u64 kcnts[]; +}; + +/* Flags */ + +#define TC_U32_TERMINAL 1 +#define TC_U32_OFFSET 2 +#define TC_U32_VAROFFSET 4 +#define TC_U32_EAT 8 + +#define TC_U32_MAXDEPTH 8 + + +/* RSVP filter */ + +enum { + TCA_RSVP_UNSPEC, + TCA_RSVP_CLASSID, + TCA_RSVP_DST, + TCA_RSVP_SRC, + TCA_RSVP_PINFO, + TCA_RSVP_POLICE, + TCA_RSVP_ACT, + __TCA_RSVP_MAX +}; + +#define TCA_RSVP_MAX (__TCA_RSVP_MAX - 1 ) + +struct tc_rsvp_gpi { + __u32 key; + __u32 mask; + int offset; +}; + +struct tc_rsvp_pinfo { + struct tc_rsvp_gpi dpi; + struct tc_rsvp_gpi spi; + __u8 protocol; + __u8 tunnelid; + __u8 tunnelhdr; + __u8 pad; +}; + +/* ROUTE filter */ + +enum { + TCA_ROUTE4_UNSPEC, + TCA_ROUTE4_CLASSID, + TCA_ROUTE4_TO, + TCA_ROUTE4_FROM, + TCA_ROUTE4_IIF, + TCA_ROUTE4_POLICE, + TCA_ROUTE4_ACT, + __TCA_ROUTE4_MAX +}; + +#define TCA_ROUTE4_MAX (__TCA_ROUTE4_MAX - 1) + + +/* FW filter */ + +enum { + TCA_FW_UNSPEC, + TCA_FW_CLASSID, + TCA_FW_POLICE, + TCA_FW_INDEV, + TCA_FW_ACT, /* used by CONFIG_NET_CLS_ACT */ + TCA_FW_MASK, + __TCA_FW_MAX +}; + +#define TCA_FW_MAX (__TCA_FW_MAX - 1) + +/* TC index filter */ + +enum { + TCA_TCINDEX_UNSPEC, + TCA_TCINDEX_HASH, + TCA_TCINDEX_MASK, + TCA_TCINDEX_SHIFT, + TCA_TCINDEX_FALL_THROUGH, + TCA_TCINDEX_CLASSID, + TCA_TCINDEX_POLICE, + TCA_TCINDEX_ACT, + __TCA_TCINDEX_MAX +}; + +#define TCA_TCINDEX_MAX (__TCA_TCINDEX_MAX - 1) + +/* Flow filter */ + +enum { + FLOW_KEY_SRC, + FLOW_KEY_DST, + FLOW_KEY_PROTO, + FLOW_KEY_PROTO_SRC, + FLOW_KEY_PROTO_DST, + FLOW_KEY_IIF, + FLOW_KEY_PRIORITY, + FLOW_KEY_MARK, + FLOW_KEY_NFCT, + FLOW_KEY_NFCT_SRC, + FLOW_KEY_NFCT_DST, + FLOW_KEY_NFCT_PROTO_SRC, + FLOW_KEY_NFCT_PROTO_DST, + FLOW_KEY_RTCLASSID, + FLOW_KEY_SKUID, + FLOW_KEY_SKGID, + FLOW_KEY_VLAN_TAG, + FLOW_KEY_RXHASH, + __FLOW_KEY_MAX, +}; + +#define FLOW_KEY_MAX (__FLOW_KEY_MAX - 1) + +enum { + FLOW_MODE_MAP, + FLOW_MODE_HASH, +}; + +enum { + TCA_FLOW_UNSPEC, + TCA_FLOW_KEYS, + TCA_FLOW_MODE, + TCA_FLOW_BASECLASS, + TCA_FLOW_RSHIFT, + TCA_FLOW_ADDEND, + TCA_FLOW_MASK, + TCA_FLOW_XOR, + TCA_FLOW_DIVISOR, + TCA_FLOW_ACT, + TCA_FLOW_POLICE, + TCA_FLOW_EMATCHES, + TCA_FLOW_PERTURB, + __TCA_FLOW_MAX +}; + +#define TCA_FLOW_MAX (__TCA_FLOW_MAX - 1) + +/* Basic filter */ + +struct tc_basic_pcnt { + __u64 rcnt; + __u64 rhit; +}; + +enum { + TCA_BASIC_UNSPEC, + TCA_BASIC_CLASSID, + TCA_BASIC_EMATCHES, + TCA_BASIC_ACT, + TCA_BASIC_POLICE, + TCA_BASIC_PCNT, + TCA_BASIC_PAD, + __TCA_BASIC_MAX +}; + +#define TCA_BASIC_MAX (__TCA_BASIC_MAX - 1) + + +/* Cgroup classifier */ + +enum { + TCA_CGROUP_UNSPEC, + TCA_CGROUP_ACT, + TCA_CGROUP_POLICE, + TCA_CGROUP_EMATCHES, + __TCA_CGROUP_MAX, +}; + +#define TCA_CGROUP_MAX (__TCA_CGROUP_MAX - 1) + +/* BPF classifier */ + +#define TCA_BPF_FLAG_ACT_DIRECT (1 << 0) + +enum { + TCA_BPF_UNSPEC, + TCA_BPF_ACT, + TCA_BPF_POLICE, + TCA_BPF_CLASSID, + TCA_BPF_OPS_LEN, + TCA_BPF_OPS, + TCA_BPF_FD, + TCA_BPF_NAME, + TCA_BPF_FLAGS, + TCA_BPF_FLAGS_GEN, + TCA_BPF_TAG, + TCA_BPF_ID, + __TCA_BPF_MAX, +}; + +#define TCA_BPF_MAX (__TCA_BPF_MAX - 1) + +/* Flower classifier */ + +enum { + TCA_FLOWER_UNSPEC, + TCA_FLOWER_CLASSID, + TCA_FLOWER_INDEV, + TCA_FLOWER_ACT, + TCA_FLOWER_KEY_ETH_DST, /* ETH_ALEN */ + TCA_FLOWER_KEY_ETH_DST_MASK, /* ETH_ALEN */ + TCA_FLOWER_KEY_ETH_SRC, /* ETH_ALEN */ + TCA_FLOWER_KEY_ETH_SRC_MASK, /* ETH_ALEN */ + TCA_FLOWER_KEY_ETH_TYPE, /* be16 */ + TCA_FLOWER_KEY_IP_PROTO, /* u8 */ + TCA_FLOWER_KEY_IPV4_SRC, /* be32 */ + TCA_FLOWER_KEY_IPV4_SRC_MASK, /* be32 */ + TCA_FLOWER_KEY_IPV4_DST, /* be32 */ + TCA_FLOWER_KEY_IPV4_DST_MASK, /* be32 */ + TCA_FLOWER_KEY_IPV6_SRC, /* struct in6_addr */ + TCA_FLOWER_KEY_IPV6_SRC_MASK, /* struct in6_addr */ + TCA_FLOWER_KEY_IPV6_DST, /* struct in6_addr */ + TCA_FLOWER_KEY_IPV6_DST_MASK, /* struct in6_addr */ + TCA_FLOWER_KEY_TCP_SRC, /* be16 */ + TCA_FLOWER_KEY_TCP_DST, /* be16 */ + TCA_FLOWER_KEY_UDP_SRC, /* be16 */ + TCA_FLOWER_KEY_UDP_DST, /* be16 */ + + TCA_FLOWER_FLAGS, + TCA_FLOWER_KEY_VLAN_ID, /* be16 */ + TCA_FLOWER_KEY_VLAN_PRIO, /* u8 */ + TCA_FLOWER_KEY_VLAN_ETH_TYPE, /* be16 */ + + TCA_FLOWER_KEY_ENC_KEY_ID, /* be32 */ + TCA_FLOWER_KEY_ENC_IPV4_SRC, /* be32 */ + TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK,/* be32 */ + TCA_FLOWER_KEY_ENC_IPV4_DST, /* be32 */ + TCA_FLOWER_KEY_ENC_IPV4_DST_MASK,/* be32 */ + TCA_FLOWER_KEY_ENC_IPV6_SRC, /* struct in6_addr */ + TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK,/* struct in6_addr */ + TCA_FLOWER_KEY_ENC_IPV6_DST, /* struct in6_addr */ + TCA_FLOWER_KEY_ENC_IPV6_DST_MASK,/* struct in6_addr */ + + TCA_FLOWER_KEY_TCP_SRC_MASK, /* be16 */ + TCA_FLOWER_KEY_TCP_DST_MASK, /* be16 */ + TCA_FLOWER_KEY_UDP_SRC_MASK, /* be16 */ + TCA_FLOWER_KEY_UDP_DST_MASK, /* be16 */ + TCA_FLOWER_KEY_SCTP_SRC_MASK, /* be16 */ + TCA_FLOWER_KEY_SCTP_DST_MASK, /* be16 */ + + TCA_FLOWER_KEY_SCTP_SRC, /* be16 */ + TCA_FLOWER_KEY_SCTP_DST, /* be16 */ + + TCA_FLOWER_KEY_ENC_UDP_SRC_PORT, /* be16 */ + TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK, /* be16 */ + TCA_FLOWER_KEY_ENC_UDP_DST_PORT, /* be16 */ + TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK, /* be16 */ + + TCA_FLOWER_KEY_FLAGS, /* be32 */ + TCA_FLOWER_KEY_FLAGS_MASK, /* be32 */ + + TCA_FLOWER_KEY_ICMPV4_CODE, /* u8 */ + TCA_FLOWER_KEY_ICMPV4_CODE_MASK,/* u8 */ + TCA_FLOWER_KEY_ICMPV4_TYPE, /* u8 */ + TCA_FLOWER_KEY_ICMPV4_TYPE_MASK,/* u8 */ + TCA_FLOWER_KEY_ICMPV6_CODE, /* u8 */ + TCA_FLOWER_KEY_ICMPV6_CODE_MASK,/* u8 */ + TCA_FLOWER_KEY_ICMPV6_TYPE, /* u8 */ + TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,/* u8 */ + + TCA_FLOWER_KEY_ARP_SIP, /* be32 */ + TCA_FLOWER_KEY_ARP_SIP_MASK, /* be32 */ + TCA_FLOWER_KEY_ARP_TIP, /* be32 */ + TCA_FLOWER_KEY_ARP_TIP_MASK, /* be32 */ + TCA_FLOWER_KEY_ARP_OP, /* u8 */ + TCA_FLOWER_KEY_ARP_OP_MASK, /* u8 */ + TCA_FLOWER_KEY_ARP_SHA, /* ETH_ALEN */ + TCA_FLOWER_KEY_ARP_SHA_MASK, /* ETH_ALEN */ + TCA_FLOWER_KEY_ARP_THA, /* ETH_ALEN */ + TCA_FLOWER_KEY_ARP_THA_MASK, /* ETH_ALEN */ + + TCA_FLOWER_KEY_MPLS_TTL, /* u8 - 8 bits */ + TCA_FLOWER_KEY_MPLS_BOS, /* u8 - 1 bit */ + TCA_FLOWER_KEY_MPLS_TC, /* u8 - 3 bits */ + TCA_FLOWER_KEY_MPLS_LABEL, /* be32 - 20 bits */ + + TCA_FLOWER_KEY_TCP_FLAGS, /* be16 */ + TCA_FLOWER_KEY_TCP_FLAGS_MASK, /* be16 */ + + TCA_FLOWER_KEY_IP_TOS, /* u8 */ + TCA_FLOWER_KEY_IP_TOS_MASK, /* u8 */ + TCA_FLOWER_KEY_IP_TTL, /* u8 */ + TCA_FLOWER_KEY_IP_TTL_MASK, /* u8 */ + + TCA_FLOWER_KEY_CVLAN_ID, /* be16 */ + TCA_FLOWER_KEY_CVLAN_PRIO, /* u8 */ + TCA_FLOWER_KEY_CVLAN_ETH_TYPE, /* be16 */ + + TCA_FLOWER_KEY_ENC_IP_TOS, /* u8 */ + TCA_FLOWER_KEY_ENC_IP_TOS_MASK, /* u8 */ + TCA_FLOWER_KEY_ENC_IP_TTL, /* u8 */ + TCA_FLOWER_KEY_ENC_IP_TTL_MASK, /* u8 */ + + TCA_FLOWER_KEY_ENC_OPTS, + TCA_FLOWER_KEY_ENC_OPTS_MASK, + + TCA_FLOWER_IN_HW_COUNT, + + TCA_FLOWER_KEY_PORT_SRC_MIN, /* be16 */ + TCA_FLOWER_KEY_PORT_SRC_MAX, /* be16 */ + TCA_FLOWER_KEY_PORT_DST_MIN, /* be16 */ + TCA_FLOWER_KEY_PORT_DST_MAX, /* be16 */ + + TCA_FLOWER_KEY_CT_STATE, /* u16 */ + TCA_FLOWER_KEY_CT_STATE_MASK, /* u16 */ + TCA_FLOWER_KEY_CT_ZONE, /* u16 */ + TCA_FLOWER_KEY_CT_ZONE_MASK, /* u16 */ + TCA_FLOWER_KEY_CT_MARK, /* u32 */ + TCA_FLOWER_KEY_CT_MARK_MASK, /* u32 */ + TCA_FLOWER_KEY_CT_LABELS, /* u128 */ + TCA_FLOWER_KEY_CT_LABELS_MASK, /* u128 */ + + TCA_FLOWER_KEY_MPLS_OPTS, + + TCA_FLOWER_KEY_HASH, /* u32 */ + TCA_FLOWER_KEY_HASH_MASK, /* u32 */ + + TCA_FLOWER_KEY_NUM_OF_VLANS, /* u8 */ + + TCA_FLOWER_KEY_PPPOE_SID, /* be16 */ + TCA_FLOWER_KEY_PPP_PROTO, /* be16 */ + + TCA_FLOWER_KEY_L2TPV3_SID, /* be32 */ + + __TCA_FLOWER_MAX, +}; + +#define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1) + +enum { + TCA_FLOWER_KEY_CT_FLAGS_NEW = 1 << 0, /* Beginning of a new connection. */ + TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED = 1 << 1, /* Part of an existing connection. */ + TCA_FLOWER_KEY_CT_FLAGS_RELATED = 1 << 2, /* Related to an established connection. */ + TCA_FLOWER_KEY_CT_FLAGS_TRACKED = 1 << 3, /* Conntrack has occurred. */ + TCA_FLOWER_KEY_CT_FLAGS_INVALID = 1 << 4, /* Conntrack is invalid. */ + TCA_FLOWER_KEY_CT_FLAGS_REPLY = 1 << 5, /* Packet is in the reply direction. */ + __TCA_FLOWER_KEY_CT_FLAGS_MAX, +}; + +enum { + TCA_FLOWER_KEY_ENC_OPTS_UNSPEC, + TCA_FLOWER_KEY_ENC_OPTS_GENEVE, /* Nested + * TCA_FLOWER_KEY_ENC_OPT_GENEVE_ + * attributes + */ + TCA_FLOWER_KEY_ENC_OPTS_VXLAN, /* Nested + * TCA_FLOWER_KEY_ENC_OPT_VXLAN_ + * attributes + */ + TCA_FLOWER_KEY_ENC_OPTS_ERSPAN, /* Nested + * TCA_FLOWER_KEY_ENC_OPT_ERSPAN_ + * attributes + */ + TCA_FLOWER_KEY_ENC_OPTS_GTP, /* Nested + * TCA_FLOWER_KEY_ENC_OPT_GTP_ + * attributes + */ + __TCA_FLOWER_KEY_ENC_OPTS_MAX, +}; + +#define TCA_FLOWER_KEY_ENC_OPTS_MAX (__TCA_FLOWER_KEY_ENC_OPTS_MAX - 1) + +enum { + TCA_FLOWER_KEY_ENC_OPT_GENEVE_UNSPEC, + TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS, /* u16 */ + TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE, /* u8 */ + TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA, /* 4 to 128 bytes */ + + __TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX, +}; + +#define TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX \ + (__TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX - 1) + +enum { + TCA_FLOWER_KEY_ENC_OPT_VXLAN_UNSPEC, + TCA_FLOWER_KEY_ENC_OPT_VXLAN_GBP, /* u32 */ + __TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX, +}; + +#define TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX \ + (__TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX - 1) + +enum { + TCA_FLOWER_KEY_ENC_OPT_ERSPAN_UNSPEC, + TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER, /* u8 */ + TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX, /* be32 */ + TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR, /* u8 */ + TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID, /* u8 */ + __TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX, +}; + +#define TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX \ + (__TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX - 1) + +enum { + TCA_FLOWER_KEY_ENC_OPT_GTP_UNSPEC, + TCA_FLOWER_KEY_ENC_OPT_GTP_PDU_TYPE, /* u8 */ + TCA_FLOWER_KEY_ENC_OPT_GTP_QFI, /* u8 */ + + __TCA_FLOWER_KEY_ENC_OPT_GTP_MAX, +}; + +#define TCA_FLOWER_KEY_ENC_OPT_GTP_MAX \ + (__TCA_FLOWER_KEY_ENC_OPT_GTP_MAX - 1) + +enum { + TCA_FLOWER_KEY_MPLS_OPTS_UNSPEC, + TCA_FLOWER_KEY_MPLS_OPTS_LSE, + __TCA_FLOWER_KEY_MPLS_OPTS_MAX, +}; + +#define TCA_FLOWER_KEY_MPLS_OPTS_MAX (__TCA_FLOWER_KEY_MPLS_OPTS_MAX - 1) + +enum { + TCA_FLOWER_KEY_MPLS_OPT_LSE_UNSPEC, + TCA_FLOWER_KEY_MPLS_OPT_LSE_DEPTH, + TCA_FLOWER_KEY_MPLS_OPT_LSE_TTL, + TCA_FLOWER_KEY_MPLS_OPT_LSE_BOS, + TCA_FLOWER_KEY_MPLS_OPT_LSE_TC, + TCA_FLOWER_KEY_MPLS_OPT_LSE_LABEL, + __TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX, +}; + +#define TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX \ + (__TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX - 1) + +enum { + TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0), + TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1), +}; + +#define TCA_FLOWER_MASK_FLAGS_RANGE (1 << 0) /* Range-based match */ + +/* Match-all classifier */ + +struct tc_matchall_pcnt { + __u64 rhit; +}; + +enum { + TCA_MATCHALL_UNSPEC, + TCA_MATCHALL_CLASSID, + TCA_MATCHALL_ACT, + TCA_MATCHALL_FLAGS, + TCA_MATCHALL_PCNT, + TCA_MATCHALL_PAD, + __TCA_MATCHALL_MAX, +}; + +#define TCA_MATCHALL_MAX (__TCA_MATCHALL_MAX - 1) + +/* Extended Matches */ + +struct tcf_ematch_tree_hdr { + __u16 nmatches; + __u16 progid; +}; + +enum { + TCA_EMATCH_TREE_UNSPEC, + TCA_EMATCH_TREE_HDR, + TCA_EMATCH_TREE_LIST, + __TCA_EMATCH_TREE_MAX +}; +#define TCA_EMATCH_TREE_MAX (__TCA_EMATCH_TREE_MAX - 1) + +struct tcf_ematch_hdr { + __u16 matchid; + __u16 kind; + __u16 flags; + __u16 pad; /* currently unused */ +}; + +/* 0 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +-----------------------+-+-+---+ + * | Unused |S|I| R | + * +-----------------------+-+-+---+ + * + * R(2) ::= relation to next ematch + * where: 0 0 END (last ematch) + * 0 1 AND + * 1 0 OR + * 1 1 Unused (invalid) + * I(1) ::= invert result + * S(1) ::= simple payload + */ +#define TCF_EM_REL_END 0 +#define TCF_EM_REL_AND (1<<0) +#define TCF_EM_REL_OR (1<<1) +#define TCF_EM_INVERT (1<<2) +#define TCF_EM_SIMPLE (1<<3) + +#define TCF_EM_REL_MASK 3 +#define TCF_EM_REL_VALID(v) (((v) & TCF_EM_REL_MASK) != TCF_EM_REL_MASK) + +enum { + TCF_LAYER_LINK, + TCF_LAYER_NETWORK, + TCF_LAYER_TRANSPORT, + __TCF_LAYER_MAX +}; +#define TCF_LAYER_MAX (__TCF_LAYER_MAX - 1) + +/* Ematch type assignments + * 1..32767 Reserved for ematches inside kernel tree + * 32768..65535 Free to use, not reliable + */ +#define TCF_EM_CONTAINER 0 +#define TCF_EM_CMP 1 +#define TCF_EM_NBYTE 2 +#define TCF_EM_U32 3 +#define TCF_EM_META 4 +#define TCF_EM_TEXT 5 +#define TCF_EM_VLAN 6 +#define TCF_EM_CANID 7 +#define TCF_EM_IPSET 8 +#define TCF_EM_IPT 9 +#define TCF_EM_MAX 9 + +enum { + TCF_EM_PROG_TC +}; + +enum { + TCF_EM_OPND_EQ, + TCF_EM_OPND_GT, + TCF_EM_OPND_LT +}; + +#endif diff --git a/include/linux-private/linux/pkt_sched.h b/include/linux-private/linux/pkt_sched.h new file mode 100644 index 0000000..51a7add --- /dev/null +++ b/include/linux-private/linux/pkt_sched.h @@ -0,0 +1,1298 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __LINUX_PKT_SCHED_H +#define __LINUX_PKT_SCHED_H + +#include +#include + +/* Logical priority bands not depending on specific packet scheduler. + Every scheduler will map them to real traffic classes, if it has + no more precise mechanism to classify packets. + + These numbers have no special meaning, though their coincidence + with obsolete IPv6 values is not occasional :-). New IPv6 drafts + preferred full anarchy inspired by diffserv group. + + Note: TC_PRIO_BESTEFFORT does not mean that it is the most unhappy + class, actually, as rule it will be handled with more care than + filler or even bulk. + */ + +#define TC_PRIO_BESTEFFORT 0 +#define TC_PRIO_FILLER 1 +#define TC_PRIO_BULK 2 +#define TC_PRIO_INTERACTIVE_BULK 4 +#define TC_PRIO_INTERACTIVE 6 +#define TC_PRIO_CONTROL 7 + +#define TC_PRIO_MAX 15 + +/* Generic queue statistics, available for all the elements. + Particular schedulers may have also their private records. + */ + +struct tc_stats { + __u64 bytes; /* Number of enqueued bytes */ + __u32 packets; /* Number of enqueued packets */ + __u32 drops; /* Packets dropped because of lack of resources */ + __u32 overlimits; /* Number of throttle events when this + * flow goes out of allocated bandwidth */ + __u32 bps; /* Current flow byte rate */ + __u32 pps; /* Current flow packet rate */ + __u32 qlen; + __u32 backlog; +}; + +struct tc_estimator { + signed char interval; + unsigned char ewma_log; +}; + +/* "Handles" + --------- + + All the traffic control objects have 32bit identifiers, or "handles". + + They can be considered as opaque numbers from user API viewpoint, + but actually they always consist of two fields: major and + minor numbers, which are interpreted by kernel specially, + that may be used by applications, though not recommended. + + F.e. qdisc handles always have minor number equal to zero, + classes (or flows) have major equal to parent qdisc major, and + minor uniquely identifying class inside qdisc. + + Macros to manipulate handles: + */ + +#define TC_H_MAJ_MASK (0xFFFF0000U) +#define TC_H_MIN_MASK (0x0000FFFFU) +#define TC_H_MAJ(h) ((h)&TC_H_MAJ_MASK) +#define TC_H_MIN(h) ((h)&TC_H_MIN_MASK) +#define TC_H_MAKE(maj,min) (((maj)&TC_H_MAJ_MASK)|((min)&TC_H_MIN_MASK)) + +#define TC_H_UNSPEC (0U) +#define TC_H_ROOT (0xFFFFFFFFU) +#define TC_H_INGRESS (0xFFFFFFF1U) +#define TC_H_CLSACT TC_H_INGRESS + +#define TC_H_MIN_PRIORITY 0xFFE0U +#define TC_H_MIN_INGRESS 0xFFF2U +#define TC_H_MIN_EGRESS 0xFFF3U + +/* Need to corrospond to iproute2 tc/tc_core.h "enum link_layer" */ +enum tc_link_layer { + TC_LINKLAYER_UNAWARE, /* Indicate unaware old iproute2 util */ + TC_LINKLAYER_ETHERNET, + TC_LINKLAYER_ATM, +}; +#define TC_LINKLAYER_MASK 0x0F /* limit use to lower 4 bits */ + +struct tc_ratespec { + unsigned char cell_log; + __u8 linklayer; /* lower 4 bits */ + unsigned short overhead; + short cell_align; + unsigned short mpu; + __u32 rate; +}; + +#define TC_RTAB_SIZE 1024 + +struct tc_sizespec { + unsigned char cell_log; + unsigned char size_log; + short cell_align; + int overhead; + unsigned int linklayer; + unsigned int mpu; + unsigned int mtu; + unsigned int tsize; +}; + +enum { + TCA_STAB_UNSPEC, + TCA_STAB_BASE, + TCA_STAB_DATA, + __TCA_STAB_MAX +}; + +#define TCA_STAB_MAX (__TCA_STAB_MAX - 1) + +/* FIFO section */ + +struct tc_fifo_qopt { + __u32 limit; /* Queue length: bytes for bfifo, packets for pfifo */ +}; + +/* SKBPRIO section */ + +/* + * Priorities go from zero to (SKBPRIO_MAX_PRIORITY - 1). + * SKBPRIO_MAX_PRIORITY should be at least 64 in order for skbprio to be able + * to map one to one the DS field of IPV4 and IPV6 headers. + * Memory allocation grows linearly with SKBPRIO_MAX_PRIORITY. + */ + +#define SKBPRIO_MAX_PRIORITY 64 + +struct tc_skbprio_qopt { + __u32 limit; /* Queue length in packets. */ +}; + +/* PRIO section */ + +#define TCQ_PRIO_BANDS 16 +#define TCQ_MIN_PRIO_BANDS 2 + +struct tc_prio_qopt { + int bands; /* Number of bands */ + __u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */ +}; + +/* MULTIQ section */ + +struct tc_multiq_qopt { + __u16 bands; /* Number of bands */ + __u16 max_bands; /* Maximum number of queues */ +}; + +/* PLUG section */ + +#define TCQ_PLUG_BUFFER 0 +#define TCQ_PLUG_RELEASE_ONE 1 +#define TCQ_PLUG_RELEASE_INDEFINITE 2 +#define TCQ_PLUG_LIMIT 3 + +struct tc_plug_qopt { + /* TCQ_PLUG_BUFFER: Inset a plug into the queue and + * buffer any incoming packets + * TCQ_PLUG_RELEASE_ONE: Dequeue packets from queue head + * to beginning of the next plug. + * TCQ_PLUG_RELEASE_INDEFINITE: Dequeue all packets from queue. + * Stop buffering packets until the next TCQ_PLUG_BUFFER + * command is received (just act as a pass-thru queue). + * TCQ_PLUG_LIMIT: Increase/decrease queue size + */ + int action; + __u32 limit; +}; + +/* TBF section */ + +struct tc_tbf_qopt { + struct tc_ratespec rate; + struct tc_ratespec peakrate; + __u32 limit; + __u32 buffer; + __u32 mtu; +}; + +enum { + TCA_TBF_UNSPEC, + TCA_TBF_PARMS, + TCA_TBF_RTAB, + TCA_TBF_PTAB, + TCA_TBF_RATE64, + TCA_TBF_PRATE64, + TCA_TBF_BURST, + TCA_TBF_PBURST, + TCA_TBF_PAD, + __TCA_TBF_MAX, +}; + +#define TCA_TBF_MAX (__TCA_TBF_MAX - 1) + + +/* TEQL section */ + +/* TEQL does not require any parameters */ + +/* SFQ section */ + +struct tc_sfq_qopt { + unsigned quantum; /* Bytes per round allocated to flow */ + int perturb_period; /* Period of hash perturbation */ + __u32 limit; /* Maximal packets in queue */ + unsigned divisor; /* Hash divisor */ + unsigned flows; /* Maximal number of flows */ +}; + +struct tc_sfqred_stats { + __u32 prob_drop; /* Early drops, below max threshold */ + __u32 forced_drop; /* Early drops, after max threshold */ + __u32 prob_mark; /* Marked packets, below max threshold */ + __u32 forced_mark; /* Marked packets, after max threshold */ + __u32 prob_mark_head; /* Marked packets, below max threshold */ + __u32 forced_mark_head;/* Marked packets, after max threshold */ +}; + +struct tc_sfq_qopt_v1 { + struct tc_sfq_qopt v0; + unsigned int depth; /* max number of packets per flow */ + unsigned int headdrop; +/* SFQRED parameters */ + __u32 limit; /* HARD maximal flow queue length (bytes) */ + __u32 qth_min; /* Min average length threshold (bytes) */ + __u32 qth_max; /* Max average length threshold (bytes) */ + unsigned char Wlog; /* log(W) */ + unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ + unsigned char Scell_log; /* cell size for idle damping */ + unsigned char flags; + __u32 max_P; /* probability, high resolution */ +/* SFQRED stats */ + struct tc_sfqred_stats stats; +}; + + +struct tc_sfq_xstats { + __s32 allot; +}; + +/* RED section */ + +enum { + TCA_RED_UNSPEC, + TCA_RED_PARMS, + TCA_RED_STAB, + TCA_RED_MAX_P, + TCA_RED_FLAGS, /* bitfield32 */ + TCA_RED_EARLY_DROP_BLOCK, /* u32 */ + TCA_RED_MARK_BLOCK, /* u32 */ + __TCA_RED_MAX, +}; + +#define TCA_RED_MAX (__TCA_RED_MAX - 1) + +struct tc_red_qopt { + __u32 limit; /* HARD maximal queue length (bytes) */ + __u32 qth_min; /* Min average length threshold (bytes) */ + __u32 qth_max; /* Max average length threshold (bytes) */ + unsigned char Wlog; /* log(W) */ + unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ + unsigned char Scell_log; /* cell size for idle damping */ + + /* This field can be used for flags that a RED-like qdisc has + * historically supported. E.g. when configuring RED, it can be used for + * ECN, HARDDROP and ADAPTATIVE. For SFQ it can be used for ECN, + * HARDDROP. Etc. Because this field has not been validated, and is + * copied back on dump, any bits besides those to which a given qdisc + * has assigned a historical meaning need to be considered for free use + * by userspace tools. + * + * Any further flags need to be passed differently, e.g. through an + * attribute (such as TCA_RED_FLAGS above). Such attribute should allow + * passing both recent and historic flags in one value. + */ + unsigned char flags; +#define TC_RED_ECN 1 +#define TC_RED_HARDDROP 2 +#define TC_RED_ADAPTATIVE 4 +#define TC_RED_NODROP 8 +}; + +#define TC_RED_HISTORIC_FLAGS (TC_RED_ECN | TC_RED_HARDDROP | TC_RED_ADAPTATIVE) + +struct tc_red_xstats { + __u32 early; /* Early drops */ + __u32 pdrop; /* Drops due to queue limits */ + __u32 other; /* Drops due to drop() calls */ + __u32 marked; /* Marked packets */ +}; + +/* GRED section */ + +#define MAX_DPs 16 + +enum { + TCA_GRED_UNSPEC, + TCA_GRED_PARMS, + TCA_GRED_STAB, + TCA_GRED_DPS, + TCA_GRED_MAX_P, + TCA_GRED_LIMIT, + TCA_GRED_VQ_LIST, /* nested TCA_GRED_VQ_ENTRY */ + __TCA_GRED_MAX, +}; + +#define TCA_GRED_MAX (__TCA_GRED_MAX - 1) + +enum { + TCA_GRED_VQ_ENTRY_UNSPEC, + TCA_GRED_VQ_ENTRY, /* nested TCA_GRED_VQ_* */ + __TCA_GRED_VQ_ENTRY_MAX, +}; +#define TCA_GRED_VQ_ENTRY_MAX (__TCA_GRED_VQ_ENTRY_MAX - 1) + +enum { + TCA_GRED_VQ_UNSPEC, + TCA_GRED_VQ_PAD, + TCA_GRED_VQ_DP, /* u32 */ + TCA_GRED_VQ_STAT_BYTES, /* u64 */ + TCA_GRED_VQ_STAT_PACKETS, /* u32 */ + TCA_GRED_VQ_STAT_BACKLOG, /* u32 */ + TCA_GRED_VQ_STAT_PROB_DROP, /* u32 */ + TCA_GRED_VQ_STAT_PROB_MARK, /* u32 */ + TCA_GRED_VQ_STAT_FORCED_DROP, /* u32 */ + TCA_GRED_VQ_STAT_FORCED_MARK, /* u32 */ + TCA_GRED_VQ_STAT_PDROP, /* u32 */ + TCA_GRED_VQ_STAT_OTHER, /* u32 */ + TCA_GRED_VQ_FLAGS, /* u32 */ + __TCA_GRED_VQ_MAX +}; + +#define TCA_GRED_VQ_MAX (__TCA_GRED_VQ_MAX - 1) + +struct tc_gred_qopt { + __u32 limit; /* HARD maximal queue length (bytes) */ + __u32 qth_min; /* Min average length threshold (bytes) */ + __u32 qth_max; /* Max average length threshold (bytes) */ + __u32 DP; /* up to 2^32 DPs */ + __u32 backlog; + __u32 qave; + __u32 forced; + __u32 early; + __u32 other; + __u32 pdrop; + __u8 Wlog; /* log(W) */ + __u8 Plog; /* log(P_max/(qth_max-qth_min)) */ + __u8 Scell_log; /* cell size for idle damping */ + __u8 prio; /* prio of this VQ */ + __u32 packets; + __u32 bytesin; +}; + +/* gred setup */ +struct tc_gred_sopt { + __u32 DPs; + __u32 def_DP; + __u8 grio; + __u8 flags; + __u16 pad1; +}; + +/* CHOKe section */ + +enum { + TCA_CHOKE_UNSPEC, + TCA_CHOKE_PARMS, + TCA_CHOKE_STAB, + TCA_CHOKE_MAX_P, + __TCA_CHOKE_MAX, +}; + +#define TCA_CHOKE_MAX (__TCA_CHOKE_MAX - 1) + +struct tc_choke_qopt { + __u32 limit; /* Hard queue length (packets) */ + __u32 qth_min; /* Min average threshold (packets) */ + __u32 qth_max; /* Max average threshold (packets) */ + unsigned char Wlog; /* log(W) */ + unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ + unsigned char Scell_log; /* cell size for idle damping */ + unsigned char flags; /* see RED flags */ +}; + +struct tc_choke_xstats { + __u32 early; /* Early drops */ + __u32 pdrop; /* Drops due to queue limits */ + __u32 other; /* Drops due to drop() calls */ + __u32 marked; /* Marked packets */ + __u32 matched; /* Drops due to flow match */ +}; + +/* HTB section */ +#define TC_HTB_NUMPRIO 8 +#define TC_HTB_MAXDEPTH 8 +#define TC_HTB_PROTOVER 3 /* the same as HTB and TC's major */ + +struct tc_htb_opt { + struct tc_ratespec rate; + struct tc_ratespec ceil; + __u32 buffer; + __u32 cbuffer; + __u32 quantum; + __u32 level; /* out only */ + __u32 prio; +}; +struct tc_htb_glob { + __u32 version; /* to match HTB/TC */ + __u32 rate2quantum; /* bps->quantum divisor */ + __u32 defcls; /* default class number */ + __u32 debug; /* debug flags */ + + /* stats */ + __u32 direct_pkts; /* count of non shaped packets */ +}; +enum { + TCA_HTB_UNSPEC, + TCA_HTB_PARMS, + TCA_HTB_INIT, + TCA_HTB_CTAB, + TCA_HTB_RTAB, + TCA_HTB_DIRECT_QLEN, + TCA_HTB_RATE64, + TCA_HTB_CEIL64, + TCA_HTB_PAD, + TCA_HTB_OFFLOAD, + __TCA_HTB_MAX, +}; + +#define TCA_HTB_MAX (__TCA_HTB_MAX - 1) + +struct tc_htb_xstats { + __u32 lends; + __u32 borrows; + __u32 giants; /* unused since 'Make HTB scheduler work with TSO.' */ + __s32 tokens; + __s32 ctokens; +}; + +/* HFSC section */ + +struct tc_hfsc_qopt { + __u16 defcls; /* default class */ +}; + +struct tc_service_curve { + __u32 m1; /* slope of the first segment in bps */ + __u32 d; /* x-projection of the first segment in us */ + __u32 m2; /* slope of the second segment in bps */ +}; + +struct tc_hfsc_stats { + __u64 work; /* total work done */ + __u64 rtwork; /* work done by real-time criteria */ + __u32 period; /* current period */ + __u32 level; /* class level in hierarchy */ +}; + +enum { + TCA_HFSC_UNSPEC, + TCA_HFSC_RSC, + TCA_HFSC_FSC, + TCA_HFSC_USC, + __TCA_HFSC_MAX, +}; + +#define TCA_HFSC_MAX (__TCA_HFSC_MAX - 1) + + +/* CBQ section */ + +#define TC_CBQ_MAXPRIO 8 +#define TC_CBQ_MAXLEVEL 8 +#define TC_CBQ_DEF_EWMA 5 + +struct tc_cbq_lssopt { + unsigned char change; + unsigned char flags; +#define TCF_CBQ_LSS_BOUNDED 1 +#define TCF_CBQ_LSS_ISOLATED 2 + unsigned char ewma_log; + unsigned char level; +#define TCF_CBQ_LSS_FLAGS 1 +#define TCF_CBQ_LSS_EWMA 2 +#define TCF_CBQ_LSS_MAXIDLE 4 +#define TCF_CBQ_LSS_MINIDLE 8 +#define TCF_CBQ_LSS_OFFTIME 0x10 +#define TCF_CBQ_LSS_AVPKT 0x20 + __u32 maxidle; + __u32 minidle; + __u32 offtime; + __u32 avpkt; +}; + +struct tc_cbq_wrropt { + unsigned char flags; + unsigned char priority; + unsigned char cpriority; + unsigned char __reserved; + __u32 allot; + __u32 weight; +}; + +struct tc_cbq_ovl { + unsigned char strategy; +#define TC_CBQ_OVL_CLASSIC 0 +#define TC_CBQ_OVL_DELAY 1 +#define TC_CBQ_OVL_LOWPRIO 2 +#define TC_CBQ_OVL_DROP 3 +#define TC_CBQ_OVL_RCLASSIC 4 + unsigned char priority2; + __u16 pad; + __u32 penalty; +}; + +struct tc_cbq_police { + unsigned char police; + unsigned char __res1; + unsigned short __res2; +}; + +struct tc_cbq_fopt { + __u32 split; + __u32 defmap; + __u32 defchange; +}; + +struct tc_cbq_xstats { + __u32 borrows; + __u32 overactions; + __s32 avgidle; + __s32 undertime; +}; + +enum { + TCA_CBQ_UNSPEC, + TCA_CBQ_LSSOPT, + TCA_CBQ_WRROPT, + TCA_CBQ_FOPT, + TCA_CBQ_OVL_STRATEGY, + TCA_CBQ_RATE, + TCA_CBQ_RTAB, + TCA_CBQ_POLICE, + __TCA_CBQ_MAX, +}; + +#define TCA_CBQ_MAX (__TCA_CBQ_MAX - 1) + +/* dsmark section */ + +enum { + TCA_DSMARK_UNSPEC, + TCA_DSMARK_INDICES, + TCA_DSMARK_DEFAULT_INDEX, + TCA_DSMARK_SET_TC_INDEX, + TCA_DSMARK_MASK, + TCA_DSMARK_VALUE, + __TCA_DSMARK_MAX, +}; + +#define TCA_DSMARK_MAX (__TCA_DSMARK_MAX - 1) + +/* ATM section */ + +enum { + TCA_ATM_UNSPEC, + TCA_ATM_FD, /* file/socket descriptor */ + TCA_ATM_PTR, /* pointer to descriptor - later */ + TCA_ATM_HDR, /* LL header */ + TCA_ATM_EXCESS, /* excess traffic class (0 for CLP) */ + TCA_ATM_ADDR, /* PVC address (for output only) */ + TCA_ATM_STATE, /* VC state (ATM_VS_*; for output only) */ + __TCA_ATM_MAX, +}; + +#define TCA_ATM_MAX (__TCA_ATM_MAX - 1) + +/* Network emulator */ + +enum { + TCA_NETEM_UNSPEC, + TCA_NETEM_CORR, + TCA_NETEM_DELAY_DIST, + TCA_NETEM_REORDER, + TCA_NETEM_CORRUPT, + TCA_NETEM_LOSS, + TCA_NETEM_RATE, + TCA_NETEM_ECN, + TCA_NETEM_RATE64, + TCA_NETEM_PAD, + TCA_NETEM_LATENCY64, + TCA_NETEM_JITTER64, + TCA_NETEM_SLOT, + TCA_NETEM_SLOT_DIST, + __TCA_NETEM_MAX, +}; + +#define TCA_NETEM_MAX (__TCA_NETEM_MAX - 1) + +struct tc_netem_qopt { + __u32 latency; /* added delay (us) */ + __u32 limit; /* fifo limit (packets) */ + __u32 loss; /* random packet loss (0=none ~0=100%) */ + __u32 gap; /* re-ordering gap (0 for none) */ + __u32 duplicate; /* random packet dup (0=none ~0=100%) */ + __u32 jitter; /* random jitter in latency (us) */ +}; + +struct tc_netem_corr { + __u32 delay_corr; /* delay correlation */ + __u32 loss_corr; /* packet loss correlation */ + __u32 dup_corr; /* duplicate correlation */ +}; + +struct tc_netem_reorder { + __u32 probability; + __u32 correlation; +}; + +struct tc_netem_corrupt { + __u32 probability; + __u32 correlation; +}; + +struct tc_netem_rate { + __u32 rate; /* byte/s */ + __s32 packet_overhead; + __u32 cell_size; + __s32 cell_overhead; +}; + +struct tc_netem_slot { + __s64 min_delay; /* nsec */ + __s64 max_delay; + __s32 max_packets; + __s32 max_bytes; + __s64 dist_delay; /* nsec */ + __s64 dist_jitter; /* nsec */ +}; + +enum { + NETEM_LOSS_UNSPEC, + NETEM_LOSS_GI, /* General Intuitive - 4 state model */ + NETEM_LOSS_GE, /* Gilbert Elliot models */ + __NETEM_LOSS_MAX +}; +#define NETEM_LOSS_MAX (__NETEM_LOSS_MAX - 1) + +/* State transition probabilities for 4 state model */ +struct tc_netem_gimodel { + __u32 p13; + __u32 p31; + __u32 p32; + __u32 p14; + __u32 p23; +}; + +/* Gilbert-Elliot models */ +struct tc_netem_gemodel { + __u32 p; + __u32 r; + __u32 h; + __u32 k1; +}; + +#define NETEM_DIST_SCALE 8192 +#define NETEM_DIST_MAX 16384 + +/* DRR */ + +enum { + TCA_DRR_UNSPEC, + TCA_DRR_QUANTUM, + __TCA_DRR_MAX +}; + +#define TCA_DRR_MAX (__TCA_DRR_MAX - 1) + +struct tc_drr_stats { + __u32 deficit; +}; + +/* MQPRIO */ +#define TC_QOPT_BITMASK 15 +#define TC_QOPT_MAX_QUEUE 16 + +enum { + TC_MQPRIO_HW_OFFLOAD_NONE, /* no offload requested */ + TC_MQPRIO_HW_OFFLOAD_TCS, /* offload TCs, no queue counts */ + __TC_MQPRIO_HW_OFFLOAD_MAX +}; + +#define TC_MQPRIO_HW_OFFLOAD_MAX (__TC_MQPRIO_HW_OFFLOAD_MAX - 1) + +enum { + TC_MQPRIO_MODE_DCB, + TC_MQPRIO_MODE_CHANNEL, + __TC_MQPRIO_MODE_MAX +}; + +#define __TC_MQPRIO_MODE_MAX (__TC_MQPRIO_MODE_MAX - 1) + +enum { + TC_MQPRIO_SHAPER_DCB, + TC_MQPRIO_SHAPER_BW_RATE, /* Add new shapers below */ + __TC_MQPRIO_SHAPER_MAX +}; + +#define __TC_MQPRIO_SHAPER_MAX (__TC_MQPRIO_SHAPER_MAX - 1) + +enum { + TC_FP_EXPRESS = 1, + TC_FP_PREEMPTIBLE = 2, +}; + +struct tc_mqprio_qopt { + __u8 num_tc; + __u8 prio_tc_map[TC_QOPT_BITMASK + 1]; + __u8 hw; + __u16 count[TC_QOPT_MAX_QUEUE]; + __u16 offset[TC_QOPT_MAX_QUEUE]; +}; + +#define TC_MQPRIO_F_MODE 0x1 +#define TC_MQPRIO_F_SHAPER 0x2 +#define TC_MQPRIO_F_MIN_RATE 0x4 +#define TC_MQPRIO_F_MAX_RATE 0x8 + +enum { + TCA_MQPRIO_TC_ENTRY_UNSPEC, + TCA_MQPRIO_TC_ENTRY_INDEX, /* u32 */ + TCA_MQPRIO_TC_ENTRY_FP, /* u32 */ + + /* add new constants above here */ + __TCA_MQPRIO_TC_ENTRY_CNT, + TCA_MQPRIO_TC_ENTRY_MAX = (__TCA_MQPRIO_TC_ENTRY_CNT - 1) +}; + +enum { + TCA_MQPRIO_UNSPEC, + TCA_MQPRIO_MODE, + TCA_MQPRIO_SHAPER, + TCA_MQPRIO_MIN_RATE64, + TCA_MQPRIO_MAX_RATE64, + TCA_MQPRIO_TC_ENTRY, + __TCA_MQPRIO_MAX, +}; + +#define TCA_MQPRIO_MAX (__TCA_MQPRIO_MAX - 1) + +/* SFB */ + +enum { + TCA_SFB_UNSPEC, + TCA_SFB_PARMS, + __TCA_SFB_MAX, +}; + +#define TCA_SFB_MAX (__TCA_SFB_MAX - 1) + +/* + * Note: increment, decrement are Q0.16 fixed-point values. + */ +struct tc_sfb_qopt { + __u32 rehash_interval; /* delay between hash move, in ms */ + __u32 warmup_time; /* double buffering warmup time in ms (warmup_time < rehash_interval) */ + __u32 max; /* max len of qlen_min */ + __u32 bin_size; /* maximum queue length per bin */ + __u32 increment; /* probability increment, (d1 in Blue) */ + __u32 decrement; /* probability decrement, (d2 in Blue) */ + __u32 limit; /* max SFB queue length */ + __u32 penalty_rate; /* inelastic flows are rate limited to 'rate' pps */ + __u32 penalty_burst; +}; + +struct tc_sfb_xstats { + __u32 earlydrop; + __u32 penaltydrop; + __u32 bucketdrop; + __u32 queuedrop; + __u32 childdrop; /* drops in child qdisc */ + __u32 marked; + __u32 maxqlen; + __u32 maxprob; + __u32 avgprob; +}; + +#define SFB_MAX_PROB 0xFFFF + +/* QFQ */ +enum { + TCA_QFQ_UNSPEC, + TCA_QFQ_WEIGHT, + TCA_QFQ_LMAX, + __TCA_QFQ_MAX +}; + +#define TCA_QFQ_MAX (__TCA_QFQ_MAX - 1) + +struct tc_qfq_stats { + __u32 weight; + __u32 lmax; +}; + +/* CODEL */ + +enum { + TCA_CODEL_UNSPEC, + TCA_CODEL_TARGET, + TCA_CODEL_LIMIT, + TCA_CODEL_INTERVAL, + TCA_CODEL_ECN, + TCA_CODEL_CE_THRESHOLD, + __TCA_CODEL_MAX +}; + +#define TCA_CODEL_MAX (__TCA_CODEL_MAX - 1) + +struct tc_codel_xstats { + __u32 maxpacket; /* largest packet we've seen so far */ + __u32 count; /* how many drops we've done since the last time we + * entered dropping state + */ + __u32 lastcount; /* count at entry to dropping state */ + __u32 ldelay; /* in-queue delay seen by most recently dequeued packet */ + __s32 drop_next; /* time to drop next packet */ + __u32 drop_overlimit; /* number of time max qdisc packet limit was hit */ + __u32 ecn_mark; /* number of packets we ECN marked instead of dropped */ + __u32 dropping; /* are we in dropping state ? */ + __u32 ce_mark; /* number of CE marked packets because of ce_threshold */ +}; + +/* FQ_CODEL */ + +#define FQ_CODEL_QUANTUM_MAX (1 << 20) + +enum { + TCA_FQ_CODEL_UNSPEC, + TCA_FQ_CODEL_TARGET, + TCA_FQ_CODEL_LIMIT, + TCA_FQ_CODEL_INTERVAL, + TCA_FQ_CODEL_ECN, + TCA_FQ_CODEL_FLOWS, + TCA_FQ_CODEL_QUANTUM, + TCA_FQ_CODEL_CE_THRESHOLD, + TCA_FQ_CODEL_DROP_BATCH_SIZE, + TCA_FQ_CODEL_MEMORY_LIMIT, + TCA_FQ_CODEL_CE_THRESHOLD_SELECTOR, + TCA_FQ_CODEL_CE_THRESHOLD_MASK, + __TCA_FQ_CODEL_MAX +}; + +#define TCA_FQ_CODEL_MAX (__TCA_FQ_CODEL_MAX - 1) + +enum { + TCA_FQ_CODEL_XSTATS_QDISC, + TCA_FQ_CODEL_XSTATS_CLASS, +}; + +struct tc_fq_codel_qd_stats { + __u32 maxpacket; /* largest packet we've seen so far */ + __u32 drop_overlimit; /* number of time max qdisc + * packet limit was hit + */ + __u32 ecn_mark; /* number of packets we ECN marked + * instead of being dropped + */ + __u32 new_flow_count; /* number of time packets + * created a 'new flow' + */ + __u32 new_flows_len; /* count of flows in new list */ + __u32 old_flows_len; /* count of flows in old list */ + __u32 ce_mark; /* packets above ce_threshold */ + __u32 memory_usage; /* in bytes */ + __u32 drop_overmemory; +}; + +struct tc_fq_codel_cl_stats { + __s32 deficit; + __u32 ldelay; /* in-queue delay seen by most recently + * dequeued packet + */ + __u32 count; + __u32 lastcount; + __u32 dropping; + __s32 drop_next; +}; + +struct tc_fq_codel_xstats { + __u32 type; + union { + struct tc_fq_codel_qd_stats qdisc_stats; + struct tc_fq_codel_cl_stats class_stats; + }; +}; + +/* FQ */ + +enum { + TCA_FQ_UNSPEC, + + TCA_FQ_PLIMIT, /* limit of total number of packets in queue */ + + TCA_FQ_FLOW_PLIMIT, /* limit of packets per flow */ + + TCA_FQ_QUANTUM, /* RR quantum */ + + TCA_FQ_INITIAL_QUANTUM, /* RR quantum for new flow */ + + TCA_FQ_RATE_ENABLE, /* enable/disable rate limiting */ + + TCA_FQ_FLOW_DEFAULT_RATE,/* obsolete, do not use */ + + TCA_FQ_FLOW_MAX_RATE, /* per flow max rate */ + + TCA_FQ_BUCKETS_LOG, /* log2(number of buckets) */ + + TCA_FQ_FLOW_REFILL_DELAY, /* flow credit refill delay in usec */ + + TCA_FQ_ORPHAN_MASK, /* mask applied to orphaned skb hashes */ + + TCA_FQ_LOW_RATE_THRESHOLD, /* per packet delay under this rate */ + + TCA_FQ_CE_THRESHOLD, /* DCTCP-like CE-marking threshold */ + + TCA_FQ_TIMER_SLACK, /* timer slack */ + + TCA_FQ_HORIZON, /* time horizon in us */ + + TCA_FQ_HORIZON_DROP, /* drop packets beyond horizon, or cap their EDT */ + + __TCA_FQ_MAX +}; + +#define TCA_FQ_MAX (__TCA_FQ_MAX - 1) + +struct tc_fq_qd_stats { + __u64 gc_flows; + __u64 highprio_packets; + __u64 tcp_retrans; + __u64 throttled; + __u64 flows_plimit; + __u64 pkts_too_long; + __u64 allocation_errors; + __s64 time_next_delayed_flow; + __u32 flows; + __u32 inactive_flows; + __u32 throttled_flows; + __u32 unthrottle_latency_ns; + __u64 ce_mark; /* packets above ce_threshold */ + __u64 horizon_drops; + __u64 horizon_caps; +}; + +/* Heavy-Hitter Filter */ + +enum { + TCA_HHF_UNSPEC, + TCA_HHF_BACKLOG_LIMIT, + TCA_HHF_QUANTUM, + TCA_HHF_HH_FLOWS_LIMIT, + TCA_HHF_RESET_TIMEOUT, + TCA_HHF_ADMIT_BYTES, + TCA_HHF_EVICT_TIMEOUT, + TCA_HHF_NON_HH_WEIGHT, + __TCA_HHF_MAX +}; + +#define TCA_HHF_MAX (__TCA_HHF_MAX - 1) + +struct tc_hhf_xstats { + __u32 drop_overlimit; /* number of times max qdisc packet limit + * was hit + */ + __u32 hh_overlimit; /* number of times max heavy-hitters was hit */ + __u32 hh_tot_count; /* number of captured heavy-hitters so far */ + __u32 hh_cur_count; /* number of current heavy-hitters */ +}; + +/* PIE */ +enum { + TCA_PIE_UNSPEC, + TCA_PIE_TARGET, + TCA_PIE_LIMIT, + TCA_PIE_TUPDATE, + TCA_PIE_ALPHA, + TCA_PIE_BETA, + TCA_PIE_ECN, + TCA_PIE_BYTEMODE, + TCA_PIE_DQ_RATE_ESTIMATOR, + __TCA_PIE_MAX +}; +#define TCA_PIE_MAX (__TCA_PIE_MAX - 1) + +struct tc_pie_xstats { + __u64 prob; /* current probability */ + __u32 delay; /* current delay in ms */ + __u32 avg_dq_rate; /* current average dq_rate in + * bits/pie_time + */ + __u32 dq_rate_estimating; /* is avg_dq_rate being calculated? */ + __u32 packets_in; /* total number of packets enqueued */ + __u32 dropped; /* packets dropped due to pie_action */ + __u32 overlimit; /* dropped due to lack of space + * in queue + */ + __u32 maxq; /* maximum queue size */ + __u32 ecn_mark; /* packets marked with ecn*/ +}; + +/* FQ PIE */ +enum { + TCA_FQ_PIE_UNSPEC, + TCA_FQ_PIE_LIMIT, + TCA_FQ_PIE_FLOWS, + TCA_FQ_PIE_TARGET, + TCA_FQ_PIE_TUPDATE, + TCA_FQ_PIE_ALPHA, + TCA_FQ_PIE_BETA, + TCA_FQ_PIE_QUANTUM, + TCA_FQ_PIE_MEMORY_LIMIT, + TCA_FQ_PIE_ECN_PROB, + TCA_FQ_PIE_ECN, + TCA_FQ_PIE_BYTEMODE, + TCA_FQ_PIE_DQ_RATE_ESTIMATOR, + __TCA_FQ_PIE_MAX +}; +#define TCA_FQ_PIE_MAX (__TCA_FQ_PIE_MAX - 1) + +struct tc_fq_pie_xstats { + __u32 packets_in; /* total number of packets enqueued */ + __u32 dropped; /* packets dropped due to fq_pie_action */ + __u32 overlimit; /* dropped due to lack of space in queue */ + __u32 overmemory; /* dropped due to lack of memory in queue */ + __u32 ecn_mark; /* packets marked with ecn */ + __u32 new_flow_count; /* count of new flows created by packets */ + __u32 new_flows_len; /* count of flows in new list */ + __u32 old_flows_len; /* count of flows in old list */ + __u32 memory_usage; /* total memory across all queues */ +}; + +/* CBS */ +struct tc_cbs_qopt { + __u8 offload; + __u8 _pad[3]; + __s32 hicredit; + __s32 locredit; + __s32 idleslope; + __s32 sendslope; +}; + +enum { + TCA_CBS_UNSPEC, + TCA_CBS_PARMS, + __TCA_CBS_MAX, +}; + +#define TCA_CBS_MAX (__TCA_CBS_MAX - 1) + + +/* ETF */ +struct tc_etf_qopt { + __s32 delta; + __s32 clockid; + __u32 flags; +#define TC_ETF_DEADLINE_MODE_ON _BITUL(0) +#define TC_ETF_OFFLOAD_ON _BITUL(1) +#define TC_ETF_SKIP_SOCK_CHECK _BITUL(2) +}; + +enum { + TCA_ETF_UNSPEC, + TCA_ETF_PARMS, + __TCA_ETF_MAX, +}; + +#define TCA_ETF_MAX (__TCA_ETF_MAX - 1) + + +/* CAKE */ +enum { + TCA_CAKE_UNSPEC, + TCA_CAKE_PAD, + TCA_CAKE_BASE_RATE64, + TCA_CAKE_DIFFSERV_MODE, + TCA_CAKE_ATM, + TCA_CAKE_FLOW_MODE, + TCA_CAKE_OVERHEAD, + TCA_CAKE_RTT, + TCA_CAKE_TARGET, + TCA_CAKE_AUTORATE, + TCA_CAKE_MEMORY, + TCA_CAKE_NAT, + TCA_CAKE_RAW, + TCA_CAKE_WASH, + TCA_CAKE_MPU, + TCA_CAKE_INGRESS, + TCA_CAKE_ACK_FILTER, + TCA_CAKE_SPLIT_GSO, + TCA_CAKE_FWMARK, + __TCA_CAKE_MAX +}; +#define TCA_CAKE_MAX (__TCA_CAKE_MAX - 1) + +enum { + __TCA_CAKE_STATS_INVALID, + TCA_CAKE_STATS_PAD, + TCA_CAKE_STATS_CAPACITY_ESTIMATE64, + TCA_CAKE_STATS_MEMORY_LIMIT, + TCA_CAKE_STATS_MEMORY_USED, + TCA_CAKE_STATS_AVG_NETOFF, + TCA_CAKE_STATS_MIN_NETLEN, + TCA_CAKE_STATS_MAX_NETLEN, + TCA_CAKE_STATS_MIN_ADJLEN, + TCA_CAKE_STATS_MAX_ADJLEN, + TCA_CAKE_STATS_TIN_STATS, + TCA_CAKE_STATS_DEFICIT, + TCA_CAKE_STATS_COBALT_COUNT, + TCA_CAKE_STATS_DROPPING, + TCA_CAKE_STATS_DROP_NEXT_US, + TCA_CAKE_STATS_P_DROP, + TCA_CAKE_STATS_BLUE_TIMER_US, + __TCA_CAKE_STATS_MAX +}; +#define TCA_CAKE_STATS_MAX (__TCA_CAKE_STATS_MAX - 1) + +enum { + __TCA_CAKE_TIN_STATS_INVALID, + TCA_CAKE_TIN_STATS_PAD, + TCA_CAKE_TIN_STATS_SENT_PACKETS, + TCA_CAKE_TIN_STATS_SENT_BYTES64, + TCA_CAKE_TIN_STATS_DROPPED_PACKETS, + TCA_CAKE_TIN_STATS_DROPPED_BYTES64, + TCA_CAKE_TIN_STATS_ACKS_DROPPED_PACKETS, + TCA_CAKE_TIN_STATS_ACKS_DROPPED_BYTES64, + TCA_CAKE_TIN_STATS_ECN_MARKED_PACKETS, + TCA_CAKE_TIN_STATS_ECN_MARKED_BYTES64, + TCA_CAKE_TIN_STATS_BACKLOG_PACKETS, + TCA_CAKE_TIN_STATS_BACKLOG_BYTES, + TCA_CAKE_TIN_STATS_THRESHOLD_RATE64, + TCA_CAKE_TIN_STATS_TARGET_US, + TCA_CAKE_TIN_STATS_INTERVAL_US, + TCA_CAKE_TIN_STATS_WAY_INDIRECT_HITS, + TCA_CAKE_TIN_STATS_WAY_MISSES, + TCA_CAKE_TIN_STATS_WAY_COLLISIONS, + TCA_CAKE_TIN_STATS_PEAK_DELAY_US, + TCA_CAKE_TIN_STATS_AVG_DELAY_US, + TCA_CAKE_TIN_STATS_BASE_DELAY_US, + TCA_CAKE_TIN_STATS_SPARSE_FLOWS, + TCA_CAKE_TIN_STATS_BULK_FLOWS, + TCA_CAKE_TIN_STATS_UNRESPONSIVE_FLOWS, + TCA_CAKE_TIN_STATS_MAX_SKBLEN, + TCA_CAKE_TIN_STATS_FLOW_QUANTUM, + __TCA_CAKE_TIN_STATS_MAX +}; +#define TCA_CAKE_TIN_STATS_MAX (__TCA_CAKE_TIN_STATS_MAX - 1) +#define TC_CAKE_MAX_TINS (8) + +enum { + CAKE_FLOW_NONE = 0, + CAKE_FLOW_SRC_IP, + CAKE_FLOW_DST_IP, + CAKE_FLOW_HOSTS, /* = CAKE_FLOW_SRC_IP | CAKE_FLOW_DST_IP */ + CAKE_FLOW_FLOWS, + CAKE_FLOW_DUAL_SRC, /* = CAKE_FLOW_SRC_IP | CAKE_FLOW_FLOWS */ + CAKE_FLOW_DUAL_DST, /* = CAKE_FLOW_DST_IP | CAKE_FLOW_FLOWS */ + CAKE_FLOW_TRIPLE, /* = CAKE_FLOW_HOSTS | CAKE_FLOW_FLOWS */ + CAKE_FLOW_MAX, +}; + +enum { + CAKE_DIFFSERV_DIFFSERV3 = 0, + CAKE_DIFFSERV_DIFFSERV4, + CAKE_DIFFSERV_DIFFSERV8, + CAKE_DIFFSERV_BESTEFFORT, + CAKE_DIFFSERV_PRECEDENCE, + CAKE_DIFFSERV_MAX +}; + +enum { + CAKE_ACK_NONE = 0, + CAKE_ACK_FILTER, + CAKE_ACK_AGGRESSIVE, + CAKE_ACK_MAX +}; + +enum { + CAKE_ATM_NONE = 0, + CAKE_ATM_ATM, + CAKE_ATM_PTM, + CAKE_ATM_MAX +}; + + +/* TAPRIO */ +enum { + TC_TAPRIO_CMD_SET_GATES = 0x00, + TC_TAPRIO_CMD_SET_AND_HOLD = 0x01, + TC_TAPRIO_CMD_SET_AND_RELEASE = 0x02, +}; + +enum { + TCA_TAPRIO_SCHED_ENTRY_UNSPEC, + TCA_TAPRIO_SCHED_ENTRY_INDEX, /* u32 */ + TCA_TAPRIO_SCHED_ENTRY_CMD, /* u8 */ + TCA_TAPRIO_SCHED_ENTRY_GATE_MASK, /* u32 */ + TCA_TAPRIO_SCHED_ENTRY_INTERVAL, /* u32 */ + __TCA_TAPRIO_SCHED_ENTRY_MAX, +}; +#define TCA_TAPRIO_SCHED_ENTRY_MAX (__TCA_TAPRIO_SCHED_ENTRY_MAX - 1) + +/* The format for schedule entry list is: + * [TCA_TAPRIO_SCHED_ENTRY_LIST] + * [TCA_TAPRIO_SCHED_ENTRY] + * [TCA_TAPRIO_SCHED_ENTRY_CMD] + * [TCA_TAPRIO_SCHED_ENTRY_GATES] + * [TCA_TAPRIO_SCHED_ENTRY_INTERVAL] + */ +enum { + TCA_TAPRIO_SCHED_UNSPEC, + TCA_TAPRIO_SCHED_ENTRY, + __TCA_TAPRIO_SCHED_MAX, +}; + +#define TCA_TAPRIO_SCHED_MAX (__TCA_TAPRIO_SCHED_MAX - 1) + +/* The format for the admin sched (dump only): + * [TCA_TAPRIO_SCHED_ADMIN_SCHED] + * [TCA_TAPRIO_ATTR_SCHED_BASE_TIME] + * [TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST] + * [TCA_TAPRIO_ATTR_SCHED_ENTRY] + * [TCA_TAPRIO_ATTR_SCHED_ENTRY_CMD] + * [TCA_TAPRIO_ATTR_SCHED_ENTRY_GATES] + * [TCA_TAPRIO_ATTR_SCHED_ENTRY_INTERVAL] + */ + +#define TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST _BITUL(0) +#define TCA_TAPRIO_ATTR_FLAG_FULL_OFFLOAD _BITUL(1) + +enum { + TCA_TAPRIO_TC_ENTRY_UNSPEC, + TCA_TAPRIO_TC_ENTRY_INDEX, /* u32 */ + TCA_TAPRIO_TC_ENTRY_MAX_SDU, /* u32 */ + TCA_TAPRIO_TC_ENTRY_FP, /* u32 */ + + /* add new constants above here */ + __TCA_TAPRIO_TC_ENTRY_CNT, + TCA_TAPRIO_TC_ENTRY_MAX = (__TCA_TAPRIO_TC_ENTRY_CNT - 1) +}; + +enum { + TCA_TAPRIO_ATTR_UNSPEC, + TCA_TAPRIO_ATTR_PRIOMAP, /* struct tc_mqprio_qopt */ + TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST, /* nested of entry */ + TCA_TAPRIO_ATTR_SCHED_BASE_TIME, /* s64 */ + TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY, /* single entry */ + TCA_TAPRIO_ATTR_SCHED_CLOCKID, /* s32 */ + TCA_TAPRIO_PAD, + TCA_TAPRIO_ATTR_ADMIN_SCHED, /* The admin sched, only used in dump */ + TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME, /* s64 */ + TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION, /* s64 */ + TCA_TAPRIO_ATTR_FLAGS, /* u32 */ + TCA_TAPRIO_ATTR_TXTIME_DELAY, /* u32 */ + TCA_TAPRIO_ATTR_TC_ENTRY, /* nest */ + __TCA_TAPRIO_ATTR_MAX, +}; + +#define TCA_TAPRIO_ATTR_MAX (__TCA_TAPRIO_ATTR_MAX - 1) + +/* ETS */ + +#define TCQ_ETS_MAX_BANDS 16 + +enum { + TCA_ETS_UNSPEC, + TCA_ETS_NBANDS, /* u8 */ + TCA_ETS_NSTRICT, /* u8 */ + TCA_ETS_QUANTA, /* nested TCA_ETS_QUANTA_BAND */ + TCA_ETS_QUANTA_BAND, /* u32 */ + TCA_ETS_PRIOMAP, /* nested TCA_ETS_PRIOMAP_BAND */ + TCA_ETS_PRIOMAP_BAND, /* u8 */ + __TCA_ETS_MAX, +}; + +#define TCA_ETS_MAX (__TCA_ETS_MAX - 1) + +#endif diff --git a/include/linux-private/linux/posix_types.h b/include/linux-private/linux/posix_types.h new file mode 100644 index 0000000..9a7a740 --- /dev/null +++ b/include/linux-private/linux/posix_types.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_POSIX_TYPES_H +#define _LINUX_POSIX_TYPES_H + +#include + +/* + * This allows for 1024 file descriptors: if NR_OPEN is ever grown + * beyond that you'll have to change this too. But 1024 fd's seem to be + * enough even for such "real" unices like OSF/1, so hopefully this is + * one limit that doesn't have to be changed [again]. + * + * Note that POSIX wants the FD_CLEAR(fd,fdsetp) defines to be in + * (and thus ) - but this is a more logical + * place for them. Solved by having dummy defines in . + */ + +/* + * This macro may have been defined in . But we always + * use the one here. + */ +#undef __FD_SETSIZE +#define __FD_SETSIZE 1024 + +typedef struct { + unsigned long fds_bits[__FD_SETSIZE / (8 * sizeof(long))]; +} __kernel_fd_set; + +/* Type of a signal handler. */ +typedef void (*__kernel_sighandler_t)(int); + +/* Type of a SYSV IPC key. */ +typedef int __kernel_key_t; +typedef int __kernel_mqd_t; + +#include + +#endif /* _LINUX_POSIX_TYPES_H */ diff --git a/include/linux/rtnetlink.h b/include/linux-private/linux/rtnetlink.h similarity index 65% rename from include/linux/rtnetlink.h rename to include/linux-private/linux/rtnetlink.h index 2363c18..2132e94 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux-private/linux/rtnetlink.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef __LINUX_RTNETLINK_H #define __LINUX_RTNETLINK_H @@ -120,6 +121,79 @@ enum { RTM_SETDCB, #define RTM_SETDCB RTM_SETDCB + RTM_NEWNETCONF = 80, +#define RTM_NEWNETCONF RTM_NEWNETCONF + RTM_DELNETCONF, +#define RTM_DELNETCONF RTM_DELNETCONF + RTM_GETNETCONF = 82, +#define RTM_GETNETCONF RTM_GETNETCONF + + RTM_NEWMDB = 84, +#define RTM_NEWMDB RTM_NEWMDB + RTM_DELMDB = 85, +#define RTM_DELMDB RTM_DELMDB + RTM_GETMDB = 86, +#define RTM_GETMDB RTM_GETMDB + + RTM_NEWNSID = 88, +#define RTM_NEWNSID RTM_NEWNSID + RTM_DELNSID = 89, +#define RTM_DELNSID RTM_DELNSID + RTM_GETNSID = 90, +#define RTM_GETNSID RTM_GETNSID + + RTM_NEWSTATS = 92, +#define RTM_NEWSTATS RTM_NEWSTATS + RTM_GETSTATS = 94, +#define RTM_GETSTATS RTM_GETSTATS + RTM_SETSTATS, +#define RTM_SETSTATS RTM_SETSTATS + + RTM_NEWCACHEREPORT = 96, +#define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT + + RTM_NEWCHAIN = 100, +#define RTM_NEWCHAIN RTM_NEWCHAIN + RTM_DELCHAIN, +#define RTM_DELCHAIN RTM_DELCHAIN + RTM_GETCHAIN, +#define RTM_GETCHAIN RTM_GETCHAIN + + RTM_NEWNEXTHOP = 104, +#define RTM_NEWNEXTHOP RTM_NEWNEXTHOP + RTM_DELNEXTHOP, +#define RTM_DELNEXTHOP RTM_DELNEXTHOP + RTM_GETNEXTHOP, +#define RTM_GETNEXTHOP RTM_GETNEXTHOP + + RTM_NEWLINKPROP = 108, +#define RTM_NEWLINKPROP RTM_NEWLINKPROP + RTM_DELLINKPROP, +#define RTM_DELLINKPROP RTM_DELLINKPROP + RTM_GETLINKPROP, +#define RTM_GETLINKPROP RTM_GETLINKPROP + + RTM_NEWVLAN = 112, +#define RTM_NEWNVLAN RTM_NEWVLAN + RTM_DELVLAN, +#define RTM_DELVLAN RTM_DELVLAN + RTM_GETVLAN, +#define RTM_GETVLAN RTM_GETVLAN + + RTM_NEWNEXTHOPBUCKET = 116, +#define RTM_NEWNEXTHOPBUCKET RTM_NEWNEXTHOPBUCKET + RTM_DELNEXTHOPBUCKET, +#define RTM_DELNEXTHOPBUCKET RTM_DELNEXTHOPBUCKET + RTM_GETNEXTHOPBUCKET, +#define RTM_GETNEXTHOPBUCKET RTM_GETNEXTHOPBUCKET + + RTM_NEWTUNNEL = 120, +#define RTM_NEWTUNNEL RTM_NEWTUNNEL + RTM_DELTUNNEL, +#define RTM_DELTUNNEL RTM_DELTUNNEL + RTM_GETTUNNEL, +#define RTM_GETTUNNEL RTM_GETTUNNEL + __RTM_MAX, #define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1) }; @@ -141,7 +215,7 @@ struct rtattr { /* Macros to handle rtattributes */ -#define RTA_ALIGNTO 4 +#define RTA_ALIGNTO 4U #define RTA_ALIGN(len) ( ((len)+RTA_ALIGNTO-1) & ~(RTA_ALIGNTO-1) ) #define RTA_OK(rta,len) ((len) >= (int)sizeof(struct rtattr) && \ (rta)->rta_len >= sizeof(struct rtattr) && \ @@ -199,12 +273,12 @@ enum { /* rtm_protocol */ -#define RTPROT_UNSPEC 0 -#define RTPROT_REDIRECT 1 /* Route installed by ICMP redirects; - not used by current IPv4 */ -#define RTPROT_KERNEL 2 /* Route installed by kernel */ -#define RTPROT_BOOT 3 /* Route installed during boot */ -#define RTPROT_STATIC 4 /* Route installed by administrator */ +#define RTPROT_UNSPEC 0 +#define RTPROT_REDIRECT 1 /* Route installed by ICMP redirects; + not used by current IPv4 */ +#define RTPROT_KERNEL 2 /* Route installed by kernel */ +#define RTPROT_BOOT 3 /* Route installed during boot */ +#define RTPROT_STATIC 4 /* Route installed by administrator */ /* Values of protocol >= RTPROT_STATIC are not interpreted by kernel; they are just passed from user and back as is. @@ -213,15 +287,24 @@ enum { avoid conflicts. */ -#define RTPROT_GATED 8 /* Apparently, GateD */ -#define RTPROT_RA 9 /* RDISC/ND router advertisements */ -#define RTPROT_MRT 10 /* Merit MRT */ -#define RTPROT_ZEBRA 11 /* Zebra */ -#define RTPROT_BIRD 12 /* BIRD */ -#define RTPROT_DNROUTED 13 /* DECnet routing daemon */ -#define RTPROT_XORP 14 /* XORP */ -#define RTPROT_NTK 15 /* Netsukuku */ -#define RTPROT_DHCP 16 /* DHCP client */ +#define RTPROT_GATED 8 /* Apparently, GateD */ +#define RTPROT_RA 9 /* RDISC/ND router advertisements */ +#define RTPROT_MRT 10 /* Merit MRT */ +#define RTPROT_ZEBRA 11 /* Zebra */ +#define RTPROT_BIRD 12 /* BIRD */ +#define RTPROT_DNROUTED 13 /* DECnet routing daemon */ +#define RTPROT_XORP 14 /* XORP */ +#define RTPROT_NTK 15 /* Netsukuku */ +#define RTPROT_DHCP 16 /* DHCP client */ +#define RTPROT_MROUTED 17 /* Multicast daemon */ +#define RTPROT_KEEPALIVED 18 /* Keepalived daemon */ +#define RTPROT_BABEL 42 /* Babel daemon */ +#define RTPROT_OPENR 99 /* Open Routing (Open/R) Routes */ +#define RTPROT_BGP 186 /* BGP Routes */ +#define RTPROT_ISIS 187 /* ISIS Routes */ +#define RTPROT_OSPF 188 /* OSPF Routes */ +#define RTPROT_RIP 189 /* RIP Routes */ +#define RTPROT_EIGRP 192 /* EIGRP Routes */ /* rtm_scope @@ -249,6 +332,15 @@ enum rt_scope_t { #define RTM_F_CLONED 0x200 /* This route is cloned */ #define RTM_F_EQUALIZE 0x400 /* Multipath equalizer: NI */ #define RTM_F_PREFIX 0x800 /* Prefix addresses */ +#define RTM_F_LOOKUP_TABLE 0x1000 /* set rtm_table to FIB lookup result */ +#define RTM_F_FIB_MATCH 0x2000 /* return full fib lookup match */ +#define RTM_F_OFFLOAD 0x4000 /* route is offloaded */ +#define RTM_F_TRAP 0x8000 /* route is trapping packets */ +#define RTM_F_OFFLOAD_FAILED 0x20000000 /* route offload failed, this value + * is chosen to avoid conflicts with + * other flags defined in + * include/uapi/linux/ipv6_route.h + */ /* Reserved table identifiers */ @@ -283,6 +375,20 @@ enum rtattr_type_t { RTA_MP_ALGO, /* no longer used */ RTA_TABLE, RTA_MARK, + RTA_MFC_STATS, + RTA_VIA, + RTA_NEWDST, + RTA_PREF, + RTA_ENCAP_TYPE, + RTA_ENCAP, + RTA_EXPIRES, + RTA_PAD, + RTA_UID, + RTA_TTL_PROPAGATE, + RTA_IP_PROTO, + RTA_SPORT, + RTA_DPORT, + RTA_NH_ID, __RTA_MAX }; @@ -312,6 +418,13 @@ struct rtnexthop { #define RTNH_F_DEAD 1 /* Nexthop is dead (used by multipath) */ #define RTNH_F_PERVASIVE 2 /* Do recursive gateway lookup */ #define RTNH_F_ONLINK 4 /* Gateway is forced on link */ +#define RTNH_F_OFFLOAD 8 /* Nexthop is offloaded */ +#define RTNH_F_LINKDOWN 16 /* carrier-down on nexthop */ +#define RTNH_F_UNRESOLVED 32 /* The entry is unresolved (ipmr) */ +#define RTNH_F_TRAP 64 /* Nexthop is trapping packets */ + +#define RTNH_COMPARE_MASK (RTNH_F_DEAD | RTNH_F_LINKDOWN | \ + RTNH_F_OFFLOAD | RTNH_F_TRAP) /* Macros to handle hexthops */ @@ -324,6 +437,12 @@ struct rtnexthop { #define RTNH_SPACE(len) RTNH_ALIGN(RTNH_LENGTH(len)) #define RTNH_DATA(rtnh) ((struct rtattr*)(((char*)(rtnh)) + RTNH_LENGTH(0))) +/* RTA_VIA */ +struct rtvia { + __kernel_sa_family_t rtvia_family; + __u8 rtvia_addr[]; +}; + /* RTM_CACHEINFO */ struct rta_cacheinfo { @@ -372,15 +491,24 @@ enum { #define RTAX_RTO_MIN RTAX_RTO_MIN RTAX_INITRWND, #define RTAX_INITRWND RTAX_INITRWND + RTAX_QUICKACK, +#define RTAX_QUICKACK RTAX_QUICKACK + RTAX_CC_ALGO, +#define RTAX_CC_ALGO RTAX_CC_ALGO + RTAX_FASTOPEN_NO_COOKIE, +#define RTAX_FASTOPEN_NO_COOKIE RTAX_FASTOPEN_NO_COOKIE __RTAX_MAX }; #define RTAX_MAX (__RTAX_MAX - 1) -#define RTAX_FEATURE_ECN 0x00000001 -#define RTAX_FEATURE_SACK 0x00000002 -#define RTAX_FEATURE_TIMESTAMP 0x00000004 -#define RTAX_FEATURE_ALLFRAG 0x00000008 +#define RTAX_FEATURE_ECN (1 << 0) +#define RTAX_FEATURE_SACK (1 << 1) +#define RTAX_FEATURE_TIMESTAMP (1 << 2) +#define RTAX_FEATURE_ALLFRAG (1 << 3) + +#define RTAX_FEATURE_MASK (RTAX_FEATURE_ECN | RTAX_FEATURE_SACK | \ + RTAX_FEATURE_TIMESTAMP | RTAX_FEATURE_ALLFRAG) struct rta_session { __u8 proto; @@ -403,6 +531,12 @@ struct rta_session { } u; }; +struct rta_mfc_stats { + __u64 mfcs_packets; + __u64 mfcs_bytes; + __u64 mfcs_wrong_if; +}; + /**** * General form of address family dependent message. ****/ @@ -471,9 +605,19 @@ struct tcmsg { int tcm_ifindex; __u32 tcm_handle; __u32 tcm_parent; +/* tcm_block_index is used instead of tcm_parent + * in case tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK + */ +#define tcm_block_index tcm_parent __u32 tcm_info; }; +/* For manipulation of filters in shared block, tcm_ifindex is set to + * TCM_IFINDEX_MAGIC_BLOCK, and tcm_parent is aliased to tcm_block_index + * which is the block index. + */ +#define TCM_IFINDEX_MAGIC_BLOCK (0xFFFFFFFFU) + enum { TCA_UNSPEC, TCA_KIND, @@ -484,11 +628,24 @@ enum { TCA_FCNT, TCA_STATS2, TCA_STAB, + TCA_PAD, + TCA_DUMP_INVISIBLE, + TCA_CHAIN, + TCA_HW_OFFLOAD, + TCA_INGRESS_BLOCK, + TCA_EGRESS_BLOCK, + TCA_DUMP_FLAGS, + TCA_EXT_WARN_MSG, __TCA_MAX }; #define TCA_MAX (__TCA_MAX - 1) +#define TCA_DUMP_FLAGS_TERSE (1 << 0) /* Means that in dump user gets only basic + * data necessary to identify the objects + * (handle, cookie, etc.) and stats. + */ + #define TCA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg)))) #define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg)) @@ -516,7 +673,6 @@ enum { #define NDUSEROPT_MAX (__NDUSEROPT_MAX - 1) -#ifndef __KERNEL__ /* RTnetlink multicast groups - backwards compatibility for userspace */ #define RTMGRP_LINK 1 #define RTMGRP_NOTIFY 2 @@ -537,7 +693,6 @@ enum { #define RTMGRP_DECnet_ROUTE 0x4000 #define RTMGRP_IPV6_PREFIX 0x20000 -#endif /* RTnetlink multicast groups */ enum rtnetlink_groups { @@ -585,6 +740,34 @@ enum rtnetlink_groups { #define RTNLGRP_PHONET_IFADDR RTNLGRP_PHONET_IFADDR RTNLGRP_PHONET_ROUTE, #define RTNLGRP_PHONET_ROUTE RTNLGRP_PHONET_ROUTE + RTNLGRP_DCB, +#define RTNLGRP_DCB RTNLGRP_DCB + RTNLGRP_IPV4_NETCONF, +#define RTNLGRP_IPV4_NETCONF RTNLGRP_IPV4_NETCONF + RTNLGRP_IPV6_NETCONF, +#define RTNLGRP_IPV6_NETCONF RTNLGRP_IPV6_NETCONF + RTNLGRP_MDB, +#define RTNLGRP_MDB RTNLGRP_MDB + RTNLGRP_MPLS_ROUTE, +#define RTNLGRP_MPLS_ROUTE RTNLGRP_MPLS_ROUTE + RTNLGRP_NSID, +#define RTNLGRP_NSID RTNLGRP_NSID + RTNLGRP_MPLS_NETCONF, +#define RTNLGRP_MPLS_NETCONF RTNLGRP_MPLS_NETCONF + RTNLGRP_IPV4_MROUTE_R, +#define RTNLGRP_IPV4_MROUTE_R RTNLGRP_IPV4_MROUTE_R + RTNLGRP_IPV6_MROUTE_R, +#define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R + RTNLGRP_NEXTHOP, +#define RTNLGRP_NEXTHOP RTNLGRP_NEXTHOP + RTNLGRP_BRVLAN, +#define RTNLGRP_BRVLAN RTNLGRP_BRVLAN + RTNLGRP_MCTP_IFADDR, +#define RTNLGRP_MCTP_IFADDR RTNLGRP_MCTP_IFADDR + RTNLGRP_TUNNEL, +#define RTNLGRP_TUNNEL RTNLGRP_TUNNEL + RTNLGRP_STATS, +#define RTNLGRP_STATS RTNLGRP_STATS __RTNLGRP_MAX }; #define RTNLGRP_MAX (__RTNLGRP_MAX - 1) @@ -595,11 +778,49 @@ struct tcamsg { unsigned char tca__pad1; unsigned short tca__pad2; }; + +enum { + TCA_ROOT_UNSPEC, + TCA_ROOT_TAB, +#define TCA_ACT_TAB TCA_ROOT_TAB +#define TCAA_MAX TCA_ROOT_TAB + TCA_ROOT_FLAGS, + TCA_ROOT_COUNT, + TCA_ROOT_TIME_DELTA, /* in msecs */ + TCA_ROOT_EXT_WARN_MSG, + __TCA_ROOT_MAX, +#define TCA_ROOT_MAX (__TCA_ROOT_MAX - 1) +}; + #define TA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcamsg)))) #define TA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcamsg)) -#define TCA_ACT_TAB 1 /* attr type must be >=1 */ -#define TCAA_MAX 1 +/* tcamsg flags stored in attribute TCA_ROOT_FLAGS + * + * TCA_ACT_FLAG_LARGE_DUMP_ON user->kernel to request for larger than + * TCA_ACT_MAX_PRIO actions in a dump. All dump responses will contain the + * number of actions being dumped stored in for user app's consumption in + * TCA_ROOT_COUNT + * + * TCA_ACT_FLAG_TERSE_DUMP user->kernel to request terse (brief) dump that only + * includes essential action info (kind, index, etc.) + * + */ +#define TCA_FLAG_LARGE_DUMP_ON (1 << 0) +#define TCA_ACT_FLAG_LARGE_DUMP_ON TCA_FLAG_LARGE_DUMP_ON +#define TCA_ACT_FLAG_TERSE_DUMP (1 << 1) + +/* New extended info filters for IFLA_EXT_MASK */ +#define RTEXT_FILTER_VF (1 << 0) +#define RTEXT_FILTER_BRVLAN (1 << 1) +#define RTEXT_FILTER_BRVLAN_COMPRESSED (1 << 2) +#define RTEXT_FILTER_SKIP_STATS (1 << 3) +#define RTEXT_FILTER_MRP (1 << 4) +#define RTEXT_FILTER_CFM_CONFIG (1 << 5) +#define RTEXT_FILTER_CFM_STATUS (1 << 6) +#define RTEXT_FILTER_MST (1 << 7) /* End of information exported to user level */ -#endif /* __LINUX_RTNETLINK_H */ + + +#endif /* __LINUX_RTNETLINK_H */ diff --git a/include/linux-private/linux/seg6.h b/include/linux-private/linux/seg6.h new file mode 100644 index 0000000..e888b00 --- /dev/null +++ b/include/linux-private/linux/seg6.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * SR-IPv6 implementation + * + * Author: + * David Lebrun + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _LINUX_SEG6_H +#define _LINUX_SEG6_H + +#include +#include /* For struct in6_addr. */ + +/* + * SRH + */ +struct ipv6_sr_hdr { + __u8 nexthdr; + __u8 hdrlen; + __u8 type; + __u8 segments_left; + __u8 first_segment; /* Represents the last_entry field of SRH */ + __u8 flags; + __u16 tag; + + struct in6_addr segments[]; +}; + +#define SR6_FLAG1_PROTECTED (1 << 6) +#define SR6_FLAG1_OAM (1 << 5) +#define SR6_FLAG1_ALERT (1 << 4) +#define SR6_FLAG1_HMAC (1 << 3) + +#define SR6_TLV_INGRESS 1 +#define SR6_TLV_EGRESS 2 +#define SR6_TLV_OPAQUE 3 +#define SR6_TLV_PADDING 4 +#define SR6_TLV_HMAC 5 + +#define sr_has_hmac(srh) ((srh)->flags & SR6_FLAG1_HMAC) + +struct sr6_tlv { + __u8 type; + __u8 len; + __u8 data[0]; +}; + +#endif diff --git a/include/linux-private/linux/seg6_hmac.h b/include/linux-private/linux/seg6_hmac.h new file mode 100644 index 0000000..3fb3412 --- /dev/null +++ b/include/linux-private/linux/seg6_hmac.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_SEG6_HMAC_H +#define _LINUX_SEG6_HMAC_H + +#include +#include + +#define SEG6_HMAC_SECRET_LEN 64 +#define SEG6_HMAC_FIELD_LEN 32 + +struct sr6_tlv_hmac { + struct sr6_tlv tlvhdr; + __u16 reserved; + __be32 hmackeyid; + __u8 hmac[SEG6_HMAC_FIELD_LEN]; +}; + +enum { + SEG6_HMAC_ALGO_SHA1 = 1, + SEG6_HMAC_ALGO_SHA256 = 2, +}; + +#endif diff --git a/include/linux-private/linux/seg6_iptunnel.h b/include/linux-private/linux/seg6_iptunnel.h new file mode 100644 index 0000000..e1929d2 --- /dev/null +++ b/include/linux-private/linux/seg6_iptunnel.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * SR-IPv6 implementation + * + * Author: + * David Lebrun + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _LINUX_SEG6_IPTUNNEL_H +#define _LINUX_SEG6_IPTUNNEL_H + +#include /* For struct ipv6_sr_hdr. */ + +enum { + SEG6_IPTUNNEL_UNSPEC, + SEG6_IPTUNNEL_SRH, + __SEG6_IPTUNNEL_MAX, +}; +#define SEG6_IPTUNNEL_MAX (__SEG6_IPTUNNEL_MAX - 1) + +struct seg6_iptunnel_encap { + int mode; + struct ipv6_sr_hdr srh[]; +}; + +#define SEG6_IPTUN_ENCAP_SIZE(x) ((sizeof(*x)) + (((x)->srh->hdrlen + 1) << 3)) + +enum { + SEG6_IPTUN_MODE_INLINE, + SEG6_IPTUN_MODE_ENCAP, + SEG6_IPTUN_MODE_L2ENCAP, + SEG6_IPTUN_MODE_ENCAP_RED, + SEG6_IPTUN_MODE_L2ENCAP_RED, +}; + +#endif diff --git a/include/linux-private/linux/seg6_local.h b/include/linux-private/linux/seg6_local.h new file mode 100644 index 0000000..6e71d97 --- /dev/null +++ b/include/linux-private/linux/seg6_local.h @@ -0,0 +1,137 @@ +/* + * SR-IPv6 implementation + * + * Author: + * David Lebrun + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _LINUX_SEG6_LOCAL_H +#define _LINUX_SEG6_LOCAL_H + +#include + +enum { + SEG6_LOCAL_UNSPEC, + SEG6_LOCAL_ACTION, + SEG6_LOCAL_SRH, + SEG6_LOCAL_TABLE, + SEG6_LOCAL_NH4, + SEG6_LOCAL_NH6, + SEG6_LOCAL_IIF, + SEG6_LOCAL_OIF, + SEG6_LOCAL_BPF, + SEG6_LOCAL_VRFTABLE, + SEG6_LOCAL_COUNTERS, + SEG6_LOCAL_FLAVORS, + __SEG6_LOCAL_MAX, +}; +#define SEG6_LOCAL_MAX (__SEG6_LOCAL_MAX - 1) + +enum { + SEG6_LOCAL_ACTION_UNSPEC = 0, + /* node segment */ + SEG6_LOCAL_ACTION_END = 1, + /* adjacency segment (IPv6 cross-connect) */ + SEG6_LOCAL_ACTION_END_X = 2, + /* lookup of next seg NH in table */ + SEG6_LOCAL_ACTION_END_T = 3, + /* decap and L2 cross-connect */ + SEG6_LOCAL_ACTION_END_DX2 = 4, + /* decap and IPv6 cross-connect */ + SEG6_LOCAL_ACTION_END_DX6 = 5, + /* decap and IPv4 cross-connect */ + SEG6_LOCAL_ACTION_END_DX4 = 6, + /* decap and lookup of DA in v6 table */ + SEG6_LOCAL_ACTION_END_DT6 = 7, + /* decap and lookup of DA in v4 table */ + SEG6_LOCAL_ACTION_END_DT4 = 8, + /* binding segment with insertion */ + SEG6_LOCAL_ACTION_END_B6 = 9, + /* binding segment with encapsulation */ + SEG6_LOCAL_ACTION_END_B6_ENCAP = 10, + /* binding segment with MPLS encap */ + SEG6_LOCAL_ACTION_END_BM = 11, + /* lookup last seg in table */ + SEG6_LOCAL_ACTION_END_S = 12, + /* forward to SR-unaware VNF with static proxy */ + SEG6_LOCAL_ACTION_END_AS = 13, + /* forward to SR-unaware VNF with masquerading */ + SEG6_LOCAL_ACTION_END_AM = 14, + /* custom BPF action */ + SEG6_LOCAL_ACTION_END_BPF = 15, + /* decap and lookup of DA in v4 or v6 table */ + SEG6_LOCAL_ACTION_END_DT46 = 16, + + __SEG6_LOCAL_ACTION_MAX, +}; + +#define SEG6_LOCAL_ACTION_MAX (__SEG6_LOCAL_ACTION_MAX - 1) + +enum { + SEG6_LOCAL_BPF_PROG_UNSPEC, + SEG6_LOCAL_BPF_PROG, + SEG6_LOCAL_BPF_PROG_NAME, + __SEG6_LOCAL_BPF_PROG_MAX, +}; + +#define SEG6_LOCAL_BPF_PROG_MAX (__SEG6_LOCAL_BPF_PROG_MAX - 1) + +/* SRv6 Behavior counters are encoded as netlink attributes guaranteeing the + * correct alignment. + * Each counter is identified by a different attribute type (i.e. + * SEG6_LOCAL_CNT_PACKETS). + * + * - SEG6_LOCAL_CNT_PACKETS: identifies a counter that counts the number of + * packets that have been CORRECTLY processed by an SRv6 Behavior instance + * (i.e., packets that generate errors or are dropped are NOT counted). + * + * - SEG6_LOCAL_CNT_BYTES: identifies a counter that counts the total amount + * of traffic in bytes of all packets that have been CORRECTLY processed by + * an SRv6 Behavior instance (i.e., packets that generate errors or are + * dropped are NOT counted). + * + * - SEG6_LOCAL_CNT_ERRORS: identifies a counter that counts the number of + * packets that have NOT been properly processed by an SRv6 Behavior instance + * (i.e., packets that generate errors or are dropped). + */ +enum { + SEG6_LOCAL_CNT_UNSPEC, + SEG6_LOCAL_CNT_PAD, /* pad for 64 bits values */ + SEG6_LOCAL_CNT_PACKETS, + SEG6_LOCAL_CNT_BYTES, + SEG6_LOCAL_CNT_ERRORS, + __SEG6_LOCAL_CNT_MAX, +}; + +#define SEG6_LOCAL_CNT_MAX (__SEG6_LOCAL_CNT_MAX - 1) + +/* SRv6 End* Flavor attributes */ +enum { + SEG6_LOCAL_FLV_UNSPEC, + SEG6_LOCAL_FLV_OPERATION, + SEG6_LOCAL_FLV_LCBLOCK_BITS, + SEG6_LOCAL_FLV_LCNODE_FN_BITS, + __SEG6_LOCAL_FLV_MAX, +}; + +#define SEG6_LOCAL_FLV_MAX (__SEG6_LOCAL_FLV_MAX - 1) + +/* Designed flavor operations for SRv6 End* Behavior */ +enum { + SEG6_LOCAL_FLV_OP_UNSPEC, + SEG6_LOCAL_FLV_OP_PSP, + SEG6_LOCAL_FLV_OP_USP, + SEG6_LOCAL_FLV_OP_USD, + SEG6_LOCAL_FLV_OP_NEXT_CSID, + __SEG6_LOCAL_FLV_OP_MAX +}; + +#define SEG6_LOCAL_FLV_OP_MAX (__SEG6_LOCAL_FLV_OP_MAX - 1) + +#endif diff --git a/include/linux/snmp.h b/include/linux-private/linux/snmp.h similarity index 66% rename from include/linux/snmp.h rename to include/linux-private/linux/snmp.h index 12b2b18..26f33a4 100644 --- a/include/linux/snmp.h +++ b/include/linux-private/linux/snmp.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * Definitions for MIBs * @@ -18,7 +19,14 @@ enum { IPSTATS_MIB_NUM = 0, +/* frequently written fields in fast path, kept in same cache line */ IPSTATS_MIB_INPKTS, /* InReceives */ + IPSTATS_MIB_INOCTETS, /* InOctets */ + IPSTATS_MIB_INDELIVERS, /* InDelivers */ + IPSTATS_MIB_OUTFORWDATAGRAMS, /* OutForwDatagrams */ + IPSTATS_MIB_OUTPKTS, /* OutRequests */ + IPSTATS_MIB_OUTOCTETS, /* OutOctets */ +/* other fields */ IPSTATS_MIB_INHDRERRORS, /* InHdrErrors */ IPSTATS_MIB_INTOOBIGERRORS, /* InTooBigErrors */ IPSTATS_MIB_INNOROUTES, /* InNoRoutes */ @@ -26,9 +34,6 @@ enum IPSTATS_MIB_INUNKNOWNPROTOS, /* InUnknownProtos */ IPSTATS_MIB_INTRUNCATEDPKTS, /* InTruncatedPkts */ IPSTATS_MIB_INDISCARDS, /* InDiscards */ - IPSTATS_MIB_INDELIVERS, /* InDelivers */ - IPSTATS_MIB_OUTFORWDATAGRAMS, /* OutForwDatagrams */ - IPSTATS_MIB_OUTPKTS, /* OutRequests */ IPSTATS_MIB_OUTDISCARDS, /* OutDiscards */ IPSTATS_MIB_OUTNOROUTES, /* OutNoRoutes */ IPSTATS_MIB_REASMTIMEOUT, /* ReasmTimeout */ @@ -42,12 +47,16 @@ enum IPSTATS_MIB_OUTMCASTPKTS, /* OutMcastPkts */ IPSTATS_MIB_INBCASTPKTS, /* InBcastPkts */ IPSTATS_MIB_OUTBCASTPKTS, /* OutBcastPkts */ - IPSTATS_MIB_INOCTETS, /* InOctets */ - IPSTATS_MIB_OUTOCTETS, /* OutOctets */ IPSTATS_MIB_INMCASTOCTETS, /* InMcastOctets */ IPSTATS_MIB_OUTMCASTOCTETS, /* OutMcastOctets */ IPSTATS_MIB_INBCASTOCTETS, /* InBcastOctets */ IPSTATS_MIB_OUTBCASTOCTETS, /* OutBcastOctets */ + IPSTATS_MIB_CSUMERRORS, /* InCsumErrors */ + IPSTATS_MIB_NOECTPKTS, /* InNoECTPkts */ + IPSTATS_MIB_ECT1PKTS, /* InECT1Pkts */ + IPSTATS_MIB_ECT0PKTS, /* InECT0Pkts */ + IPSTATS_MIB_CEPKTS, /* InCEPkts */ + IPSTATS_MIB_REASM_OVERLAPS, /* ReasmOverlaps */ __IPSTATS_MIB_MAX }; @@ -85,6 +94,9 @@ enum ICMP_MIB_OUTTIMESTAMPREPS, /* OutTimestampReps */ ICMP_MIB_OUTADDRMASKS, /* OutAddrMasks */ ICMP_MIB_OUTADDRMASKREPS, /* OutAddrMaskReps */ + ICMP_MIB_CSUMERRORS, /* InCsumErrors */ + ICMP_MIB_RATELIMITGLOBAL, /* OutRateLimitGlobal */ + ICMP_MIB_RATELIMITHOST, /* OutRateLimitHost */ __ICMP_MIB_MAX }; @@ -101,6 +113,8 @@ enum ICMP6_MIB_INERRORS, /* InErrors */ ICMP6_MIB_OUTMSGS, /* OutMsgs */ ICMP6_MIB_OUTERRORS, /* OutErrors */ + ICMP6_MIB_CSUMERRORS, /* InCsumErrors */ + ICMP6_MIB_RATELIMITHOST, /* OutRateLimitHost */ __ICMP6_MIB_MAX }; @@ -128,6 +142,7 @@ enum TCP_MIB_RETRANSSEGS, /* RetransSegs */ TCP_MIB_INERRS, /* InErrs */ TCP_MIB_OUTRSTS, /* OutRsts */ + TCP_MIB_CSUMERRORS, /* InCsumErrors */ __TCP_MIB_MAX }; @@ -145,6 +160,9 @@ enum UDP_MIB_OUTDATAGRAMS, /* OutDatagrams */ UDP_MIB_RCVBUFERRORS, /* RcvbufErrors */ UDP_MIB_SNDBUFERRORS, /* SndbufErrors */ + UDP_MIB_CSUMERRORS, /* InCsumErrors */ + UDP_MIB_IGNOREDMULTI, /* IgnoredMulti */ + UDP_MIB_MEMERRORS, /* MemErrors */ __UDP_MIB_MAX }; @@ -165,7 +183,6 @@ enum LINUX_MIB_TIMEWAITED, /* TimeWaited */ LINUX_MIB_TIMEWAITRECYCLED, /* TimeWaitRecycled */ LINUX_MIB_TIMEWAITKILLED, /* TimeWaitKilled */ - LINUX_MIB_PAWSPASSIVEREJECTED, /* PAWSPassiveRejected */ LINUX_MIB_PAWSACTIVEREJECTED, /* PAWSActiveRejected */ LINUX_MIB_PAWSESTABREJECTED, /* PAWSEstabRejected */ LINUX_MIB_DELAYEDACKS, /* DelayedACKs */ @@ -173,18 +190,12 @@ enum LINUX_MIB_DELAYEDACKLOST, /* DelayedACKLost */ LINUX_MIB_LISTENOVERFLOWS, /* ListenOverflows */ LINUX_MIB_LISTENDROPS, /* ListenDrops */ - LINUX_MIB_TCPPREQUEUED, /* TCPPrequeued */ - LINUX_MIB_TCPDIRECTCOPYFROMBACKLOG, /* TCPDirectCopyFromBacklog */ - LINUX_MIB_TCPDIRECTCOPYFROMPREQUEUE, /* TCPDirectCopyFromPrequeue */ - LINUX_MIB_TCPPREQUEUEDROPPED, /* TCPPrequeueDropped */ LINUX_MIB_TCPHPHITS, /* TCPHPHits */ - LINUX_MIB_TCPHPHITSTOUSER, /* TCPHPHitsToUser */ LINUX_MIB_TCPPUREACKS, /* TCPPureAcks */ LINUX_MIB_TCPHPACKS, /* TCPHPAcks */ LINUX_MIB_TCPRENORECOVERY, /* TCPRenoRecovery */ LINUX_MIB_TCPSACKRECOVERY, /* TCPSackRecovery */ LINUX_MIB_TCPSACKRENEGING, /* TCPSACKReneging */ - LINUX_MIB_TCPFACKREORDER, /* TCPFACKReorder */ LINUX_MIB_TCPSACKREORDER, /* TCPSACKReorder */ LINUX_MIB_TCPRENOREORDER, /* TCPRenoReorder */ LINUX_MIB_TCPTSREORDER, /* TCPTSReorder */ @@ -192,24 +203,22 @@ enum LINUX_MIB_TCPPARTIALUNDO, /* TCPPartialUndo */ LINUX_MIB_TCPDSACKUNDO, /* TCPDSACKUndo */ LINUX_MIB_TCPLOSSUNDO, /* TCPLossUndo */ - LINUX_MIB_TCPLOSS, /* TCPLoss */ LINUX_MIB_TCPLOSTRETRANSMIT, /* TCPLostRetransmit */ LINUX_MIB_TCPRENOFAILURES, /* TCPRenoFailures */ LINUX_MIB_TCPSACKFAILURES, /* TCPSackFailures */ LINUX_MIB_TCPLOSSFAILURES, /* TCPLossFailures */ LINUX_MIB_TCPFASTRETRANS, /* TCPFastRetrans */ - LINUX_MIB_TCPFORWARDRETRANS, /* TCPForwardRetrans */ LINUX_MIB_TCPSLOWSTARTRETRANS, /* TCPSlowStartRetrans */ LINUX_MIB_TCPTIMEOUTS, /* TCPTimeouts */ + LINUX_MIB_TCPLOSSPROBES, /* TCPLossProbes */ + LINUX_MIB_TCPLOSSPROBERECOVERY, /* TCPLossProbeRecovery */ LINUX_MIB_TCPRENORECOVERYFAIL, /* TCPRenoRecoveryFail */ LINUX_MIB_TCPSACKRECOVERYFAIL, /* TCPSackRecoveryFail */ - LINUX_MIB_TCPSCHEDULERFAILED, /* TCPSchedulerFailed */ LINUX_MIB_TCPRCVCOLLAPSED, /* TCPRcvCollapsed */ LINUX_MIB_TCPDSACKOLDSENT, /* TCPDSACKOldSent */ LINUX_MIB_TCPDSACKOFOSENT, /* TCPDSACKOfoSent */ LINUX_MIB_TCPDSACKRECV, /* TCPDSACKRecv */ LINUX_MIB_TCPDSACKOFORECV, /* TCPDSACKOfoRecv */ - LINUX_MIB_TCPABORTONSYN, /* TCPAbortOnSyn */ LINUX_MIB_TCPABORTONDATA, /* TCPAbortOnData */ LINUX_MIB_TCPABORTONCLOSE, /* TCPAbortOnClose */ LINUX_MIB_TCPABORTONMEMORY, /* TCPAbortOnMemory */ @@ -217,20 +226,76 @@ enum LINUX_MIB_TCPABORTONLINGER, /* TCPAbortOnLinger */ LINUX_MIB_TCPABORTFAILED, /* TCPAbortFailed */ LINUX_MIB_TCPMEMORYPRESSURES, /* TCPMemoryPressures */ + LINUX_MIB_TCPMEMORYPRESSURESCHRONO, /* TCPMemoryPressuresChrono */ LINUX_MIB_TCPSACKDISCARD, /* TCPSACKDiscard */ LINUX_MIB_TCPDSACKIGNOREDOLD, /* TCPSACKIgnoredOld */ LINUX_MIB_TCPDSACKIGNOREDNOUNDO, /* TCPSACKIgnoredNoUndo */ LINUX_MIB_TCPSPURIOUSRTOS, /* TCPSpuriousRTOs */ LINUX_MIB_TCPMD5NOTFOUND, /* TCPMD5NotFound */ LINUX_MIB_TCPMD5UNEXPECTED, /* TCPMD5Unexpected */ + LINUX_MIB_TCPMD5FAILURE, /* TCPMD5Failure */ LINUX_MIB_SACKSHIFTED, LINUX_MIB_SACKMERGED, LINUX_MIB_SACKSHIFTFALLBACK, LINUX_MIB_TCPBACKLOGDROP, + LINUX_MIB_PFMEMALLOCDROP, LINUX_MIB_TCPMINTTLDROP, /* RFC 5082 */ LINUX_MIB_TCPDEFERACCEPTDROP, LINUX_MIB_IPRPFILTER, /* IP Reverse Path Filter (rp_filter) */ LINUX_MIB_TCPTIMEWAITOVERFLOW, /* TCPTimeWaitOverflow */ + LINUX_MIB_TCPREQQFULLDOCOOKIES, /* TCPReqQFullDoCookies */ + LINUX_MIB_TCPREQQFULLDROP, /* TCPReqQFullDrop */ + LINUX_MIB_TCPRETRANSFAIL, /* TCPRetransFail */ + LINUX_MIB_TCPRCVCOALESCE, /* TCPRcvCoalesce */ + LINUX_MIB_TCPBACKLOGCOALESCE, /* TCPBacklogCoalesce */ + LINUX_MIB_TCPOFOQUEUE, /* TCPOFOQueue */ + LINUX_MIB_TCPOFODROP, /* TCPOFODrop */ + LINUX_MIB_TCPOFOMERGE, /* TCPOFOMerge */ + LINUX_MIB_TCPCHALLENGEACK, /* TCPChallengeACK */ + LINUX_MIB_TCPSYNCHALLENGE, /* TCPSYNChallenge */ + LINUX_MIB_TCPFASTOPENACTIVE, /* TCPFastOpenActive */ + LINUX_MIB_TCPFASTOPENACTIVEFAIL, /* TCPFastOpenActiveFail */ + LINUX_MIB_TCPFASTOPENPASSIVE, /* TCPFastOpenPassive*/ + LINUX_MIB_TCPFASTOPENPASSIVEFAIL, /* TCPFastOpenPassiveFail */ + LINUX_MIB_TCPFASTOPENLISTENOVERFLOW, /* TCPFastOpenListenOverflow */ + LINUX_MIB_TCPFASTOPENCOOKIEREQD, /* TCPFastOpenCookieReqd */ + LINUX_MIB_TCPFASTOPENBLACKHOLE, /* TCPFastOpenBlackholeDetect */ + LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES, /* TCPSpuriousRtxHostQueues */ + LINUX_MIB_BUSYPOLLRXPACKETS, /* BusyPollRxPackets */ + LINUX_MIB_TCPAUTOCORKING, /* TCPAutoCorking */ + LINUX_MIB_TCPFROMZEROWINDOWADV, /* TCPFromZeroWindowAdv */ + LINUX_MIB_TCPTOZEROWINDOWADV, /* TCPToZeroWindowAdv */ + LINUX_MIB_TCPWANTZEROWINDOWADV, /* TCPWantZeroWindowAdv */ + LINUX_MIB_TCPSYNRETRANS, /* TCPSynRetrans */ + LINUX_MIB_TCPORIGDATASENT, /* TCPOrigDataSent */ + LINUX_MIB_TCPHYSTARTTRAINDETECT, /* TCPHystartTrainDetect */ + LINUX_MIB_TCPHYSTARTTRAINCWND, /* TCPHystartTrainCwnd */ + LINUX_MIB_TCPHYSTARTDELAYDETECT, /* TCPHystartDelayDetect */ + LINUX_MIB_TCPHYSTARTDELAYCWND, /* TCPHystartDelayCwnd */ + LINUX_MIB_TCPACKSKIPPEDSYNRECV, /* TCPACKSkippedSynRecv */ + LINUX_MIB_TCPACKSKIPPEDPAWS, /* TCPACKSkippedPAWS */ + LINUX_MIB_TCPACKSKIPPEDSEQ, /* TCPACKSkippedSeq */ + LINUX_MIB_TCPACKSKIPPEDFINWAIT2, /* TCPACKSkippedFinWait2 */ + LINUX_MIB_TCPACKSKIPPEDTIMEWAIT, /* TCPACKSkippedTimeWait */ + LINUX_MIB_TCPACKSKIPPEDCHALLENGE, /* TCPACKSkippedChallenge */ + LINUX_MIB_TCPWINPROBE, /* TCPWinProbe */ + LINUX_MIB_TCPKEEPALIVE, /* TCPKeepAlive */ + LINUX_MIB_TCPMTUPFAIL, /* TCPMTUPFail */ + LINUX_MIB_TCPMTUPSUCCESS, /* TCPMTUPSuccess */ + LINUX_MIB_TCPDELIVERED, /* TCPDelivered */ + LINUX_MIB_TCPDELIVEREDCE, /* TCPDeliveredCE */ + LINUX_MIB_TCPACKCOMPRESSED, /* TCPAckCompressed */ + LINUX_MIB_TCPZEROWINDOWDROP, /* TCPZeroWindowDrop */ + LINUX_MIB_TCPRCVQDROP, /* TCPRcvQDrop */ + LINUX_MIB_TCPWQUEUETOOBIG, /* TCPWqueueTooBig */ + LINUX_MIB_TCPFASTOPENPASSIVEALTKEY, /* TCPFastOpenPassiveAltKey */ + LINUX_MIB_TCPTIMEOUTREHASH, /* TCPTimeoutRehash */ + LINUX_MIB_TCPDUPLICATEDATAREHASH, /* TCPDuplicateDataRehash */ + LINUX_MIB_TCPDSACKRECVSEGS, /* TCPDSACKRecvSegs */ + LINUX_MIB_TCPDSACKIGNOREDDUBIOUS, /* TCPDSACKIgnoredDubious */ + LINUX_MIB_TCPMIGRATEREQSUCCESS, /* TCPMigrateReqSuccess */ + LINUX_MIB_TCPMIGRATEREQFAILURE, /* TCPMigrateReqFailure */ + LINUX_MIB_TCPPLBREHASH, /* TCPPLBRehash */ __LINUX_MIB_MAX }; @@ -264,7 +329,28 @@ enum LINUX_MIB_XFRMOUTPOLDEAD, /* XfrmOutPolDead */ LINUX_MIB_XFRMOUTPOLERROR, /* XfrmOutPolError */ LINUX_MIB_XFRMFWDHDRERROR, /* XfrmFwdHdrError*/ + LINUX_MIB_XFRMOUTSTATEINVALID, /* XfrmOutStateInvalid */ + LINUX_MIB_XFRMACQUIREERROR, /* XfrmAcquireError */ __LINUX_MIB_XFRMMAX }; +/* linux TLS mib definitions */ +enum +{ + LINUX_MIB_TLSNUM = 0, + LINUX_MIB_TLSCURRTXSW, /* TlsCurrTxSw */ + LINUX_MIB_TLSCURRRXSW, /* TlsCurrRxSw */ + LINUX_MIB_TLSCURRTXDEVICE, /* TlsCurrTxDevice */ + LINUX_MIB_TLSCURRRXDEVICE, /* TlsCurrRxDevice */ + LINUX_MIB_TLSTXSW, /* TlsTxSw */ + LINUX_MIB_TLSRXSW, /* TlsRxSw */ + LINUX_MIB_TLSTXDEVICE, /* TlsTxDevice */ + LINUX_MIB_TLSRXDEVICE, /* TlsRxDevice */ + LINUX_MIB_TLSDECRYPTERROR, /* TlsDecryptError */ + LINUX_MIB_TLSRXDEVICERESYNC, /* TlsRxDeviceResync */ + LINUX_MIB_TLSDECRYPTRETRY, /* TlsDecryptRetry */ + LINUX_MIB_TLSRXNOPADVIOL, /* TlsRxNoPadViolation */ + __LINUX_MIB_TLSMAX +}; + #endif /* _LINUX_SNMP_H */ diff --git a/include/linux-private/linux/sock_diag.h b/include/linux-private/linux/sock_diag.h new file mode 100644 index 0000000..35c0ce6 --- /dev/null +++ b/include/linux-private/linux/sock_diag.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __SOCK_DIAG_H__ +#define __SOCK_DIAG_H__ + +#include + +#define SOCK_DIAG_BY_FAMILY 20 +#define SOCK_DESTROY 21 + +struct sock_diag_req { + __u8 sdiag_family; + __u8 sdiag_protocol; +}; + +enum { + SK_MEMINFO_RMEM_ALLOC, + SK_MEMINFO_RCVBUF, + SK_MEMINFO_WMEM_ALLOC, + SK_MEMINFO_SNDBUF, + SK_MEMINFO_FWD_ALLOC, + SK_MEMINFO_WMEM_QUEUED, + SK_MEMINFO_OPTMEM, + SK_MEMINFO_BACKLOG, + SK_MEMINFO_DROPS, + + SK_MEMINFO_VARS, +}; + +enum sknetlink_groups { + SKNLGRP_NONE, + SKNLGRP_INET_TCP_DESTROY, + SKNLGRP_INET_UDP_DESTROY, + SKNLGRP_INET6_TCP_DESTROY, + SKNLGRP_INET6_UDP_DESTROY, + __SKNLGRP_MAX, +}; +#define SKNLGRP_MAX (__SKNLGRP_MAX - 1) + +enum { + SK_DIAG_BPF_STORAGE_REQ_NONE, + SK_DIAG_BPF_STORAGE_REQ_MAP_FD, + __SK_DIAG_BPF_STORAGE_REQ_MAX, +}; + +#define SK_DIAG_BPF_STORAGE_REQ_MAX (__SK_DIAG_BPF_STORAGE_REQ_MAX - 1) + +enum { + SK_DIAG_BPF_STORAGE_REP_NONE, + SK_DIAG_BPF_STORAGE, + __SK_DIAG_BPF_STORAGE_REP_MAX, +}; + +#define SK_DIAB_BPF_STORAGE_REP_MAX (__SK_DIAG_BPF_STORAGE_REP_MAX - 1) + +enum { + SK_DIAG_BPF_STORAGE_NONE, + SK_DIAG_BPF_STORAGE_PAD, + SK_DIAG_BPF_STORAGE_MAP_ID, + SK_DIAG_BPF_STORAGE_MAP_VALUE, + __SK_DIAG_BPF_STORAGE_MAX, +}; + +#define SK_DIAG_BPF_STORAGE_MAX (__SK_DIAG_BPF_STORAGE_MAX - 1) + +#endif /* __SOCK_DIAG_H__ */ diff --git a/include/linux-private/linux/socket.h b/include/linux-private/linux/socket.h new file mode 100644 index 0000000..89c227f --- /dev/null +++ b/include/linux-private/linux/socket.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_SOCKET_H +#define _LINUX_SOCKET_H + +/* + * Desired design of maximum size and alignment (see RFC2553) + */ +#define _K_SS_MAXSIZE 128 /* Implementation specific max size */ + +typedef unsigned short __kernel_sa_family_t; + +/* + * The definition uses anonymous union and struct in order to control the + * default alignment. + */ +struct __kernel_sockaddr_storage { + union { + struct { + __kernel_sa_family_t ss_family; /* address family */ + /* Following field(s) are implementation specific */ + char __data[_K_SS_MAXSIZE - sizeof(unsigned short)]; + /* space to achieve desired size, */ + /* _SS_MAXSIZE value minus size of ss_family */ + }; + void *__align; /* implementation specific desired alignment */ + }; +}; + +#define SOCK_SNDBUF_LOCK 1 +#define SOCK_RCVBUF_LOCK 2 + +#define SOCK_BUF_LOCK_MASK (SOCK_SNDBUF_LOCK | SOCK_RCVBUF_LOCK) + +#define SOCK_TXREHASH_DEFAULT 255 +#define SOCK_TXREHASH_DISABLED 0 +#define SOCK_TXREHASH_ENABLED 1 + +#endif /* _LINUX_SOCKET_H */ diff --git a/include/linux-private/linux/stddef.h b/include/linux-private/linux/stddef.h new file mode 100644 index 0000000..bb6ea51 --- /dev/null +++ b/include/linux-private/linux/stddef.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_STDDEF_H +#define _LINUX_STDDEF_H + + + +#ifndef __always_inline +#define __always_inline __inline__ +#endif + +/** + * __struct_group() - Create a mirrored named and anonyomous struct + * + * @TAG: The tag name for the named sub-struct (usually empty) + * @NAME: The identifier name of the mirrored sub-struct + * @ATTRS: Any struct attributes (usually empty) + * @MEMBERS: The member declarations for the mirrored structs + * + * Used to create an anonymous union of two structs with identical layout + * and size: one anonymous and one named. The former's members can be used + * normally without sub-struct naming, and the latter can be used to + * reason about the start, end, and size of the group of struct members. + * The named struct can also be explicitly tagged for layer reuse, as well + * as both having struct attributes appended. + */ +#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \ + union { \ + struct { MEMBERS } ATTRS; \ + struct TAG { MEMBERS } ATTRS NAME; \ + } + +/** + * __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union + * + * @TYPE: The type of each flexible array element + * @NAME: The name of the flexible array member + * + * In order to have a flexible array member in a union or alone in a + * struct, it needs to be wrapped in an anonymous struct with at least 1 + * named member, but that member can be empty. + */ +#define __DECLARE_FLEX_ARRAY(TYPE, NAME) \ + struct { \ + struct { } __empty_ ## NAME; \ + TYPE NAME[]; \ + } +#endif diff --git a/include/linux-private/linux/swab.h b/include/linux-private/linux/swab.h new file mode 100644 index 0000000..7e3bad5 --- /dev/null +++ b/include/linux-private/linux/swab.h @@ -0,0 +1,305 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_SWAB_H +#define _LINUX_SWAB_H + +#include +#include +#include +#include + +/* + * casts are necessary for constants, because we never know how for sure + * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way. + */ +#define ___constant_swab16(x) ((__u16)( \ + (((__u16)(x) & (__u16)0x00ffU) << 8) | \ + (((__u16)(x) & (__u16)0xff00U) >> 8))) + +#define ___constant_swab32(x) ((__u32)( \ + (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ + (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ + (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ + (((__u32)(x) & (__u32)0xff000000UL) >> 24))) + +#define ___constant_swab64(x) ((__u64)( \ + (((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \ + (((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \ + (((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \ + (((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \ + (((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \ + (((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ + (((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \ + (((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56))) + +#define ___constant_swahw32(x) ((__u32)( \ + (((__u32)(x) & (__u32)0x0000ffffUL) << 16) | \ + (((__u32)(x) & (__u32)0xffff0000UL) >> 16))) + +#define ___constant_swahb32(x) ((__u32)( \ + (((__u32)(x) & (__u32)0x00ff00ffUL) << 8) | \ + (((__u32)(x) & (__u32)0xff00ff00UL) >> 8))) + +/* + * Implement the following as inlines, but define the interface using + * macros to allow constant folding when possible: + * ___swab16, ___swab32, ___swab64, ___swahw32, ___swahb32 + */ + +static __inline__ __u16 __fswab16(__u16 val) +{ +#if defined (__arch_swab16) + return __arch_swab16(val); +#else + return ___constant_swab16(val); +#endif +} + +static __inline__ __u32 __fswab32(__u32 val) +{ +#if defined(__arch_swab32) + return __arch_swab32(val); +#else + return ___constant_swab32(val); +#endif +} + +static __inline__ __u64 __fswab64(__u64 val) +{ +#if defined (__arch_swab64) + return __arch_swab64(val); +#elif defined(__SWAB_64_THRU_32__) + __u32 h = val >> 32; + __u32 l = val & ((1ULL << 32) - 1); + return (((__u64)__fswab32(l)) << 32) | ((__u64)(__fswab32(h))); +#else + return ___constant_swab64(val); +#endif +} + +static __inline__ __u32 __fswahw32(__u32 val) +{ +#ifdef __arch_swahw32 + return __arch_swahw32(val); +#else + return ___constant_swahw32(val); +#endif +} + +static __inline__ __u32 __fswahb32(__u32 val) +{ +#ifdef __arch_swahb32 + return __arch_swahb32(val); +#else + return ___constant_swahb32(val); +#endif +} + +/** + * __swab16 - return a byteswapped 16-bit value + * @x: value to byteswap + */ +#ifdef __HAVE_BUILTIN_BSWAP16__ +#define __swab16(x) (__u16)__builtin_bswap16((__u16)(x)) +#else +#define __swab16(x) \ + (__u16)(__builtin_constant_p(x) ? \ + ___constant_swab16(x) : \ + __fswab16(x)) +#endif + +/** + * __swab32 - return a byteswapped 32-bit value + * @x: value to byteswap + */ +#ifdef __HAVE_BUILTIN_BSWAP32__ +#define __swab32(x) (__u32)__builtin_bswap32((__u32)(x)) +#else +#define __swab32(x) \ + (__u32)(__builtin_constant_p(x) ? \ + ___constant_swab32(x) : \ + __fswab32(x)) +#endif + +/** + * __swab64 - return a byteswapped 64-bit value + * @x: value to byteswap + */ +#ifdef __HAVE_BUILTIN_BSWAP64__ +#define __swab64(x) (__u64)__builtin_bswap64((__u64)(x)) +#else +#define __swab64(x) \ + (__u64)(__builtin_constant_p(x) ? \ + ___constant_swab64(x) : \ + __fswab64(x)) +#endif + +static __always_inline unsigned long __swab(const unsigned long y) +{ +#if __BITS_PER_LONG == 64 + return __swab64(y); +#else /* __BITS_PER_LONG == 32 */ + return __swab32(y); +#endif +} + +/** + * __swahw32 - return a word-swapped 32-bit value + * @x: value to wordswap + * + * __swahw32(0x12340000) is 0x00001234 + */ +#define __swahw32(x) \ + (__builtin_constant_p((__u32)(x)) ? \ + ___constant_swahw32(x) : \ + __fswahw32(x)) + +/** + * __swahb32 - return a high and low byte-swapped 32-bit value + * @x: value to byteswap + * + * __swahb32(0x12345678) is 0x34127856 + */ +#define __swahb32(x) \ + (__builtin_constant_p((__u32)(x)) ? \ + ___constant_swahb32(x) : \ + __fswahb32(x)) + +/** + * __swab16p - return a byteswapped 16-bit value from a pointer + * @p: pointer to a naturally-aligned 16-bit value + */ +static __always_inline __u16 __swab16p(const __u16 *p) +{ +#ifdef __arch_swab16p + return __arch_swab16p(p); +#else + return __swab16(*p); +#endif +} + +/** + * __swab32p - return a byteswapped 32-bit value from a pointer + * @p: pointer to a naturally-aligned 32-bit value + */ +static __always_inline __u32 __swab32p(const __u32 *p) +{ +#ifdef __arch_swab32p + return __arch_swab32p(p); +#else + return __swab32(*p); +#endif +} + +/** + * __swab64p - return a byteswapped 64-bit value from a pointer + * @p: pointer to a naturally-aligned 64-bit value + */ +static __always_inline __u64 __swab64p(const __u64 *p) +{ +#ifdef __arch_swab64p + return __arch_swab64p(p); +#else + return __swab64(*p); +#endif +} + +/** + * __swahw32p - return a wordswapped 32-bit value from a pointer + * @p: pointer to a naturally-aligned 32-bit value + * + * See __swahw32() for details of wordswapping. + */ +static __inline__ __u32 __swahw32p(const __u32 *p) +{ +#ifdef __arch_swahw32p + return __arch_swahw32p(p); +#else + return __swahw32(*p); +#endif +} + +/** + * __swahb32p - return a high and low byteswapped 32-bit value from a pointer + * @p: pointer to a naturally-aligned 32-bit value + * + * See __swahb32() for details of high/low byteswapping. + */ +static __inline__ __u32 __swahb32p(const __u32 *p) +{ +#ifdef __arch_swahb32p + return __arch_swahb32p(p); +#else + return __swahb32(*p); +#endif +} + +/** + * __swab16s - byteswap a 16-bit value in-place + * @p: pointer to a naturally-aligned 16-bit value + */ +static __inline__ void __swab16s(__u16 *p) +{ +#ifdef __arch_swab16s + __arch_swab16s(p); +#else + *p = __swab16p(p); +#endif +} +/** + * __swab32s - byteswap a 32-bit value in-place + * @p: pointer to a naturally-aligned 32-bit value + */ +static __always_inline void __swab32s(__u32 *p) +{ +#ifdef __arch_swab32s + __arch_swab32s(p); +#else + *p = __swab32p(p); +#endif +} + +/** + * __swab64s - byteswap a 64-bit value in-place + * @p: pointer to a naturally-aligned 64-bit value + */ +static __always_inline void __swab64s(__u64 *p) +{ +#ifdef __arch_swab64s + __arch_swab64s(p); +#else + *p = __swab64p(p); +#endif +} + +/** + * __swahw32s - wordswap a 32-bit value in-place + * @p: pointer to a naturally-aligned 32-bit value + * + * See __swahw32() for details of wordswapping + */ +static __inline__ void __swahw32s(__u32 *p) +{ +#ifdef __arch_swahw32s + __arch_swahw32s(p); +#else + *p = __swahw32p(p); +#endif +} + +/** + * __swahb32s - high and low byteswap a 32-bit value in-place + * @p: pointer to a naturally-aligned 32-bit value + * + * See __swahb32() for details of high and low byte swapping + */ +static __inline__ void __swahb32s(__u32 *p) +{ +#ifdef __arch_swahb32s + __arch_swahb32s(p); +#else + *p = __swahb32p(p); +#endif +} + + +#endif /* _LINUX_SWAB_H */ diff --git a/include/linux-private/linux/taskstats.h b/include/linux-private/linux/taskstats.h new file mode 100644 index 0000000..b50b2eb --- /dev/null +++ b/include/linux-private/linux/taskstats.h @@ -0,0 +1,252 @@ +/* SPDX-License-Identifier: LGPL-2.1 WITH Linux-syscall-note */ +/* taskstats.h - exporting per-task statistics + * + * Copyright (C) Shailabh Nagar, IBM Corp. 2006 + * (C) Balbir Singh, IBM Corp. 2006 + * (C) Jay Lan, SGI, 2006 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef _LINUX_TASKSTATS_H +#define _LINUX_TASKSTATS_H + +#include + +/* Format for per-task data returned to userland when + * - a task exits + * - listener requests stats for a task + * + * The struct is versioned. Newer versions should only add fields to + * the bottom of the struct to maintain backward compatibility. + * + * + * To add new fields + * a) bump up TASKSTATS_VERSION + * b) add comment indicating new version number at end of struct + * c) add new fields after version comment; maintain 64-bit alignment + */ + + +#define TASKSTATS_VERSION 14 +#define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN + * in linux/sched.h */ + +struct taskstats { + + /* The version number of this struct. This field is always set to + * TAKSTATS_VERSION, which is defined in . + * Each time the struct is changed, the value should be incremented. + */ + __u16 version; + __u32 ac_exitcode; /* Exit status */ + + /* The accounting flags of a task as defined in + * Defined values are AFORK, ASU, ACOMPAT, ACORE, AXSIG, and AGROUP. + * (AGROUP since version 12). + */ + __u8 ac_flag; /* Record flags */ + __u8 ac_nice; /* task_nice */ + + /* Delay accounting fields start + * + * All values, until comment "Delay accounting fields end" are + * available only if delay accounting is enabled, even though the last + * few fields are not delays + * + * xxx_count is the number of delay values recorded + * xxx_delay_total is the corresponding cumulative delay in nanoseconds + * + * xxx_delay_total wraps around to zero on overflow + * xxx_count incremented regardless of overflow + */ + + /* Delay waiting for cpu, while runnable + * count, delay_total NOT updated atomically + */ + __u64 cpu_count __attribute__((aligned(8))); + __u64 cpu_delay_total; + + /* Following four fields atomically updated using task->delays->lock */ + + /* Delay waiting for synchronous block I/O to complete + * does not account for delays in I/O submission + */ + __u64 blkio_count; + __u64 blkio_delay_total; + + /* Delay waiting for page fault I/O (swap in only) */ + __u64 swapin_count; + __u64 swapin_delay_total; + + /* cpu "wall-clock" running time + * On some architectures, value will adjust for cpu time stolen + * from the kernel in involuntary waits due to virtualization. + * Value is cumulative, in nanoseconds, without a corresponding count + * and wraps around to zero silently on overflow + */ + __u64 cpu_run_real_total; + + /* cpu "virtual" running time + * Uses time intervals seen by the kernel i.e. no adjustment + * for kernel's involuntary waits due to virtualization. + * Value is cumulative, in nanoseconds, without a corresponding count + * and wraps around to zero silently on overflow + */ + __u64 cpu_run_virtual_total; + /* Delay accounting fields end */ + /* version 1 ends here */ + + /* Basic Accounting Fields start */ + char ac_comm[TS_COMM_LEN]; /* Command name */ + __u8 ac_sched __attribute__((aligned(8))); + /* Scheduling discipline */ + __u8 ac_pad[3]; + __u32 ac_uid __attribute__((aligned(8))); + /* User ID */ + __u32 ac_gid; /* Group ID */ + __u32 ac_pid; /* Process ID */ + __u32 ac_ppid; /* Parent process ID */ + /* __u32 range means times from 1970 to 2106 */ + __u32 ac_btime; /* Begin time [sec since 1970] */ + __u64 ac_etime __attribute__((aligned(8))); + /* Elapsed time [usec] */ + __u64 ac_utime; /* User CPU time [usec] */ + __u64 ac_stime; /* SYstem CPU time [usec] */ + __u64 ac_minflt; /* Minor Page Fault Count */ + __u64 ac_majflt; /* Major Page Fault Count */ + /* Basic Accounting Fields end */ + + /* Extended accounting fields start */ + /* Accumulated RSS usage in duration of a task, in MBytes-usecs. + * The current rss usage is added to this counter every time + * a tick is charged to a task's system time. So, at the end we + * will have memory usage multiplied by system time. Thus an + * average usage per system time unit can be calculated. + */ + __u64 coremem; /* accumulated RSS usage in MB-usec */ + /* Accumulated virtual memory usage in duration of a task. + * Same as acct_rss_mem1 above except that we keep track of VM usage. + */ + __u64 virtmem; /* accumulated VM usage in MB-usec */ + + /* High watermark of RSS and virtual memory usage in duration of + * a task, in KBytes. + */ + __u64 hiwater_rss; /* High-watermark of RSS usage, in KB */ + __u64 hiwater_vm; /* High-water VM usage, in KB */ + + /* The following four fields are I/O statistics of a task. */ + __u64 read_char; /* bytes read */ + __u64 write_char; /* bytes written */ + __u64 read_syscalls; /* read syscalls */ + __u64 write_syscalls; /* write syscalls */ + /* Extended accounting fields end */ + +#define TASKSTATS_HAS_IO_ACCOUNTING + /* Per-task storage I/O accounting starts */ + __u64 read_bytes; /* bytes of read I/O */ + __u64 write_bytes; /* bytes of write I/O */ + __u64 cancelled_write_bytes; /* bytes of cancelled write I/O */ + + __u64 nvcsw; /* voluntary_ctxt_switches */ + __u64 nivcsw; /* nonvoluntary_ctxt_switches */ + + /* time accounting for SMT machines */ + __u64 ac_utimescaled; /* utime scaled on frequency etc */ + __u64 ac_stimescaled; /* stime scaled on frequency etc */ + __u64 cpu_scaled_run_real_total; /* scaled cpu_run_real_total */ + + /* Delay waiting for memory reclaim */ + __u64 freepages_count; + __u64 freepages_delay_total; + + /* Delay waiting for thrashing page */ + __u64 thrashing_count; + __u64 thrashing_delay_total; + + /* v10: 64-bit btime to avoid overflow */ + __u64 ac_btime64; /* 64-bit begin time */ + + /* v11: Delay waiting for memory compact */ + __u64 compact_count; + __u64 compact_delay_total; + + /* v12 begin */ + __u32 ac_tgid; /* thread group ID */ + /* Thread group walltime up to now. This is total process walltime if + * AGROUP flag is set. + */ + __u64 ac_tgetime __attribute__((aligned(8))); + /* Lightweight information to identify process binary files. + * This leaves userspace to match this to a file system path, using + * MAJOR() and MINOR() macros to identify a device and mount point, + * the inode to identify the executable file. This is /proc/self/exe + * at the end, so matching the most recent exec(). Values are zero + * for kernel threads. + */ + __u64 ac_exe_dev; /* program binary device ID */ + __u64 ac_exe_inode; /* program binary inode number */ + /* v12 end */ + + /* v13: Delay waiting for write-protect copy */ + __u64 wpcopy_count; + __u64 wpcopy_delay_total; + + /* v14: Delay waiting for IRQ/SOFTIRQ */ + __u64 irq_count; + __u64 irq_delay_total; +}; + + +/* + * Commands sent from userspace + * Not versioned. New commands should only be inserted at the enum's end + * prior to __TASKSTATS_CMD_MAX + */ + +enum { + TASKSTATS_CMD_UNSPEC = 0, /* Reserved */ + TASKSTATS_CMD_GET, /* user->kernel request/get-response */ + TASKSTATS_CMD_NEW, /* kernel->user event */ + __TASKSTATS_CMD_MAX, +}; + +#define TASKSTATS_CMD_MAX (__TASKSTATS_CMD_MAX - 1) + +enum { + TASKSTATS_TYPE_UNSPEC = 0, /* Reserved */ + TASKSTATS_TYPE_PID, /* Process id */ + TASKSTATS_TYPE_TGID, /* Thread group id */ + TASKSTATS_TYPE_STATS, /* taskstats structure */ + TASKSTATS_TYPE_AGGR_PID, /* contains pid + stats */ + TASKSTATS_TYPE_AGGR_TGID, /* contains tgid + stats */ + TASKSTATS_TYPE_NULL, /* contains nothing */ + __TASKSTATS_TYPE_MAX, +}; + +#define TASKSTATS_TYPE_MAX (__TASKSTATS_TYPE_MAX - 1) + +enum { + TASKSTATS_CMD_ATTR_UNSPEC = 0, + TASKSTATS_CMD_ATTR_PID, + TASKSTATS_CMD_ATTR_TGID, + TASKSTATS_CMD_ATTR_REGISTER_CPUMASK, + TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK, + __TASKSTATS_CMD_ATTR_MAX, +}; + +#define TASKSTATS_CMD_ATTR_MAX (__TASKSTATS_CMD_ATTR_MAX - 1) + +/* NETLINK_GENERIC related info */ + +#define TASKSTATS_GENL_NAME "TASKSTATS" +#define TASKSTATS_GENL_VERSION 0x1 + +#endif /* _LINUX_TASKSTATS_H */ diff --git a/include/linux-private/linux/tc_act/tc_gact.h b/include/linux-private/linux/tc_act/tc_gact.h new file mode 100644 index 0000000..37e5392 --- /dev/null +++ b/include/linux-private/linux/tc_act/tc_gact.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __LINUX_TC_GACT_H +#define __LINUX_TC_GACT_H + +#include +#include + +struct tc_gact { + tc_gen; + +}; + +struct tc_gact_p { +#define PGACT_NONE 0 +#define PGACT_NETRAND 1 +#define PGACT_DETERM 2 +#define MAX_RAND (PGACT_DETERM + 1 ) + __u16 ptype; + __u16 pval; + int paction; +}; + +enum { + TCA_GACT_UNSPEC, + TCA_GACT_TM, + TCA_GACT_PARMS, + TCA_GACT_PROB, + TCA_GACT_PAD, + __TCA_GACT_MAX +}; +#define TCA_GACT_MAX (__TCA_GACT_MAX - 1) + +#endif diff --git a/include/linux-private/linux/tc_act/tc_mirred.h b/include/linux-private/linux/tc_act/tc_mirred.h new file mode 100644 index 0000000..2500a00 --- /dev/null +++ b/include/linux-private/linux/tc_act/tc_mirred.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __LINUX_TC_MIR_H +#define __LINUX_TC_MIR_H + +#include +#include + +#define TCA_EGRESS_REDIR 1 /* packet redirect to EGRESS*/ +#define TCA_EGRESS_MIRROR 2 /* mirror packet to EGRESS */ +#define TCA_INGRESS_REDIR 3 /* packet redirect to INGRESS*/ +#define TCA_INGRESS_MIRROR 4 /* mirror packet to INGRESS */ + +struct tc_mirred { + tc_gen; + int eaction; /* one of IN/EGRESS_MIRROR/REDIR */ + __u32 ifindex; /* ifindex of egress port */ +}; + +enum { + TCA_MIRRED_UNSPEC, + TCA_MIRRED_TM, + TCA_MIRRED_PARMS, + TCA_MIRRED_PAD, + __TCA_MIRRED_MAX +}; +#define TCA_MIRRED_MAX (__TCA_MIRRED_MAX - 1) + +#endif diff --git a/include/linux-private/linux/tc_act/tc_nat.h b/include/linux-private/linux/tc_act/tc_nat.h new file mode 100644 index 0000000..21399c2 --- /dev/null +++ b/include/linux-private/linux/tc_act/tc_nat.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __LINUX_TC_NAT_H +#define __LINUX_TC_NAT_H + +#include +#include + +enum { + TCA_NAT_UNSPEC, + TCA_NAT_PARMS, + TCA_NAT_TM, + TCA_NAT_PAD, + __TCA_NAT_MAX +}; +#define TCA_NAT_MAX (__TCA_NAT_MAX - 1) + +#define TCA_NAT_FLAG_EGRESS 1 + +struct tc_nat { + tc_gen; + __be32 old_addr; + __be32 new_addr; + __be32 mask; + __u32 flags; +}; + +#endif diff --git a/include/linux-private/linux/tc_act/tc_skbedit.h b/include/linux-private/linux/tc_act/tc_skbedit.h new file mode 100644 index 0000000..6403251 --- /dev/null +++ b/include/linux-private/linux/tc_act/tc_skbedit.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Copyright (c) 2008, Intel Corporation. + * + * Author: Alexander Duyck + */ + +#ifndef __LINUX_TC_SKBEDIT_H +#define __LINUX_TC_SKBEDIT_H + +#include + +#define SKBEDIT_F_PRIORITY 0x1 +#define SKBEDIT_F_QUEUE_MAPPING 0x2 +#define SKBEDIT_F_MARK 0x4 +#define SKBEDIT_F_PTYPE 0x8 +#define SKBEDIT_F_MASK 0x10 +#define SKBEDIT_F_INHERITDSFIELD 0x20 +#define SKBEDIT_F_TXQ_SKBHASH 0x40 + +struct tc_skbedit { + tc_gen; +}; + +enum { + TCA_SKBEDIT_UNSPEC, + TCA_SKBEDIT_TM, + TCA_SKBEDIT_PARMS, + TCA_SKBEDIT_PRIORITY, + TCA_SKBEDIT_QUEUE_MAPPING, + TCA_SKBEDIT_MARK, + TCA_SKBEDIT_PAD, + TCA_SKBEDIT_PTYPE, + TCA_SKBEDIT_MASK, + TCA_SKBEDIT_FLAGS, + TCA_SKBEDIT_QUEUE_MAPPING_MAX, + __TCA_SKBEDIT_MAX +}; +#define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1) + +#endif diff --git a/include/linux-private/linux/tc_act/tc_vlan.h b/include/linux-private/linux/tc_act/tc_vlan.h new file mode 100644 index 0000000..3e1f8e5 --- /dev/null +++ b/include/linux-private/linux/tc_act/tc_vlan.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * Copyright (c) 2014 Jiri Pirko + */ + +#ifndef __LINUX_TC_VLAN_H +#define __LINUX_TC_VLAN_H + +#include + +#define TCA_VLAN_ACT_POP 1 +#define TCA_VLAN_ACT_PUSH 2 +#define TCA_VLAN_ACT_MODIFY 3 +#define TCA_VLAN_ACT_POP_ETH 4 +#define TCA_VLAN_ACT_PUSH_ETH 5 + +struct tc_vlan { + tc_gen; + int v_action; +}; + +enum { + TCA_VLAN_UNSPEC, + TCA_VLAN_TM, + TCA_VLAN_PARMS, + TCA_VLAN_PUSH_VLAN_ID, + TCA_VLAN_PUSH_VLAN_PROTOCOL, + TCA_VLAN_PAD, + TCA_VLAN_PUSH_VLAN_PRIORITY, + TCA_VLAN_PUSH_ETH_DST, + TCA_VLAN_PUSH_ETH_SRC, + __TCA_VLAN_MAX, +}; +#define TCA_VLAN_MAX (__TCA_VLAN_MAX - 1) + +#endif diff --git a/include/linux-private/linux/tc_ematch/tc_em_cmp.h b/include/linux-private/linux/tc_ematch/tc_em_cmp.h new file mode 100644 index 0000000..2549d9d --- /dev/null +++ b/include/linux-private/linux/tc_ematch/tc_em_cmp.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __LINUX_TC_EM_CMP_H +#define __LINUX_TC_EM_CMP_H + +#include +#include + +struct tcf_em_cmp { + __u32 val; + __u32 mask; + __u16 off; + __u8 align:4; + __u8 flags:4; + __u8 layer:4; + __u8 opnd:4; +}; + +enum { + TCF_EM_ALIGN_U8 = 1, + TCF_EM_ALIGN_U16 = 2, + TCF_EM_ALIGN_U32 = 4 +}; + +#define TCF_EM_CMP_TRANS 1 + +#endif diff --git a/include/linux/tc_ematch/tc_em_meta.h b/include/linux-private/linux/tc_ematch/tc_em_meta.h similarity index 91% rename from include/linux/tc_ematch/tc_em_meta.h rename to include/linux-private/linux/tc_ematch/tc_em_meta.h index fe815e2..cf30b5b 100644 --- a/include/linux/tc_ematch/tc_em_meta.h +++ b/include/linux-private/linux/tc_ematch/tc_em_meta.h @@ -1,6 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef __LINUX_TC_EM_META_H #define __LINUX_TC_EM_META_H +#include +#include + enum { TCA_EM_META_UNSPEC, TCA_EM_META_HDR, @@ -64,7 +68,7 @@ enum { TCF_META_ID_SK_FORWARD_ALLOCS, TCF_META_ID_SK_SNDBUF, TCF_META_ID_SK_ALLOCS, - TCF_META_ID_SK_ROUTE_CAPS, + __TCF_META_ID_SK_ROUTE_CAPS, /* unimplemented but in ABI already */ TCF_META_ID_SK_HASH, TCF_META_ID_SK_LINGERTIME, TCF_META_ID_SK_ACK_BACKLOG, diff --git a/include/linux-private/linux/tc_ematch/tc_em_nbyte.h b/include/linux-private/linux/tc_ematch/tc_em_nbyte.h new file mode 100644 index 0000000..c76333f --- /dev/null +++ b/include/linux-private/linux/tc_ematch/tc_em_nbyte.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __LINUX_TC_EM_NBYTE_H +#define __LINUX_TC_EM_NBYTE_H + +#include +#include + +struct tcf_em_nbyte { + __u16 off; + __u16 len:12; + __u8 layer:4; +}; + +#endif diff --git a/include/linux-private/linux/tc_ematch/tc_em_text.h b/include/linux-private/linux/tc_ematch/tc_em_text.h new file mode 100644 index 0000000..b0a9225 --- /dev/null +++ b/include/linux-private/linux/tc_ematch/tc_em_text.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __LINUX_TC_EM_TEXT_H +#define __LINUX_TC_EM_TEXT_H + +#include +#include + +#define TC_EM_TEXT_ALGOSIZ 16 + +struct tcf_em_text { + char algo[TC_EM_TEXT_ALGOSIZ]; + __u16 from_offset; + __u16 to_offset; + __u16 pattern_len; + __u8 from_layer:4; + __u8 to_layer:4; + __u8 pad; +}; + +#endif diff --git a/include/linux-private/linux/types.h b/include/linux-private/linux/types.h new file mode 100644 index 0000000..6546100 --- /dev/null +++ b/include/linux-private/linux/types.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_TYPES_H +#define _LINUX_TYPES_H + +#include + +#ifndef __ASSEMBLY__ + +#include + + +/* + * Below are truly Linux-specific types that should never collide with + * any application/library that wants linux/types.h. + */ + +/* sparse defines __CHECKER__; see Documentation/dev-tools/sparse.rst */ +#ifdef __CHECKER__ +#define __bitwise __attribute__((bitwise)) +#else +#define __bitwise +#endif + +/* The kernel doesn't use this legacy form, but user space does */ +#define __bitwise__ __bitwise + +typedef __u16 __bitwise __le16; +typedef __u16 __bitwise __be16; +typedef __u32 __bitwise __le32; +typedef __u32 __bitwise __be32; +typedef __u64 __bitwise __le64; +typedef __u64 __bitwise __be64; + +typedef __u16 __bitwise __sum16; +typedef __u32 __bitwise __wsum; + +/* + * aligned_u64 should be used in defining kernel<->userspace ABIs to avoid + * common 32/64-bit compat problems. + * 64-bit values align to 4-byte boundaries on x86_32 (and possibly other + * architectures) and to 8-byte boundaries on 64-bit architectures. The new + * aligned_64 type enforces 8-byte alignment so that structs containing + * aligned_64 values have the same alignment on 32-bit and 64-bit architectures. + * No conversions are necessary between 32-bit user-space and a 64-bit kernel. + */ +#define __aligned_u64 __u64 __attribute__((aligned(8))) +#define __aligned_be64 __be64 __attribute__((aligned(8))) +#define __aligned_le64 __le64 __attribute__((aligned(8))) + +typedef unsigned __bitwise __poll_t; + +#endif /* __ASSEMBLY__ */ +#endif /* _LINUX_TYPES_H */ diff --git a/include/linux-private/linux/version.h b/include/linux-private/linux/version.h new file mode 100644 index 0000000..4ae7bc0 --- /dev/null +++ b/include/linux-private/linux/version.h @@ -0,0 +1,5 @@ +#define LINUX_VERSION_CODE 394240 +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c))) +#define LINUX_VERSION_MAJOR 6 +#define LINUX_VERSION_PATCHLEVEL 4 +#define LINUX_VERSION_SUBLEVEL 0 diff --git a/include/linux-private/linux/veth.h b/include/linux-private/linux/veth.h new file mode 100644 index 0000000..52b58e5 --- /dev/null +++ b/include/linux-private/linux/veth.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __NET_VETH_H_ +#define __NET_VETH_H_ + +enum { + VETH_INFO_UNSPEC, + VETH_INFO_PEER, + + __VETH_INFO_MAX +#define VETH_INFO_MAX (__VETH_INFO_MAX - 1) +}; + +#endif diff --git a/include/linux-private/linux/xfrm.h b/include/linux-private/linux/xfrm.h new file mode 100644 index 0000000..10bdef8 --- /dev/null +++ b/include/linux-private/linux/xfrm.h @@ -0,0 +1,568 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_XFRM_H +#define _LINUX_XFRM_H + +#include +#include + +/* All of the structures in this file may not change size as they are + * passed into the kernel from userspace via netlink sockets. + */ + +/* Structure to encapsulate addresses. I do not want to use + * "standard" structure. My apologies. + */ +typedef union { + __be32 a4; + __be32 a6[4]; + struct in6_addr in6; +} xfrm_address_t; + +/* Ident of a specific xfrm_state. It is used on input to lookup + * the state by (spi,daddr,ah/esp) or to store information about + * spi, protocol and tunnel address on output. + */ +struct xfrm_id { + xfrm_address_t daddr; + __be32 spi; + __u8 proto; +}; + +struct xfrm_sec_ctx { + __u8 ctx_doi; + __u8 ctx_alg; + __u16 ctx_len; + __u32 ctx_sid; + char ctx_str[]; +}; + +/* Security Context Domains of Interpretation */ +#define XFRM_SC_DOI_RESERVED 0 +#define XFRM_SC_DOI_LSM 1 + +/* Security Context Algorithms */ +#define XFRM_SC_ALG_RESERVED 0 +#define XFRM_SC_ALG_SELINUX 1 + +/* Selector, used as selector both on policy rules (SPD) and SAs. */ + +struct xfrm_selector { + xfrm_address_t daddr; + xfrm_address_t saddr; + __be16 dport; + __be16 dport_mask; + __be16 sport; + __be16 sport_mask; + __u16 family; + __u8 prefixlen_d; + __u8 prefixlen_s; + __u8 proto; + int ifindex; + __kernel_uid32_t user; +}; + +#define XFRM_INF (~(__u64)0) + +struct xfrm_lifetime_cfg { + __u64 soft_byte_limit; + __u64 hard_byte_limit; + __u64 soft_packet_limit; + __u64 hard_packet_limit; + __u64 soft_add_expires_seconds; + __u64 hard_add_expires_seconds; + __u64 soft_use_expires_seconds; + __u64 hard_use_expires_seconds; +}; + +struct xfrm_lifetime_cur { + __u64 bytes; + __u64 packets; + __u64 add_time; + __u64 use_time; +}; + +struct xfrm_replay_state { + __u32 oseq; + __u32 seq; + __u32 bitmap; +}; + +#define XFRMA_REPLAY_ESN_MAX 4096 + +struct xfrm_replay_state_esn { + unsigned int bmp_len; + __u32 oseq; + __u32 seq; + __u32 oseq_hi; + __u32 seq_hi; + __u32 replay_window; + __u32 bmp[]; +}; + +struct xfrm_algo { + char alg_name[64]; + unsigned int alg_key_len; /* in bits */ + char alg_key[]; +}; + +struct xfrm_algo_auth { + char alg_name[64]; + unsigned int alg_key_len; /* in bits */ + unsigned int alg_trunc_len; /* in bits */ + char alg_key[]; +}; + +struct xfrm_algo_aead { + char alg_name[64]; + unsigned int alg_key_len; /* in bits */ + unsigned int alg_icv_len; /* in bits */ + char alg_key[]; +}; + +struct xfrm_stats { + __u32 replay_window; + __u32 replay; + __u32 integrity_failed; +}; + +enum { + XFRM_POLICY_TYPE_MAIN = 0, + XFRM_POLICY_TYPE_SUB = 1, + XFRM_POLICY_TYPE_MAX = 2, + XFRM_POLICY_TYPE_ANY = 255 +}; + +enum { + XFRM_POLICY_IN = 0, + XFRM_POLICY_OUT = 1, + XFRM_POLICY_FWD = 2, + XFRM_POLICY_MASK = 3, + XFRM_POLICY_MAX = 3 +}; + +enum { + XFRM_SHARE_ANY, /* No limitations */ + XFRM_SHARE_SESSION, /* For this session only */ + XFRM_SHARE_USER, /* For this user only */ + XFRM_SHARE_UNIQUE /* Use once */ +}; + +#define XFRM_MODE_TRANSPORT 0 +#define XFRM_MODE_TUNNEL 1 +#define XFRM_MODE_ROUTEOPTIMIZATION 2 +#define XFRM_MODE_IN_TRIGGER 3 +#define XFRM_MODE_BEET 4 +#define XFRM_MODE_MAX 5 + +/* Netlink configuration messages. */ +enum { + XFRM_MSG_BASE = 0x10, + + XFRM_MSG_NEWSA = 0x10, +#define XFRM_MSG_NEWSA XFRM_MSG_NEWSA + XFRM_MSG_DELSA, +#define XFRM_MSG_DELSA XFRM_MSG_DELSA + XFRM_MSG_GETSA, +#define XFRM_MSG_GETSA XFRM_MSG_GETSA + + XFRM_MSG_NEWPOLICY, +#define XFRM_MSG_NEWPOLICY XFRM_MSG_NEWPOLICY + XFRM_MSG_DELPOLICY, +#define XFRM_MSG_DELPOLICY XFRM_MSG_DELPOLICY + XFRM_MSG_GETPOLICY, +#define XFRM_MSG_GETPOLICY XFRM_MSG_GETPOLICY + + XFRM_MSG_ALLOCSPI, +#define XFRM_MSG_ALLOCSPI XFRM_MSG_ALLOCSPI + XFRM_MSG_ACQUIRE, +#define XFRM_MSG_ACQUIRE XFRM_MSG_ACQUIRE + XFRM_MSG_EXPIRE, +#define XFRM_MSG_EXPIRE XFRM_MSG_EXPIRE + + XFRM_MSG_UPDPOLICY, +#define XFRM_MSG_UPDPOLICY XFRM_MSG_UPDPOLICY + XFRM_MSG_UPDSA, +#define XFRM_MSG_UPDSA XFRM_MSG_UPDSA + + XFRM_MSG_POLEXPIRE, +#define XFRM_MSG_POLEXPIRE XFRM_MSG_POLEXPIRE + + XFRM_MSG_FLUSHSA, +#define XFRM_MSG_FLUSHSA XFRM_MSG_FLUSHSA + XFRM_MSG_FLUSHPOLICY, +#define XFRM_MSG_FLUSHPOLICY XFRM_MSG_FLUSHPOLICY + + XFRM_MSG_NEWAE, +#define XFRM_MSG_NEWAE XFRM_MSG_NEWAE + XFRM_MSG_GETAE, +#define XFRM_MSG_GETAE XFRM_MSG_GETAE + + XFRM_MSG_REPORT, +#define XFRM_MSG_REPORT XFRM_MSG_REPORT + + XFRM_MSG_MIGRATE, +#define XFRM_MSG_MIGRATE XFRM_MSG_MIGRATE + + XFRM_MSG_NEWSADINFO, +#define XFRM_MSG_NEWSADINFO XFRM_MSG_NEWSADINFO + XFRM_MSG_GETSADINFO, +#define XFRM_MSG_GETSADINFO XFRM_MSG_GETSADINFO + + XFRM_MSG_NEWSPDINFO, +#define XFRM_MSG_NEWSPDINFO XFRM_MSG_NEWSPDINFO + XFRM_MSG_GETSPDINFO, +#define XFRM_MSG_GETSPDINFO XFRM_MSG_GETSPDINFO + + XFRM_MSG_MAPPING, +#define XFRM_MSG_MAPPING XFRM_MSG_MAPPING + + XFRM_MSG_SETDEFAULT, +#define XFRM_MSG_SETDEFAULT XFRM_MSG_SETDEFAULT + XFRM_MSG_GETDEFAULT, +#define XFRM_MSG_GETDEFAULT XFRM_MSG_GETDEFAULT + __XFRM_MSG_MAX +}; +#define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1) + +#define XFRM_NR_MSGTYPES (XFRM_MSG_MAX + 1 - XFRM_MSG_BASE) + +/* + * Generic LSM security context for comunicating to user space + * NOTE: Same format as sadb_x_sec_ctx + */ +struct xfrm_user_sec_ctx { + __u16 len; + __u16 exttype; + __u8 ctx_alg; /* LSMs: e.g., selinux == 1 */ + __u8 ctx_doi; + __u16 ctx_len; +}; + +struct xfrm_user_tmpl { + struct xfrm_id id; + __u16 family; + xfrm_address_t saddr; + __u32 reqid; + __u8 mode; + __u8 share; + __u8 optional; + __u32 aalgos; + __u32 ealgos; + __u32 calgos; +}; + +struct xfrm_encap_tmpl { + __u16 encap_type; + __be16 encap_sport; + __be16 encap_dport; + xfrm_address_t encap_oa; +}; + +/* AEVENT flags */ +enum xfrm_ae_ftype_t { + XFRM_AE_UNSPEC, + XFRM_AE_RTHR=1, /* replay threshold*/ + XFRM_AE_RVAL=2, /* replay value */ + XFRM_AE_LVAL=4, /* lifetime value */ + XFRM_AE_ETHR=8, /* expiry timer threshold */ + XFRM_AE_CR=16, /* Event cause is replay update */ + XFRM_AE_CE=32, /* Event cause is timer expiry */ + XFRM_AE_CU=64, /* Event cause is policy update */ + __XFRM_AE_MAX + +#define XFRM_AE_MAX (__XFRM_AE_MAX - 1) +}; + +struct xfrm_userpolicy_type { + __u8 type; + __u16 reserved1; + __u8 reserved2; +}; + +/* Netlink message attributes. */ +enum xfrm_attr_type_t { + XFRMA_UNSPEC, + XFRMA_ALG_AUTH, /* struct xfrm_algo */ + XFRMA_ALG_CRYPT, /* struct xfrm_algo */ + XFRMA_ALG_COMP, /* struct xfrm_algo */ + XFRMA_ENCAP, /* struct xfrm_algo + struct xfrm_encap_tmpl */ + XFRMA_TMPL, /* 1 or more struct xfrm_user_tmpl */ + XFRMA_SA, /* struct xfrm_usersa_info */ + XFRMA_POLICY, /*struct xfrm_userpolicy_info */ + XFRMA_SEC_CTX, /* struct xfrm_sec_ctx */ + XFRMA_LTIME_VAL, + XFRMA_REPLAY_VAL, + XFRMA_REPLAY_THRESH, + XFRMA_ETIMER_THRESH, + XFRMA_SRCADDR, /* xfrm_address_t */ + XFRMA_COADDR, /* xfrm_address_t */ + XFRMA_LASTUSED, /* __u64 */ + XFRMA_POLICY_TYPE, /* struct xfrm_userpolicy_type */ + XFRMA_MIGRATE, + XFRMA_ALG_AEAD, /* struct xfrm_algo_aead */ + XFRMA_KMADDRESS, /* struct xfrm_user_kmaddress */ + XFRMA_ALG_AUTH_TRUNC, /* struct xfrm_algo_auth */ + XFRMA_MARK, /* struct xfrm_mark */ + XFRMA_TFCPAD, /* __u32 */ + XFRMA_REPLAY_ESN_VAL, /* struct xfrm_replay_state_esn */ + XFRMA_SA_EXTRA_FLAGS, /* __u32 */ + XFRMA_PROTO, /* __u8 */ + XFRMA_ADDRESS_FILTER, /* struct xfrm_address_filter */ + XFRMA_PAD, + XFRMA_OFFLOAD_DEV, /* struct xfrm_user_offload */ + XFRMA_SET_MARK, /* __u32 */ + XFRMA_SET_MARK_MASK, /* __u32 */ + XFRMA_IF_ID, /* __u32 */ + XFRMA_MTIMER_THRESH, /* __u32 in seconds for input SA */ + __XFRMA_MAX + +#define XFRMA_OUTPUT_MARK XFRMA_SET_MARK /* Compatibility */ +#define XFRMA_MAX (__XFRMA_MAX - 1) +}; + +struct xfrm_mark { + __u32 v; /* value */ + __u32 m; /* mask */ +}; + +enum xfrm_sadattr_type_t { + XFRMA_SAD_UNSPEC, + XFRMA_SAD_CNT, + XFRMA_SAD_HINFO, + __XFRMA_SAD_MAX + +#define XFRMA_SAD_MAX (__XFRMA_SAD_MAX - 1) +}; + +struct xfrmu_sadhinfo { + __u32 sadhcnt; /* current hash bkts */ + __u32 sadhmcnt; /* max allowed hash bkts */ +}; + +enum xfrm_spdattr_type_t { + XFRMA_SPD_UNSPEC, + XFRMA_SPD_INFO, + XFRMA_SPD_HINFO, + XFRMA_SPD_IPV4_HTHRESH, + XFRMA_SPD_IPV6_HTHRESH, + __XFRMA_SPD_MAX + +#define XFRMA_SPD_MAX (__XFRMA_SPD_MAX - 1) +}; + +struct xfrmu_spdinfo { + __u32 incnt; + __u32 outcnt; + __u32 fwdcnt; + __u32 inscnt; + __u32 outscnt; + __u32 fwdscnt; +}; + +struct xfrmu_spdhinfo { + __u32 spdhcnt; + __u32 spdhmcnt; +}; + +struct xfrmu_spdhthresh { + __u8 lbits; + __u8 rbits; +}; + +struct xfrm_usersa_info { + struct xfrm_selector sel; + struct xfrm_id id; + xfrm_address_t saddr; + struct xfrm_lifetime_cfg lft; + struct xfrm_lifetime_cur curlft; + struct xfrm_stats stats; + __u32 seq; + __u32 reqid; + __u16 family; + __u8 mode; /* XFRM_MODE_xxx */ + __u8 replay_window; + __u8 flags; +#define XFRM_STATE_NOECN 1 +#define XFRM_STATE_DECAP_DSCP 2 +#define XFRM_STATE_NOPMTUDISC 4 +#define XFRM_STATE_WILDRECV 8 +#define XFRM_STATE_ICMP 16 +#define XFRM_STATE_AF_UNSPEC 32 +#define XFRM_STATE_ALIGN4 64 +#define XFRM_STATE_ESN 128 +}; + +#define XFRM_SA_XFLAG_DONT_ENCAP_DSCP 1 +#define XFRM_SA_XFLAG_OSEQ_MAY_WRAP 2 + +struct xfrm_usersa_id { + xfrm_address_t daddr; + __be32 spi; + __u16 family; + __u8 proto; +}; + +struct xfrm_aevent_id { + struct xfrm_usersa_id sa_id; + xfrm_address_t saddr; + __u32 flags; + __u32 reqid; +}; + +struct xfrm_userspi_info { + struct xfrm_usersa_info info; + __u32 min; + __u32 max; +}; + +struct xfrm_userpolicy_info { + struct xfrm_selector sel; + struct xfrm_lifetime_cfg lft; + struct xfrm_lifetime_cur curlft; + __u32 priority; + __u32 index; + __u8 dir; + __u8 action; +#define XFRM_POLICY_ALLOW 0 +#define XFRM_POLICY_BLOCK 1 + __u8 flags; +#define XFRM_POLICY_LOCALOK 1 /* Allow user to override global policy */ + /* Automatically expand selector to include matching ICMP payloads. */ +#define XFRM_POLICY_ICMP 2 + __u8 share; +}; + +struct xfrm_userpolicy_id { + struct xfrm_selector sel; + __u32 index; + __u8 dir; +}; + +struct xfrm_user_acquire { + struct xfrm_id id; + xfrm_address_t saddr; + struct xfrm_selector sel; + struct xfrm_userpolicy_info policy; + __u32 aalgos; + __u32 ealgos; + __u32 calgos; + __u32 seq; +}; + +struct xfrm_user_expire { + struct xfrm_usersa_info state; + __u8 hard; +}; + +struct xfrm_user_polexpire { + struct xfrm_userpolicy_info pol; + __u8 hard; +}; + +struct xfrm_usersa_flush { + __u8 proto; +}; + +struct xfrm_user_report { + __u8 proto; + struct xfrm_selector sel; +}; + +/* Used by MIGRATE to pass addresses IKE should use to perform + * SA negotiation with the peer */ +struct xfrm_user_kmaddress { + xfrm_address_t local; + xfrm_address_t remote; + __u32 reserved; + __u16 family; +}; + +struct xfrm_user_migrate { + xfrm_address_t old_daddr; + xfrm_address_t old_saddr; + xfrm_address_t new_daddr; + xfrm_address_t new_saddr; + __u8 proto; + __u8 mode; + __u16 reserved; + __u32 reqid; + __u16 old_family; + __u16 new_family; +}; + +struct xfrm_user_mapping { + struct xfrm_usersa_id id; + __u32 reqid; + xfrm_address_t old_saddr; + xfrm_address_t new_saddr; + __be16 old_sport; + __be16 new_sport; +}; + +struct xfrm_address_filter { + xfrm_address_t saddr; + xfrm_address_t daddr; + __u16 family; + __u8 splen; + __u8 dplen; +}; + +struct xfrm_user_offload { + int ifindex; + __u8 flags; +}; +/* This flag was exposed without any kernel code that supports it. + * Unfortunately, strongswan has the code that sets this flag, + * which makes it impossible to reuse this bit. + * + * So leave it here to make sure that it won't be reused by mistake. + */ +#define XFRM_OFFLOAD_IPV6 1 +#define XFRM_OFFLOAD_INBOUND 2 +/* Two bits above are relevant for state path only, while + * offload is used for both policy and state flows. + * + * In policy offload mode, they are free and can be safely reused. + */ +#define XFRM_OFFLOAD_PACKET 4 + +struct xfrm_userpolicy_default { +#define XFRM_USERPOLICY_UNSPEC 0 +#define XFRM_USERPOLICY_BLOCK 1 +#define XFRM_USERPOLICY_ACCEPT 2 + __u8 in; + __u8 fwd; + __u8 out; +}; + +/* backwards compatibility for userspace */ +#define XFRMGRP_ACQUIRE 1 +#define XFRMGRP_EXPIRE 2 +#define XFRMGRP_SA 4 +#define XFRMGRP_POLICY 8 +#define XFRMGRP_REPORT 0x20 + +enum xfrm_nlgroups { + XFRMNLGRP_NONE, +#define XFRMNLGRP_NONE XFRMNLGRP_NONE + XFRMNLGRP_ACQUIRE, +#define XFRMNLGRP_ACQUIRE XFRMNLGRP_ACQUIRE + XFRMNLGRP_EXPIRE, +#define XFRMNLGRP_EXPIRE XFRMNLGRP_EXPIRE + XFRMNLGRP_SA, +#define XFRMNLGRP_SA XFRMNLGRP_SA + XFRMNLGRP_POLICY, +#define XFRMNLGRP_POLICY XFRMNLGRP_POLICY + XFRMNLGRP_AEVENTS, +#define XFRMNLGRP_AEVENTS XFRMNLGRP_AEVENTS + XFRMNLGRP_REPORT, +#define XFRMNLGRP_REPORT XFRMNLGRP_REPORT + XFRMNLGRP_MIGRATE, +#define XFRMNLGRP_MIGRATE XFRMNLGRP_MIGRATE + XFRMNLGRP_MAPPING, +#define XFRMNLGRP_MAPPING XFRMNLGRP_MAPPING + __XFRMNLGRP_MAX +}; +#define XFRMNLGRP_MAX (__XFRMNLGRP_MAX - 1) + +#endif /* _LINUX_XFRM_H */ diff --git a/include/linux/if.h b/include/linux/if.h deleted file mode 100644 index 238cf43..0000000 --- a/include/linux/if.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Global definitions for the INET interface module. - * - * Version: @(#)if.h 1.0.2 04/18/93 - * - * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988 - * Ross Biro - * Fred N. van Kempen, - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _LINUX_IF_H -#define _LINUX_IF_H - -#define IFNAMSIZ 16 -#define IFALIASZ 256 - -/* Standard interface flags (netdevice->flags). */ -#define IFF_UP 0x1 /* interface is up */ -#define IFF_BROADCAST 0x2 /* broadcast address valid */ -#define IFF_DEBUG 0x4 /* turn on debugging */ -#define IFF_LOOPBACK 0x8 /* is a loopback net */ -#define IFF_POINTOPOINT 0x10 /* interface is has p-p link */ -#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */ -#define IFF_RUNNING 0x40 /* interface RFC2863 OPER_UP */ -#define IFF_NOARP 0x80 /* no ARP protocol */ -#define IFF_PROMISC 0x100 /* receive all packets */ -#define IFF_ALLMULTI 0x200 /* receive all multicast packets*/ - -#define IFF_MASTER 0x400 /* master of a load balancer */ -#define IFF_SLAVE 0x800 /* slave of a load balancer */ - -#define IFF_MULTICAST 0x1000 /* Supports multicast */ - -#define IFF_PORTSEL 0x2000 /* can set media type */ -#define IFF_AUTOMEDIA 0x4000 /* auto media select active */ -#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/ - -#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ -#define IFF_DORMANT 0x20000 /* driver signals dormant */ - -#define IFF_ECHO 0x40000 /* echo sent packets */ - -#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\ - IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT) - -/* Private (from user) interface flags (netdevice->priv_flags). */ -#define IFF_802_1Q_VLAN 0x1 /* 802.1Q VLAN device. */ -#define IFF_EBRIDGE 0x2 /* Ethernet bridging device. */ -#define IFF_SLAVE_INACTIVE 0x4 /* bonding slave not the curr. active */ -#define IFF_MASTER_8023AD 0x8 /* bonding master, 802.3ad. */ -#define IFF_MASTER_ALB 0x10 /* bonding master, balance-alb. */ -#define IFF_BONDING 0x20 /* bonding master or slave */ -#define IFF_SLAVE_NEEDARP 0x40 /* need ARPs for validation */ -#define IFF_ISATAP 0x80 /* ISATAP interface (RFC4214) */ -#define IFF_MASTER_ARPMON 0x100 /* bonding master, ARP mon in use */ -#define IFF_WAN_HDLC 0x200 /* WAN HDLC device */ -#define IFF_XMIT_DST_RELEASE 0x400 /* dev_hard_start_xmit() is allowed to - * release skb->dst - */ -#define IFF_DONT_BRIDGE 0x800 /* disallow bridging this ether dev */ -#define IFF_IN_NETPOLL 0x1000 /* whether we are processing netpoll */ -#define IFF_DISABLE_NETPOLL 0x2000 /* disable netpoll at run-time */ -#define IFF_MACVLAN_PORT 0x4000 /* device used as macvlan port */ -#define IFF_BRIDGE_PORT 0x8000 /* device used as bridge port */ -#define IFF_OVS_DATAPATH 0x10000 /* device used as Open vSwitch - * datapath port */ - -#define IF_GET_IFACE 0x0001 /* for querying only */ -#define IF_GET_PROTO 0x0002 - -/* For definitions see hdlc.h */ -#define IF_IFACE_V35 0x1000 /* V.35 serial interface */ -#define IF_IFACE_V24 0x1001 /* V.24 serial interface */ -#define IF_IFACE_X21 0x1002 /* X.21 serial interface */ -#define IF_IFACE_T1 0x1003 /* T1 telco serial interface */ -#define IF_IFACE_E1 0x1004 /* E1 telco serial interface */ -#define IF_IFACE_SYNC_SERIAL 0x1005 /* can't be set by software */ -#define IF_IFACE_X21D 0x1006 /* X.21 Dual Clocking (FarSite) */ - -/* For definitions see hdlc.h */ -#define IF_PROTO_HDLC 0x2000 /* raw HDLC protocol */ -#define IF_PROTO_PPP 0x2001 /* PPP protocol */ -#define IF_PROTO_CISCO 0x2002 /* Cisco HDLC protocol */ -#define IF_PROTO_FR 0x2003 /* Frame Relay protocol */ -#define IF_PROTO_FR_ADD_PVC 0x2004 /* Create FR PVC */ -#define IF_PROTO_FR_DEL_PVC 0x2005 /* Delete FR PVC */ -#define IF_PROTO_X25 0x2006 /* X.25 */ -#define IF_PROTO_HDLC_ETH 0x2007 /* raw HDLC, Ethernet emulation */ -#define IF_PROTO_FR_ADD_ETH_PVC 0x2008 /* Create FR Ethernet-bridged PVC */ -#define IF_PROTO_FR_DEL_ETH_PVC 0x2009 /* Delete FR Ethernet-bridged PVC */ -#define IF_PROTO_FR_PVC 0x200A /* for reading PVC status */ -#define IF_PROTO_FR_ETH_PVC 0x200B -#define IF_PROTO_RAW 0x200C /* RAW Socket */ - -/* RFC 2863 operational status */ -enum { - IF_OPER_UNKNOWN, - IF_OPER_NOTPRESENT, - IF_OPER_DOWN, - IF_OPER_LOWERLAYERDOWN, - IF_OPER_TESTING, - IF_OPER_DORMANT, - IF_OPER_UP, -}; - -/* link modes */ -enum { - IF_LINK_MODE_DEFAULT, - IF_LINK_MODE_DORMANT, /* limit upward transition to dormant */ -}; - -/* carrier state */ -enum { - IF_CARRIER_DOWN, - IF_CARRIER_UP -}; - -/* - * Device mapping structure. I'd just gone off and designed a - * beautiful scheme using only loadable modules with arguments - * for driver options and along come the PCMCIA people 8) - * - * Ah well. The get() side of this is good for WDSETUP, and it'll - * be handy for debugging things. The set side is fine for now and - * being very small might be worth keeping for clean configuration. - */ - -struct ifmap { - unsigned long mem_start; - unsigned long mem_end; - unsigned short base_addr; - unsigned char irq; - unsigned char dma; - unsigned char port; - /* 3 bytes spare */ -}; - -#endif /* _LINUX_IF_H */ diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h deleted file mode 100644 index 5db2975..0000000 --- a/include/linux/if_bridge.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Linux ethernet bridge - * - * Authors: - * Lennert Buytenhek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#ifndef _UAPI_LINUX_IF_BRIDGE_H -#define _UAPI_LINUX_IF_BRIDGE_H - -#include - -#define SYSFS_BRIDGE_ATTR "bridge" -#define SYSFS_BRIDGE_FDB "brforward" -#define SYSFS_BRIDGE_PORT_SUBDIR "brif" -#define SYSFS_BRIDGE_PORT_ATTR "brport" -#define SYSFS_BRIDGE_PORT_LINK "bridge" - -#define BRCTL_VERSION 1 - -#define BRCTL_GET_VERSION 0 -#define BRCTL_GET_BRIDGES 1 -#define BRCTL_ADD_BRIDGE 2 -#define BRCTL_DEL_BRIDGE 3 -#define BRCTL_ADD_IF 4 -#define BRCTL_DEL_IF 5 -#define BRCTL_GET_BRIDGE_INFO 6 -#define BRCTL_GET_PORT_LIST 7 -#define BRCTL_SET_BRIDGE_FORWARD_DELAY 8 -#define BRCTL_SET_BRIDGE_HELLO_TIME 9 -#define BRCTL_SET_BRIDGE_MAX_AGE 10 -#define BRCTL_SET_AGEING_TIME 11 -#define BRCTL_SET_GC_INTERVAL 12 -#define BRCTL_GET_PORT_INFO 13 -#define BRCTL_SET_BRIDGE_STP_STATE 14 -#define BRCTL_SET_BRIDGE_PRIORITY 15 -#define BRCTL_SET_PORT_PRIORITY 16 -#define BRCTL_SET_PATH_COST 17 -#define BRCTL_GET_FDB_ENTRIES 18 - -#define BR_STATE_DISABLED 0 -#define BR_STATE_LISTENING 1 -#define BR_STATE_LEARNING 2 -#define BR_STATE_FORWARDING 3 -#define BR_STATE_BLOCKING 4 - -struct __bridge_info { - __u64 designated_root; - __u64 bridge_id; - __u32 root_path_cost; - __u32 max_age; - __u32 hello_time; - __u32 forward_delay; - __u32 bridge_max_age; - __u32 bridge_hello_time; - __u32 bridge_forward_delay; - __u8 topology_change; - __u8 topology_change_detected; - __u8 root_port; - __u8 stp_enabled; - __u32 ageing_time; - __u32 gc_interval; - __u32 hello_timer_value; - __u32 tcn_timer_value; - __u32 topology_change_timer_value; - __u32 gc_timer_value; -}; - -struct __port_info { - __u64 designated_root; - __u64 designated_bridge; - __u16 port_id; - __u16 designated_port; - __u32 path_cost; - __u32 designated_cost; - __u8 state; - __u8 top_change_ack; - __u8 config_pending; - __u8 unused0; - __u32 message_age_timer_value; - __u32 forward_delay_timer_value; - __u32 hold_timer_value; -}; - -struct __fdb_entry { - __u8 mac_addr[6]; - __u8 port_no; - __u8 is_local; - __u32 ageing_timer_value; - __u8 port_hi; - __u8 pad0; - __u16 unused; -}; - -/* Bridge Flags */ -#define BRIDGE_FLAGS_MASTER 1 /* Bridge command to/from master */ -#define BRIDGE_FLAGS_SELF 2 /* Bridge command to/from lowerdev */ - -#define BRIDGE_MODE_VEB 0 /* Default loopback mode */ -#define BRIDGE_MODE_VEPA 1 /* 802.1Qbg defined VEPA mode */ - -/* Bridge management nested attributes - * [IFLA_AF_SPEC] = { - * [IFLA_BRIDGE_FLAGS] - * [IFLA_BRIDGE_MODE] - * } - */ -enum { - IFLA_BRIDGE_FLAGS, - IFLA_BRIDGE_MODE, - __IFLA_BRIDGE_MAX, -}; -#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1) - -/* Bridge multicast database attributes - * [MDBA_MDB] = { - * [MDBA_MDB_ENTRY] = { - * [MDBA_MDB_ENTRY_INFO] - * } - * } - * [MDBA_ROUTER] = { - * [MDBA_ROUTER_PORT] - * } - */ -enum { - MDBA_UNSPEC, - MDBA_MDB, - MDBA_ROUTER, - __MDBA_MAX, -}; -#define MDBA_MAX (__MDBA_MAX - 1) - -enum { - MDBA_MDB_UNSPEC, - MDBA_MDB_ENTRY, - __MDBA_MDB_MAX, -}; -#define MDBA_MDB_MAX (__MDBA_MDB_MAX - 1) - -enum { - MDBA_MDB_ENTRY_UNSPEC, - MDBA_MDB_ENTRY_INFO, - __MDBA_MDB_ENTRY_MAX, -}; -#define MDBA_MDB_ENTRY_MAX (__MDBA_MDB_ENTRY_MAX - 1) - -enum { - MDBA_ROUTER_UNSPEC, - MDBA_ROUTER_PORT, - __MDBA_ROUTER_MAX, -}; -#define MDBA_ROUTER_MAX (__MDBA_ROUTER_MAX - 1) - -struct br_port_msg { - __u8 family; - __u32 ifindex; -}; - -struct br_mdb_entry { - __u32 ifindex; -#define MDB_TEMPORARY 0 -#define MDB_PERMANENT 1 - __u8 state; - struct { - union { - __be32 ip4; - struct in6_addr ip6; - } u; - __be16 proto; - } addr; -}; - -enum { - MDBA_SET_ENTRY_UNSPEC, - MDBA_SET_ENTRY, - __MDBA_SET_ENTRY_MAX, -}; -#define MDBA_SET_ENTRY_MAX (__MDBA_SET_ENTRY_MAX - 1) - -#endif /* _UAPI_LINUX_IF_BRIDGE_H */ diff --git a/include/linux/if_link.h b/include/linux/if_link.h deleted file mode 100644 index 73ee05c..0000000 --- a/include/linux/if_link.h +++ /dev/null @@ -1,446 +0,0 @@ -#ifndef _UAPI_LINUX_IF_LINK_H -#define _UAPI_LINUX_IF_LINK_H - -#include -#include - -/* This struct should be in sync with struct rtnl_link_stats64 */ -struct rtnl_link_stats { - __u32 rx_packets; /* total packets received */ - __u32 tx_packets; /* total packets transmitted */ - __u32 rx_bytes; /* total bytes received */ - __u32 tx_bytes; /* total bytes transmitted */ - __u32 rx_errors; /* bad packets received */ - __u32 tx_errors; /* packet transmit problems */ - __u32 rx_dropped; /* no space in linux buffers */ - __u32 tx_dropped; /* no space available in linux */ - __u32 multicast; /* multicast packets received */ - __u32 collisions; - - /* detailed rx_errors: */ - __u32 rx_length_errors; - __u32 rx_over_errors; /* receiver ring buff overflow */ - __u32 rx_crc_errors; /* recved pkt with crc error */ - __u32 rx_frame_errors; /* recv'd frame alignment error */ - __u32 rx_fifo_errors; /* recv'r fifo overrun */ - __u32 rx_missed_errors; /* receiver missed packet */ - - /* detailed tx_errors */ - __u32 tx_aborted_errors; - __u32 tx_carrier_errors; - __u32 tx_fifo_errors; - __u32 tx_heartbeat_errors; - __u32 tx_window_errors; - - /* for cslip etc */ - __u32 rx_compressed; - __u32 tx_compressed; -}; - -/* The main device statistics structure */ -struct rtnl_link_stats64 { - __u64 rx_packets; /* total packets received */ - __u64 tx_packets; /* total packets transmitted */ - __u64 rx_bytes; /* total bytes received */ - __u64 tx_bytes; /* total bytes transmitted */ - __u64 rx_errors; /* bad packets received */ - __u64 tx_errors; /* packet transmit problems */ - __u64 rx_dropped; /* no space in linux buffers */ - __u64 tx_dropped; /* no space available in linux */ - __u64 multicast; /* multicast packets received */ - __u64 collisions; - - /* detailed rx_errors: */ - __u64 rx_length_errors; - __u64 rx_over_errors; /* receiver ring buff overflow */ - __u64 rx_crc_errors; /* recved pkt with crc error */ - __u64 rx_frame_errors; /* recv'd frame alignment error */ - __u64 rx_fifo_errors; /* recv'r fifo overrun */ - __u64 rx_missed_errors; /* receiver missed packet */ - - /* detailed tx_errors */ - __u64 tx_aborted_errors; - __u64 tx_carrier_errors; - __u64 tx_fifo_errors; - __u64 tx_heartbeat_errors; - __u64 tx_window_errors; - - /* for cslip etc */ - __u64 rx_compressed; - __u64 tx_compressed; -}; - -/* The struct should be in sync with struct ifmap */ -struct rtnl_link_ifmap { - __u64 mem_start; - __u64 mem_end; - __u64 base_addr; - __u16 irq; - __u8 dma; - __u8 port; -}; - -/* - * IFLA_AF_SPEC - * Contains nested attributes for address family specific attributes. - * Each address family may create a attribute with the address family - * number as type and create its own attribute structure in it. - * - * Example: - * [IFLA_AF_SPEC] = { - * [AF_INET] = { - * [IFLA_INET_CONF] = ..., - * }, - * [AF_INET6] = { - * [IFLA_INET6_FLAGS] = ..., - * [IFLA_INET6_CONF] = ..., - * } - * } - */ - -enum { - IFLA_UNSPEC, - IFLA_ADDRESS, - IFLA_BROADCAST, - IFLA_IFNAME, - IFLA_MTU, - IFLA_LINK, - IFLA_QDISC, - IFLA_STATS, - IFLA_COST, -#define IFLA_COST IFLA_COST - IFLA_PRIORITY, -#define IFLA_PRIORITY IFLA_PRIORITY - IFLA_MASTER, -#define IFLA_MASTER IFLA_MASTER - IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */ -#define IFLA_WIRELESS IFLA_WIRELESS - IFLA_PROTINFO, /* Protocol specific information for a link */ -#define IFLA_PROTINFO IFLA_PROTINFO - IFLA_TXQLEN, -#define IFLA_TXQLEN IFLA_TXQLEN - IFLA_MAP, -#define IFLA_MAP IFLA_MAP - IFLA_WEIGHT, -#define IFLA_WEIGHT IFLA_WEIGHT - IFLA_OPERSTATE, - IFLA_LINKMODE, - IFLA_LINKINFO, -#define IFLA_LINKINFO IFLA_LINKINFO - IFLA_NET_NS_PID, - IFLA_IFALIAS, - IFLA_NUM_VF, /* Number of VFs if device is SR-IOV PF */ - IFLA_VFINFO_LIST, - IFLA_STATS64, - IFLA_VF_PORTS, - IFLA_PORT_SELF, - IFLA_AF_SPEC, - IFLA_GROUP, /* Group the device belongs to */ - IFLA_NET_NS_FD, - IFLA_EXT_MASK, /* Extended info mask, VFs, etc */ - IFLA_PROMISCUITY, /* Promiscuity count: > 0 means acts PROMISC */ -#define IFLA_PROMISCUITY IFLA_PROMISCUITY - IFLA_NUM_TX_QUEUES, - IFLA_NUM_RX_QUEUES, - IFLA_CARRIER, - __IFLA_MAX -}; - - -#define IFLA_MAX (__IFLA_MAX - 1) - -enum { - IFLA_INET_UNSPEC, - IFLA_INET_CONF, - __IFLA_INET_MAX, -}; - -#define IFLA_INET_MAX (__IFLA_INET_MAX - 1) - -/* ifi_flags. - - IFF_* flags. - - The only change is: - IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are - more not changeable by user. They describe link media - characteristics and set by device driver. - - Comments: - - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid - - If neither of these three flags are set; - the interface is NBMA. - - - IFF_MULTICAST does not mean anything special: - multicasts can be used on all not-NBMA links. - IFF_MULTICAST means that this media uses special encapsulation - for multicast frames. Apparently, all IFF_POINTOPOINT and - IFF_BROADCAST devices are able to use multicasts too. - */ - -/* IFLA_LINK. - For usual devices it is equal ifi_index. - If it is a "virtual interface" (f.e. tunnel), ifi_link - can point to real physical interface (f.e. for bandwidth calculations), - or maybe 0, what means, that real media is unknown (usual - for IPIP tunnels, when route to endpoint is allowed to change) - */ - -/* Subtype attributes for IFLA_PROTINFO */ -enum { - IFLA_INET6_UNSPEC, - IFLA_INET6_FLAGS, /* link flags */ - IFLA_INET6_CONF, /* sysctl parameters */ - IFLA_INET6_STATS, /* statistics */ - IFLA_INET6_MCAST, /* MC things. What of them? */ - IFLA_INET6_CACHEINFO, /* time values and max reasm size */ - IFLA_INET6_ICMP6STATS, /* statistics (icmpv6) */ - __IFLA_INET6_MAX -}; - -#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) - -enum { - BRIDGE_MODE_UNSPEC, - BRIDGE_MODE_HAIRPIN, -}; - -enum { - IFLA_BRPORT_UNSPEC, - IFLA_BRPORT_STATE, /* Spanning tree state */ - IFLA_BRPORT_PRIORITY, /* " priority */ - IFLA_BRPORT_COST, /* " cost */ - IFLA_BRPORT_MODE, /* mode (hairpin) */ - IFLA_BRPORT_GUARD, /* bpdu guard */ - IFLA_BRPORT_PROTECT, /* root port protection */ - IFLA_BRPORT_FAST_LEAVE, /* multicast fast leave */ - __IFLA_BRPORT_MAX -}; -#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) - -struct ifla_cacheinfo { - __u32 max_reasm_len; - __u32 tstamp; /* ipv6InterfaceTable updated timestamp */ - __u32 reachable_time; - __u32 retrans_time; -}; - -enum { - IFLA_INFO_UNSPEC, - IFLA_INFO_KIND, - IFLA_INFO_DATA, - IFLA_INFO_XSTATS, - __IFLA_INFO_MAX, -}; - -#define IFLA_INFO_MAX (__IFLA_INFO_MAX - 1) - -/* VLAN section */ - -enum { - IFLA_VLAN_UNSPEC, - IFLA_VLAN_ID, - IFLA_VLAN_FLAGS, - IFLA_VLAN_EGRESS_QOS, - IFLA_VLAN_INGRESS_QOS, - __IFLA_VLAN_MAX, -}; - -#define IFLA_VLAN_MAX (__IFLA_VLAN_MAX - 1) - -struct ifla_vlan_flags { - __u32 flags; - __u32 mask; -}; - -enum { - IFLA_VLAN_QOS_UNSPEC, - IFLA_VLAN_QOS_MAPPING, - __IFLA_VLAN_QOS_MAX -}; - -#define IFLA_VLAN_QOS_MAX (__IFLA_VLAN_QOS_MAX - 1) - -struct ifla_vlan_qos_mapping { - __u32 from; - __u32 to; -}; - -/* MACVLAN section */ -enum { - IFLA_MACVLAN_UNSPEC, - IFLA_MACVLAN_MODE, - IFLA_MACVLAN_FLAGS, - __IFLA_MACVLAN_MAX, -}; - -#define IFLA_MACVLAN_MAX (__IFLA_MACVLAN_MAX - 1) - -enum macvlan_mode { - MACVLAN_MODE_PRIVATE = 1, /* don't talk to other macvlans */ - MACVLAN_MODE_VEPA = 2, /* talk to other ports through ext bridge */ - MACVLAN_MODE_BRIDGE = 4, /* talk to bridge ports directly */ - MACVLAN_MODE_PASSTHRU = 8,/* take over the underlying device */ -}; - -#define MACVLAN_FLAG_NOPROMISC 1 - -/* VXLAN section */ -enum { - IFLA_VXLAN_UNSPEC, - IFLA_VXLAN_ID, - IFLA_VXLAN_GROUP, - IFLA_VXLAN_LINK, - IFLA_VXLAN_LOCAL, - IFLA_VXLAN_TTL, - IFLA_VXLAN_TOS, - IFLA_VXLAN_LEARNING, - IFLA_VXLAN_AGEING, - IFLA_VXLAN_LIMIT, - IFLA_VXLAN_PORT_RANGE, - IFLA_VXLAN_PROXY, - IFLA_VXLAN_RSC, - IFLA_VXLAN_L2MISS, - IFLA_VXLAN_L3MISS, - __IFLA_VXLAN_MAX -}; -#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) - -struct ifla_vxlan_port_range { - __be16 low; - __be16 high; -}; - -/* SR-IOV virtual function management section */ - -enum { - IFLA_VF_INFO_UNSPEC, - IFLA_VF_INFO, - __IFLA_VF_INFO_MAX, -}; - -#define IFLA_VF_INFO_MAX (__IFLA_VF_INFO_MAX - 1) - -enum { - IFLA_VF_UNSPEC, - IFLA_VF_MAC, /* Hardware queue specific attributes */ - IFLA_VF_VLAN, - IFLA_VF_TX_RATE, /* TX Bandwidth Allocation */ - IFLA_VF_SPOOFCHK, /* Spoof Checking on/off switch */ - __IFLA_VF_MAX, -}; - -#define IFLA_VF_MAX (__IFLA_VF_MAX - 1) - -struct ifla_vf_mac { - __u32 vf; - __u8 mac[32]; /* MAX_ADDR_LEN */ -}; - -struct ifla_vf_vlan { - __u32 vf; - __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */ - __u32 qos; -}; - -struct ifla_vf_tx_rate { - __u32 vf; - __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */ -}; - -struct ifla_vf_spoofchk { - __u32 vf; - __u32 setting; -}; - -/* VF ports management section - * - * Nested layout of set/get msg is: - * - * [IFLA_NUM_VF] - * [IFLA_VF_PORTS] - * [IFLA_VF_PORT] - * [IFLA_PORT_*], ... - * [IFLA_VF_PORT] - * [IFLA_PORT_*], ... - * ... - * [IFLA_PORT_SELF] - * [IFLA_PORT_*], ... - */ - -enum { - IFLA_VF_PORT_UNSPEC, - IFLA_VF_PORT, /* nest */ - __IFLA_VF_PORT_MAX, -}; - -#define IFLA_VF_PORT_MAX (__IFLA_VF_PORT_MAX - 1) - -enum { - IFLA_PORT_UNSPEC, - IFLA_PORT_VF, /* __u32 */ - IFLA_PORT_PROFILE, /* string */ - IFLA_PORT_VSI_TYPE, /* 802.1Qbg (pre-)standard VDP */ - IFLA_PORT_INSTANCE_UUID, /* binary UUID */ - IFLA_PORT_HOST_UUID, /* binary UUID */ - IFLA_PORT_REQUEST, /* __u8 */ - IFLA_PORT_RESPONSE, /* __u16, output only */ - __IFLA_PORT_MAX, -}; - -#define IFLA_PORT_MAX (__IFLA_PORT_MAX - 1) - -#define PORT_PROFILE_MAX 40 -#define PORT_UUID_MAX 16 -#define PORT_SELF_VF -1 - -enum { - PORT_REQUEST_PREASSOCIATE = 0, - PORT_REQUEST_PREASSOCIATE_RR, - PORT_REQUEST_ASSOCIATE, - PORT_REQUEST_DISASSOCIATE, -}; - -enum { - PORT_VDP_RESPONSE_SUCCESS = 0, - PORT_VDP_RESPONSE_INVALID_FORMAT, - PORT_VDP_RESPONSE_INSUFFICIENT_RESOURCES, - PORT_VDP_RESPONSE_UNUSED_VTID, - PORT_VDP_RESPONSE_VTID_VIOLATION, - PORT_VDP_RESPONSE_VTID_VERSION_VIOALTION, - PORT_VDP_RESPONSE_OUT_OF_SYNC, - /* 0x08-0xFF reserved for future VDP use */ - PORT_PROFILE_RESPONSE_SUCCESS = 0x100, - PORT_PROFILE_RESPONSE_INPROGRESS, - PORT_PROFILE_RESPONSE_INVALID, - PORT_PROFILE_RESPONSE_BADSTATE, - PORT_PROFILE_RESPONSE_INSUFFICIENT_RESOURCES, - PORT_PROFILE_RESPONSE_ERROR, -}; - -struct ifla_port_vsi { - __u8 vsi_mgr_id; - __u8 vsi_type_id[3]; - __u8 vsi_type_version; - __u8 pad[3]; -}; - - -/* IPoIB section */ - -enum { - IFLA_IPOIB_UNSPEC, - IFLA_IPOIB_PKEY, - IFLA_IPOIB_MODE, - IFLA_IPOIB_UMCAST, - __IFLA_IPOIB_MAX -}; - -enum { - IPOIB_MODE_DATAGRAM = 0, /* using unreliable datagram QPs */ - IPOIB_MODE_CONNECTED = 1, /* using connected QPs */ -}; - -#define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1) - -#endif /* _UAPI_LINUX_IF_LINK_H */ diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h deleted file mode 100644 index fd4d2df..0000000 --- a/include/linux/inetdevice.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef _LINUX_INETDEVICE_H -#define _LINUX_INETDEVICE_H - -enum -{ - IPV4_DEVCONF_FORWARDING=1, - IPV4_DEVCONF_MC_FORWARDING, - IPV4_DEVCONF_PROXY_ARP, - IPV4_DEVCONF_ACCEPT_REDIRECTS, - IPV4_DEVCONF_SECURE_REDIRECTS, - IPV4_DEVCONF_SEND_REDIRECTS, - IPV4_DEVCONF_SHARED_MEDIA, - IPV4_DEVCONF_RP_FILTER, - IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE, - IPV4_DEVCONF_BOOTP_RELAY, - IPV4_DEVCONF_LOG_MARTIANS, - IPV4_DEVCONF_TAG, - IPV4_DEVCONF_ARPFILTER, - IPV4_DEVCONF_MEDIUM_ID, - IPV4_DEVCONF_NOXFRM, - IPV4_DEVCONF_NOPOLICY, - IPV4_DEVCONF_FORCE_IGMP_VERSION, - IPV4_DEVCONF_ARP_ANNOUNCE, - IPV4_DEVCONF_ARP_IGNORE, - IPV4_DEVCONF_PROMOTE_SECONDARIES, - IPV4_DEVCONF_ARP_ACCEPT, - IPV4_DEVCONF_ARP_NOTIFY, - IPV4_DEVCONF_ACCEPT_LOCAL, - IPV4_DEVCONF_SRC_VMARK, - IPV4_DEVCONF_PROXY_ARP_PVLAN, - __IPV4_DEVCONF_MAX -}; - -#define IPV4_DEVCONF_MAX (__IPV4_DEVCONF_MAX - 1) - -#endif /* _LINUX_INETDEVICE_H */ diff --git a/include/linux/ip_mp_alg.h b/include/linux/ip_mp_alg.h deleted file mode 100644 index e234e20..0000000 --- a/include/linux/ip_mp_alg.h +++ /dev/null @@ -1,22 +0,0 @@ -/* ip_mp_alg.h: IPV4 multipath algorithm support, user-visible values. - * - * Copyright (C) 2004, 2005 Einar Lueck - * Copyright (C) 2005 David S. Miller - */ - -#ifndef _LINUX_IP_MP_ALG_H -#define _LINUX_IP_MP_ALG_H - -enum ip_mp_alg { - IP_MP_ALG_NONE, - IP_MP_ALG_RR, - IP_MP_ALG_DRR, - IP_MP_ALG_RANDOM, - IP_MP_ALG_WRANDOM, - __IP_MP_ALG_MAX -}; - -#define IP_MP_ALG_MAX (__IP_MP_ALG_MAX - 1) - -#endif /* _LINUX_IP_MP_ALG_H */ - diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h deleted file mode 100644 index 7999885..0000000 --- a/include/linux/netfilter.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef __LINUX_NETFILTER_H -#define __LINUX_NETFILTER_H - -#include - -/* Responses from hook functions. */ -#define NF_DROP 0 -#define NF_ACCEPT 1 -#define NF_STOLEN 2 -#define NF_QUEUE 3 -#define NF_REPEAT 4 -#define NF_STOP 5 -#define NF_MAX_VERDICT NF_STOP - -/* we overload the higher bits for encoding auxiliary data such as the queue - * number. Not nice, but better than additional function arguments. */ -#define NF_VERDICT_MASK 0x0000ffff -#define NF_VERDICT_BITS 16 - -#define NF_VERDICT_QMASK 0xffff0000 -#define NF_VERDICT_QBITS 16 - -#define NF_QUEUE_NR(x) ((((x) << NF_VERDICT_BITS) & NF_VERDICT_QMASK) | NF_QUEUE) - -/* Generic cache responses from hook functions. - <= 0x2000 is used for protocol-flags. */ -#define NFC_UNKNOWN 0x4000 -#define NFC_ALTERED 0x8000 - -enum nf_inet_hooks { - NF_INET_PRE_ROUTING, - NF_INET_LOCAL_IN, - NF_INET_FORWARD, - NF_INET_LOCAL_OUT, - NF_INET_POST_ROUTING, - NF_INET_NUMHOOKS -}; - -enum { - NFPROTO_UNSPEC = 0, - NFPROTO_IPV4 = 2, - NFPROTO_ARP = 3, - NFPROTO_BRIDGE = 7, - NFPROTO_IPV6 = 10, - NFPROTO_DECNET = 12, - NFPROTO_NUMPROTO, -}; - -union nf_inet_addr { - __u32 all[4]; - __be32 ip; - __be32 ip6[4]; - struct in_addr in; - struct in6_addr in6; -}; - -#endif /*__LINUX_NETFILTER_H*/ diff --git a/include/linux/netlink.h b/include/linux/netlink.h deleted file mode 100644 index 3925254..0000000 --- a/include/linux/netlink.h +++ /dev/null @@ -1,149 +0,0 @@ -#ifndef __LINUX_NETLINK_H -#define __LINUX_NETLINK_H - -#include /* for sa_family_t */ -#include - -#define NETLINK_ROUTE 0 /* Routing/device hook */ -#define NETLINK_UNUSED 1 /* Unused number */ -#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */ -#define NETLINK_FIREWALL 3 /* Firewalling hook */ -#define NETLINK_INET_DIAG 4 /* INET socket monitoring */ -#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */ -#define NETLINK_XFRM 6 /* ipsec */ -#define NETLINK_SELINUX 7 /* SELinux event notifications */ -#define NETLINK_ISCSI 8 /* Open-iSCSI */ -#define NETLINK_AUDIT 9 /* auditing */ -#define NETLINK_FIB_LOOKUP 10 -#define NETLINK_CONNECTOR 11 -#define NETLINK_NETFILTER 12 /* netfilter subsystem */ -#define NETLINK_IP6_FW 13 -#define NETLINK_DNRTMSG 14 /* DECnet routing messages */ -#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */ -#define NETLINK_GENERIC 16 -/* leave room for NETLINK_DM (DM Events) */ -#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */ -#define NETLINK_ECRYPTFS 19 -#define NETLINK_RDMA 20 - -#define MAX_LINKS 32 - -struct sockaddr_nl { - sa_family_t nl_family; /* AF_NETLINK */ - unsigned short nl_pad; /* zero */ - __u32 nl_pid; /* port ID */ - __u32 nl_groups; /* multicast groups mask */ -}; - -struct nlmsghdr { - __u32 nlmsg_len; /* Length of message including header */ - __u16 nlmsg_type; /* Message content */ - __u16 nlmsg_flags; /* Additional flags */ - __u32 nlmsg_seq; /* Sequence number */ - __u32 nlmsg_pid; /* Sending process port ID */ -}; - -/* Flags values */ - -#define NLM_F_REQUEST 1 /* It is request message. */ -#define NLM_F_MULTI 2 /* Multipart message, terminated by NLMSG_DONE */ -#define NLM_F_ACK 4 /* Reply with ack, with zero or error code */ -#define NLM_F_ECHO 8 /* Echo this request */ -#define NLM_F_DUMP_INTR 16 /* Dump was inconsistent due to sequence change */ - -/* Modifiers to GET request */ -#define NLM_F_ROOT 0x100 /* specify tree root */ -#define NLM_F_MATCH 0x200 /* return all matching */ -#define NLM_F_ATOMIC 0x400 /* atomic GET */ -#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH) - -/* Modifiers to NEW request */ -#define NLM_F_REPLACE 0x100 /* Override existing */ -#define NLM_F_EXCL 0x200 /* Do not touch, if it exists */ -#define NLM_F_CREATE 0x400 /* Create, if it does not exist */ -#define NLM_F_APPEND 0x800 /* Add to end of list */ - -/* - 4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL - 4.4BSD CHANGE NLM_F_REPLACE - - True CHANGE NLM_F_CREATE|NLM_F_REPLACE - Append NLM_F_CREATE - Check NLM_F_EXCL - */ - -#define NLMSG_ALIGNTO 4U -#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) ) -#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr))) -#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN)) -#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len)) -#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0))) -#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \ - (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len))) -#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \ - (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \ - (nlh)->nlmsg_len <= (len)) -#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len))) - -#define NLMSG_NOOP 0x1 /* Nothing. */ -#define NLMSG_ERROR 0x2 /* Error */ -#define NLMSG_DONE 0x3 /* End of a dump */ -#define NLMSG_OVERRUN 0x4 /* Data lost */ - -#define NLMSG_MIN_TYPE 0x10 /* < 0x10: reserved control messages */ - -struct nlmsgerr { - int error; - struct nlmsghdr msg; -}; - -#define NETLINK_ADD_MEMBERSHIP 1 -#define NETLINK_DROP_MEMBERSHIP 2 -#define NETLINK_PKTINFO 3 -#define NETLINK_BROADCAST_ERROR 4 -#define NETLINK_NO_ENOBUFS 5 - -struct nl_pktinfo { - __u32 group; -}; - -#define NET_MAJOR 36 /* Major 36 is reserved for networking */ - -enum { - NETLINK_UNCONNECTED = 0, - NETLINK_CONNECTED, -}; - -/* - * <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)--> - * +---------------------+- - -+- - - - - - - - - -+- - -+ - * | Header | Pad | Payload | Pad | - * | (struct nlattr) | ing | | ing | - * +---------------------+- - -+- - - - - - - - - -+- - -+ - * <-------------- nlattr->nla_len --------------> - */ - -struct nlattr { - __u16 nla_len; - __u16 nla_type; -}; - -/* - * nla_type (16 bits) - * +---+---+-------------------------------+ - * | N | O | Attribute Type | - * +---+---+-------------------------------+ - * N := Carries nested attributes - * O := Payload stored in network byte order - * - * Note: The N and O flag are mutually exclusive. - */ -#define NLA_F_NESTED (1 << 15) -#define NLA_F_NET_BYTEORDER (1 << 14) -#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER) - -#define NLA_ALIGNTO 4 -#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1)) -#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr))) - -#endif /* __LINUX_NETLINK_H */ diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h deleted file mode 100644 index defbde2..0000000 --- a/include/linux/pkt_cls.h +++ /dev/null @@ -1,467 +0,0 @@ -#ifndef __LINUX_PKT_CLS_H -#define __LINUX_PKT_CLS_H - -#include -#include - -/* I think i could have done better macros ; for now this is stolen from - * some arch/mips code - jhs -*/ -#define _TC_MAKE32(x) ((x)) - -#define _TC_MAKEMASK1(n) (_TC_MAKE32(1) << _TC_MAKE32(n)) -#define _TC_MAKEMASK(v,n) (_TC_MAKE32((_TC_MAKE32(1)<<(v))-1) << _TC_MAKE32(n)) -#define _TC_MAKEVALUE(v,n) (_TC_MAKE32(v) << _TC_MAKE32(n)) -#define _TC_GETVALUE(v,n,m) ((_TC_MAKE32(v) & _TC_MAKE32(m)) >> _TC_MAKE32(n)) - -/* verdict bit breakdown - * -bit 0: when set -> this packet has been munged already - -bit 1: when set -> It is ok to munge this packet - -bit 2,3,4,5: Reclassify counter - sort of reverse TTL - if exceeded -assume loop - -bit 6,7: Where this packet was last seen -0: Above the transmit example at the socket level -1: on the Ingress -2: on the Egress - -bit 8: when set --> Request not to classify on ingress. - -bits 9,10,11: redirect counter - redirect TTL. Loop avoidance - - * - * */ - -#define TC_MUNGED _TC_MAKEMASK1(0) -#define SET_TC_MUNGED(v) ( TC_MUNGED | (v & ~TC_MUNGED)) -#define CLR_TC_MUNGED(v) ( v & ~TC_MUNGED) - -#define TC_OK2MUNGE _TC_MAKEMASK1(1) -#define SET_TC_OK2MUNGE(v) ( TC_OK2MUNGE | (v & ~TC_OK2MUNGE)) -#define CLR_TC_OK2MUNGE(v) ( v & ~TC_OK2MUNGE) - -#define S_TC_VERD _TC_MAKE32(2) -#define M_TC_VERD _TC_MAKEMASK(4,S_TC_VERD) -#define G_TC_VERD(x) _TC_GETVALUE(x,S_TC_VERD,M_TC_VERD) -#define V_TC_VERD(x) _TC_MAKEVALUE(x,S_TC_VERD) -#define SET_TC_VERD(v,n) ((V_TC_VERD(n)) | (v & ~M_TC_VERD)) - -#define S_TC_FROM _TC_MAKE32(6) -#define M_TC_FROM _TC_MAKEMASK(2,S_TC_FROM) -#define G_TC_FROM(x) _TC_GETVALUE(x,S_TC_FROM,M_TC_FROM) -#define V_TC_FROM(x) _TC_MAKEVALUE(x,S_TC_FROM) -#define SET_TC_FROM(v,n) ((V_TC_FROM(n)) | (v & ~M_TC_FROM)) -#define AT_STACK 0x0 -#define AT_INGRESS 0x1 -#define AT_EGRESS 0x2 - -#define TC_NCLS _TC_MAKEMASK1(8) -#define SET_TC_NCLS(v) ( TC_NCLS | (v & ~TC_NCLS)) -#define CLR_TC_NCLS(v) ( v & ~TC_NCLS) - -#define S_TC_RTTL _TC_MAKE32(9) -#define M_TC_RTTL _TC_MAKEMASK(3,S_TC_RTTL) -#define G_TC_RTTL(x) _TC_GETVALUE(x,S_TC_RTTL,M_TC_RTTL) -#define V_TC_RTTL(x) _TC_MAKEVALUE(x,S_TC_RTTL) -#define SET_TC_RTTL(v,n) ((V_TC_RTTL(n)) | (v & ~M_TC_RTTL)) - -#define S_TC_AT _TC_MAKE32(12) -#define M_TC_AT _TC_MAKEMASK(2,S_TC_AT) -#define G_TC_AT(x) _TC_GETVALUE(x,S_TC_AT,M_TC_AT) -#define V_TC_AT(x) _TC_MAKEVALUE(x,S_TC_AT) -#define SET_TC_AT(v,n) ((V_TC_AT(n)) | (v & ~M_TC_AT)) - -/* Action attributes */ -enum { - TCA_ACT_UNSPEC, - TCA_ACT_KIND, - TCA_ACT_OPTIONS, - TCA_ACT_INDEX, - TCA_ACT_STATS, - __TCA_ACT_MAX -}; - -#define TCA_ACT_MAX __TCA_ACT_MAX -#define TCA_OLD_COMPAT (TCA_ACT_MAX+1) -#define TCA_ACT_MAX_PRIO 32 -#define TCA_ACT_BIND 1 -#define TCA_ACT_NOBIND 0 -#define TCA_ACT_UNBIND 1 -#define TCA_ACT_NOUNBIND 0 -#define TCA_ACT_REPLACE 1 -#define TCA_ACT_NOREPLACE 0 -#define MAX_REC_LOOP 4 -#define MAX_RED_LOOP 4 - -#define TC_ACT_UNSPEC (-1) -#define TC_ACT_OK 0 -#define TC_ACT_RECLASSIFY 1 -#define TC_ACT_SHOT 2 -#define TC_ACT_PIPE 3 -#define TC_ACT_STOLEN 4 -#define TC_ACT_QUEUED 5 -#define TC_ACT_REPEAT 6 -#define TC_ACT_JUMP 0x10000000 - -/* Action type identifiers*/ -enum { - TCA_ID_UNSPEC=0, - TCA_ID_POLICE=1, - /* other actions go here */ - __TCA_ID_MAX=255 -}; - -#define TCA_ID_MAX __TCA_ID_MAX - -struct tc_police { - __u32 index; - int action; -#define TC_POLICE_UNSPEC TC_ACT_UNSPEC -#define TC_POLICE_OK TC_ACT_OK -#define TC_POLICE_RECLASSIFY TC_ACT_RECLASSIFY -#define TC_POLICE_SHOT TC_ACT_SHOT -#define TC_POLICE_PIPE TC_ACT_PIPE - - __u32 limit; - __u32 burst; - __u32 mtu; - struct tc_ratespec rate; - struct tc_ratespec peakrate; - int refcnt; - int bindcnt; - __u32 capab; -}; - -struct tcf_t { - __u64 install; - __u64 lastuse; - __u64 expires; -}; - -struct tc_cnt { - int refcnt; - int bindcnt; -}; - -#define tc_gen \ - __u32 index; \ - __u32 capab; \ - int action; \ - int refcnt; \ - int bindcnt - -enum { - TCA_POLICE_UNSPEC, - TCA_POLICE_TBF, - TCA_POLICE_RATE, - TCA_POLICE_PEAKRATE, - TCA_POLICE_AVRATE, - TCA_POLICE_RESULT, - __TCA_POLICE_MAX -#define TCA_POLICE_RESULT TCA_POLICE_RESULT -}; - -#define TCA_POLICE_MAX (__TCA_POLICE_MAX - 1) - -/* U32 filters */ - -#define TC_U32_HTID(h) ((h)&0xFFF00000) -#define TC_U32_USERHTID(h) (TC_U32_HTID(h)>>20) -#define TC_U32_HASH(h) (((h)>>12)&0xFF) -#define TC_U32_NODE(h) ((h)&0xFFF) -#define TC_U32_KEY(h) ((h)&0xFFFFF) -#define TC_U32_UNSPEC 0 -#define TC_U32_ROOT (0xFFF00000) - -enum { - TCA_U32_UNSPEC, - TCA_U32_CLASSID, - TCA_U32_HASH, - TCA_U32_LINK, - TCA_U32_DIVISOR, - TCA_U32_SEL, - TCA_U32_POLICE, - TCA_U32_ACT, - TCA_U32_INDEV, - TCA_U32_PCNT, - TCA_U32_MARK, - __TCA_U32_MAX -}; - -#define TCA_U32_MAX (__TCA_U32_MAX - 1) - -struct tc_u32_key { - __be32 mask; - __be32 val; - int off; - int offmask; -}; - -struct tc_u32_sel { - unsigned char flags; - unsigned char offshift; - unsigned char nkeys; - - __be16 offmask; - __u16 off; - short offoff; - - short hoff; - __be32 hmask; - struct tc_u32_key keys[0]; -}; - -struct tc_u32_mark { - __u32 val; - __u32 mask; - __u32 success; -}; - -struct tc_u32_pcnt { - __u64 rcnt; - __u64 rhit; - __u64 kcnts[0]; -}; - -/* Flags */ - -#define TC_U32_TERMINAL 1 -#define TC_U32_OFFSET 2 -#define TC_U32_VAROFFSET 4 -#define TC_U32_EAT 8 - -#define TC_U32_MAXDEPTH 8 - - -/* RSVP filter */ - -enum { - TCA_RSVP_UNSPEC, - TCA_RSVP_CLASSID, - TCA_RSVP_DST, - TCA_RSVP_SRC, - TCA_RSVP_PINFO, - TCA_RSVP_POLICE, - TCA_RSVP_ACT, - __TCA_RSVP_MAX -}; - -#define TCA_RSVP_MAX (__TCA_RSVP_MAX - 1 ) - -struct tc_rsvp_gpi { - __u32 key; - __u32 mask; - int offset; -}; - -struct tc_rsvp_pinfo { - struct tc_rsvp_gpi dpi; - struct tc_rsvp_gpi spi; - __u8 protocol; - __u8 tunnelid; - __u8 tunnelhdr; - __u8 pad; -}; - -/* ROUTE filter */ - -enum { - TCA_ROUTE4_UNSPEC, - TCA_ROUTE4_CLASSID, - TCA_ROUTE4_TO, - TCA_ROUTE4_FROM, - TCA_ROUTE4_IIF, - TCA_ROUTE4_POLICE, - TCA_ROUTE4_ACT, - __TCA_ROUTE4_MAX -}; - -#define TCA_ROUTE4_MAX (__TCA_ROUTE4_MAX - 1) - - -/* FW filter */ - -enum { - TCA_FW_UNSPEC, - TCA_FW_CLASSID, - TCA_FW_POLICE, - TCA_FW_INDEV, /* used by CONFIG_NET_CLS_IND */ - TCA_FW_ACT, /* used by CONFIG_NET_CLS_ACT */ - TCA_FW_MASK, - __TCA_FW_MAX -}; - -#define TCA_FW_MAX (__TCA_FW_MAX - 1) - -/* TC index filter */ - -enum { - TCA_TCINDEX_UNSPEC, - TCA_TCINDEX_HASH, - TCA_TCINDEX_MASK, - TCA_TCINDEX_SHIFT, - TCA_TCINDEX_FALL_THROUGH, - TCA_TCINDEX_CLASSID, - TCA_TCINDEX_POLICE, - TCA_TCINDEX_ACT, - __TCA_TCINDEX_MAX -}; - -#define TCA_TCINDEX_MAX (__TCA_TCINDEX_MAX - 1) - -/* Flow filter */ - -enum { - FLOW_KEY_SRC, - FLOW_KEY_DST, - FLOW_KEY_PROTO, - FLOW_KEY_PROTO_SRC, - FLOW_KEY_PROTO_DST, - FLOW_KEY_IIF, - FLOW_KEY_PRIORITY, - FLOW_KEY_MARK, - FLOW_KEY_NFCT, - FLOW_KEY_NFCT_SRC, - FLOW_KEY_NFCT_DST, - FLOW_KEY_NFCT_PROTO_SRC, - FLOW_KEY_NFCT_PROTO_DST, - FLOW_KEY_RTCLASSID, - FLOW_KEY_SKUID, - FLOW_KEY_SKGID, - FLOW_KEY_VLAN_TAG, - FLOW_KEY_RXHASH, - __FLOW_KEY_MAX, -}; - -#define FLOW_KEY_MAX (__FLOW_KEY_MAX - 1) - -enum { - FLOW_MODE_MAP, - FLOW_MODE_HASH, -}; - -enum { - TCA_FLOW_UNSPEC, - TCA_FLOW_KEYS, - TCA_FLOW_MODE, - TCA_FLOW_BASECLASS, - TCA_FLOW_RSHIFT, - TCA_FLOW_ADDEND, - TCA_FLOW_MASK, - TCA_FLOW_XOR, - TCA_FLOW_DIVISOR, - TCA_FLOW_ACT, - TCA_FLOW_POLICE, - TCA_FLOW_EMATCHES, - TCA_FLOW_PERTURB, - __TCA_FLOW_MAX -}; - -#define TCA_FLOW_MAX (__TCA_FLOW_MAX - 1) - -/* Basic filter */ - -enum { - TCA_BASIC_UNSPEC, - TCA_BASIC_CLASSID, - TCA_BASIC_EMATCHES, - TCA_BASIC_ACT, - TCA_BASIC_POLICE, - __TCA_BASIC_MAX -}; - -#define TCA_BASIC_MAX (__TCA_BASIC_MAX - 1) - - -/* Cgroup classifier */ - -enum { - TCA_CGROUP_UNSPEC, - TCA_CGROUP_ACT, - TCA_CGROUP_POLICE, - TCA_CGROUP_EMATCHES, - __TCA_CGROUP_MAX, -}; - -#define TCA_CGROUP_MAX (__TCA_CGROUP_MAX - 1) - -/* Extended Matches */ - -struct tcf_ematch_tree_hdr { - __u16 nmatches; - __u16 progid; -}; - -enum { - TCA_EMATCH_TREE_UNSPEC, - TCA_EMATCH_TREE_HDR, - TCA_EMATCH_TREE_LIST, - __TCA_EMATCH_TREE_MAX -}; -#define TCA_EMATCH_TREE_MAX (__TCA_EMATCH_TREE_MAX - 1) - -struct tcf_ematch_hdr { - __u16 matchid; - __u16 kind; - __u16 flags; - __u16 pad; /* currently unused */ -}; - -/* 0 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +-----------------------+-+-+---+ - * | Unused |S|I| R | - * +-----------------------+-+-+---+ - * - * R(2) ::= relation to next ematch - * where: 0 0 END (last ematch) - * 0 1 AND - * 1 0 OR - * 1 1 Unused (invalid) - * I(1) ::= invert result - * S(1) ::= simple payload - */ -#define TCF_EM_REL_END 0 -#define TCF_EM_REL_AND (1<<0) -#define TCF_EM_REL_OR (1<<1) -#define TCF_EM_INVERT (1<<2) -#define TCF_EM_SIMPLE (1<<3) - -#define TCF_EM_REL_MASK 3 -#define TCF_EM_REL_VALID(v) (((v) & TCF_EM_REL_MASK) != TCF_EM_REL_MASK) - -enum { - TCF_LAYER_LINK, - TCF_LAYER_NETWORK, - TCF_LAYER_TRANSPORT, - __TCF_LAYER_MAX -}; -#define TCF_LAYER_MAX (__TCF_LAYER_MAX - 1) - -/* Ematch type assignments - * 1..32767 Reserved for ematches inside kernel tree - * 32768..65535 Free to use, not reliable - */ -#define TCF_EM_CONTAINER 0 -#define TCF_EM_CMP 1 -#define TCF_EM_NBYTE 2 -#define TCF_EM_U32 3 -#define TCF_EM_META 4 -#define TCF_EM_TEXT 5 -#define TCF_EM_VLAN 6 -#define TCF_EM_MAX 6 - -enum { - TCF_EM_PROG_TC -}; - -enum { - TCF_EM_OPND_EQ, - TCF_EM_OPND_GT, - TCF_EM_OPND_LT -}; - -#endif diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h deleted file mode 100644 index 7ccc1fd..0000000 --- a/include/linux/pkt_sched.h +++ /dev/null @@ -1,627 +0,0 @@ -#ifndef __LINUX_PKT_SCHED_H -#define __LINUX_PKT_SCHED_H - -#include - -/* Logical priority bands not depending on specific packet scheduler. - Every scheduler will map them to real traffic classes, if it has - no more precise mechanism to classify packets. - - These numbers have no special meaning, though their coincidence - with obsolete IPv6 values is not occasional :-). New IPv6 drafts - preferred full anarchy inspired by diffserv group. - - Note: TC_PRIO_BESTEFFORT does not mean that it is the most unhappy - class, actually, as rule it will be handled with more care than - filler or even bulk. - */ - -#define TC_PRIO_BESTEFFORT 0 -#define TC_PRIO_FILLER 1 -#define TC_PRIO_BULK 2 -#define TC_PRIO_INTERACTIVE_BULK 4 -#define TC_PRIO_INTERACTIVE 6 -#define TC_PRIO_CONTROL 7 - -#define TC_PRIO_MAX 15 - -/* Generic queue statistics, available for all the elements. - Particular schedulers may have also their private records. - */ - -struct tc_stats { - __u64 bytes; /* NUmber of enqueues bytes */ - __u32 packets; /* Number of enqueued packets */ - __u32 drops; /* Packets dropped because of lack of resources */ - __u32 overlimits; /* Number of throttle events when this - * flow goes out of allocated bandwidth */ - __u32 bps; /* Current flow byte rate */ - __u32 pps; /* Current flow packet rate */ - __u32 qlen; - __u32 backlog; -}; - -struct tc_estimator { - signed char interval; - unsigned char ewma_log; -}; - -/* "Handles" - --------- - - All the traffic control objects have 32bit identifiers, or "handles". - - They can be considered as opaque numbers from user API viewpoint, - but actually they always consist of two fields: major and - minor numbers, which are interpreted by kernel specially, - that may be used by applications, though not recommended. - - F.e. qdisc handles always have minor number equal to zero, - classes (or flows) have major equal to parent qdisc major, and - minor uniquely identifying class inside qdisc. - - Macros to manipulate handles: - */ - -#define TC_H_MAJ_MASK (0xFFFF0000U) -#define TC_H_MIN_MASK (0x0000FFFFU) -#define TC_H_MAJ(h) ((h)&TC_H_MAJ_MASK) -#define TC_H_MIN(h) ((h)&TC_H_MIN_MASK) -#define TC_H_MAKE(maj,min) (((maj)&TC_H_MAJ_MASK)|((min)&TC_H_MIN_MASK)) - -#define TC_H_UNSPEC (0U) -#define TC_H_ROOT (0xFFFFFFFFU) -#define TC_H_INGRESS (0xFFFFFFF1U) - -struct tc_ratespec { - unsigned char cell_log; - unsigned char __reserved; - unsigned short overhead; - short cell_align; - unsigned short mpu; - __u32 rate; -}; - -#define TC_RTAB_SIZE 1024 - -struct tc_sizespec { - unsigned char cell_log; - unsigned char size_log; - short cell_align; - int overhead; - unsigned int linklayer; - unsigned int mpu; - unsigned int mtu; - unsigned int tsize; -}; - -enum { - TCA_STAB_UNSPEC, - TCA_STAB_BASE, - TCA_STAB_DATA, - __TCA_STAB_MAX -}; - -#define TCA_STAB_MAX (__TCA_STAB_MAX - 1) - -/* FIFO section */ - -struct tc_fifo_qopt { - __u32 limit; /* Queue length: bytes for bfifo, packets for pfifo */ -}; - -/* PRIO section */ - -#define TCQ_PRIO_BANDS 16 -#define TCQ_MIN_PRIO_BANDS 2 - -struct tc_prio_qopt { - int bands; /* Number of bands */ - __u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */ -}; - -/* MULTIQ section */ - -struct tc_multiq_qopt { - __u16 bands; /* Number of bands */ - __u16 max_bands; /* Maximum number of queues */ -}; - -/* PLUG section */ - -#define TCQ_PLUG_BUFFER 0 -#define TCQ_PLUG_RELEASE_ONE 1 -#define TCQ_PLUG_RELEASE_INDEFINITE 2 -#define TCQ_PLUG_LIMIT 3 - -struct tc_plug_qopt { - /* TCQ_PLUG_BUFFER: Inset a plug into the queue and - * buffer any incoming packets - * TCQ_PLUG_RELEASE_ONE: Dequeue packets from queue head - * to beginning of the next plug. - * TCQ_PLUG_RELEASE_INDEFINITE: Dequeue all packets from queue. - * Stop buffering packets until the next TCQ_PLUG_BUFFER - * command is received (just act as a pass-thru queue). - * TCQ_PLUG_LIMIT: Increase/decrease queue size - */ - int action; - __u32 limit; -}; - -/* TBF section */ - -struct tc_tbf_qopt { - struct tc_ratespec rate; - struct tc_ratespec peakrate; - __u32 limit; - __u32 buffer; - __u32 mtu; -}; - -enum { - TCA_TBF_UNSPEC, - TCA_TBF_PARMS, - TCA_TBF_RTAB, - TCA_TBF_PTAB, - __TCA_TBF_MAX, -}; - -#define TCA_TBF_MAX (__TCA_TBF_MAX - 1) - - -/* TEQL section */ - -/* TEQL does not require any parameters */ - -/* SFQ section */ - -struct tc_sfq_qopt { - unsigned quantum; /* Bytes per round allocated to flow */ - int perturb_period; /* Period of hash perturbation */ - __u32 limit; /* Maximal packets in queue */ - unsigned divisor; /* Hash divisor */ - unsigned flows; /* Maximal number of flows */ -}; - -struct tc_sfq_xstats { - __s32 allot; -}; - -/* - * NOTE: limit, divisor and flows are hardwired to code at the moment. - * - * limit=flows=128, divisor=1024; - * - * The only reason for this is efficiency, it is possible - * to change these parameters in compile time. - */ - -/* RED section */ - -enum { - TCA_RED_UNSPEC, - TCA_RED_PARMS, - TCA_RED_STAB, - __TCA_RED_MAX, -}; - -#define TCA_RED_MAX (__TCA_RED_MAX - 1) - -struct tc_red_qopt { - __u32 limit; /* HARD maximal queue length (bytes) */ - __u32 qth_min; /* Min average length threshold (bytes) */ - __u32 qth_max; /* Max average length threshold (bytes) */ - unsigned char Wlog; /* log(W) */ - unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ - unsigned char Scell_log; /* cell size for idle damping */ - unsigned char flags; -#define TC_RED_ECN 1 -#define TC_RED_HARDDROP 2 -}; - -struct tc_red_xstats { - __u32 early; /* Early drops */ - __u32 pdrop; /* Drops due to queue limits */ - __u32 other; /* Drops due to drop() calls */ - __u32 marked; /* Marked packets */ -}; - -/* GRED section */ - -#define MAX_DPs 16 - -enum { - TCA_GRED_UNSPEC, - TCA_GRED_PARMS, - TCA_GRED_STAB, - TCA_GRED_DPS, - __TCA_GRED_MAX, -}; - -#define TCA_GRED_MAX (__TCA_GRED_MAX - 1) - -struct tc_gred_qopt { - __u32 limit; /* HARD maximal queue length (bytes) */ - __u32 qth_min; /* Min average length threshold (bytes) */ - __u32 qth_max; /* Max average length threshold (bytes) */ - __u32 DP; /* up to 2^32 DPs */ - __u32 backlog; - __u32 qave; - __u32 forced; - __u32 early; - __u32 other; - __u32 pdrop; - __u8 Wlog; /* log(W) */ - __u8 Plog; /* log(P_max/(qth_max-qth_min)) */ - __u8 Scell_log; /* cell size for idle damping */ - __u8 prio; /* prio of this VQ */ - __u32 packets; - __u32 bytesin; -}; - -/* gred setup */ -struct tc_gred_sopt { - __u32 DPs; - __u32 def_DP; - __u8 grio; - __u8 flags; - __u16 pad1; -}; - -/* CHOKe section */ - -enum { - TCA_CHOKE_UNSPEC, - TCA_CHOKE_PARMS, - TCA_CHOKE_STAB, - __TCA_CHOKE_MAX, -}; - -#define TCA_CHOKE_MAX (__TCA_CHOKE_MAX - 1) - -struct tc_choke_qopt { - __u32 limit; /* Hard queue length (packets) */ - __u32 qth_min; /* Min average threshold (packets) */ - __u32 qth_max; /* Max average threshold (packets) */ - unsigned char Wlog; /* log(W) */ - unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ - unsigned char Scell_log; /* cell size for idle damping */ - unsigned char flags; /* see RED flags */ -}; - -struct tc_choke_xstats { - __u32 early; /* Early drops */ - __u32 pdrop; /* Drops due to queue limits */ - __u32 other; /* Drops due to drop() calls */ - __u32 marked; /* Marked packets */ - __u32 matched; /* Drops due to flow match */ -}; - -/* HTB section */ -#define TC_HTB_NUMPRIO 8 -#define TC_HTB_MAXDEPTH 8 -#define TC_HTB_PROTOVER 3 /* the same as HTB and TC's major */ - -struct tc_htb_opt { - struct tc_ratespec rate; - struct tc_ratespec ceil; - __u32 buffer; - __u32 cbuffer; - __u32 quantum; - __u32 level; /* out only */ - __u32 prio; -}; -struct tc_htb_glob { - __u32 version; /* to match HTB/TC */ - __u32 rate2quantum; /* bps->quantum divisor */ - __u32 defcls; /* default class number */ - __u32 debug; /* debug flags */ - - /* stats */ - __u32 direct_pkts; /* count of non shapped packets */ -}; -enum { - TCA_HTB_UNSPEC, - TCA_HTB_PARMS, - TCA_HTB_INIT, - TCA_HTB_CTAB, - TCA_HTB_RTAB, - __TCA_HTB_MAX, -}; - -#define TCA_HTB_MAX (__TCA_HTB_MAX - 1) - -struct tc_htb_xstats { - __u32 lends; - __u32 borrows; - __u32 giants; /* too big packets (rate will not be accurate) */ - __u32 tokens; - __u32 ctokens; -}; - -/* HFSC section */ - -struct tc_hfsc_qopt { - __u16 defcls; /* default class */ -}; - -struct tc_service_curve { - __u32 m1; /* slope of the first segment in bps */ - __u32 d; /* x-projection of the first segment in us */ - __u32 m2; /* slope of the second segment in bps */ -}; - -struct tc_hfsc_stats { - __u64 work; /* total work done */ - __u64 rtwork; /* work done by real-time criteria */ - __u32 period; /* current period */ - __u32 level; /* class level in hierarchy */ -}; - -enum { - TCA_HFSC_UNSPEC, - TCA_HFSC_RSC, - TCA_HFSC_FSC, - TCA_HFSC_USC, - __TCA_HFSC_MAX, -}; - -#define TCA_HFSC_MAX (__TCA_HFSC_MAX - 1) - - -/* CBQ section */ - -#define TC_CBQ_MAXPRIO 8 -#define TC_CBQ_MAXLEVEL 8 -#define TC_CBQ_DEF_EWMA 5 - -struct tc_cbq_lssopt { - unsigned char change; - unsigned char flags; -#define TCF_CBQ_LSS_BOUNDED 1 -#define TCF_CBQ_LSS_ISOLATED 2 - unsigned char ewma_log; - unsigned char level; -#define TCF_CBQ_LSS_FLAGS 1 -#define TCF_CBQ_LSS_EWMA 2 -#define TCF_CBQ_LSS_MAXIDLE 4 -#define TCF_CBQ_LSS_MINIDLE 8 -#define TCF_CBQ_LSS_OFFTIME 0x10 -#define TCF_CBQ_LSS_AVPKT 0x20 - __u32 maxidle; - __u32 minidle; - __u32 offtime; - __u32 avpkt; -}; - -struct tc_cbq_wrropt { - unsigned char flags; - unsigned char priority; - unsigned char cpriority; - unsigned char __reserved; - __u32 allot; - __u32 weight; -}; - -struct tc_cbq_ovl { - unsigned char strategy; -#define TC_CBQ_OVL_CLASSIC 0 -#define TC_CBQ_OVL_DELAY 1 -#define TC_CBQ_OVL_LOWPRIO 2 -#define TC_CBQ_OVL_DROP 3 -#define TC_CBQ_OVL_RCLASSIC 4 - unsigned char priority2; - __u16 pad; - __u32 penalty; -}; - -struct tc_cbq_police { - unsigned char police; - unsigned char __res1; - unsigned short __res2; -}; - -struct tc_cbq_fopt { - __u32 split; - __u32 defmap; - __u32 defchange; -}; - -struct tc_cbq_xstats { - __u32 borrows; - __u32 overactions; - __s32 avgidle; - __s32 undertime; -}; - -enum { - TCA_CBQ_UNSPEC, - TCA_CBQ_LSSOPT, - TCA_CBQ_WRROPT, - TCA_CBQ_FOPT, - TCA_CBQ_OVL_STRATEGY, - TCA_CBQ_RATE, - TCA_CBQ_RTAB, - TCA_CBQ_POLICE, - __TCA_CBQ_MAX, -}; - -#define TCA_CBQ_MAX (__TCA_CBQ_MAX - 1) - -/* dsmark section */ - -enum { - TCA_DSMARK_UNSPEC, - TCA_DSMARK_INDICES, - TCA_DSMARK_DEFAULT_INDEX, - TCA_DSMARK_SET_TC_INDEX, - TCA_DSMARK_MASK, - TCA_DSMARK_VALUE, - __TCA_DSMARK_MAX, -}; - -#define TCA_DSMARK_MAX (__TCA_DSMARK_MAX - 1) - -/* ATM section */ - -enum { - TCA_ATM_UNSPEC, - TCA_ATM_FD, /* file/socket descriptor */ - TCA_ATM_PTR, /* pointer to descriptor - later */ - TCA_ATM_HDR, /* LL header */ - TCA_ATM_EXCESS, /* excess traffic class (0 for CLP) */ - TCA_ATM_ADDR, /* PVC address (for output only) */ - TCA_ATM_STATE, /* VC state (ATM_VS_*; for output only) */ - __TCA_ATM_MAX, -}; - -#define TCA_ATM_MAX (__TCA_ATM_MAX - 1) - -/* Network emulator */ - -enum { - TCA_NETEM_UNSPEC, - TCA_NETEM_CORR, - TCA_NETEM_DELAY_DIST, - TCA_NETEM_REORDER, - TCA_NETEM_CORRUPT, - TCA_NETEM_LOSS, - __TCA_NETEM_MAX, -}; - -#define TCA_NETEM_MAX (__TCA_NETEM_MAX - 1) - -struct tc_netem_qopt { - __u32 latency; /* added delay (us) */ - __u32 limit; /* fifo limit (packets) */ - __u32 loss; /* random packet loss (0=none ~0=100%) */ - __u32 gap; /* re-ordering gap (0 for none) */ - __u32 duplicate; /* random packet dup (0=none ~0=100%) */ - __u32 jitter; /* random jitter in latency (us) */ -}; - -struct tc_netem_corr { - __u32 delay_corr; /* delay correlation */ - __u32 loss_corr; /* packet loss correlation */ - __u32 dup_corr; /* duplicate correlation */ -}; - -struct tc_netem_reorder { - __u32 probability; - __u32 correlation; -}; - -struct tc_netem_corrupt { - __u32 probability; - __u32 correlation; -}; - -enum { - NETEM_LOSS_UNSPEC, - NETEM_LOSS_GI, /* General Intuitive - 4 state model */ - NETEM_LOSS_GE, /* Gilbert Elliot models */ - __NETEM_LOSS_MAX -}; -#define NETEM_LOSS_MAX (__NETEM_LOSS_MAX - 1) - -/* State transition probablities for 4 state model */ -struct tc_netem_gimodel { - __u32 p13; - __u32 p31; - __u32 p32; - __u32 p14; - __u32 p23; -}; - -/* Gilbert-Elliot models */ -struct tc_netem_gemodel { - __u32 p; - __u32 r; - __u32 h; - __u32 k1; -}; - -#define NETEM_DIST_SCALE 8192 -#define NETEM_DIST_MAX 16384 - -/* DRR */ - -enum { - TCA_DRR_UNSPEC, - TCA_DRR_QUANTUM, - __TCA_DRR_MAX -}; - -#define TCA_DRR_MAX (__TCA_DRR_MAX - 1) - -struct tc_drr_stats { - __u32 deficit; -}; - -/* MQPRIO */ -#define TC_QOPT_BITMASK 15 -#define TC_QOPT_MAX_QUEUE 16 - -struct tc_mqprio_qopt { - __u8 num_tc; - __u8 prio_tc_map[TC_QOPT_BITMASK + 1]; - __u8 hw; - __u16 count[TC_QOPT_MAX_QUEUE]; - __u16 offset[TC_QOPT_MAX_QUEUE]; -}; - -/* SFB */ - -enum { - TCA_SFB_UNSPEC, - TCA_SFB_PARMS, - __TCA_SFB_MAX, -}; - -#define TCA_SFB_MAX (__TCA_SFB_MAX - 1) - -/* - * Note: increment, decrement are Q0.16 fixed-point values. - */ -struct tc_sfb_qopt { - __u32 rehash_interval; /* delay between hash move, in ms */ - __u32 warmup_time; /* double buffering warmup time in ms (warmup_time < rehash_interval) */ - __u32 max; /* max len of qlen_min */ - __u32 bin_size; /* maximum queue length per bin */ - __u32 increment; /* probability increment, (d1 in Blue) */ - __u32 decrement; /* probability decrement, (d2 in Blue) */ - __u32 limit; /* max SFB queue length */ - __u32 penalty_rate; /* inelastic flows are rate limited to 'rate' pps */ - __u32 penalty_burst; -}; - -struct tc_sfb_xstats { - __u32 earlydrop; - __u32 penaltydrop; - __u32 bucketdrop; - __u32 queuedrop; - __u32 childdrop; /* drops in child qdisc */ - __u32 marked; - __u32 maxqlen; - __u32 maxprob; - __u32 avgprob; -}; - -#define SFB_MAX_PROB 0xFFFF - -/* QFQ */ -enum { - TCA_QFQ_UNSPEC, - TCA_QFQ_WEIGHT, - TCA_QFQ_LMAX, - __TCA_QFQ_MAX -}; - -#define TCA_QFQ_MAX (__TCA_QFQ_MAX - 1) - -struct tc_qfq_stats { - __u32 weight; - __u32 lmax; -}; - -#endif diff --git a/include/netlink-private/genl.h b/include/netlink-private/genl.h deleted file mode 100644 index 5b93db3..0000000 --- a/include/netlink-private/genl.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * netlink-private/genl.h Local Generic Netlink Interface - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * Copyright (c) 2003-2013 Thomas Graf - */ - -#ifndef NETLINK_GENL_PRIV_H_ -#define NETLINK_GENL_PRIV_H_ - -#include -#include - -#define GENL_HDRSIZE(hdrlen) (GENL_HDRLEN + (hdrlen)) - -extern int genl_resolve_id(struct genl_ops *ops); - -#endif diff --git a/include/netlink-private/netlink.h b/include/netlink-private/netlink.h deleted file mode 100644 index 2e511bf..0000000 --- a/include/netlink-private/netlink.h +++ /dev/null @@ -1,262 +0,0 @@ -/* - * netlink-private/netlink.h Local Netlink Interface - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * Copyright (c) 2003-2013 Thomas Graf - */ - -#ifndef NETLINK_LOCAL_H_ -#define NETLINK_LOCAL_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#ifndef SOL_NETLINK -#define SOL_NETLINK 270 -#endif - -#include - -/* local header copies */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef DISABLE_PTHREADS -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -struct trans_tbl { - int i; - const char *a; -}; - -#define __ADD(id, name) { .i = id, .a = #name }, - -struct trans_list { - int i; - char *a; - struct nl_list_head list; -}; - -#ifdef NL_DEBUG -#define NL_DBG(LVL,FMT,ARG...) \ - do { \ - if (LVL <= nl_debug) \ - fprintf(stderr, \ - "DBG<" #LVL ">%20s:%-4u %s: " FMT, \ - __FILE__, __LINE__, \ - __PRETTY_FUNCTION__, ##ARG); \ - } while (0) -#else /* NL_DEBUG */ -#define NL_DBG(LVL,FMT,ARG...) do { } while(0) -#endif /* NL_DEBUG */ - -#define BUG() \ - do { \ - fprintf(stderr, "BUG at file position %s:%d:%s\n", \ - __FILE__, __LINE__, __PRETTY_FUNCTION__); \ - assert(0); \ - } while (0) - -#define APPBUG(msg) \ - do { \ - fprintf(stderr, "APPLICATION BUG: %s:%d:%s: %s\n", \ - __FILE__, __LINE__, __PRETTY_FUNCTION__, msg); \ - assert(0); \ - } while(0) - -extern int __nl_read_num_str_file(const char *path, - int (*cb)(long, const char *)); - -extern int __trans_list_add(int, const char *, struct nl_list_head *); -extern void __trans_list_clear(struct nl_list_head *); - -extern char *__type2str(int, char *, size_t, const struct trans_tbl *, size_t); -extern int __str2type(const char *, const struct trans_tbl *, size_t); - -extern char *__list_type2str(int, char *, size_t, struct nl_list_head *); -extern int __list_str2type(const char *, struct nl_list_head *); - -extern char *__flags2str(int, char *, size_t, const struct trans_tbl *, size_t); -extern int __str2flags(const char *, const struct trans_tbl *, size_t); - -extern void dump_from_ops(struct nl_object *, struct nl_dump_params *); - -static inline int nl_cb_call(struct nl_cb *cb, int type, struct nl_msg *msg) -{ - return cb->cb_set[type](msg, cb->cb_args[type]); -} - -#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0])) - -/* This is also defined in stddef.h */ -#ifndef offsetof -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) -#endif - -#define __init __attribute__ ((constructor)) -#define __exit __attribute__ ((destructor)) -#undef __deprecated -#define __deprecated __attribute__ ((deprecated)) - -#define min(x,y) ({ \ - typeof(x) _x = (x); \ - typeof(y) _y = (y); \ - (void) (&_x == &_y); \ - _x < _y ? _x : _y; }) - -#define max(x,y) ({ \ - typeof(x) _x = (x); \ - typeof(y) _y = (y); \ - (void) (&_x == &_y); \ - _x > _y ? _x : _y; }) - -#define min_t(type,x,y) \ - ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) -#define max_t(type,x,y) \ - ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) - -extern int nl_cache_parse(struct nl_cache_ops *, struct sockaddr_nl *, - struct nlmsghdr *, struct nl_parser_param *); - - -static inline void rtnl_copy_ratespec(struct rtnl_ratespec *dst, - struct tc_ratespec *src) -{ - dst->rs_cell_log = src->cell_log; - dst->rs_overhead = src->overhead; - dst->rs_cell_align = src->cell_align; - dst->rs_mpu = src->mpu; - dst->rs_rate = src->rate; -} - -static inline void rtnl_rcopy_ratespec(struct tc_ratespec *dst, - struct rtnl_ratespec *src) -{ - dst->cell_log = src->rs_cell_log; - dst->overhead = src->rs_overhead; - dst->cell_align = src->rs_cell_align; - dst->mpu = src->rs_mpu; - dst->rate = src->rs_rate; -} - -static inline char *nl_cache_name(struct nl_cache *cache) -{ - return cache->c_ops ? cache->c_ops->co_name : "unknown"; -} - -#define GENL_FAMILY(id, name) \ - { \ - { id, NL_ACT_UNSPEC, name }, \ - END_OF_MSGTYPES_LIST, \ - } - -static inline int wait_for_ack(struct nl_sock *sk) -{ - if (sk->s_flags & NL_NO_AUTO_ACK) - return 0; - else - return nl_wait_for_ack(sk); -} - -static inline int build_sysconf_path(char **strp, const char *filename) -{ - char *sysconfdir; - - sysconfdir = getenv("NLSYSCONFDIR"); - - if (!sysconfdir) - sysconfdir = SYSCONFDIR; - - return asprintf(strp, "%s/%s", sysconfdir, filename); -} - -#ifndef DISABLE_PTHREADS -#define NL_LOCK(NAME) pthread_mutex_t (NAME) = PTHREAD_MUTEX_INITIALIZER -#define NL_RW_LOCK(NAME) pthread_rwlock_t (NAME) = PTHREAD_RWLOCK_INITIALIZER - -static inline void nl_lock(pthread_mutex_t *lock) -{ - pthread_mutex_lock(lock); -} - -static inline void nl_unlock(pthread_mutex_t *lock) -{ - pthread_mutex_unlock(lock); -} - -static inline void nl_read_lock(pthread_rwlock_t *lock) -{ - pthread_rwlock_rdlock(lock); -} - -static inline void nl_read_unlock(pthread_rwlock_t *lock) -{ - pthread_rwlock_unlock(lock); -} - -static inline void nl_write_lock(pthread_rwlock_t *lock) -{ - pthread_rwlock_wrlock(lock); -} - -static inline void nl_write_unlock(pthread_rwlock_t *lock) -{ - pthread_rwlock_unlock(lock); -} - -#else -#define NL_LOCK(NAME) int __unused_lock_ ##NAME __attribute__((unused)) -#define NL_RW_LOCK(NAME) int __unused_lock_ ##NAME __attribute__((unused)) - -#define nl_lock(LOCK) do { } while(0) -#define nl_unlock(LOCK) do { } while(0) -#define nl_read_lock(LOCK) do { } while(0) -#define nl_read_unlock(LOCK) do { } while(0) -#define nl_write_lock(LOCK) do { } while(0) -#define nl_write_unlock(LOCK) do { } while(0) -#endif - -#endif diff --git a/include/netlink-private/route/tc-api.h b/include/netlink-private/route/tc-api.h deleted file mode 100644 index bf0c8a3..0000000 --- a/include/netlink-private/route/tc-api.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * netlink-private/route/tc-api.h Traffic Control API - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * Copyright (c) 2011-2013 Thomas Graf - */ - -#ifndef NETLINK_TC_API_H_ -#define NETLINK_TC_API_H_ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Traffic control object operations - * @ingroup tc - * - * This structure holds function pointers and settings implementing - * the features of each traffic control object implementation. - */ -struct rtnl_tc_ops -{ - /** - * Name of traffic control module - */ - char *to_kind; - - /** - * Type of traffic control object - */ - enum rtnl_tc_type to_type; - - - /** - * Size of private data - */ - size_t to_size; - - /** - * Dump callbacks - */ - void (*to_dump[NL_DUMP_MAX+1])(struct rtnl_tc *, void *, - struct nl_dump_params *); - /** - * Used to fill the contents of TCA_OPTIONS - */ - int (*to_msg_fill)(struct rtnl_tc *, void *, struct nl_msg *); - - /** - * Uesd to to fill tc related messages, unlike with to_msg_fill, - * the contents is not encapsulated with a TCA_OPTIONS nested - * attribute. - */ - int (*to_msg_fill_raw)(struct rtnl_tc *, void *, struct nl_msg *); - - /** - * TCA_OPTIONS message parser - */ - int (*to_msg_parser)(struct rtnl_tc *, void *); - - /** - * Called before a tc object is destroyed - */ - void (*to_free_data)(struct rtnl_tc *, void *); - - /** - * Called whenever a classifier object needs to be cloned - */ - int (*to_clone)(void *, void *); - - /** - * Internal, don't touch - */ - struct nl_list_head to_list; -}; - -struct rtnl_tc_type_ops -{ - enum rtnl_tc_type tt_type; - - char *tt_dump_prefix; - - /** - * Dump callbacks - */ - void (*tt_dump[NL_DUMP_MAX+1])(struct rtnl_tc *, - struct nl_dump_params *); -}; - -extern int rtnl_tc_msg_parse(struct nlmsghdr *, - struct rtnl_tc *); -extern int rtnl_tc_msg_build(struct rtnl_tc *, int, - int, struct nl_msg **); - -extern void rtnl_tc_free_data(struct nl_object *); -extern int rtnl_tc_clone(struct nl_object *, - struct nl_object *); -extern void rtnl_tc_dump_line(struct nl_object *, - struct nl_dump_params *); -extern void rtnl_tc_dump_details(struct nl_object *, - struct nl_dump_params *); -extern void rtnl_tc_dump_stats(struct nl_object *, - struct nl_dump_params *); -extern int rtnl_tc_compare(struct nl_object *, - struct nl_object *, - uint32_t, int); - -extern void * rtnl_tc_data(struct rtnl_tc *); -extern void * rtnl_tc_data_check(struct rtnl_tc *, - struct rtnl_tc_ops *); - -extern struct rtnl_tc_ops * rtnl_tc_lookup_ops(enum rtnl_tc_type, - const char *); -extern struct rtnl_tc_ops * rtnl_tc_get_ops(struct rtnl_tc *); -extern int rtnl_tc_register(struct rtnl_tc_ops *); -extern void rtnl_tc_unregister(struct rtnl_tc_ops *); - -extern void rtnl_tc_type_register(struct rtnl_tc_type_ops *); -extern void rtnl_tc_type_unregister(struct rtnl_tc_type_ops *); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/netlink-private/tc.h b/include/netlink-private/tc.h deleted file mode 100644 index 182adaa..0000000 --- a/include/netlink-private/tc.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * netlink-private/tc.h Local Traffic Control Interface - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * Copyright (c) 2003-2013 Thomas Graf - */ - -#ifndef NETLINK_TC_PRIV_H_ -#define NETLINK_TC_PRIV_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define TCA_ATTR_HANDLE 0x0001 -#define TCA_ATTR_PARENT 0x0002 -#define TCA_ATTR_IFINDEX 0x0004 -#define TCA_ATTR_KIND 0x0008 -#define TCA_ATTR_FAMILY 0x0010 -#define TCA_ATTR_INFO 0x0020 -#define TCA_ATTR_OPTS 0x0040 -#define TCA_ATTR_STATS 0x0080 -#define TCA_ATTR_XSTATS 0x0100 -#define TCA_ATTR_LINK 0x0200 -#define TCA_ATTR_MTU 0x0400 -#define TCA_ATTR_MPU 0x0800 -#define TCA_ATTR_OVERHEAD 0x1000 -#define TCA_ATTR_LINKTYPE 0x2000 -#define TCA_ATTR_MAX TCA_ATTR_LINKTYPE - -extern int tca_parse(struct nlattr **, int, struct rtnl_tc *, - struct nla_policy *); - -#define RTNL_TC_RTABLE_SIZE 256 - -extern int rtnl_tc_build_rate_table(struct rtnl_tc *tc, struct rtnl_ratespec *, - uint32_t *); - - -static inline void *tca_xstats(struct rtnl_tc *tca) -{ - return tca->tc_xstats->d_data; -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/netlink-private/types.h b/include/netlink-private/types.h deleted file mode 100644 index 89f6418..0000000 --- a/include/netlink-private/types.h +++ /dev/null @@ -1,912 +0,0 @@ -/* - * netlink-private/types.h Netlink Types (Private) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * Copyright (c) 2003-2013 Thomas Graf - */ - -#ifndef NETLINK_LOCAL_TYPES_H_ -#define NETLINK_LOCAL_TYPES_H_ - -#include -#include -#include -#include -#include -#include - -#define NL_SOCK_BUFSIZE_SET (1<<0) -#define NL_SOCK_PASSCRED (1<<1) -#define NL_OWN_PORT (1<<2) -#define NL_MSG_PEEK (1<<3) -#define NL_NO_AUTO_ACK (1<<4) - -#define NL_MSG_CRED_PRESENT 1 - -struct nl_cache_ops; -struct nl_sock; -struct nl_object; -struct nl_hash_table; - -struct nl_cb -{ - nl_recvmsg_msg_cb_t cb_set[NL_CB_TYPE_MAX+1]; - void * cb_args[NL_CB_TYPE_MAX+1]; - - nl_recvmsg_err_cb_t cb_err; - void * cb_err_arg; - - /** May be used to replace nl_recvmsgs with your own implementation - * in all internal calls to nl_recvmsgs. */ - int (*cb_recvmsgs_ow)(struct nl_sock *, - struct nl_cb *); - - /** Overwrite internal calls to nl_recv, must return the number of - * octets read and allocate a buffer for the received data. */ - int (*cb_recv_ow)(struct nl_sock *, - struct sockaddr_nl *, - unsigned char **, - struct ucred **); - - /** Overwrites internal calls to nl_send, must send the netlink - * message. */ - int (*cb_send_ow)(struct nl_sock *, - struct nl_msg *); - - int cb_refcnt; -}; - -struct nl_sock -{ - struct sockaddr_nl s_local; - struct sockaddr_nl s_peer; - int s_fd; - int s_proto; - unsigned int s_seq_next; - unsigned int s_seq_expect; - int s_flags; - struct nl_cb * s_cb; - size_t s_bufsize; -}; - -struct nl_cache -{ - struct nl_list_head c_items; - int c_nitems; - int c_iarg1; - int c_iarg2; - int c_refcnt; - unsigned int c_flags; - struct nl_hash_table * hashtable; - struct nl_cache_ops * c_ops; -}; - -struct nl_cache_assoc -{ - struct nl_cache * ca_cache; - change_func_t ca_change; - void * ca_change_data; -}; - -struct nl_cache_mngr -{ - int cm_protocol; - int cm_flags; - int cm_nassocs; - struct nl_sock * cm_sock; - struct nl_sock * cm_sync_sock; - struct nl_cache_assoc * cm_assocs; -}; - -struct nl_parser_param; - -#define LOOSE_COMPARISON 1 - -#define NL_OBJ_MARK 1 - -struct nl_data -{ - size_t d_size; - void * d_data; -}; - -struct nl_addr -{ - int a_family; - unsigned int a_maxsize; - unsigned int a_len; - int a_prefixlen; - int a_refcnt; - char a_addr[0]; -}; - -struct nl_msg -{ - int nm_protocol; - int nm_flags; - struct sockaddr_nl nm_src; - struct sockaddr_nl nm_dst; - struct ucred nm_creds; - struct nlmsghdr * nm_nlh; - size_t nm_size; - int nm_refcnt; -}; - -struct rtnl_link_map -{ - uint64_t lm_mem_start; - uint64_t lm_mem_end; - uint64_t lm_base_addr; - uint16_t lm_irq; - uint8_t lm_dma; - uint8_t lm_port; -}; - -#define IFQDISCSIZ 32 - -struct rtnl_link -{ - NLHDR_COMMON - - char l_name[IFNAMSIZ]; - uint32_t l_family; - uint32_t l_arptype; - uint32_t l_index; - uint32_t l_flags; - uint32_t l_change; - uint32_t l_mtu; - uint32_t l_link; - uint32_t l_txqlen; - uint32_t l_weight; - uint32_t l_master; - struct nl_addr * l_addr; - struct nl_addr * l_bcast; - char l_qdisc[IFQDISCSIZ]; - struct rtnl_link_map l_map; - uint64_t l_stats[RTNL_LINK_STATS_MAX+1]; - uint32_t l_flag_mask; - uint32_t l_num_vf; - uint8_t l_operstate; - uint8_t l_linkmode; - /* 2 byte hole */ - char * l_info_kind; - struct rtnl_link_info_ops * l_info_ops; - void * l_af_data[AF_MAX]; - void * l_info; - char * l_ifalias; - uint32_t l_promiscuity; - uint32_t l_num_tx_queues; - uint32_t l_num_rx_queues; - uint32_t l_group; - uint8_t l_carrier; - /* 3 byte hole */ - struct rtnl_link_af_ops * l_af_ops; -}; - -struct rtnl_ncacheinfo -{ - uint32_t nci_confirmed; /**< Time since neighbour validty was last confirmed */ - uint32_t nci_used; /**< Time since neighbour entry was last ued */ - uint32_t nci_updated; /**< Time since last update */ - uint32_t nci_refcnt; /**< Reference counter */ -}; - - -struct rtnl_neigh -{ - NLHDR_COMMON - uint32_t n_family; - uint32_t n_ifindex; - uint16_t n_state; - uint8_t n_flags; - uint8_t n_type; - struct nl_addr *n_lladdr; - struct nl_addr *n_dst; - uint32_t n_probes; - struct rtnl_ncacheinfo n_cacheinfo; - uint32_t n_state_mask; - uint32_t n_flag_mask; - uint32_t n_master; -}; - - -struct rtnl_addr_cacheinfo -{ - /* Preferred lifetime in seconds */ - uint32_t aci_prefered; - - /* Valid lifetime in seconds */ - uint32_t aci_valid; - - /* Timestamp of creation in 1/100s seince boottime */ - uint32_t aci_cstamp; - - /* Timestamp of last update in 1/100s since boottime */ - uint32_t aci_tstamp; -}; - -struct rtnl_addr -{ - NLHDR_COMMON - - uint8_t a_family; - uint8_t a_prefixlen; - uint8_t a_flags; - uint8_t a_scope; - uint32_t a_ifindex; - - struct nl_addr *a_peer; - struct nl_addr *a_local; - struct nl_addr *a_bcast; - struct nl_addr *a_anycast; - struct nl_addr *a_multicast; - - struct rtnl_addr_cacheinfo a_cacheinfo; - - char a_label[IFNAMSIZ]; - uint32_t a_flag_mask; - struct rtnl_link *a_link; -}; - -struct rtnl_nexthop -{ - uint8_t rtnh_flags; - uint8_t rtnh_flag_mask; - uint8_t rtnh_weight; - /* 1 byte spare */ - uint32_t rtnh_ifindex; - struct nl_addr * rtnh_gateway; - uint32_t ce_mask; /* HACK to support attr macros */ - struct nl_list_head rtnh_list; - uint32_t rtnh_realms; -}; - -struct rtnl_route -{ - NLHDR_COMMON - - uint8_t rt_family; - uint8_t rt_dst_len; - uint8_t rt_src_len; - uint8_t rt_tos; - uint8_t rt_protocol; - uint8_t rt_scope; - uint8_t rt_type; - uint8_t rt_nmetrics; - uint32_t rt_flags; - struct nl_addr * rt_dst; - struct nl_addr * rt_src; - uint32_t rt_table; - uint32_t rt_iif; - uint32_t rt_prio; - uint32_t rt_metrics[RTAX_MAX]; - uint32_t rt_metrics_mask; - uint32_t rt_nr_nh; - struct nl_addr * rt_pref_src; - struct nl_list_head rt_nexthops; - struct rtnl_rtcacheinfo rt_cacheinfo; - uint32_t rt_flag_mask; -}; - -struct rtnl_rule -{ - NLHDR_COMMON - uint8_t r_family; - uint8_t r_action; - uint8_t r_dsfield; /* ipv4 only */ - uint8_t r_unused; - uint32_t r_table; - uint32_t r_flags; - uint32_t r_prio; - uint32_t r_mark; - uint32_t r_mask; - uint32_t r_goto; - uint32_t r_flow; /* ipv4 only */ - struct nl_addr *r_src; - struct nl_addr *r_dst; - char r_iifname[IFNAMSIZ]; - char r_oifname[IFNAMSIZ]; -}; - -struct rtnl_neightbl_parms -{ - /** - * Interface index of the device this parameter set is assigned - * to or 0 for the default set. - */ - uint32_t ntp_ifindex; - - /** - * Number of references to this parameter set. - */ - uint32_t ntp_refcnt; - - /** - * Queue length for pending arp requests, i.e. the number of - * packets which are accepted from other layers while the - * neighbour address is still being resolved - */ - uint32_t ntp_queue_len; - - /** - * Number of requests to send to the user level ARP daemon. - * Specify 0 to disable. - */ - uint32_t ntp_app_probes; - - /** - * Maximum number of retries for unicast solicitation. - */ - uint32_t ntp_ucast_probes; - - /** - * Maximum number of retries for multicast solicitation. - */ - uint32_t ntp_mcast_probes; - - /** - * Base value in milliseconds to ompute reachable time, see RFC2461. - */ - uint64_t ntp_base_reachable_time; - - /** - * Actual reachable time (read-only) - */ - uint64_t ntp_reachable_time; /* secs */ - - /** - * The time in milliseconds between retransmitted Neighbor - * Solicitation messages. - */ - uint64_t ntp_retrans_time; - - /** - * Interval in milliseconds to check for stale neighbour - * entries. - */ - uint64_t ntp_gc_stale_time; /* secs */ - - /** - * Delay in milliseconds for the first time probe if - * the neighbour is reachable. - */ - uint64_t ntp_probe_delay; /* secs */ - - /** - * Maximum delay in milliseconds of an answer to a neighbour - * solicitation message. - */ - uint64_t ntp_anycast_delay; - - /** - * Minimum age in milliseconds before a neighbour entry - * may be replaced. - */ - uint64_t ntp_locktime; - - /** - * Delay in milliseconds before answering to an ARP request - * for which a proxy ARP entry exists. - */ - uint64_t ntp_proxy_delay; - - /** - * Queue length for the delayed proxy arp requests. - */ - uint32_t ntp_proxy_qlen; - - /** - * Mask of available parameter attributes - */ - uint32_t ntp_mask; -}; - -#define NTBLNAMSIZ 32 - -/** - * Neighbour table - * @ingroup neightbl - */ -struct rtnl_neightbl -{ - NLHDR_COMMON - - char nt_name[NTBLNAMSIZ]; - uint32_t nt_family; - uint32_t nt_gc_thresh1; - uint32_t nt_gc_thresh2; - uint32_t nt_gc_thresh3; - uint64_t nt_gc_interval; - struct ndt_config nt_config; - struct rtnl_neightbl_parms nt_parms; - struct ndt_stats nt_stats; -}; - -struct rtnl_ratespec -{ - uint8_t rs_cell_log; - uint16_t rs_overhead; - int16_t rs_cell_align; - uint16_t rs_mpu; - uint32_t rs_rate; -}; - -struct rtnl_tstats -{ - struct { - uint64_t bytes; - uint64_t packets; - } tcs_basic; - - struct { - uint32_t bps; - uint32_t pps; - } tcs_rate_est; - - struct { - uint32_t qlen; - uint32_t backlog; - uint32_t drops; - uint32_t requeues; - uint32_t overlimits; - } tcs_queue; -}; - -#define TCKINDSIZ 32 - -#define NL_TC_GENERIC(pre) \ - NLHDR_COMMON \ - uint32_t pre ##_family; \ - uint32_t pre ##_ifindex; \ - uint32_t pre ##_handle; \ - uint32_t pre ##_parent; \ - uint32_t pre ##_info; \ - uint32_t pre ##_mtu; \ - uint32_t pre ##_mpu; \ - uint32_t pre ##_overhead; \ - uint32_t pre ##_linktype; \ - char pre ##_kind[TCKINDSIZ]; \ - struct nl_data * pre ##_opts; \ - uint64_t pre ##_stats[RTNL_TC_STATS_MAX+1]; \ - struct nl_data * pre ##_xstats; \ - struct nl_data * pre ##_subdata; \ - struct rtnl_link * pre ##_link; \ - struct rtnl_tc_ops * pre ##_ops; \ - enum rtnl_tc_type pre ##_type - -struct rtnl_tc -{ - NL_TC_GENERIC(tc); -}; - -struct rtnl_qdisc -{ - NL_TC_GENERIC(q); -}; - -struct rtnl_class -{ - NL_TC_GENERIC(c); -}; - -struct rtnl_cls -{ - NL_TC_GENERIC(c); - uint16_t c_prio; - uint16_t c_protocol; -}; - -struct rtnl_u32 -{ - uint32_t cu_divisor; - uint32_t cu_hash; - uint32_t cu_classid; - uint32_t cu_link; - struct nl_data * cu_pcnt; - struct nl_data * cu_selector; - struct nl_data * cu_act; - struct nl_data * cu_police; - char cu_indev[IFNAMSIZ]; - int cu_mask; -}; - -struct rtnl_cgroup -{ - struct rtnl_ematch_tree *cg_ematch; - int cg_mask; -}; - -struct rtnl_fw -{ - uint32_t cf_classid; - struct nl_data * cf_act; - struct nl_data * cf_police; - char cf_indev[IFNAMSIZ]; - uint32_t cf_fwmask; - int cf_mask; -}; - -struct rtnl_ematch -{ - uint16_t e_id; - uint16_t e_kind; - uint16_t e_flags; - uint16_t e_index; - size_t e_datalen; - - struct nl_list_head e_childs; - struct nl_list_head e_list; - struct rtnl_ematch_ops *e_ops; - - void * e_data; -}; - -struct rtnl_ematch_tree -{ - uint16_t et_progid; - struct nl_list_head et_list; - -}; - -struct rtnl_dsmark_qdisc -{ - uint16_t qdm_indices; - uint16_t qdm_default_index; - uint32_t qdm_set_tc_index; - uint32_t qdm_mask; -}; - -struct rtnl_dsmark_class -{ - uint8_t cdm_bmask; - uint8_t cdm_value; - uint32_t cdm_mask; -}; - -struct rtnl_fifo -{ - uint32_t qf_limit; - uint32_t qf_mask; -}; - -struct rtnl_prio -{ - uint32_t qp_bands; - uint8_t qp_priomap[TC_PRIO_MAX+1]; - uint32_t qp_mask; -}; - -struct rtnl_tbf -{ - uint32_t qt_limit; - struct rtnl_ratespec qt_rate; - uint32_t qt_rate_bucket; - uint32_t qt_rate_txtime; - struct rtnl_ratespec qt_peakrate; - uint32_t qt_peakrate_bucket; - uint32_t qt_peakrate_txtime; - uint32_t qt_mask; -}; - -struct rtnl_sfq -{ - uint32_t qs_quantum; - uint32_t qs_perturb; - uint32_t qs_limit; - uint32_t qs_divisor; - uint32_t qs_flows; - uint32_t qs_mask; -}; - -struct rtnl_netem_corr -{ - uint32_t nmc_delay; - uint32_t nmc_loss; - uint32_t nmc_duplicate; -}; - -struct rtnl_netem_reo -{ - uint32_t nmro_probability; - uint32_t nmro_correlation; -}; - -struct rtnl_netem_crpt -{ - uint32_t nmcr_probability; - uint32_t nmcr_correlation; -}; - -struct rtnl_netem_dist -{ - int16_t * dist_data; - size_t dist_size; -}; - -struct rtnl_netem -{ - uint32_t qnm_latency; - uint32_t qnm_limit; - uint32_t qnm_loss; - uint32_t qnm_gap; - uint32_t qnm_duplicate; - uint32_t qnm_jitter; - uint32_t qnm_mask; - struct rtnl_netem_corr qnm_corr; - struct rtnl_netem_reo qnm_ro; - struct rtnl_netem_crpt qnm_crpt; - struct rtnl_netem_dist qnm_dist; -}; - -struct rtnl_htb_qdisc -{ - uint32_t qh_rate2quantum; - uint32_t qh_defcls; - uint32_t qh_mask; - uint32_t qh_direct_pkts; -}; - -struct rtnl_htb_class -{ - uint32_t ch_prio; - struct rtnl_ratespec ch_rate; - struct rtnl_ratespec ch_ceil; - uint32_t ch_rbuffer; - uint32_t ch_cbuffer; - uint32_t ch_quantum; - uint32_t ch_mask; - uint32_t ch_level; -}; - -struct rtnl_cbq -{ - struct tc_cbq_lssopt cbq_lss; - struct tc_ratespec cbq_rate; - struct tc_cbq_wrropt cbq_wrr; - struct tc_cbq_ovl cbq_ovl; - struct tc_cbq_fopt cbq_fopt; - struct tc_cbq_police cbq_police; -}; - -struct rtnl_red -{ - uint32_t qr_limit; - uint32_t qr_qth_min; - uint32_t qr_qth_max; - uint8_t qr_flags; - uint8_t qr_wlog; - uint8_t qr_plog; - uint8_t qr_scell_log; - uint32_t qr_mask; -}; - -struct rtnl_plug -{ - int action; - uint32_t limit; -}; - -struct flnl_request -{ - NLHDR_COMMON - - struct nl_addr * lr_addr; - uint32_t lr_fwmark; - uint8_t lr_tos; - uint8_t lr_scope; - uint8_t lr_table; -}; - - -struct flnl_result -{ - NLHDR_COMMON - - struct flnl_request * fr_req; - uint8_t fr_table_id; - uint8_t fr_prefixlen; - uint8_t fr_nh_sel; - uint8_t fr_type; - uint8_t fr_scope; - uint32_t fr_error; -}; - -#define GENL_OP_HAS_POLICY 1 -#define GENL_OP_HAS_DOIT 2 -#define GENL_OP_HAS_DUMPIT 4 - -struct genl_family_op -{ - uint32_t o_id; - uint32_t o_flags; - - struct nl_list_head o_list; -}; - -struct genl_family_grp { - struct genl_family *family; /* private */ - struct nl_list_head list; /* private */ - char name[GENL_NAMSIZ]; - u_int32_t id; -}; - -struct genl_family -{ - NLHDR_COMMON - - uint16_t gf_id; - char gf_name[GENL_NAMSIZ]; - uint32_t gf_version; - uint32_t gf_hdrsize; - uint32_t gf_maxattr; - - struct nl_list_head gf_ops; - struct nl_list_head gf_mc_grps; -}; - -union nfnl_ct_proto -{ - struct { - uint16_t src; - uint16_t dst; - } port; - struct { - uint16_t id; - uint8_t type; - uint8_t code; - } icmp; -}; - -struct nfnl_ct_dir { - struct nl_addr * src; - struct nl_addr * dst; - union nfnl_ct_proto proto; - uint64_t packets; - uint64_t bytes; -}; - -union nfnl_ct_protoinfo { - struct { - uint8_t state; - } tcp; -}; - -struct nfnl_ct { - NLHDR_COMMON - - uint8_t ct_family; - uint8_t ct_proto; - union nfnl_ct_protoinfo ct_protoinfo; - - uint32_t ct_status; - uint32_t ct_status_mask; - uint32_t ct_timeout; - uint32_t ct_mark; - uint32_t ct_use; - uint32_t ct_id; - - struct nfnl_ct_dir ct_orig; - struct nfnl_ct_dir ct_repl; -}; - -union nfnl_exp_protodata { - struct { - uint16_t src; - uint16_t dst; - } port; - struct { - uint16_t id; - uint8_t type; - uint8_t code; - } icmp; -}; - -// Allow for different master/expect l4 protocols -struct nfnl_exp_proto -{ - uint8_t l4protonum; - union nfnl_exp_protodata l4protodata; -}; - -struct nfnl_exp_dir { - struct nl_addr * src; - struct nl_addr * dst; - struct nfnl_exp_proto proto; -}; - -struct nfnl_exp { - NLHDR_COMMON - - uint8_t exp_family; - uint32_t exp_timeout; - uint32_t exp_id; - uint16_t exp_zone; - uint32_t exp_class; - uint32_t exp_flags; - char * exp_helper_name; - char * exp_fn; - uint8_t exp_nat_dir; - - struct nfnl_exp_dir exp_expect; - struct nfnl_exp_dir exp_master; - struct nfnl_exp_dir exp_mask; - struct nfnl_exp_dir exp_nat; -}; - -struct nfnl_log { - NLHDR_COMMON - - uint16_t log_group; - uint8_t log_copy_mode; - uint32_t log_copy_range; - uint32_t log_flush_timeout; - uint32_t log_alloc_size; - uint32_t log_queue_threshold; - uint32_t log_flags; - uint32_t log_flag_mask; -}; - -struct nfnl_log_msg { - NLHDR_COMMON - - uint8_t log_msg_family; - uint8_t log_msg_hook; - uint16_t log_msg_hwproto; - uint32_t log_msg_mark; - struct timeval log_msg_timestamp; - uint32_t log_msg_indev; - uint32_t log_msg_outdev; - uint32_t log_msg_physindev; - uint32_t log_msg_physoutdev; - uint8_t log_msg_hwaddr[8]; - int log_msg_hwaddr_len; - void * log_msg_payload; - int log_msg_payload_len; - char * log_msg_prefix; - uint32_t log_msg_uid; - uint32_t log_msg_gid; - uint32_t log_msg_seq; - uint32_t log_msg_seq_global; -}; - -struct nfnl_queue { - NLHDR_COMMON - - uint16_t queue_group; - uint32_t queue_maxlen; - uint32_t queue_copy_range; - uint8_t queue_copy_mode; -}; - -struct nfnl_queue_msg { - NLHDR_COMMON - - uint16_t queue_msg_group; - uint8_t queue_msg_family; - uint8_t queue_msg_hook; - uint16_t queue_msg_hwproto; - uint32_t queue_msg_packetid; - uint32_t queue_msg_mark; - struct timeval queue_msg_timestamp; - uint32_t queue_msg_indev; - uint32_t queue_msg_outdev; - uint32_t queue_msg_physindev; - uint32_t queue_msg_physoutdev; - uint8_t queue_msg_hwaddr[8]; - int queue_msg_hwaddr_len; - void * queue_msg_payload; - int queue_msg_payload_len; - uint32_t queue_msg_verdict; -}; - -struct ematch_quoted { - char * data; - size_t len; - int index; -}; - -#endif diff --git a/include/netlink/addr.h b/include/netlink/addr.h index db3e4c2..851e940 100644 --- a/include/netlink/addr.h +++ b/include/netlink/addr.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/addr.h Abstract Address - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2013 Thomas Graf */ @@ -18,46 +12,51 @@ extern "C" { #endif +struct nlattr; + struct nl_addr; /* Creation */ extern struct nl_addr * nl_addr_alloc(size_t); -extern struct nl_addr * nl_addr_alloc_attr(struct nlattr *, int); -extern struct nl_addr * nl_addr_build(int, void *, size_t); +extern struct nl_addr * nl_addr_alloc_attr(const struct nlattr *, int); +extern struct nl_addr * nl_addr_build(int, const void *, size_t); extern int nl_addr_parse(const char *, int, struct nl_addr **); -extern struct nl_addr * nl_addr_clone(struct nl_addr *); +extern struct nl_addr * nl_addr_clone(const struct nl_addr *); /* Usage Management */ extern struct nl_addr * nl_addr_get(struct nl_addr *); extern void nl_addr_put(struct nl_addr *); -extern int nl_addr_shared(struct nl_addr *); +extern int nl_addr_shared(const struct nl_addr *); -extern int nl_addr_cmp(struct nl_addr *, struct nl_addr *); -extern int nl_addr_cmp_prefix(struct nl_addr *, struct nl_addr *); -extern int nl_addr_iszero(struct nl_addr *); -extern int nl_addr_valid(char *, int); -extern int nl_addr_guess_family(struct nl_addr *); -extern int nl_addr_fill_sockaddr(struct nl_addr *, +extern int nl_addr_cmp(const struct nl_addr *, + const struct nl_addr *); +extern int nl_addr_cmp_prefix(const struct nl_addr *, + const struct nl_addr *); +extern int nl_addr_iszero(const struct nl_addr *); +extern int nl_addr_valid(const char *, int); +extern int nl_addr_guess_family(const struct nl_addr *); +extern int nl_addr_fill_sockaddr(const struct nl_addr *, struct sockaddr *, socklen_t *); -extern int nl_addr_info(struct nl_addr *, struct addrinfo **); -extern int nl_addr_resolve(struct nl_addr *, char *, size_t); +extern int nl_addr_info(const struct nl_addr *, + struct addrinfo **); +extern int nl_addr_resolve(const struct nl_addr *, char *, size_t); /* Access Functions */ extern void nl_addr_set_family(struct nl_addr *, int); -extern int nl_addr_get_family(struct nl_addr *); -extern int nl_addr_set_binary_addr(struct nl_addr *, void *, +extern int nl_addr_get_family(const struct nl_addr *); +extern int nl_addr_set_binary_addr(struct nl_addr *, const void *, size_t); -extern void * nl_addr_get_binary_addr(struct nl_addr *); -extern unsigned int nl_addr_get_len(struct nl_addr *); +extern void * nl_addr_get_binary_addr(const struct nl_addr *); +extern unsigned int nl_addr_get_len(const struct nl_addr *); extern void nl_addr_set_prefixlen(struct nl_addr *, int); -extern unsigned int nl_addr_get_prefixlen(struct nl_addr *); +extern unsigned int nl_addr_get_prefixlen(const struct nl_addr *); /* Address Family Translations */ extern char * nl_af2str(int, char *, size_t); extern int nl_str2af(const char *); /* Translations to Strings */ -extern char * nl_addr2str(struct nl_addr *, char *, size_t); +extern char * nl_addr2str(const struct nl_addr *, char *, size_t); #ifdef __cplusplus } diff --git a/include/netlink/attr.h b/include/netlink/attr.h index 0ed3da3..2cd32ee 100644 --- a/include/netlink/attr.h +++ b/include/netlink/attr.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/attr.h Netlink 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-2013 Thomas Graf */ @@ -21,6 +15,8 @@ extern "C" { #endif +struct nlattr; + struct nl_msg; /** @@ -44,6 +40,13 @@ enum { NLA_FLAG, /**< Flag */ NLA_MSECS, /**< Micro seconds (64bit) */ NLA_NESTED, /**< Nested attributes */ + NLA_NESTED_COMPAT, + NLA_NUL_STRING, + NLA_BINARY, + NLA_S8, + NLA_S16, + NLA_S32, + NLA_S64, __NLA_TYPE_MAX, }; @@ -80,13 +83,13 @@ extern int nla_len(const struct nlattr *); extern int nla_ok(const struct nlattr *, int); extern struct nlattr * nla_next(const struct nlattr *, int *); extern int nla_parse(struct nlattr **, int, struct nlattr *, - int, struct nla_policy *); -extern int nla_validate(struct nlattr *, int, int, - struct nla_policy *); -extern struct nlattr * nla_find(struct nlattr *, int, int); + int, const struct nla_policy *); +extern int nla_validate(const struct nlattr *, int, int, + const struct nla_policy *); +extern struct nlattr * nla_find(const struct nlattr *, int, int); /* Helper Functions */ -extern int nla_memcpy(void *, struct nlattr *, int); +extern int nla_memcpy(void *, const struct nlattr *, int); extern size_t nla_strlcpy(char *, const struct nlattr *, size_t); extern int nla_memcmp(const struct nlattr *, const void *, size_t); extern int nla_strcmp(const struct nlattr *, const char *); @@ -94,40 +97,51 @@ extern int nla_strcmp(const struct nlattr *, const char *); /* Unspecific attribute */ extern struct nlattr * nla_reserve(struct nl_msg *, int, int); extern int nla_put(struct nl_msg *, int, int, const void *); -extern int nla_put_data(struct nl_msg *, int, struct nl_data *); +extern int nla_put_data(struct nl_msg *, int, + const struct nl_data *); extern int nla_put_addr(struct nl_msg *, int, struct nl_addr *); /* Integer attribute */ -extern uint8_t nla_get_u8(struct nlattr *); +extern int8_t nla_get_s8(const struct nlattr *); +extern int nla_put_s8(struct nl_msg *, int, int8_t); +extern uint8_t nla_get_u8(const struct nlattr *); extern int nla_put_u8(struct nl_msg *, int, uint8_t); -extern uint16_t nla_get_u16(struct nlattr *); +extern int16_t nla_get_s16(const struct nlattr *); +extern int nla_put_s16(struct nl_msg *, int, int16_t); +extern uint16_t nla_get_u16(const struct nlattr *); extern int nla_put_u16(struct nl_msg *, int, uint16_t); -extern uint32_t nla_get_u32(struct nlattr *); +extern int32_t nla_get_s32(const struct nlattr *); +extern int nla_put_s32(struct nl_msg *, int, int32_t); +extern uint32_t nla_get_u32(const struct nlattr *); extern int nla_put_u32(struct nl_msg *, int, uint32_t); -extern uint64_t nla_get_u64(struct nlattr *); +extern int64_t nla_get_s64(const struct nlattr *); +extern int nla_put_s64(struct nl_msg *, int, int64_t); +extern uint64_t nla_get_u64(const struct nlattr *); extern int nla_put_u64(struct nl_msg *, int, uint64_t); /* String attribute */ -extern char * nla_get_string(struct nlattr *); -extern char * nla_strdup(struct nlattr *); +extern char * nla_get_string(const struct nlattr *); +extern char * nla_strdup(const struct nlattr *); extern int nla_put_string(struct nl_msg *, int, const char *); /* Flag attribute */ -extern int nla_get_flag(struct nlattr *); +extern int nla_get_flag(const struct nlattr *); extern int nla_put_flag(struct nl_msg *, int); /* Msec attribute */ -extern unsigned long nla_get_msecs(struct nlattr *); +extern unsigned long nla_get_msecs(const struct nlattr *); extern int nla_put_msecs(struct nl_msg *, int, unsigned long); /* Attribute nesting */ -extern int nla_put_nested(struct nl_msg *, int, struct nl_msg *); +extern int nla_put_nested(struct nl_msg *, int, + const struct nl_msg *); extern struct nlattr * nla_nest_start(struct nl_msg *, int); extern int nla_nest_end(struct nl_msg *, struct nlattr *); -extern void nla_nest_cancel(struct nl_msg *, struct nlattr *); +extern int nla_nest_end_keep_empty(struct nl_msg *, struct nlattr *); +extern void nla_nest_cancel(struct nl_msg *, const struct nlattr *); extern int nla_parse_nested(struct nlattr **, int, struct nlattr *, - struct nla_policy *); -extern int nla_is_nested(struct nlattr *); + const struct nla_policy *); +extern int nla_is_nested(const struct nlattr *); /** * @name Attribute Construction (Exception Based) @@ -163,6 +177,15 @@ extern int nla_is_nested(struct nlattr *); } while(0) /** + * Add 8 bit signed integer attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg value Numeric value. + */ +#define NLA_PUT_S8(msg, attrtype, value) \ + NLA_PUT_TYPE(msg, int8_t, attrtype, value) + +/** * Add 8 bit integer attribute to netlink message. * @arg msg Netlink message. * @arg attrtype Attribute type. @@ -172,6 +195,15 @@ extern int nla_is_nested(struct nlattr *); NLA_PUT_TYPE(msg, uint8_t, attrtype, value) /** + * Add 16 bit signed integer attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg value Numeric value. + */ +#define NLA_PUT_S16(msg, attrtype, value) \ + NLA_PUT_TYPE(msg, int16_t, attrtype, value) + +/** * Add 16 bit integer attribute to netlink message. * @arg msg Netlink message. * @arg attrtype Attribute type. @@ -181,6 +213,15 @@ extern int nla_is_nested(struct nlattr *); NLA_PUT_TYPE(msg, uint16_t, attrtype, value) /** + * Add 32 bit signed integer attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg value Numeric value. + */ +#define NLA_PUT_S32(msg, attrtype, value) \ + NLA_PUT_TYPE(msg, int32_t, attrtype, value) + +/** * Add 32 bit integer attribute to netlink message. * @arg msg Netlink message. * @arg attrtype Attribute type. @@ -190,6 +231,15 @@ extern int nla_is_nested(struct nlattr *); NLA_PUT_TYPE(msg, uint32_t, attrtype, value) /** + * Add 64 bit signed integer attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg value Numeric value. + */ +#define NLA_PUT_S64(msg, attrtype, value) \ + NLA_PUT_TYPE(msg, int64_t, attrtype, value) + +/** * Add 64 bit integer attribute to netlink message. * @arg msg Netlink message. * @arg attrtype Attribute type. @@ -205,7 +255,7 @@ extern int nla_is_nested(struct nlattr *); * @arg value NUL terminated character string. */ #define NLA_PUT_STRING(msg, attrtype, value) \ - NLA_PUT(msg, attrtype, strlen(value) + 1, value) + NLA_PUT(msg, attrtype, (int) strlen(value) + 1, value) /** * Add flag attribute to netlink message. @@ -272,7 +322,7 @@ extern int nla_is_nested(struct nlattr *); * @arg rem initialized to len, holds bytes currently remaining in stream */ #define nla_for_each_nested(pos, nla, rem) \ - for (pos = nla_data(nla), rem = nla_len(nla); \ + for (pos = (struct nlattr *) nla_data(nla), rem = nla_len(nla); \ nla_ok(pos, rem); \ pos = nla_next(pos, &(rem))) diff --git a/include/netlink/cache-api.h b/include/netlink/cache-api.h index e43c7ca..851eca0 100644 --- a/include/netlink/cache-api.h +++ b/include/netlink/cache-api.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/cache-api.h Caching API - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2013 Thomas Graf */ diff --git a/include/netlink/cache.h b/include/netlink/cache.h index 415bb00..abeeccb 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/cache.h Caching Module - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -35,6 +29,8 @@ enum { struct nl_cache; typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int, void *); +typedef void (*change_func_v2_t)(struct nl_cache *, struct nl_object *old_obj, + struct nl_object *new_obj, uint64_t, int, void *); /** * @ingroup cache @@ -71,11 +67,15 @@ extern int nl_cache_add(struct nl_cache *, struct nl_object *); extern int nl_cache_parse_and_add(struct nl_cache *, struct nl_msg *); +extern int nl_cache_move(struct nl_cache *, + struct nl_object *); extern void nl_cache_remove(struct nl_object *); extern int nl_cache_refill(struct nl_sock *, struct nl_cache *); extern int nl_cache_pickup(struct nl_sock *, struct nl_cache *); +extern int nl_cache_pickup_checkdup(struct nl_sock *, + struct nl_cache *); extern int nl_cache_resync(struct nl_sock *, struct nl_cache *, change_func_t, @@ -84,6 +84,10 @@ extern int nl_cache_include(struct nl_cache *, struct nl_object *, change_func_t, void *); +extern int nl_cache_include_v2(struct nl_cache *, + struct nl_object *, + change_func_v2_t, + void *); extern void nl_cache_set_arg1(struct nl_cache *, int); extern void nl_cache_set_arg2(struct nl_cache *, int); extern void nl_cache_set_flags(struct nl_cache *, unsigned int); @@ -92,8 +96,8 @@ extern void nl_cache_set_flags(struct nl_cache *, unsigned int); extern int nl_cache_is_empty(struct nl_cache *); extern struct nl_object * nl_cache_search(struct nl_cache *, struct nl_object *); -extern struct nl_object * nl_cache_lookup(struct nl_cache *, - struct nl_object *); +extern struct nl_object *nl_cache_find(struct nl_cache *, + struct nl_object *); extern void nl_cache_mark_all(struct nl_cache *); /* Dumping */ @@ -150,6 +154,9 @@ extern int nl_cache_mngr_add(struct nl_cache_mngr *, extern int nl_cache_mngr_add_cache(struct nl_cache_mngr *mngr, struct nl_cache *cache, change_func_t cb, void *data); +extern int nl_cache_mngr_add_cache_v2(struct nl_cache_mngr *mngr, + struct nl_cache *cache, + change_func_v2_t cb, void *data); extern int nl_cache_mngr_get_fd(struct nl_cache_mngr *); extern int nl_cache_mngr_poll(struct nl_cache_mngr *, int); @@ -160,6 +167,8 @@ extern void nl_cache_mngr_free(struct nl_cache_mngr *); extern void nl_cache_ops_get(struct nl_cache_ops *); extern void nl_cache_ops_put(struct nl_cache_ops *); +extern void nl_cache_ops_set_flags(struct nl_cache_ops *, + unsigned int); #ifdef __cplusplus } diff --git a/include/netlink/cli/addr.h b/include/netlink/cli/addr.h index d0fd055..5fcf734 100644 --- a/include/netlink/cli/addr.h +++ b/include/netlink/cli/addr.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/cli/addr.h CLI Address 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 */ @@ -14,6 +8,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + #define nl_cli_addr_alloc_cache(sk) \ nl_cli_alloc_cache((sk), "address", rtnl_addr_alloc_cache) @@ -29,4 +27,8 @@ extern void nl_cli_addr_parse_broadcast(struct rtnl_addr *, char *); extern void nl_cli_addr_parse_preferred(struct rtnl_addr *, char *); extern void nl_cli_addr_parse_valid(struct rtnl_addr *, char *); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/netlink/cli/class.h b/include/netlink/cli/class.h index 5001e42..9552374 100644 --- a/include/netlink/cli/class.h +++ b/include/netlink/cli/class.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/cli/class.h 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 Thomas Graf */ @@ -15,7 +9,15 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + extern struct rtnl_class *nl_cli_class_alloc(void); extern struct nl_cache *nl_cli_class_alloc_cache(struct nl_sock *, int); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/netlink/cli/cls.h b/include/netlink/cli/cls.h index a2707b8..602b198 100644 --- a/include/netlink/cli/cls.h +++ b/include/netlink/cli/cls.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/cli/cls.h 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 Thomas Graf */ @@ -15,10 +9,18 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + extern struct rtnl_cls * nl_cli_cls_alloc(void); extern struct nl_cache * nl_cli_cls_alloc_cache(struct nl_sock *, int, uint32_t); extern void nl_cli_cls_parse_proto(struct rtnl_cls *, char *); extern struct rtnl_ematch_tree *nl_cli_cls_parse_ematch(struct rtnl_cls *, char *); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/netlink/cli/ct.h b/include/netlink/cli/ct.h index bed776b..a50b430 100644 --- a/include/netlink/cli/ct.h +++ b/include/netlink/cli/ct.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/cli/ct.h CLI Conntrack Helper - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2008-2009 Thomas Graf */ @@ -15,6 +9,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + extern struct nfnl_ct *nl_cli_ct_alloc(void); extern struct nl_cache *nl_cli_ct_alloc_cache(struct nl_sock *); @@ -30,5 +28,10 @@ extern void nl_cli_ct_parse_src_port(struct nfnl_ct *, int, char *); extern void nl_cli_ct_parse_dst_port(struct nfnl_ct *, int, char *); extern void nl_cli_ct_parse_tcp_state(struct nfnl_ct *, char *); extern void nl_cli_ct_parse_status(struct nfnl_ct *, char *); +extern void nl_cli_ct_parse_zone(struct nfnl_ct *, char *); + +#ifdef __cplusplus +} +#endif #endif diff --git a/include/netlink/cli/exp.h b/include/netlink/cli/exp.h index b2418f8..64d3b08 100644 --- a/include/netlink/cli/exp.h +++ b/include/netlink/cli/exp.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/cli/exp.h CLI Expectation Helper - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2012 Rich Fought * Copyright (c) 2008-2009 Thomas Graf */ @@ -16,6 +10,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + extern struct nfnl_exp *nl_cli_exp_alloc(void); extern struct nl_cache *nl_cli_exp_alloc_cache(struct nl_sock *); @@ -38,5 +36,8 @@ extern void nl_cli_exp_parse_icmp_id(struct nfnl_exp *, int, char *); extern void nl_cli_exp_parse_icmp_type(struct nfnl_exp *, int, char *); extern void nl_cli_exp_parse_icmp_code(struct nfnl_exp *, int, char *); +#ifdef __cplusplus +} +#endif #endif diff --git a/include/netlink/cli/link.h b/include/netlink/cli/link.h index 3f37948..fb6c0a4 100644 --- a/include/netlink/cli/link.h +++ b/include/netlink/cli/link.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/cli/link.h CLI Link 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-2010 Thomas Graf */ @@ -15,9 +9,17 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + extern struct rtnl_link *nl_cli_link_alloc(void); extern struct nl_cache *nl_cli_link_alloc_cache_family(struct nl_sock *, int); +extern struct nl_cache *nl_cli_link_alloc_cache_family_flags(struct nl_sock *, int, + unsigned int); extern struct nl_cache *nl_cli_link_alloc_cache(struct nl_sock *); +extern struct nl_cache *nl_cli_link_alloc_cache_flags(struct nl_sock *, + unsigned int); extern void nl_cli_link_parse_family(struct rtnl_link *, char *); extern void nl_cli_link_parse_name(struct rtnl_link *, char *); @@ -27,4 +29,8 @@ extern void nl_cli_link_parse_txqlen(struct rtnl_link *, char *); extern void nl_cli_link_parse_weight(struct rtnl_link *, char *); extern void nl_cli_link_parse_ifalias(struct rtnl_link *, char *); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/netlink/cli/mdb.h b/include/netlink/cli/mdb.h new file mode 100644 index 0000000..cd37604 --- /dev/null +++ b/include/netlink/cli/mdb.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#ifndef __NETLINK_CLI_MDB_H_ +#define __NETLINK_CLI_MDB_H_ + +#include + +#define nl_cli_mdb_alloc_cache(sk) \ + nl_cli_alloc_cache_flags((sk), "mdb", NL_CACHE_AF_ITER, rtnl_mdb_alloc_cache) + +#endif diff --git a/include/netlink/cli/neigh.h b/include/netlink/cli/neigh.h index 5440012..89a336c 100644 --- a/include/netlink/cli/neigh.h +++ b/include/netlink/cli/neigh.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/cli/neighbour.h CLI Neighbour 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 */ @@ -14,8 +8,13 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + #define nl_cli_neigh_alloc_cache(sk) \ - nl_cli_alloc_cache((sk), "neighbour", rtnl_neigh_alloc_cache) + nl_cli_alloc_cache_flags((sk), "neighbour", NL_CACHE_AF_ITER, \ + rtnl_neigh_alloc_cache_flags) extern struct rtnl_neigh *nl_cli_neigh_alloc(void); extern void nl_cli_neigh_parse_dst(struct rtnl_neigh *, char *); @@ -24,4 +23,8 @@ extern void nl_cli_neigh_parse_dev(struct rtnl_neigh *, struct nl_cache *, char extern void nl_cli_neigh_parse_family(struct rtnl_neigh *, char *); extern void nl_cli_neigh_parse_state(struct rtnl_neigh *, char *); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/netlink/cli/nh.h b/include/netlink/cli/nh.h new file mode 100644 index 0000000..ee08c8e --- /dev/null +++ b/include/netlink/cli/nh.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2022 Stanislav Zaikin + */ + +#ifndef __NETLINK_CLI_NH_H_ +#define __NETLINK_CLI_NH_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct rtnl_nh *nl_cli_nh_alloc(void); +extern struct nl_cache *nl_cli_nh_alloc_cache_family(struct nl_sock *, int); +extern struct nl_cache *nl_cli_nh_alloc_cache_family_flags(struct nl_sock *, + int, unsigned int); +extern struct nl_cache *nl_cli_nh_alloc_cache(struct nl_sock *); +extern struct nl_cache *nl_cli_nh_alloc_cache_flags(struct nl_sock *, + unsigned int); + +extern void nl_cli_nh_parse_family(struct rtnl_nh *, char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/cli/qdisc.h b/include/netlink/cli/qdisc.h index b102da4..d70e559 100644 --- a/include/netlink/cli/qdisc.h +++ b/include/netlink/cli/qdisc.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/cli/qdisc.h CLI QDisc 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-2011 Thomas Graf */ @@ -14,10 +8,18 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + #define nl_cli_qdisc_alloc_cache(sk) \ nl_cli_alloc_cache((sk), "queueing disciplines", \ rtnl_qdisc_alloc_cache) extern struct rtnl_qdisc *nl_cli_qdisc_alloc(void); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/netlink/cli/route.h b/include/netlink/cli/route.h index 089c658..3650d8b 100644 --- a/include/netlink/cli/route.h +++ b/include/netlink/cli/route.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/cli//route.h CLI Route 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 */ @@ -14,6 +8,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + extern struct rtnl_route *nl_cli_route_alloc(void); extern struct nl_cache *nl_cli_route_alloc_cache(struct nl_sock *, int); @@ -31,4 +29,8 @@ extern void nl_cli_route_parse_protocol(struct rtnl_route *, char *); extern void nl_cli_route_parse_type(struct rtnl_route *, char *); extern void nl_cli_route_parse_iif(struct rtnl_route *, char *, struct nl_cache *); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/netlink/cli/rule.h b/include/netlink/cli/rule.h index 61cd63e..82bf067 100644 --- a/include/netlink/cli/rule.h +++ b/include/netlink/cli/rule.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/cli/rule.h CLI Routing Rule 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 */ @@ -14,8 +8,16 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + extern struct rtnl_rule *nl_cli_rule_alloc(void); extern struct nl_cache *nl_cli_rule_alloc_cache(struct nl_sock *); extern void nl_cli_rule_parse_family(struct rtnl_rule *, char *); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/netlink/cli/tc.h b/include/netlink/cli/tc.h index 77042c7..7d4ed7a 100644 --- a/include/netlink/cli/tc.h +++ b/include/netlink/cli/tc.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/cli/tc.h 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-2011 Thomas Graf */ @@ -14,6 +8,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + struct rtnl_tc_ops; extern void nl_cli_tc_parse_dev(struct rtnl_tc *, struct nl_cache *, char *); @@ -38,4 +36,8 @@ extern struct nl_cli_tc_module *nl_cli_tc_lookup(struct rtnl_tc_ops *); extern void nl_cli_tc_register(struct nl_cli_tc_module *); extern void nl_cli_tc_unregister(struct nl_cli_tc_module *); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/netlink/cli/utils.h b/include/netlink/cli/utils.h index da41c10..7047d2e 100644 --- a/include/netlink/cli/utils.h +++ b/include/netlink/cli/utils.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/utils.h Utilities - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2009 Thomas Graf */ @@ -22,9 +16,9 @@ #include #include #include -#include #include #include +#include #include #include @@ -61,8 +55,10 @@ extern "C" { #endif extern uint32_t nl_cli_parse_u32(const char *); -extern void nl_cli_print_version(void); -extern void nl_cli_fatal(int, const char *, ...); +extern void nl_cli_print_version(void) + __attribute__((noreturn)); +extern void nl_cli_fatal(int, const char *, ...) + __attribute__((noreturn)); extern struct nl_addr * nl_cli_addr_parse(const char *, int); extern int nl_cli_connect(struct nl_sock *, int); extern struct nl_sock * nl_cli_alloc_socket(void); @@ -73,6 +69,10 @@ extern int nl_cli_confirm(struct nl_object *, extern struct nl_cache *nl_cli_alloc_cache(struct nl_sock *, const char *, int (*ac)(struct nl_sock *, struct nl_cache **)); +extern struct nl_cache *nl_cli_alloc_cache_flags(struct nl_sock *, const char *, + unsigned int flags, + int (*ac)(struct nl_sock *, struct nl_cache **, unsigned int)); + extern void nl_cli_load_module(const char *, const char *); #ifdef __cplusplus diff --git a/include/netlink/data.h b/include/netlink/data.h index 071159e..c9c76a1 100644 --- a/include/netlink/data.h +++ b/include/netlink/data.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/data.h Abstract Data - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf */ @@ -18,21 +12,24 @@ extern "C" { #endif +struct nlattr; + struct nl_data; /* General */ -extern struct nl_data * nl_data_alloc(void *, size_t); -extern struct nl_data * nl_data_alloc_attr(struct nlattr *); -extern struct nl_data * nl_data_clone(struct nl_data *); -extern int nl_data_append(struct nl_data *, void *, size_t); +extern struct nl_data * nl_data_alloc(const void *, size_t); +extern struct nl_data * nl_data_alloc_attr(const struct nlattr *); +extern struct nl_data * nl_data_clone(const struct nl_data *); +extern int nl_data_append(struct nl_data *, const void *, size_t); extern void nl_data_free(struct nl_data *); /* Access Functions */ -extern void * nl_data_get(struct nl_data *); -extern size_t nl_data_get_size(struct nl_data *); +extern void * nl_data_get(const struct nl_data *); +extern size_t nl_data_get_size(const struct nl_data *); /* Misc */ -extern int nl_data_cmp(struct nl_data *, struct nl_data *); +extern int nl_data_cmp(const struct nl_data *, + const struct nl_data *); #ifdef __cplusplus } diff --git a/include/netlink/errno.h b/include/netlink/errno.h index f8b5130..6a5b4de 100644 --- a/include/netlink/errno.h +++ b/include/netlink/errno.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/errno.h Error Numbers - * - * 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 Thomas Graf */ @@ -50,8 +44,9 @@ extern "C" { #define NLE_NODEV 31 #define NLE_IMMUTABLE 32 #define NLE_DUMP_INTR 33 +#define NLE_ATTRSIZE 34 -#define NLE_MAX NLE_DUMP_INTR +#define NLE_MAX NLE_ATTRSIZE extern const char * nl_geterror(int); extern void nl_perror(int, const char *); diff --git a/include/netlink/fib_lookup/lookup.h b/include/netlink/fib_lookup/lookup.h index 8bf27b8..81fa435 100644 --- a/include/netlink/fib_lookup/lookup.h +++ b/include/netlink/fib_lookup/lookup.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/fib_lookup/fib_lookup.h FIB Lookup - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf */ @@ -35,6 +29,13 @@ extern int flnl_lookup(struct nl_sock *, struct flnl_request *, struct nl_cache *); +extern int flnl_result_get_table_id(struct flnl_result *res); +extern int flnl_result_get_prefixlen(struct flnl_result *res); +extern int flnl_result_get_nexthop_sel(struct flnl_result *res); +extern int flnl_result_get_type(struct flnl_result *res); +extern int flnl_result_get_scope(struct flnl_result *res); +extern int flnl_result_get_error(struct flnl_result *res); + #ifdef __cplusplus } #endif diff --git a/include/netlink/fib_lookup/request.h b/include/netlink/fib_lookup/request.h index 60e8820..ed7cdd8 100644 --- a/include/netlink/fib_lookup/request.h +++ b/include/netlink/fib_lookup/request.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/fib_lookup/request.h FIB Lookup Request - * - * 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 */ diff --git a/include/netlink/genl/ctrl.h b/include/netlink/genl/ctrl.h index 017b8fd..92d60b3 100644 --- a/include/netlink/genl/ctrl.h +++ b/include/netlink/genl/ctrl.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/genl/ctrl.h Generic Netlink Controller - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ diff --git a/include/netlink/genl/family.h b/include/netlink/genl/family.h index 5432b59..2e9f9fd 100644 --- a/include/netlink/genl/family.h +++ b/include/netlink/genl/family.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/genl/family.h Generic Netlink Family - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ diff --git a/include/netlink/genl/genl.h b/include/netlink/genl/genl.h index e455581..f1e3a65 100644 --- a/include/netlink/genl/genl.h +++ b/include/netlink/genl/genl.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/genl/genl.h Generic Netlink - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -29,9 +23,9 @@ extern void * genlmsg_put(struct nl_msg *, uint32_t, uint32_t, extern int genlmsg_valid_hdr(struct nlmsghdr *, int); extern int genlmsg_validate(struct nlmsghdr *, int, int, - struct nla_policy *); + const struct nla_policy *); extern int genlmsg_parse(struct nlmsghdr *, int, struct nlattr **, - int, struct nla_policy *); + int, const struct nla_policy *); extern struct genlmsghdr * genlmsg_hdr(struct nlmsghdr *); extern void * genlmsg_data(const struct genlmsghdr *); diff --git a/include/netlink/genl/mngt.h b/include/netlink/genl/mngt.h index 8a51ccd..af9edb3 100644 --- a/include/netlink/genl/mngt.h +++ b/include/netlink/genl/mngt.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/genl/mngt.h Generic Netlink Management - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ diff --git a/include/netlink/handlers.h b/include/netlink/handlers.h index dfa2809..2043844 100644 --- a/include/netlink/handlers.h +++ b/include/netlink/handlers.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/handlers.c default netlink message handlers - * - * 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 */ @@ -22,10 +16,13 @@ extern "C" { #endif +struct nlmsgerr; +struct sockaddr_nl; +struct ucred; + struct nl_cb; struct nl_sock; struct nl_msg; -struct ucred; /** * @name Callback Typedefs @@ -36,7 +33,7 @@ struct ucred; * nl_recvmsgs() callback for message processing customization * @ingroup cb * @arg msg netlink message being processed - * @arg arg argument passwd on through caller + * @arg arg argument passed on through caller */ typedef int (*nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg); @@ -57,7 +54,7 @@ typedef int (*nl_recvmsg_err_cb_t)(struct sockaddr_nl *nla, * @ingroup cb */ enum nl_cb_action { - /** Proceed with wathever would come next */ + /** Proceed with whatever would come next */ NL_OK, /** Skip this message */ NL_SKIP, @@ -96,7 +93,7 @@ enum nl_cb_type { NL_CB_OVERRUN, /** Message wants to be skipped */ NL_CB_SKIPPED, - /** Message is an acknowledge */ + /** Message is an acknowledgement */ NL_CB_ACK, /** Called for every message received */ NL_CB_MSG_IN, @@ -139,6 +136,8 @@ extern void nl_cb_overwrite_send(struct nl_cb *, int (*func)(struct nl_sock *, struct nl_msg *)); +extern enum nl_cb_type nl_cb_active_type(struct nl_cb *cb); + #ifdef __cplusplus } #endif diff --git a/include/netlink/hash.h b/include/netlink/hash.h index 0bda74e..5df4099 100644 --- a/include/netlink/hash.h +++ b/include/netlink/hash.h @@ -5,6 +5,7 @@ */ #ifndef CCAN_HASH_H #define CCAN_HASH_H + #include #include #include @@ -14,6 +15,10 @@ * http://burtleburtle.net/bob/c/lookup3.c */ +#ifdef __cplusplus +extern "C" { +#endif + #ifdef __LITTLE_ENDIAN # define HAVE_LITTLE_ENDIAN 1 #elif __BIG_ENDIAN @@ -66,4 +71,8 @@ /* Our underlying operations. */ uint32_t nl_hash_any(const void *key, size_t length, uint32_t base); +#ifdef __cplusplus +} +#endif + #endif /* HASH_H */ diff --git a/include/netlink/hashtable.h b/include/netlink/hashtable.h index d9e6ee4..32578dc 100644 --- a/include/netlink/hashtable.h +++ b/include/netlink/hashtable.h @@ -1,17 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/hashtable.h Netlink hashtable Utilities - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2012 Cumulus Networks, Inc */ #ifndef NETLINK_HASHTABLE_H_ #define NETLINK_HASHTABLE_H_ +#include +#include + #ifdef __cplusplus extern "C" { #endif diff --git a/include/netlink/idiag/idiagnl.h b/include/netlink/idiag/idiagnl.h new file mode 100644 index 0000000..7385d5f --- /dev/null +++ b/include/netlink/idiag/idiagnl.h @@ -0,0 +1,145 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Sassano Systems LLC + */ + +#ifndef NETLINK_IDIAGNL_H_ +#define NETLINK_IDIAGNL_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************* + * The following part contains DEPRECATED names and defines. + * Don't use them. + *************************************************************/ + +/** + * Inet Diag message types + * + * deprecated: use TCPDIAG_GETSOCK, DCCPDIAG_GETSOCK and + * INET_DIAG_GETSOCK_MAX from linux/inet_diag.h + */ +#define IDIAG_TCPDIAG_GETSOCK 18 +#define IDIAG_DCCPDIAG_GETSOCK 19 +#define IDIAG_GETSOCK_MAX 24 + +/** + * Socket state identifiers + * @ingroup idiag + * @deprecated: use instead the TCP_* defines from netinet/tcp.h. + */ +enum { + IDIAG_SS_UNKNOWN = 0, + + IDIAG_SS_ESTABLISHED = 1, /* TCP_ESTABLISHED */ + IDIAG_SS_SYN_SENT = 2, /* TCP_SYN_SENT */ + IDIAG_SS_SYN_RECV = 3, /* TCP_SYN_RECV */ + IDIAG_SS_FIN_WAIT1 = 4, /* TCP_FIN_WAIT1 */ + IDIAG_SS_FIN_WAIT2 = 5, /* TCP_FIN_WAIT2 */ + IDIAG_SS_TIME_WAIT = 6, /* TCP_TIME_WAIT */ + IDIAG_SS_CLOSE = 7, /* TCP_CLOSE */ + IDIAG_SS_CLOSE_WAIT = 8, /* TCP_CLOSE_WAIT */ + IDIAG_SS_LAST_ACK = 9, /* TCP_LAST_ACK */ + IDIAG_SS_LISTEN = 10, /* TCP_LISTEN */ + IDIAG_SS_CLOSING = 11, /* TCP_CLOSING */ + + IDIAG_SS_MAX = 12, +}; + +/** + * Macro to represent all socket states. + * @ingroup idiag + * @deprecated + */ +#define IDIAG_SS_ALL IDIAGNL_SS_ALL + + +/** + * Inet Diag extended attributes + * @ingroup idiag + * @deprecated These attributes should not be used. They mirror the + * INET_DIAG_* extension flags from kernel headers. Use those instead. */ +enum { + IDIAG_ATTR_NONE = 0, /* INET_DIAG_NONE */ + IDIAG_ATTR_MEMINFO = 1, /* INET_DIAG_MEMINFO */ + IDIAG_ATTR_INFO = 2, /* INET_DIAG_INFO */ + IDIAG_ATTR_VEGASINFO = 3, /* INET_DIAG_VEGASINFO */ + IDIAG_ATTR_CONG = 4, /* INET_DIAG_CONG */ + IDIAG_ATTR_TOS = 5, /* INET_DIAG_TOS */ + IDIAG_ATTR_TCLASS = 6, /* INET_DIAG_TCLASS */ + IDIAG_ATTR_SKMEMINFO = 7, /* INET_DIAG_SKMEMINFO */ + IDIAG_ATTR_SHUTDOWN = 8, /* INET_DIAG_SHUTDOWN */ + + /* IDIAG_ATTR_MAX was wrong, because it did not correspond to + * INET_DIAG_MAX. Anyway, freeze it to the previous value. */ + IDIAG_ATTR_MAX = 9, + + IDIAG_ATTR_ALL = (1< + */ + +#ifndef NETLINK_IDIAGNL_MEMINFO_H_ +#define NETLINK_IDIAGNL_MEMINFO_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +extern struct nl_object_ops idiagnl_meminfo_obj_ops; + +extern struct idiagnl_meminfo *idiagnl_meminfo_alloc(void); +extern void idiagnl_meminfo_get(struct idiagnl_meminfo *); +extern void idiagnl_meminfo_put(struct idiagnl_meminfo *); + +extern uint32_t idiagnl_meminfo_get_rmem(const struct idiagnl_meminfo *); +extern uint32_t idiagnl_meminfo_get_wmem(const struct idiagnl_meminfo *); +extern uint32_t idiagnl_meminfo_get_fmem(const struct idiagnl_meminfo *); +extern uint32_t idiagnl_meminfo_get_tmem(const struct idiagnl_meminfo *); + +extern void idiagnl_meminfo_set_rmem(struct idiagnl_meminfo *, uint32_t); +extern void idiagnl_meminfo_set_wmem(struct idiagnl_meminfo *, uint32_t); +extern void idiagnl_meminfo_set_fmem(struct idiagnl_meminfo *, uint32_t); +extern void idiagnl_meminfo_set_tmem(struct idiagnl_meminfo *, uint32_t); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* NETLINK_IDIAGNL_MEMINFO_H_ */ diff --git a/include/netlink/idiag/msg.h b/include/netlink/idiag/msg.h new file mode 100644 index 0000000..f2a79ce --- /dev/null +++ b/include/netlink/idiag/msg.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Sassano Systems LLC + */ + +#ifndef NETLINK_IDIAGNL_MSG_H_ +#define NETLINK_IDIAGNL_MSG_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct idiagnl_msg; + +/* @deprecated: DO NOT USE this variable. */ +extern struct nl_object_ops idiagnl_msg_obj_ops; + +extern struct idiagnl_msg * idiagnl_msg_alloc(void); +extern int idiagnl_msg_alloc_cache(struct nl_sock *, int, int, + struct nl_cache**); +extern void idiagnl_msg_get(struct idiagnl_msg *); +extern void idiagnl_msg_put(struct idiagnl_msg *); +extern uint8_t idiagnl_msg_get_family(const struct idiagnl_msg *); +extern void idiagnl_msg_set_family(struct idiagnl_msg *, uint8_t); +extern uint8_t idiagnl_msg_get_state(const struct idiagnl_msg *); +extern void idiagnl_msg_set_state(struct idiagnl_msg *, uint8_t); +extern uint8_t idiagnl_msg_get_timer(const struct idiagnl_msg *); +extern void idiagnl_msg_set_timer(struct idiagnl_msg *, uint8_t); +extern uint8_t idiagnl_msg_get_retrans(const struct idiagnl_msg *); +extern void idiagnl_msg_set_retrans(struct idiagnl_msg *, uint8_t); +extern uint16_t idiagnl_msg_get_sport(struct idiagnl_msg *); +extern void idiagnl_msg_set_sport(struct idiagnl_msg *, uint16_t); +extern uint16_t idiagnl_msg_get_dport(struct idiagnl_msg *); +extern void idiagnl_msg_set_dport(struct idiagnl_msg *, uint16_t); +extern struct nl_addr * idiagnl_msg_get_src(const struct idiagnl_msg *); +extern int idiagnl_msg_set_src(struct idiagnl_msg *, + struct nl_addr *); +extern struct nl_addr * idiagnl_msg_get_dst(const struct idiagnl_msg *); +extern int idiagnl_msg_set_dst(struct idiagnl_msg *, + struct nl_addr *); +extern uint32_t idiagnl_msg_get_ifindex(const struct idiagnl_msg *); +extern void idiagnl_msg_set_ifindex(struct idiagnl_msg *, uint32_t); +extern uint32_t idiagnl_msg_get_expires(const struct idiagnl_msg *); +extern void idiagnl_msg_set_expires(struct idiagnl_msg *, uint32_t); +extern uint32_t idiagnl_msg_get_rqueue(const struct idiagnl_msg *); +extern void idiagnl_msg_set_rqueue(struct idiagnl_msg *, uint32_t); +extern uint32_t idiagnl_msg_get_wqueue(const struct idiagnl_msg *); +extern void idiagnl_msg_set_wqueue(struct idiagnl_msg *, uint32_t); +extern uint32_t idiagnl_msg_get_uid(const struct idiagnl_msg *); +extern void idiagnl_msg_set_uid(struct idiagnl_msg *, uint32_t); +extern uint32_t idiagnl_msg_get_inode(const struct idiagnl_msg *); +extern void idiagnl_msg_set_inode(struct idiagnl_msg *, uint32_t); +extern uint8_t idiagnl_msg_get_tos(const struct idiagnl_msg *); +extern void idiagnl_msg_set_tos(struct idiagnl_msg *, uint8_t); +extern uint8_t idiagnl_msg_get_tclass(const struct idiagnl_msg *); +extern void idiagnl_msg_set_tclass(struct idiagnl_msg *, uint8_t); +extern uint8_t idiagnl_msg_get_shutdown(const struct idiagnl_msg *); +extern void idiagnl_msg_set_shutdown(struct idiagnl_msg *, uint8_t); +extern char * idiagnl_msg_get_cong(const struct idiagnl_msg *); +extern void idiagnl_msg_set_cong(struct idiagnl_msg *, char *); +extern struct idiagnl_meminfo *idiagnl_msg_get_meminfo(const struct idiagnl_msg *); +extern void idiagnl_msg_set_meminfo(struct idiagnl_msg *, + struct idiagnl_meminfo *); +extern struct idiagnl_vegasinfo *idiagnl_msg_get_vegasinfo(const struct idiagnl_msg *); +extern void idiagnl_msg_set_vegasinfo(struct idiagnl_msg *, + struct idiagnl_vegasinfo *); +extern struct tcp_info idiagnl_msg_get_tcpinfo(const struct idiagnl_msg *); +extern void idiagnl_msg_set_tcpinfo(struct idiagnl_msg *, + struct tcp_info *); + +extern int idiagnl_msg_parse(struct nlmsghdr *, + struct idiagnl_msg **); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* NETLINK_IDIAGNL_MSG_H_ */ diff --git a/include/netlink/idiag/req.h b/include/netlink/idiag/req.h new file mode 100644 index 0000000..fb75b96 --- /dev/null +++ b/include/netlink/idiag/req.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Sassano Systems LLC + */ + +#ifndef NETLINK_IDIAGNL_REQ_H_ +#define NETLINK_IDIAGNL_REQ_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct idiagnl_req; +extern struct nl_object_ops idiagnl_req_obj_ops; + +extern struct idiagnl_req * idiagnl_req_alloc(void); +extern void idiagnl_req_get(struct idiagnl_req *); +extern void idiagnl_req_put(struct idiagnl_req *); +extern uint8_t idiagnl_req_get_family(const struct idiagnl_req *); +extern void idiagnl_req_set_family(struct idiagnl_req *, + uint8_t); +extern uint8_t idiagnl_req_get_ext(const struct idiagnl_req *); +extern void idiagnl_req_set_ext(struct idiagnl_req *, uint8_t); +extern uint32_t idiagnl_req_get_ifindex(const struct idiagnl_req *); +extern void idiagnl_req_set_ifindex(struct idiagnl_req *, + uint32_t); +extern uint32_t idiagnl_req_get_states(const struct idiagnl_req *); +extern void idiagnl_req_set_states(struct idiagnl_req *, + uint32_t); +extern uint32_t idiagnl_req_get_dbs(const struct idiagnl_req *); +extern void idiagnl_req_set_dbs(struct idiagnl_req *, uint32_t); +extern struct nl_addr * idiagnl_req_get_src(const struct idiagnl_req *); +extern int idiagnl_req_set_src(struct idiagnl_req *, + struct nl_addr *); +extern struct nl_addr * idiagnl_req_get_dst(const struct idiagnl_req *); +extern int idiagnl_req_set_dst(struct idiagnl_req *, + struct nl_addr *); + +extern int idiagnl_req_parse(struct nlmsghdr *nlh, + struct idiagnl_req **result); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* NETLINK_IDIAGNL_REQ_H_ */ diff --git a/include/netlink/idiag/vegasinfo.h b/include/netlink/idiag/vegasinfo.h new file mode 100644 index 0000000..890c175 --- /dev/null +++ b/include/netlink/idiag/vegasinfo.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Sassano Systems LLC + */ + +#ifndef NETLINK_IDIAGNL_VEGASINFO_H_ +#define NETLINK_IDIAGNL_VEGASINFO_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +extern struct nl_object_ops idiagnl_vegasinfo_obj_ops; +extern struct idiagnl_vegasinfo * idiagnl_vegasinfo_alloc(void); +extern void idiagnl_vegasinfo_get(struct idiagnl_vegasinfo *); +extern void idiagnl_vegasinfo_put(struct idiagnl_vegasinfo *); + +extern uint32_t idiagnl_vegasinfo_get_enabled(const struct idiagnl_vegasinfo *); +extern uint32_t idiagnl_vegasinfo_get_rttcnt(const struct idiagnl_vegasinfo *); +extern uint32_t idiagnl_vegasinfo_get_rtt(const struct idiagnl_vegasinfo *); +extern uint32_t idiagnl_vegasinfo_get_minrtt(const struct idiagnl_vegasinfo *); + +extern void idiagnl_vegasinfo_set_enabled(struct idiagnl_vegasinfo *, + uint32_t); +extern void idiagnl_vegasinfo_set_rttcnt(struct idiagnl_vegasinfo *, + uint32_t); +extern void idiagnl_vegasinfo_set_rtt(struct idiagnl_vegasinfo *, uint32_t); +extern void idiagnl_vegasinfo_set_minrtt(struct idiagnl_vegasinfo *, + uint32_t); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* NETLINK_IDIAGNL_VEGASINFO_H_ */ diff --git a/include/netlink/list.h b/include/netlink/list.h index 28712ed..7f300df 100644 --- a/include/netlink/list.h +++ b/include/netlink/list.h @@ -1,17 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/list.h Netlink List Utilities - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2006 Thomas Graf */ #ifndef NETLINK_LIST_H_ #define NETLINK_LIST_H_ +#include + +#ifdef __cplusplus +extern "C" { +#endif + struct nl_list_head { struct nl_list_head * next; @@ -58,8 +58,8 @@ static inline int nl_list_empty(struct nl_list_head *head) } #define nl_container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - ((size_t) &((type *)0)->member));}) + const __typeof__( ((type *)0)->member ) *__mptr = (ptr);\ + (type *)( (char *)__mptr - (offsetof(type, member)));}) #define nl_list_entry(ptr, type, member) \ nl_container_of(ptr, type, member) @@ -77,17 +77,21 @@ static inline int nl_list_empty(struct nl_list_head *head) nl_list_entry((head)->next, type, member) #define nl_list_for_each_entry(pos, head, member) \ - for (pos = nl_list_entry((head)->next, typeof(*pos), member); \ + for (pos = nl_list_entry((head)->next, __typeof__(*pos), member); \ &(pos)->member != (head); \ - (pos) = nl_list_entry((pos)->member.next, typeof(*(pos)), member)) + (pos) = nl_list_entry((pos)->member.next, __typeof__(*(pos)), member)) #define nl_list_for_each_entry_safe(pos, n, head, member) \ - for (pos = nl_list_entry((head)->next, typeof(*pos), member), \ - n = nl_list_entry(pos->member.next, typeof(*pos), member); \ + for (pos = nl_list_entry((head)->next, __typeof__(*pos), member), \ + n = nl_list_entry(pos->member.next, __typeof__(*pos), member); \ &(pos)->member != (head); \ - pos = n, n = nl_list_entry(n->member.next, typeof(*n), member)) + pos = n, n = nl_list_entry(n->member.next, __typeof__(*n), member)) #define nl_init_list_head(head) \ do { (head)->next = (head); (head)->prev = (head); } while (0) +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/netlink/msg.h b/include/netlink/msg.h index f3d50ae..84aaa60 100644 --- a/include/netlink/msg.h +++ b/include/netlink/msg.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/msg.c Netlink Messages Interface - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2006 Thomas Graf */ @@ -20,6 +14,8 @@ extern "C" { #endif +struct nlmsghdr; + #define NL_DONTPAD 0 /** @@ -64,10 +60,10 @@ extern int nlmsg_valid_hdr(const struct nlmsghdr *, int); extern int nlmsg_ok(const struct nlmsghdr *, int); extern struct nlmsghdr * nlmsg_next(struct nlmsghdr *, int *); extern int nlmsg_parse(struct nlmsghdr *, int, struct nlattr **, - int, struct nla_policy *); + int, const struct nla_policy *); extern struct nlattr * nlmsg_find_attr(struct nlmsghdr *, int, int); extern int nlmsg_validate(struct nlmsghdr *, int, int, - struct nla_policy *); + const struct nla_policy *); extern struct nl_msg * nlmsg_alloc(void); extern struct nl_msg * nlmsg_alloc_size(size_t); diff --git a/include/netlink/netfilter/ct.h b/include/netlink/netfilter/ct.h index 57fbe53..ddf1373 100644 --- a/include/netlink/netfilter/ct.h +++ b/include/netlink/netfilter/ct.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/netfilter/ct.h Conntrack - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation @@ -18,6 +12,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -25,6 +20,11 @@ extern "C" { struct nfnl_ct; +struct nfnl_ct_timestamp { + uint64_t start; + uint64_t stop; +}; + extern struct nl_object_ops ct_obj_ops; extern struct nfnl_ct * nfnl_ct_alloc(void); @@ -32,6 +32,7 @@ extern int nfnl_ct_alloc_cache(struct nl_sock *, struct nl_cache **); extern int nfnlmsg_ct_group(struct nlmsghdr *); extern int nfnlmsg_ct_parse(struct nlmsghdr *, struct nfnl_ct **); +extern int nfnlmsg_ct_parse_nested(struct nlattr *, struct nfnl_ct **); extern void nfnl_ct_get(struct nfnl_ct *); extern void nfnl_ct_put(struct nfnl_ct *); @@ -65,6 +66,7 @@ extern int nfnl_ct_str2tcp_state(const char *name); extern void nfnl_ct_set_status(struct nfnl_ct *, uint32_t); extern void nfnl_ct_unset_status(struct nfnl_ct *, uint32_t); +extern int nfnl_ct_test_status(const struct nfnl_ct *ct); extern uint32_t nfnl_ct_get_status(const struct nfnl_ct *); extern char * nfnl_ct_status2str(int, char *, size_t); extern int nfnl_ct_str2status(const char *); @@ -85,6 +87,10 @@ extern void nfnl_ct_set_id(struct nfnl_ct *, uint32_t); extern int nfnl_ct_test_id(const struct nfnl_ct *); extern uint32_t nfnl_ct_get_id(const struct nfnl_ct *); +extern void nfnl_ct_set_zone(struct nfnl_ct *, uint16_t); +extern int nfnl_ct_test_zone(const struct nfnl_ct *); +extern uint16_t nfnl_ct_get_zone(const struct nfnl_ct *); + extern int nfnl_ct_set_src(struct nfnl_ct *, int, struct nl_addr *); extern struct nl_addr * nfnl_ct_get_src(const struct nfnl_ct *, int); @@ -119,6 +125,10 @@ extern void nfnl_ct_set_bytes(struct nfnl_ct *, int, uint64_t); extern int nfnl_ct_test_bytes(const struct nfnl_ct *, int); extern uint64_t nfnl_ct_get_bytes(const struct nfnl_ct *, int); +extern void nfnl_ct_set_timestamp(struct nfnl_ct *, uint64_t, uint64_t); +extern int nfnl_ct_test_timestamp(const struct nfnl_ct *); +extern const struct nfnl_ct_timestamp *nfnl_ct_get_timestamp(const struct nfnl_ct *); + #ifdef __cplusplus } #endif diff --git a/include/netlink/netfilter/exp.h b/include/netlink/netfilter/exp.h index 4e95014..bd80514 100644 --- a/include/netlink/netfilter/exp.h +++ b/include/netlink/netfilter/exp.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/netfilter/exp.h Conntrack Expectation - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation @@ -82,7 +76,10 @@ extern uint16_t nfnl_exp_get_zone(const struct nfnl_exp *); extern void nfnl_exp_set_flags(struct nfnl_exp *, uint32_t); extern int nfnl_exp_test_flags(const struct nfnl_exp *); +extern void nfnl_exp_unset_flags(struct nfnl_exp *exp, uint32_t flags); extern uint32_t nfnl_exp_get_flags(const struct nfnl_exp *); +extern char * nfnl_exp_flags2str(int flags, char *buf, size_t len); +int nfnl_exp_str2flags(const char *name); extern void nfnl_exp_set_class(struct nfnl_exp *, uint32_t); extern int nfnl_exp_test_class(const struct nfnl_exp *); diff --git a/include/netlink/netfilter/log.h b/include/netlink/netfilter/log.h index 2002fa8..a8ca81d 100644 --- a/include/netlink/netfilter/log.h +++ b/include/netlink/netfilter/log.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/netfilter/log.h Netfilter Log - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2006 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation @@ -36,6 +30,7 @@ enum nfnl_log_copy_mode { enum nfnl_log_flags { NFNL_LOG_FLAG_SEQ = 0x1, NFNL_LOG_FLAG_SEQ_GLOBAL = 0x2, + NFNL_LOG_FLAG_CONNTRACK = 0x4, }; /* General */ @@ -58,7 +53,7 @@ extern enum nfnl_log_copy_mode nfnl_log_get_copy_mode(const struct nfnl_log *); extern char * nfnl_log_copy_mode2str(enum nfnl_log_copy_mode, char *, size_t); -extern enum nfnl_log_copy_mode nfnl_log_str2copy_mode(const char *); +extern int nfnl_log_str2copy_mode(const char *); extern void nfnl_log_set_copy_range(struct nfnl_log *, uint32_t); extern int nfnl_log_test_copy_range(const struct nfnl_log *); diff --git a/include/netlink/netfilter/log_msg.h b/include/netlink/netfilter/log_msg.h index 63b0f64..b3672da 100644 --- a/include/netlink/netfilter/log_msg.h +++ b/include/netlink/netfilter/log_msg.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/netfilter/log_msg.h Netfilter Log Message - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation @@ -23,6 +17,7 @@ extern "C" { struct nlmsghdr; struct nfnl_log_msg; +struct nfnl_ct; extern struct nl_object_ops log_msg_obj_ops; @@ -90,6 +85,36 @@ extern void nfnl_log_msg_set_seq_global(struct nfnl_log_msg *, uint32_t); extern int nfnl_log_msg_test_seq_global(const struct nfnl_log_msg *); extern uint32_t nfnl_log_msg_get_seq_global(const struct nfnl_log_msg *); +extern void nfnl_log_msg_set_hwtype(struct nfnl_log_msg *, uint16_t); +extern int nfnl_log_msg_test_hwtype(const struct nfnl_log_msg *); +extern uint16_t nfnl_log_msg_get_hwtype(const struct nfnl_log_msg *); + +extern void nfnl_log_msg_set_hwlen(struct nfnl_log_msg *, uint16_t); +extern int nfnl_log_msg_test_hwlen(const struct nfnl_log_msg *); +extern uint16_t nfnl_log_msg_get_hwlen(const struct nfnl_log_msg *); + +extern int nfnl_log_msg_set_hwheader(struct nfnl_log_msg *, void *, int); +extern int nfnl_log_msg_test_hwheader(const struct nfnl_log_msg *); +extern const void * nfnl_log_msg_get_hwheader(const struct nfnl_log_msg *, int *); + +extern void nfnl_log_msg_set_vlan_proto(struct nfnl_log_msg *, uint16_t); +extern int nfnl_log_msg_test_vlan_proto(const struct nfnl_log_msg *); +extern uint16_t nfnl_log_msg_get_vlan_proto(const struct nfnl_log_msg *); +extern void nfnl_log_msg_set_vlan_tag(struct nfnl_log_msg *, uint16_t); +extern int nfnl_log_msg_test_vlan_tag(const struct nfnl_log_msg *); +extern uint16_t nfnl_log_msg_get_vlan_tag(const struct nfnl_log_msg *); +extern uint16_t nfnl_log_msg_get_vlan_id(const struct nfnl_log_msg *); +extern uint16_t nfnl_log_msg_get_vlan_cfi(const struct nfnl_log_msg *); +extern uint16_t nfnl_log_msg_get_vlan_prio(const struct nfnl_log_msg *); + +extern void nfnl_log_msg_set_ct_info(struct nfnl_log_msg *, uint32_t); +extern int nfnl_log_msg_test_ct_info(const struct nfnl_log_msg *); +extern uint32_t nfnl_log_msg_get_ct_info(const struct nfnl_log_msg *); + +extern void nfnl_log_msg_set_ct(struct nfnl_log_msg *, struct nfnl_ct *); +extern int nfnl_log_msg_test_ct(const struct nfnl_log_msg *); +extern struct nfnl_ct * nfnl_log_msg_get_ct(const struct nfnl_log_msg *); + #ifdef __cplusplus } #endif diff --git a/include/netlink/netfilter/netfilter.h b/include/netlink/netfilter/netfilter.h index dd3589c..f365a21 100644 --- a/include/netlink/netfilter/netfilter.h +++ b/include/netlink/netfilter/netfilter.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/netfilter/netfilter.h Netfilter generic functions - * - * 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 Patrick McHardy */ diff --git a/include/netlink/netfilter/nfnl.h b/include/netlink/netfilter/nfnl.h index 8da4ba1..6e349ad 100644 --- a/include/netlink/netfilter/nfnl.h +++ b/include/netlink/netfilter/nfnl.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/nfnl/nfnl.h Netfilter Netlink - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation diff --git a/include/netlink/netfilter/queue.h b/include/netlink/netfilter/queue.h index 664610d..f393f4e 100644 --- a/include/netlink/netfilter/queue.h +++ b/include/netlink/netfilter/queue.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/netfilter/queue.h Netfilter Queue - * - * 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) 2007, 2008 Patrick McHardy */ @@ -54,7 +48,7 @@ extern enum nfnl_queue_copy_mode nfnl_queue_get_copy_mode(const struct nfnl_queu extern char * nfnl_queue_copy_mode2str(enum nfnl_queue_copy_mode, char *, size_t); -extern enum nfnl_queue_copy_mode nfnl_queue_str2copy_mode(const char *); +extern int nfnl_queue_str2copy_mode(const char *); extern void nfnl_queue_set_copy_range(struct nfnl_queue *, uint32_t); diff --git a/include/netlink/netfilter/queue_msg.h b/include/netlink/netfilter/queue_msg.h index 24ed081..dc333e0 100644 --- a/include/netlink/netfilter/queue_msg.h +++ b/include/netlink/netfilter/queue_msg.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/netfilter/queue_msg.h Netfilter Queue Messages - * - * 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) 2007, 2008 Patrick McHardy */ @@ -93,6 +87,10 @@ extern unsigned int nfnl_queue_msg_get_verdict(const struct nfnl_queue_msg *); extern struct nl_msg * nfnl_queue_msg_build_verdict(const struct nfnl_queue_msg *); extern int nfnl_queue_msg_send_verdict(struct nl_sock *, const struct nfnl_queue_msg *); + +extern struct nl_msg * nfnl_queue_msg_build_verdict_batch(const struct nfnl_queue_msg *msg); +extern int nfnl_queue_msg_send_verdict_batch(struct nl_sock *, + const struct nfnl_queue_msg *); extern int nfnl_queue_msg_send_verdict_payload(struct nl_sock *, const struct nfnl_queue_msg *, const void *, unsigned ); diff --git a/include/netlink/netlink-compat.h b/include/netlink/netlink-compat.h index 17ec9fc..76b4595 100644 --- a/include/netlink/netlink-compat.h +++ b/include/netlink/netlink-compat.h @@ -1,17 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/netlink-compat.h Netlink Compatability - * - * 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 */ #ifndef NETLINK_COMPAT_H_ #define NETLINK_COMPAT_H_ +#ifdef __cplusplus +extern "C" { +#endif + #if !defined _LINUX_SOCKET_H && !defined _BITS_SOCKADDR_H typedef unsigned short sa_family_t; #endif @@ -47,4 +45,12 @@ typedef unsigned short sa_family_t; #define AF_LLC 26 #endif +#ifndef AF_MPLS +#define AF_MPLS 28 +#endif + +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/netlink/netlink.h b/include/netlink/netlink.h index 1d74ba1..c5ec350 100644 --- a/include/netlink/netlink.h +++ b/include/netlink/netlink.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/netlink.h Netlink Interface - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2013 Thomas Graf */ @@ -16,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -26,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -37,6 +32,7 @@ extern "C" { #endif +struct nlmsghdr; struct ucred; struct nl_cache_ops; struct nl_parser_param; @@ -86,6 +82,11 @@ extern int nl_pickup(struct nl_sock *, struct nlmsghdr *, struct nl_parser_param *), struct nl_object **); +extern int nl_pickup_keep_syserr(struct nl_sock *sk, + int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *, + struct nlmsghdr *, struct nl_parser_param *), + struct nl_object **result, + int *syserror); /* Netlink Family Translations */ extern char * nl_nlfamily2str(int, char *, size_t); extern int nl_str2nlfamily(const char *); diff --git a/include/netlink/object-api.h b/include/netlink/object-api.h index 75f29cb..d08bafa 100644 --- a/include/netlink/object-api.h +++ b/include/netlink/object-api.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/object-api.h Object API - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2013 Thomas Graf */ diff --git a/include/netlink/object.h b/include/netlink/object.h index a95feda..7448df6 100644 --- a/include/netlink/object.h +++ b/include/netlink/object.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/object.c Generic Cacheable Object - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -43,6 +37,8 @@ extern int nl_object_identical(struct nl_object *, struct nl_object *); extern uint32_t nl_object_diff(struct nl_object *, struct nl_object *); +extern uint64_t nl_object_diff64(struct nl_object *, + struct nl_object *); extern int nl_object_match_filter(struct nl_object *, struct nl_object *); extern char * nl_object_attrs2str(struct nl_object *, diff --git a/include/netlink/route/act/gact.h b/include/netlink/route/act/gact.h new file mode 100644 index 0000000..b3a57f7 --- /dev/null +++ b/include/netlink/route/act/gact.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2016 Sushma Sitaram + */ + +#ifndef NETLINK_GACT_H_ +#define NETLINK_GACT_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_gact_set_action(struct rtnl_act *act, int action); +extern int rtnl_gact_get_action(struct rtnl_act *act); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/act/mirred.h b/include/netlink/route/act/mirred.h new file mode 100644 index 0000000..14fe988 --- /dev/null +++ b/include/netlink/route/act/mirred.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Cong Wang + */ + +#ifndef NETLINK_MIRRED_H_ +#define NETLINK_MIRRED_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_mirred_set_action(struct rtnl_act *, int); +extern int rtnl_mirred_get_action(struct rtnl_act *); +extern int rtnl_mirred_set_ifindex(struct rtnl_act *, uint32_t); +extern uint32_t rtnl_mirred_get_ifindex(struct rtnl_act *); +extern int rtnl_mirred_set_policy(struct rtnl_act *, int); +extern int rtnl_mirred_get_policy(struct rtnl_act *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/act/nat.h b/include/netlink/route/act/nat.h new file mode 100644 index 0000000..41295ce --- /dev/null +++ b/include/netlink/route/act/nat.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2016 Magnus Öberg + */ + +#ifndef NETLINK_NAT_H_ +#define NETLINK_NAT_H_ + +#include +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_nat_set_old_addr(struct rtnl_act *act, in_addr_t addr); +extern int rtnl_nat_get_old_addr(struct rtnl_act *act, in_addr_t *addr); +extern int rtnl_nat_set_new_addr(struct rtnl_act *act, in_addr_t addr); +extern int rtnl_nat_get_new_addr(struct rtnl_act *act, in_addr_t *addr); +extern int rtnl_nat_set_mask(struct rtnl_act *act, in_addr_t bitmask); +extern int rtnl_nat_get_mask(struct rtnl_act *act, in_addr_t *bitmask); +extern int rtnl_nat_set_flags(struct rtnl_act *act, uint32_t flags); +extern int rtnl_nat_get_flags(struct rtnl_act *act, uint32_t *flags); +extern int rtnl_nat_set_action(struct rtnl_act *act, int action); +extern int rtnl_nat_get_action(struct rtnl_act *act, int *action); + +#ifdef __cplusplus +} +#endif + +#endif /* NETLINK_NAT_H */ diff --git a/include/netlink/route/act/skbedit.h b/include/netlink/route/act/skbedit.h new file mode 100644 index 0000000..3e662ad --- /dev/null +++ b/include/netlink/route/act/skbedit.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2015 Cong Wang + */ + +#ifndef NETLINK_SKBEDIT_H_ +#define NETLINK_SKBEDIT_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_skbedit_set_action(struct rtnl_act *act, int action); +extern int rtnl_skbedit_get_action(struct rtnl_act *act); +extern int rtnl_skbedit_set_queue_mapping(struct rtnl_act *act, uint16_t index); +extern int rtnl_skbedit_get_queue_mapping(struct rtnl_act *act, uint16_t *index); +extern int rtnl_skbedit_set_mark(struct rtnl_act *act, uint32_t mark); +extern int rtnl_skbedit_get_mark(struct rtnl_act *act, uint32_t *mark); +extern int rtnl_skbedit_set_priority(struct rtnl_act *act, uint32_t prio); +extern int rtnl_skbedit_get_priority(struct rtnl_act *act, uint32_t *prio); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/act/vlan.h b/include/netlink/route/act/vlan.h new file mode 100644 index 0000000..f5001ba --- /dev/null +++ b/include/netlink/route/act/vlan.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2018 Volodymyr Bendiuga + */ + +#ifndef NETLINK_VLAN_H_ +#define NETLINK_VLAN_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_vlan_set_mode(struct rtnl_act *act, int mode); +extern int rtnl_vlan_get_mode(struct rtnl_act *act, int *out_mode); +extern int rtnl_vlan_set_action(struct rtnl_act *act, int action); +extern int rtnl_vlan_get_action(struct rtnl_act *act, int *out_action); +extern int rtnl_vlan_set_protocol(struct rtnl_act *act, uint16_t protocol); +extern int rtnl_vlan_get_protocol(struct rtnl_act *act, uint16_t *out_protocol); +extern int rtnl_vlan_set_vlan_id(struct rtnl_act *act, uint16_t vid); +extern int rtnl_vlan_get_vlan_id(struct rtnl_act *act, uint16_t *out_vid); +extern int rtnl_vlan_set_vlan_prio(struct rtnl_act *act, uint8_t prio); +extern int rtnl_vlan_get_vlan_prio(struct rtnl_act *act, uint8_t *out_prio); + +#ifdef __cplusplus +} +#endif + +#endif /* NETLINK_VLAN_H_ */ diff --git a/include/netlink/route/action.h b/include/netlink/route/action.h new file mode 100644 index 0000000..fed491f --- /dev/null +++ b/include/netlink/route/action.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Cong Wang + */ + +#ifndef NETLINK_ACTION_H_ +#define NETLINK_ACTION_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct rtnl_act *rtnl_act_alloc(void); +extern struct rtnl_act *rtnl_act_next(struct rtnl_act *); +extern void rtnl_act_get(struct rtnl_act *); +extern void rtnl_act_put(struct rtnl_act *); +extern int rtnl_act_build_add_request(struct rtnl_act *, int, + struct nl_msg **); +extern int rtnl_act_add(struct nl_sock *, struct rtnl_act *, int); +extern int rtnl_act_change(struct nl_sock *, struct rtnl_act *, int); + +extern int rtnl_act_build_change_request(struct rtnl_act *, int, + struct nl_msg **); +extern int rtnl_act_build_delete_request(struct rtnl_act *, int, + struct nl_msg **); +extern int rtnl_act_delete(struct nl_sock *, struct rtnl_act *, + int); +extern int rtnl_act_append(struct rtnl_act **, struct rtnl_act *); +extern int rtnl_act_remove(struct rtnl_act **, struct rtnl_act *); +extern int rtnl_act_fill(struct nl_msg *, int, struct rtnl_act *); +extern void rtnl_act_put_all(struct rtnl_act **); +extern int rtnl_act_parse(struct rtnl_act **, struct nlattr *); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/addr.h b/include/netlink/route/addr.h index 56c12e7..240ae48 100644 --- a/include/netlink/route/addr.h +++ b/include/netlink/route/addr.h @@ -1,14 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/addr.c rtnetlink addr layer - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf - * Copyright (c) 2003-2006 Baruch Even , - * Mediatrix Telecom, inc. + * Copyright (c) 2003-2006 Baruch Even + * Copyright (c) 2003-2006 Mediatrix Telecom, inc. */ #ifndef NETADDR_ADDR_H_ diff --git a/include/netlink/route/class.h b/include/netlink/route/class.h index e73b60a..91252f1 100644 --- a/include/netlink/route/class.h +++ b/include/netlink/route/class.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/class.h Traffic Classes - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf */ @@ -31,6 +25,9 @@ extern int rtnl_class_alloc_cache(struct nl_sock *, int, extern struct rtnl_class * rtnl_class_get(struct nl_cache *, int, uint32_t); +extern struct rtnl_class * + rtnl_class_get_by_parent(struct nl_cache *, int, uint32_t); + extern struct rtnl_qdisc * rtnl_class_leaf_qdisc(struct rtnl_class *, struct nl_cache *); diff --git a/include/netlink/route/classifier.h b/include/netlink/route/classifier.h index 647bf1e..d92652b 100644 --- a/include/netlink/route/classifier.h +++ b/include/netlink/route/classifier.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/classifier.h Classifiers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf */ @@ -26,10 +20,17 @@ extern void rtnl_cls_put(struct rtnl_cls *); extern int rtnl_cls_alloc_cache(struct nl_sock *, int, uint32_t, struct nl_cache **); +extern struct rtnl_cls *rtnl_cls_find_by_handle(struct nl_cache *cache, int ifindex, + uint32_t parent, uint32_t handle); +extern struct rtnl_cls *rtnl_cls_find_by_prio(struct nl_cache *cache, int ifindex, + uint32_t parent, uint16_t prio); + +extern void rtnl_cls_cache_set_tc_params(struct nl_cache *, int, uint32_t); extern int rtnl_cls_build_add_request(struct rtnl_cls *, int, struct nl_msg **); extern int rtnl_cls_add(struct nl_sock *, struct rtnl_cls *, int); +extern int rtnl_cls_change(struct nl_sock *, struct rtnl_cls *, int); extern int rtnl_cls_build_change_request(struct rtnl_cls *, int, struct nl_msg **); diff --git a/include/netlink/route/cls/basic.h b/include/netlink/route/cls/basic.h index 603fa88..98bbe67 100644 --- a/include/netlink/route/cls/basic.h +++ b/include/netlink/route/cls/basic.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/cls/basic.h Basic Classifier - * - * 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-2010 Thomas Graf */ @@ -15,6 +9,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -25,6 +20,9 @@ extern uint32_t rtnl_basic_get_target(struct rtnl_cls *); extern void rtnl_basic_set_ematch(struct rtnl_cls *, struct rtnl_ematch_tree *); extern struct rtnl_ematch_tree *rtnl_basic_get_ematch(struct rtnl_cls *); +extern int rtnl_basic_add_action(struct rtnl_cls *, struct rtnl_act *); +extern int rtnl_basic_del_action(struct rtnl_cls *, struct rtnl_act *); +extern struct rtnl_act* rtnl_basic_get_action(struct rtnl_cls *); #ifdef __cplusplus } diff --git a/include/netlink/route/cls/cgroup.h b/include/netlink/route/cls/cgroup.h index 9cd4845..8452f6c 100644 --- a/include/netlink/route/cls/cgroup.h +++ b/include/netlink/route/cls/cgroup.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/cls/cgroup.h Control Groups Classifier - * - * 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) 2009-2010 Thomas Graf */ diff --git a/include/netlink/route/cls/ematch.h b/include/netlink/route/cls/ematch.h index 13f9c32..4362423 100644 --- a/include/netlink/route/cls/ematch.h +++ b/include/netlink/route/cls/ematch.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/cls/ematch.h Extended Matches - * - * 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-2010 Thomas Graf */ @@ -73,6 +67,8 @@ extern void rtnl_ematch_tree_free(struct rtnl_ematch_tree *); extern void rtnl_ematch_tree_add(struct rtnl_ematch_tree *, struct rtnl_ematch *); +extern struct rtnl_ematch_tree *rtnl_ematch_tree_clone(struct rtnl_ematch_tree *); + extern int rtnl_ematch_parse_attr(struct nlattr *, struct rtnl_ematch_tree **); extern int rtnl_ematch_fill_attr(struct nl_msg *, int, diff --git a/include/netlink/route/cls/ematch/cmp.h b/include/netlink/route/cls/ematch/cmp.h index 308113e..8aacb51 100644 --- a/include/netlink/route/cls/ematch/cmp.h +++ b/include/netlink/route/cls/ematch/cmp.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/cls/ematch/cmp.h Simple Comparison - * - * 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-2010 Thomas Graf */ @@ -20,6 +14,8 @@ extern "C" { #endif +struct tcf_em_cmp; + extern void rtnl_ematch_cmp_set(struct rtnl_ematch *, struct tcf_em_cmp *); extern struct tcf_em_cmp * diff --git a/include/netlink/route/cls/ematch/meta.h b/include/netlink/route/cls/ematch/meta.h index 2fe5899..b197246 100644 --- a/include/netlink/route/cls/ematch/meta.h +++ b/include/netlink/route/cls/ematch/meta.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/cls/ematch/meta.h Metadata Match - * - * 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 */ diff --git a/include/netlink/route/cls/ematch/nbyte.h b/include/netlink/route/cls/ematch/nbyte.h index 014c719..6bcf7f2 100644 --- a/include/netlink/route/cls/ematch/nbyte.h +++ b/include/netlink/route/cls/ematch/nbyte.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/cls/ematch/nbyte.h N-Byte Comparison - * - * 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 */ diff --git a/include/netlink/route/cls/ematch/text.h b/include/netlink/route/cls/ematch/text.h index e599abf..1493b09 100644 --- a/include/netlink/route/cls/ematch/text.h +++ b/include/netlink/route/cls/ematch/text.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/cls/ematch/text.h Text Search - * - * 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 */ diff --git a/include/netlink/route/cls/flower.h b/include/netlink/route/cls/flower.h new file mode 100644 index 0000000..1a772a8 --- /dev/null +++ b/include/netlink/route/cls/flower.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2018 Volodymyr Bendiuga + */ + +#ifndef NETLINK_FLOWER_H_ +#define NETLINK_FLOWER_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_flower_set_proto(struct rtnl_cls *cls, uint16_t); +extern int rtnl_flower_get_proto(struct rtnl_cls *cls, uint16_t *); + +extern int rtnl_flower_set_vlan_id(struct rtnl_cls *, uint16_t); +extern int rtnl_flower_get_vlan_id(struct rtnl_cls *, uint16_t *); + +extern int rtnl_flower_set_vlan_prio(struct rtnl_cls *, uint8_t); +extern int rtnl_flower_get_vlan_prio(struct rtnl_cls *, uint8_t *); + +extern int rtnl_flower_set_vlan_ethtype(struct rtnl_cls *, uint16_t); + +extern int rtnl_flower_set_dst_mac(struct rtnl_cls *, unsigned char *, + unsigned char *); +extern int rtnl_flower_get_dst_mac(struct rtnl_cls *, unsigned char *, + unsigned char *); + +extern int rtnl_flower_set_src_mac(struct rtnl_cls *, unsigned char *, + unsigned char *); +extern int rtnl_flower_get_src_mac(struct rtnl_cls *, unsigned char *, + unsigned char *); + +extern int rtnl_flower_set_ip_dscp(struct rtnl_cls *, uint8_t, uint8_t); +extern int rtnl_flower_get_ip_dscp(struct rtnl_cls *, uint8_t *, uint8_t *); + +extern int rtnl_flower_set_ipv4_src(struct rtnl_cls *, in_addr_t, in_addr_t); +extern int rtnl_flower_get_ipv4_src(struct rtnl_cls *, in_addr_t *, + in_addr_t *); +extern int rtnl_flower_set_ipv4_dst(struct rtnl_cls *, in_addr_t, in_addr_t); +extern int rtnl_flower_get_ipv4_dst(struct rtnl_cls *, in_addr_t *, + in_addr_t *); + +extern int rtnl_flower_set_flags(struct rtnl_cls *, int); + +extern int rtnl_flower_append_action(struct rtnl_cls *, struct rtnl_act *); +extern int rtnl_flower_del_action(struct rtnl_cls *, struct rtnl_act *); +extern struct rtnl_act* rtnl_flower_get_action(struct rtnl_cls *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/cls/fw.h b/include/netlink/route/cls/fw.h index 2e1bade..57d7c3f 100644 --- a/include/netlink/route/cls/fw.h +++ b/include/netlink/route/cls/fw.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/cls/fw.h fw classifier - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2006 Thomas Graf * Copyright (c) 2006 Petr Gotthard * Copyright (c) 2006 Siemens AG Oesterreich diff --git a/include/netlink/route/cls/matchall.h b/include/netlink/route/cls/matchall.h new file mode 100644 index 0000000..bfe1e7c --- /dev/null +++ b/include/netlink/route/cls/matchall.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2017 Volodymyr Bendiuga + */ + +#ifndef NETLINK_MATCHALL_H_ +#define NETLINK_MATCHALL_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_mall_set_classid(struct rtnl_cls *, uint32_t); +extern int rtnl_mall_get_classid(struct rtnl_cls *, uint32_t *); +extern int rtnl_mall_set_flags(struct rtnl_cls *, uint32_t); +extern int rtnl_mall_get_flags(struct rtnl_cls *, uint32_t *); +extern int rtnl_mall_append_action(struct rtnl_cls *, struct rtnl_act *); +extern struct rtnl_act *rtnl_mall_get_first_action(struct rtnl_cls *); +extern int rtnl_mall_del_action(struct rtnl_cls *, struct rtnl_act *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/cls/police.h b/include/netlink/route/cls/police.h index cd1efb0..9c18b87 100644 --- a/include/netlink/route/cls/police.h +++ b/include/netlink/route/cls/police.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/cls/police.h Policer - * - * 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 */ diff --git a/include/netlink/route/cls/u32.h b/include/netlink/route/cls/u32.h index 59bed33..b8f0223 100644 --- a/include/netlink/route/cls/u32.h +++ b/include/netlink/route/cls/u32.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/cls/u32.h u32 classifier - * - * 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 */ @@ -15,6 +9,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -22,25 +17,34 @@ extern "C" { extern void rtnl_u32_set_handle(struct rtnl_cls *, int, int, int); extern int rtnl_u32_set_classid(struct rtnl_cls *, uint32_t); +extern int rtnl_u32_get_classid(struct rtnl_cls *, uint32_t *); extern int rtnl_u32_set_divisor(struct rtnl_cls *, uint32_t); extern int rtnl_u32_set_link(struct rtnl_cls *, uint32_t); extern int rtnl_u32_set_hashtable(struct rtnl_cls *, uint32_t); extern int rtnl_u32_set_hashmask(struct rtnl_cls *, uint32_t, uint32_t); +extern int rtnl_u32_set_selector(struct rtnl_cls *, int, uint32_t, char, uint16_t, char); extern int rtnl_u32_set_cls_terminal(struct rtnl_cls *); extern int rtnl_u32_set_flags(struct rtnl_cls *, int); +extern int rtnl_u32_add_mark(struct rtnl_cls *, uint32_t, uint32_t); +extern int rtnl_u32_del_mark(struct rtnl_cls *); extern int rtnl_u32_add_key(struct rtnl_cls *, uint32_t, uint32_t, int, int); +extern int rtnl_u32_get_key(struct rtnl_cls *, uint8_t, uint32_t *, uint32_t *, + int *, int *); extern int rtnl_u32_add_key_uint8(struct rtnl_cls *, uint8_t, uint8_t, int, int); extern int rtnl_u32_add_key_uint16(struct rtnl_cls *, uint16_t, uint16_t, int, int); extern int rtnl_u32_add_key_uint32(struct rtnl_cls *, uint32_t, uint32_t, int, int); -extern int rtnl_u32_add_key_in_addr(struct rtnl_cls *, struct in_addr *, +extern int rtnl_u32_add_key_in_addr(struct rtnl_cls *, const struct in_addr *, uint8_t, int, int); -extern int rtnl_u32_add_key_in6_addr(struct rtnl_cls *, struct in6_addr *, +extern int rtnl_u32_add_key_in6_addr(struct rtnl_cls *, const struct in6_addr *, uint8_t, int, int); +extern int rtnl_u32_add_action(struct rtnl_cls *, struct rtnl_act *); +extern int rtnl_u32_del_action(struct rtnl_cls *, struct rtnl_act *); +extern struct rtnl_act* rtnl_u32_get_action(struct rtnl_cls *); #ifdef __cplusplus } diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h index 321a80d..add464b 100644 --- a/include/netlink/route/link.h +++ b/include/netlink/route/link.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/link.h Links (Interfaces) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -15,7 +9,7 @@ #include #include #include -#include +#include #ifdef __cplusplus extern "C" { @@ -35,196 +29,239 @@ struct rtnl_link; * @ingroup link */ typedef enum { - RTNL_LINK_RX_PACKETS, /*!< Packets received */ - RTNL_LINK_TX_PACKETS, /*!< Packets sent */ - RTNL_LINK_RX_BYTES, /*!< Bytes received */ - RTNL_LINK_TX_BYTES, /*!< Bytes sent */ - RTNL_LINK_RX_ERRORS, /*!< Receive errors */ - RTNL_LINK_TX_ERRORS, /*!< Send errors */ - RTNL_LINK_RX_DROPPED, /*!< Received packets dropped */ - RTNL_LINK_TX_DROPPED, /*!< Packets dropped during transmit */ - RTNL_LINK_RX_COMPRESSED, /*!< Compressed packets received */ - RTNL_LINK_TX_COMPRESSED, /*!< Compressed packets sent */ - RTNL_LINK_RX_FIFO_ERR, /*!< Receive FIFO errors */ - RTNL_LINK_TX_FIFO_ERR, /*!< Send FIFO errors */ - RTNL_LINK_RX_LEN_ERR, /*!< Length errors */ - RTNL_LINK_RX_OVER_ERR, /*!< Over errors */ - RTNL_LINK_RX_CRC_ERR, /*!< CRC errors */ - RTNL_LINK_RX_FRAME_ERR, /*!< Frame errors */ - RTNL_LINK_RX_MISSED_ERR, /*!< Missed errors */ - RTNL_LINK_TX_ABORT_ERR, /*!< Aborted errors */ - RTNL_LINK_TX_CARRIER_ERR, /*!< Carrier errors */ - RTNL_LINK_TX_HBEAT_ERR, /*!< Heartbeat errors */ - RTNL_LINK_TX_WIN_ERR, /*!< Window errors */ - RTNL_LINK_COLLISIONS, /*!< Send collisions */ - RTNL_LINK_MULTICAST, /*!< Multicast */ - RTNL_LINK_IP6_INPKTS, /*!< IPv6 SNMP InReceives */ - RTNL_LINK_IP6_INHDRERRORS, /*!< IPv6 SNMP InHdrErrors */ - RTNL_LINK_IP6_INTOOBIGERRORS, /*!< IPv6 SNMP InTooBigErrors */ - RTNL_LINK_IP6_INNOROUTES, /*!< IPv6 SNMP InNoRoutes */ - RTNL_LINK_IP6_INADDRERRORS, /*!< IPv6 SNMP InAddrErrors */ - RTNL_LINK_IP6_INUNKNOWNPROTOS, /*!< IPv6 SNMP InUnknownProtos */ - RTNL_LINK_IP6_INTRUNCATEDPKTS, /*!< IPv6 SNMP InTruncatedPkts */ - RTNL_LINK_IP6_INDISCARDS, /*!< IPv6 SNMP InDiscards */ - RTNL_LINK_IP6_INDELIVERS, /*!< IPv6 SNMP InDelivers */ - RTNL_LINK_IP6_OUTFORWDATAGRAMS, /*!< IPv6 SNMP OutForwDatagrams */ - RTNL_LINK_IP6_OUTPKTS, /*!< IPv6 SNMP OutRequests */ - RTNL_LINK_IP6_OUTDISCARDS, /*!< IPv6 SNMP OutDiscards */ - RTNL_LINK_IP6_OUTNOROUTES, /*!< IPv6 SNMP OutNoRoutes */ - RTNL_LINK_IP6_REASMTIMEOUT, /*!< IPv6 SNMP ReasmTimeout */ - RTNL_LINK_IP6_REASMREQDS, /*!< IPv6 SNMP ReasmReqds */ - RTNL_LINK_IP6_REASMOKS, /*!< IPv6 SNMP ReasmOKs */ - RTNL_LINK_IP6_REASMFAILS, /*!< IPv6 SNMP ReasmFails */ - RTNL_LINK_IP6_FRAGOKS, /*!< IPv6 SNMP FragOKs */ - RTNL_LINK_IP6_FRAGFAILS, /*!< IPv6 SNMP FragFails */ - RTNL_LINK_IP6_FRAGCREATES, /*!< IPv6 SNMP FragCreates */ - RTNL_LINK_IP6_INMCASTPKTS, /*!< IPv6 SNMP InMcastPkts */ - RTNL_LINK_IP6_OUTMCASTPKTS, /*!< IPv6 SNMP OutMcastPkts */ - RTNL_LINK_IP6_INBCASTPKTS, /*!< IPv6 SNMP InBcastPkts */ - RTNL_LINK_IP6_OUTBCASTPKTS, /*!< IPv6 SNMP OutBcastPkts */ - RTNL_LINK_IP6_INOCTETS, /*!< IPv6 SNMP InOctets */ - RTNL_LINK_IP6_OUTOCTETS, /*!< IPv6 SNMP OutOctets */ - RTNL_LINK_IP6_INMCASTOCTETS, /*!< IPv6 SNMP InMcastOctets */ - RTNL_LINK_IP6_OUTMCASTOCTETS, /*!< IPv6 SNMP OutMcastOctets */ - RTNL_LINK_IP6_INBCASTOCTETS, /*!< IPv6 SNMP InBcastOctets */ - RTNL_LINK_IP6_OUTBCASTOCTETS, /*!< IPv6 SNMP OutBcastOctets */ - RTNL_LINK_ICMP6_INMSGS, /*!< ICMPv6 SNMP InMsgs */ - RTNL_LINK_ICMP6_INERRORS, /*!< ICMPv6 SNMP InErrors */ - RTNL_LINK_ICMP6_OUTMSGS, /*!< ICMPv6 SNMP OutMsgs */ - RTNL_LINK_ICMP6_OUTERRORS, /*!< ICMPv6 SNMP OutErrors */ + RTNL_LINK_RX_PACKETS, /*!< Packets received */ + RTNL_LINK_TX_PACKETS, /*!< Packets sent */ + RTNL_LINK_RX_BYTES, /*!< Bytes received */ + RTNL_LINK_TX_BYTES, /*!< Bytes sent */ + RTNL_LINK_RX_ERRORS, /*!< Receive errors */ + RTNL_LINK_TX_ERRORS, /*!< Send errors */ + RTNL_LINK_RX_DROPPED, /*!< Received packets dropped */ + RTNL_LINK_TX_DROPPED, /*!< Packets dropped during transmit */ + RTNL_LINK_RX_COMPRESSED, /*!< Compressed packets received */ + RTNL_LINK_TX_COMPRESSED, /*!< Compressed packets sent */ + RTNL_LINK_RX_FIFO_ERR, /*!< Receive FIFO errors */ + RTNL_LINK_TX_FIFO_ERR, /*!< Send FIFO errors */ + RTNL_LINK_RX_LEN_ERR, /*!< Length errors */ + RTNL_LINK_RX_OVER_ERR, /*!< Over errors */ + RTNL_LINK_RX_CRC_ERR, /*!< CRC errors */ + RTNL_LINK_RX_FRAME_ERR, /*!< Frame errors */ + RTNL_LINK_RX_MISSED_ERR, /*!< Missed errors */ + RTNL_LINK_TX_ABORT_ERR, /*!< Aborted errors */ + RTNL_LINK_TX_CARRIER_ERR, /*!< Carrier errors */ + RTNL_LINK_TX_HBEAT_ERR, /*!< Heartbeat errors */ + RTNL_LINK_TX_WIN_ERR, /*!< Window errors */ + RTNL_LINK_COLLISIONS, /*!< Send collisions */ + RTNL_LINK_MULTICAST, /*!< Multicast */ + RTNL_LINK_IP6_INPKTS, /*!< IPv6 SNMP InReceives */ + RTNL_LINK_IP6_INHDRERRORS, /*!< IPv6 SNMP InHdrErrors */ + RTNL_LINK_IP6_INTOOBIGERRORS, /*!< IPv6 SNMP InTooBigErrors */ + RTNL_LINK_IP6_INNOROUTES, /*!< IPv6 SNMP InNoRoutes */ + RTNL_LINK_IP6_INADDRERRORS, /*!< IPv6 SNMP InAddrErrors */ + RTNL_LINK_IP6_INUNKNOWNPROTOS, /*!< IPv6 SNMP InUnknownProtos */ + RTNL_LINK_IP6_INTRUNCATEDPKTS, /*!< IPv6 SNMP InTruncatedPkts */ + RTNL_LINK_IP6_INDISCARDS, /*!< IPv6 SNMP InDiscards */ + RTNL_LINK_IP6_INDELIVERS, /*!< IPv6 SNMP InDelivers */ + RTNL_LINK_IP6_OUTFORWDATAGRAMS, /*!< IPv6 SNMP OutForwDatagrams */ + RTNL_LINK_IP6_OUTPKTS, /*!< IPv6 SNMP OutRequests */ + RTNL_LINK_IP6_OUTDISCARDS, /*!< IPv6 SNMP OutDiscards */ + RTNL_LINK_IP6_OUTNOROUTES, /*!< IPv6 SNMP OutNoRoutes */ + RTNL_LINK_IP6_REASMTIMEOUT, /*!< IPv6 SNMP ReasmTimeout */ + RTNL_LINK_IP6_REASMREQDS, /*!< IPv6 SNMP ReasmReqds */ + RTNL_LINK_IP6_REASMOKS, /*!< IPv6 SNMP ReasmOKs */ + RTNL_LINK_IP6_REASMFAILS, /*!< IPv6 SNMP ReasmFails */ + RTNL_LINK_IP6_FRAGOKS, /*!< IPv6 SNMP FragOKs */ + RTNL_LINK_IP6_FRAGFAILS, /*!< IPv6 SNMP FragFails */ + RTNL_LINK_IP6_FRAGCREATES, /*!< IPv6 SNMP FragCreates */ + RTNL_LINK_IP6_INMCASTPKTS, /*!< IPv6 SNMP InMcastPkts */ + RTNL_LINK_IP6_OUTMCASTPKTS, /*!< IPv6 SNMP OutMcastPkts */ + RTNL_LINK_IP6_INBCASTPKTS, /*!< IPv6 SNMP InBcastPkts */ + RTNL_LINK_IP6_OUTBCASTPKTS, /*!< IPv6 SNMP OutBcastPkts */ + RTNL_LINK_IP6_INOCTETS, /*!< IPv6 SNMP InOctets */ + RTNL_LINK_IP6_OUTOCTETS, /*!< IPv6 SNMP OutOctets */ + RTNL_LINK_IP6_INMCASTOCTETS, /*!< IPv6 SNMP InMcastOctets */ + RTNL_LINK_IP6_OUTMCASTOCTETS, /*!< IPv6 SNMP OutMcastOctets */ + RTNL_LINK_IP6_INBCASTOCTETS, /*!< IPv6 SNMP InBcastOctets */ + RTNL_LINK_IP6_OUTBCASTOCTETS, /*!< IPv6 SNMP OutBcastOctets */ + RTNL_LINK_ICMP6_INMSGS, /*!< ICMPv6 SNMP InMsgs */ + RTNL_LINK_ICMP6_INERRORS, /*!< ICMPv6 SNMP InErrors */ + RTNL_LINK_ICMP6_OUTMSGS, /*!< ICMPv6 SNMP OutMsgs */ + RTNL_LINK_ICMP6_OUTERRORS, /*!< ICMPv6 SNMP OutErrors */ + RTNL_LINK_ICMP6_CSUMERRORS, /*!< ICMPv6 SNMP InCsumErrors */ + RTNL_LINK_IP6_CSUMERRORS, /*!< IPv6 SNMP InCsumErrors */ + RTNL_LINK_IP6_NOECTPKTS, /*!< IPv6 SNMP InNoECTPkts */ + RTNL_LINK_IP6_ECT1PKTS, /*!< IPv6 SNMP InECT1Pkts */ + RTNL_LINK_IP6_ECT0PKTS, /*!< IPv6 SNMP InECT0Pkts */ + RTNL_LINK_IP6_CEPKTS, /*!< IPv6 SNMP InCEPkts */ + RTNL_LINK_RX_NOHANDLER, /*!< Received packets dropped on inactive device */ + RTNL_LINK_REASM_OVERLAPS, /*!< SNMP ReasmOverlaps */ __RTNL_LINK_STATS_MAX, } rtnl_link_stat_id_t; #define RTNL_LINK_STATS_MAX (__RTNL_LINK_STATS_MAX - 1) +extern struct nla_policy rtln_link_policy[]; + extern struct rtnl_link *rtnl_link_alloc(void); -extern void rtnl_link_put(struct rtnl_link *); +extern void rtnl_link_put(struct rtnl_link *); -extern int rtnl_link_alloc_cache(struct nl_sock *, int, struct nl_cache **); +extern int rtnl_link_alloc_cache(struct nl_sock *, int, struct nl_cache **); +extern int rtnl_link_alloc_cache_flags(struct nl_sock *, int, + struct nl_cache **, + unsigned int flags); extern struct rtnl_link *rtnl_link_get(struct nl_cache *, int); extern struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *, const char *); -extern int rtnl_link_build_add_request(struct rtnl_link *, int, - struct nl_msg **); -extern int rtnl_link_add(struct nl_sock *, struct rtnl_link *, int); -extern int rtnl_link_build_change_request(struct rtnl_link *, - struct rtnl_link *, int, - struct nl_msg **); -extern int rtnl_link_change(struct nl_sock *, struct rtnl_link *, - struct rtnl_link *, int); +extern int rtnl_link_build_add_request(struct rtnl_link *, int, + struct nl_msg **); +extern int rtnl_link_add(struct nl_sock *, struct rtnl_link *, int); +extern int rtnl_link_build_change_request(struct rtnl_link *, + struct rtnl_link *, int, + struct nl_msg **); +extern int rtnl_link_change(struct nl_sock *, struct rtnl_link *, + struct rtnl_link *, int); -extern int rtnl_link_build_delete_request(const struct rtnl_link *, - struct nl_msg **); -extern int rtnl_link_delete(struct nl_sock *, const struct rtnl_link *); -extern int rtnl_link_build_get_request(int, const char *, - struct nl_msg **); -extern int rtnl_link_get_kernel(struct nl_sock *, int, const char *, - struct rtnl_link **); +extern int rtnl_link_build_delete_request(const struct rtnl_link *, + struct nl_msg **); +extern int rtnl_link_delete(struct nl_sock *, const struct rtnl_link *); +extern int rtnl_link_build_get_request(int, const char *, + struct nl_msg **); +extern int rtnl_link_get_kernel(struct nl_sock *, int, const char *, + struct rtnl_link **); /* Name <-> Index Translations */ -extern char * rtnl_link_i2name(struct nl_cache *, int, char *, size_t); -extern int rtnl_link_name2i(struct nl_cache *, const char *); +extern char * rtnl_link_i2name(struct nl_cache *, int, char *, size_t); +extern int rtnl_link_name2i(struct nl_cache *, const char *); /* Name <-> Statistic Translations */ -extern char * rtnl_link_stat2str(int, char *, size_t); -extern int rtnl_link_str2stat(const char *); +extern char * rtnl_link_stat2str(int, char *, size_t); +extern int rtnl_link_str2stat(const char *); /* Link Flags Translations */ -extern char * rtnl_link_flags2str(int, char *, size_t); -extern int rtnl_link_str2flags(const char *); +extern char * rtnl_link_flags2str(int, char *, size_t); +extern int rtnl_link_str2flags(const char *); -extern char * rtnl_link_operstate2str(uint8_t, char *, size_t); -extern int rtnl_link_str2operstate(const char *); +extern char * rtnl_link_operstate2str(uint8_t, char *, size_t); +extern int rtnl_link_str2operstate(const char *); -extern char * rtnl_link_mode2str(uint8_t, char *, size_t); -extern int rtnl_link_str2mode(const char *); +extern char * rtnl_link_mode2str(uint8_t, char *, size_t); +extern int rtnl_link_str2mode(const char *); /* Carrier State Translations */ -extern char * rtnl_link_carrier2str(uint8_t, char *, size_t); -extern int rtnl_link_str2carrier(const char *); +extern char * rtnl_link_carrier2str(uint8_t, char *, size_t); +extern int rtnl_link_str2carrier(const char *); /* Access Functions */ -extern void rtnl_link_set_qdisc(struct rtnl_link *, const char *); -extern char * rtnl_link_get_qdisc(struct rtnl_link *); +extern void rtnl_link_set_qdisc(struct rtnl_link *, const char *); +extern char * rtnl_link_get_qdisc(struct rtnl_link *); -extern void rtnl_link_set_name(struct rtnl_link *, const char *); -extern char * rtnl_link_get_name(struct rtnl_link *); +extern void rtnl_link_set_name(struct rtnl_link *, const char *); +extern char * rtnl_link_get_name(struct rtnl_link *); -extern void rtnl_link_set_group(struct rtnl_link *, uint32_t); -extern uint32_t rtnl_link_get_group(struct rtnl_link *); +extern void rtnl_link_set_group(struct rtnl_link *, uint32_t); +extern uint32_t rtnl_link_get_group(struct rtnl_link *); -extern void rtnl_link_set_flags(struct rtnl_link *, unsigned int); -extern void rtnl_link_unset_flags(struct rtnl_link *, unsigned int); +extern void rtnl_link_set_flags(struct rtnl_link *, unsigned int); +extern void rtnl_link_unset_flags(struct rtnl_link *, unsigned int); extern unsigned int rtnl_link_get_flags(struct rtnl_link *); -extern void rtnl_link_set_mtu(struct rtnl_link *, unsigned int); +extern void rtnl_link_set_mtu(struct rtnl_link *, unsigned int); extern unsigned int rtnl_link_get_mtu(struct rtnl_link *); -extern void rtnl_link_set_txqlen(struct rtnl_link *, unsigned int); +extern void rtnl_link_set_txqlen(struct rtnl_link *, unsigned int); extern unsigned int rtnl_link_get_txqlen(struct rtnl_link *); -extern void rtnl_link_set_ifindex(struct rtnl_link *, int); -extern int rtnl_link_get_ifindex(struct rtnl_link *); +extern void rtnl_link_set_ifindex(struct rtnl_link *, int); +extern int rtnl_link_get_ifindex(struct rtnl_link *); -extern void rtnl_link_set_family(struct rtnl_link *, int); -extern int rtnl_link_get_family(struct rtnl_link *); +extern void rtnl_link_set_family(struct rtnl_link *, int); +extern int rtnl_link_get_family(struct rtnl_link *); -extern void rtnl_link_set_arptype(struct rtnl_link *, unsigned int); +extern void rtnl_link_set_arptype(struct rtnl_link *, unsigned int); extern unsigned int rtnl_link_get_arptype(struct rtnl_link *); -extern void rtnl_link_set_addr(struct rtnl_link *, struct nl_addr *); +extern void rtnl_link_set_addr(struct rtnl_link *, struct nl_addr *); extern struct nl_addr *rtnl_link_get_addr(struct rtnl_link *); -extern void rtnl_link_set_broadcast(struct rtnl_link *, struct nl_addr *); +extern void rtnl_link_set_broadcast(struct rtnl_link *, struct nl_addr *); extern struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *); -extern void rtnl_link_set_link(struct rtnl_link *, int); -extern int rtnl_link_get_link(struct rtnl_link *); +extern void rtnl_link_set_link(struct rtnl_link *, int); +extern int rtnl_link_get_link(struct rtnl_link *); + +extern void rtnl_link_set_master(struct rtnl_link *, int); +extern int rtnl_link_get_master(struct rtnl_link *); -extern void rtnl_link_set_master(struct rtnl_link *, int); -extern int rtnl_link_get_master(struct rtnl_link *); +extern void rtnl_link_set_carrier(struct rtnl_link *, uint8_t); +extern uint8_t rtnl_link_get_carrier(struct rtnl_link *); -extern void rtnl_link_set_carrier(struct rtnl_link *, uint8_t); -extern uint8_t rtnl_link_get_carrier(struct rtnl_link *); +extern int rtnl_link_get_carrier_changes(struct rtnl_link *, uint32_t *); -extern void rtnl_link_set_operstate(struct rtnl_link *, uint8_t); -extern uint8_t rtnl_link_get_operstate(struct rtnl_link *); +extern void rtnl_link_set_operstate(struct rtnl_link *, uint8_t); +extern uint8_t rtnl_link_get_operstate(struct rtnl_link *); -extern void rtnl_link_set_linkmode(struct rtnl_link *, uint8_t); -extern uint8_t rtnl_link_get_linkmode(struct rtnl_link *); +extern void rtnl_link_set_linkmode(struct rtnl_link *, uint8_t); +extern uint8_t rtnl_link_get_linkmode(struct rtnl_link *); -extern const char * rtnl_link_get_ifalias(struct rtnl_link *); -extern void rtnl_link_set_ifalias(struct rtnl_link *, const char *); +int rtnl_link_set_link_netnsid(struct rtnl_link *link, int32_t link_netnsid); +int rtnl_link_get_link_netnsid(const struct rtnl_link *link, int32_t *out_link_netnsid); -extern int rtnl_link_get_num_vf(struct rtnl_link *, uint32_t *); +extern const char * rtnl_link_get_ifalias(struct rtnl_link *); +extern void rtnl_link_set_ifalias(struct rtnl_link *, const char *); + +extern int rtnl_link_get_num_vf(struct rtnl_link *, uint32_t *); extern uint64_t rtnl_link_get_stat(struct rtnl_link *, rtnl_link_stat_id_t); -extern int rtnl_link_set_stat(struct rtnl_link *, rtnl_link_stat_id_t, - const uint64_t); +extern int rtnl_link_set_stat(struct rtnl_link *, rtnl_link_stat_id_t, + const uint64_t); + +extern int rtnl_link_set_type(struct rtnl_link *, const char *); +extern char * rtnl_link_get_type(struct rtnl_link *); + +extern int rtnl_link_set_slave_type(struct rtnl_link *, const char *); +extern const char * rtnl_link_get_slave_type(const struct rtnl_link *); + +extern void rtnl_link_set_promiscuity(struct rtnl_link *, uint32_t); +extern uint32_t rtnl_link_get_promiscuity(struct rtnl_link *); + +extern void rtnl_link_set_num_tx_queues(struct rtnl_link *, uint32_t); +extern uint32_t rtnl_link_get_num_tx_queues(struct rtnl_link *); + +extern void rtnl_link_set_num_rx_queues(struct rtnl_link *, uint32_t); +extern uint32_t rtnl_link_get_num_rx_queues(struct rtnl_link *); + +extern int rtnl_link_get_gso_max_segs(struct rtnl_link *, uint32_t *); + +extern int rtnl_link_get_gso_max_size(struct rtnl_link *, uint32_t *); + +extern struct nl_data * rtnl_link_get_phys_port_id(struct rtnl_link *); + +extern char* rtnl_link_get_phys_port_name(struct rtnl_link *); -extern int rtnl_link_set_type(struct rtnl_link *, const char *); -extern char * rtnl_link_get_type(struct rtnl_link *); +extern struct nl_data * rtnl_link_get_phys_switch_id(struct rtnl_link *); -extern void rtnl_link_set_promiscuity(struct rtnl_link *, uint32_t); -extern uint32_t rtnl_link_get_promiscuity(struct rtnl_link *); +extern void rtnl_link_set_ns_fd(struct rtnl_link *, int); +extern int rtnl_link_get_ns_fd(struct rtnl_link *); +extern void rtnl_link_set_ns_pid(struct rtnl_link *, pid_t); +extern pid_t rtnl_link_get_ns_pid(struct rtnl_link *); -extern void rtnl_link_set_num_tx_queues(struct rtnl_link *, uint32_t); -extern uint32_t rtnl_link_get_num_tx_queues(struct rtnl_link *); +extern int rtnl_link_enslave_ifindex(struct nl_sock *, int, int); +extern int rtnl_link_enslave(struct nl_sock *, struct rtnl_link *, + struct rtnl_link *); +extern int rtnl_link_release_ifindex(struct nl_sock *, int); +extern int rtnl_link_release(struct nl_sock *, struct rtnl_link *); +extern int rtnl_link_fill_info(struct nl_msg *, struct rtnl_link *); +extern int rtnl_link_info_parse(struct rtnl_link *, struct nlattr **); -extern void rtnl_link_set_num_rx_queues(struct rtnl_link *, uint32_t); -extern uint32_t rtnl_link_get_num_rx_queues(struct rtnl_link *); +extern int rtnl_link_has_vf_list(struct rtnl_link *); +extern void rtnl_link_set_vf_list(struct rtnl_link *); +extern void rtnl_link_unset_vf_list(struct rtnl_link *); -extern int rtnl_link_enslave_ifindex(struct nl_sock *, int, int); -extern int rtnl_link_enslave(struct nl_sock *, struct rtnl_link *, - struct rtnl_link *); -extern int rtnl_link_release_ifindex(struct nl_sock *, int); -extern int rtnl_link_release(struct nl_sock *, struct rtnl_link *); /* deprecated */ -extern int rtnl_link_set_info_type(struct rtnl_link *, const char *) __attribute__((deprecated)); -extern char * rtnl_link_get_info_type(struct rtnl_link *) __attribute__((deprecated)); -extern void rtnl_link_set_weight(struct rtnl_link *, unsigned int) __attribute__((deprecated)); +extern int rtnl_link_set_info_type(struct rtnl_link *, const char *) __attribute__((deprecated)); +extern char * rtnl_link_get_info_type(struct rtnl_link *) __attribute__((deprecated)); +extern void rtnl_link_set_weight(struct rtnl_link *, unsigned int) __attribute__((deprecated)); extern unsigned int rtnl_link_get_weight(struct rtnl_link *) __attribute__((deprecated)); diff --git a/include/netlink/route/link/api.h b/include/netlink/route/link/api.h index 03b1e5e..abdd8b2 100644 --- a/include/netlink/route/link/api.h +++ b/include/netlink/route/link/api.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/link/api.h Link Modules API - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2013 Thomas Graf */ diff --git a/include/netlink/route/link/bonding.h b/include/netlink/route/link/bonding.h index 5c34662..e12d8a5 100644 --- a/include/netlink/route/link/bonding.h +++ b/include/netlink/route/link/bonding.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/link/bonding.h Bonding Interface - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2011-2013 Thomas Graf */ @@ -31,6 +25,12 @@ extern int rtnl_link_bond_enslave(struct nl_sock *, struct rtnl_link *, extern int rtnl_link_bond_release_ifindex(struct nl_sock *, int); extern int rtnl_link_bond_release(struct nl_sock *, struct rtnl_link *); +extern void rtnl_link_bond_set_mode(struct rtnl_link *link, uint8_t mode); +extern void rtnl_link_bond_set_activeslave(struct rtnl_link *link, int active_slave); +extern void rtnl_link_bond_set_hashing_type (struct rtnl_link *link, uint8_t type); +extern void rtnl_link_bond_set_miimon (struct rtnl_link *link, uint32_t miimon); +extern void rtnl_link_bond_set_min_links (struct rtnl_link *link, uint32_t min_links); + #ifdef __cplusplus } #endif diff --git a/include/netlink/route/link/bridge.h b/include/netlink/route/link/bridge.h index 71dcc24..e606bd4 100644 --- a/include/netlink/route/link/bridge.h +++ b/include/netlink/route/link/bridge.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/link/bridge.h Bridge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2013 Thomas Graf */ @@ -19,6 +13,16 @@ extern "C" { #endif +#define RTNL_LINK_BRIDGE_VLAN_BITMAP_MAX 4096 +#define RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN (RTNL_LINK_BRIDGE_VLAN_BITMAP_MAX / 32) + +struct rtnl_link_bridge_vlan +{ + uint16_t pvid; + uint32_t vlan_bitmap[RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN]; + uint32_t untagged_bitmap[RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN]; +}; + /** * Bridge flags * @ingroup bridge @@ -28,8 +32,16 @@ enum rtnl_link_bridge_flags { RTNL_BRIDGE_BPDU_GUARD = 0x0002, RTNL_BRIDGE_ROOT_BLOCK = 0x0004, RTNL_BRIDGE_FAST_LEAVE = 0x0008, + RTNL_BRIDGE_UNICAST_FLOOD = 0x0010, + RTNL_BRIDGE_LEARNING = 0x0020, + RTNL_BRIDGE_LEARNING_SYNC = 0x0040, }; +#define RTNL_BRIDGE_HWMODE_VEB BRIDGE_MODE_VEB +#define RTNL_BRIDGE_HWMODE_VEPA BRIDGE_MODE_VEPA +#define RTNL_BRIDGE_HWMODE_MAX BRIDGE_MODE_VEPA +#define RTNL_BRIDGE_HWMODE_UNDEF BRIDGE_MODE_UNDEF + extern struct rtnl_link *rtnl_link_bridge_alloc(void); extern int rtnl_link_is_bridge(struct rtnl_link *); @@ -48,6 +60,26 @@ extern int rtnl_link_bridge_unset_flags(struct rtnl_link *, unsigned int); extern int rtnl_link_bridge_set_flags(struct rtnl_link *, unsigned int); extern int rtnl_link_bridge_get_flags(struct rtnl_link *); +extern int rtnl_link_bridge_set_self(struct rtnl_link *); + +extern int rtnl_link_bridge_get_hwmode(struct rtnl_link *, uint16_t *); +extern int rtnl_link_bridge_set_hwmode(struct rtnl_link *, uint16_t); + +extern char * rtnl_link_bridge_flags2str(int, char *, size_t); +extern int rtnl_link_bridge_str2flags(const char *); + +extern char * rtnl_link_bridge_portstate2str(int, char *, size_t); +extern int rtnl_link_bridge_str2portstate(const char *); + +extern char * rtnl_link_bridge_hwmode2str(uint16_t, char *, size_t); +extern uint16_t rtnl_link_bridge_str2hwmode(const char *); + +extern int rtnl_link_bridge_add(struct nl_sock *sk, const char *name); + +extern int rtnl_link_bridge_pvid(struct rtnl_link *link); +extern int rtnl_link_bridge_has_vlan(struct rtnl_link *link); + +extern struct rtnl_link_bridge_vlan *rtnl_link_bridge_get_port_vlan(struct rtnl_link *link); #ifdef __cplusplus } #endif diff --git a/include/netlink/route/link/bridge_info.h b/include/netlink/route/link/bridge_info.h new file mode 100644 index 0000000..09689b3 --- /dev/null +++ b/include/netlink/route/link/bridge_info.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2022 MaxLinear, Inc. + */ + +#ifndef NETLINK_LINK_BRIDGE_INFO_H_ +#define NETLINK_LINK_BRIDGE_INFO_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern void rtnl_link_bridge_set_vlan_filtering(struct rtnl_link *link, + uint8_t vlan_filtering); +extern int rtnl_link_bridge_get_vlan_filtering(struct rtnl_link *link, + uint8_t *vlan_filtering); + +extern void rtnl_link_bridge_set_vlan_protocol(struct rtnl_link *link, + uint16_t vlan_protocol); +extern int rtnl_link_bridge_get_vlan_protocol(struct rtnl_link *link, + uint16_t *vlan_protocol); + +extern void rtnl_link_bridge_set_vlan_stats_enabled(struct rtnl_link *link, + uint8_t vlan_stats_enabled); +extern int rtnl_link_bridge_get_vlan_stats_enabled(struct rtnl_link *link, + uint8_t *vlan_stats_enabled); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/can.h b/include/netlink/route/link/can.h index 61c9f47..1c23660 100644 --- a/include/netlink/route/link/can.h +++ b/include/netlink/route/link/can.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/link/can.h CAN interface - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2012 Benedikt Spranger */ @@ -20,6 +14,10 @@ extern "C" { #endif +struct can_bittiming_const; +struct can_bittiming; +struct can_berr_counter; + extern int rtnl_link_is_can(struct rtnl_link *link); extern char *rtnl_link_can_ctrlmode2str(int, char *, size_t); @@ -34,11 +32,11 @@ extern int rtnl_link_can_berr_tx(struct rtnl_link *); extern int rtnl_link_can_berr(struct rtnl_link *, struct can_berr_counter *); extern int rtnl_link_can_get_bt_const(struct rtnl_link *, - struct can_bittiming_const *); + struct can_bittiming_const *); extern int rtnl_link_can_get_bittiming(struct rtnl_link *, - struct can_bittiming *); + struct can_bittiming *); extern int rtnl_link_can_set_bittiming(struct rtnl_link *, - struct can_bittiming *); + const struct can_bittiming *); extern int rtnl_link_can_get_bitrate(struct rtnl_link *, uint32_t *); extern int rtnl_link_can_set_bitrate(struct rtnl_link *, uint32_t); @@ -53,6 +51,18 @@ extern int rtnl_link_can_get_ctrlmode(struct rtnl_link *, uint32_t *); extern int rtnl_link_can_set_ctrlmode(struct rtnl_link *, uint32_t); extern int rtnl_link_can_unset_ctrlmode(struct rtnl_link *, uint32_t); +extern int rtnl_link_can_get_data_bittiming_const(struct rtnl_link *, + struct can_bittiming_const *); +extern int rtnl_link_can_set_data_bittiming_const(struct rtnl_link *, + const struct can_bittiming_const *); +extern int rtnl_link_can_get_data_bittiming(struct rtnl_link *, + struct can_bittiming *); +extern int rtnl_link_can_set_data_bittiming(struct rtnl_link *, + const struct can_bittiming *); + +extern int rtnl_link_can_get_device_stats(struct rtnl_link *, + struct can_device_stats *); + #ifdef __cplusplus } #endif diff --git a/include/netlink/route/link/geneve.h b/include/netlink/route/link/geneve.h new file mode 100644 index 0000000..cf37c4e --- /dev/null +++ b/include/netlink/route/link/geneve.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#ifndef NETLINK_LINK_GENEVE_H_ +#define NETLINK_LINK_GENEVE_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define RTNL_GENEVE_ID_MAX 16777215 + +#define RTNL_LINK_GENEVE_F_COLLECT_METADATA (1<<0) + +extern struct rtnl_link *rtnl_link_geneve_alloc(void); +extern int rtnl_link_is_geneve(struct rtnl_link *); + +extern int rtnl_link_geneve_set_id(struct rtnl_link *, uint32_t); +extern int rtnl_link_geneve_get_id(struct rtnl_link *, uint32_t *); + +extern int rtnl_link_geneve_set_remote(struct rtnl_link *, struct nl_addr *); +extern int rtnl_link_geneve_get_remote(struct rtnl_link *, struct nl_addr **); + +extern int rtnl_link_geneve_set_ttl(struct rtnl_link *, uint8_t); +extern int rtnl_link_geneve_get_ttl(struct rtnl_link *); + +extern int rtnl_link_geneve_set_tos(struct rtnl_link *, uint8_t); +extern int rtnl_link_geneve_get_tos(struct rtnl_link *); + +extern int rtnl_link_geneve_set_port(struct rtnl_link *, uint32_t); +extern int rtnl_link_geneve_get_port(struct rtnl_link *, uint32_t *); + +extern int rtnl_link_geneve_set_label(struct rtnl_link *, uint32_t); +extern int rtnl_link_geneve_get_label(struct rtnl_link *, uint32_t *); + +extern int rtnl_link_geneve_set_udp_csum(struct rtnl_link *, uint8_t); +extern int rtnl_link_geneve_get_udp_csum(struct rtnl_link *); + +extern int rtnl_link_geneve_set_udp_zero_csum6_tx(struct rtnl_link *, uint8_t); +extern int rtnl_link_geneve_get_udp_zero_csum6_tx(struct rtnl_link *); + +extern int rtnl_link_geneve_set_udp_zero_csum6_rx(struct rtnl_link *, uint8_t); +extern int rtnl_link_geneve_get_udp_zero_csum6_rx(struct rtnl_link *); + +extern int rtnl_link_geneve_set_flags(struct rtnl_link *, uint8_t flags, int enable); +extern int rtnl_link_geneve_get_flags(struct rtnl_link *, uint8_t *flags); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/inet.h b/include/netlink/route/link/inet.h index 506542f..b1318d1 100644 --- a/include/netlink/route/link/inet.h +++ b/include/netlink/route/link/inet.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/link/inet.h INET Link Module - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2010 Thomas Graf */ @@ -13,6 +7,7 @@ #define NETLINK_LINK_INET_H_ #include +#include #ifdef __cplusplus extern "C" { diff --git a/include/netlink/route/link/inet6.h b/include/netlink/route/link/inet6.h new file mode 100644 index 0000000..8939427 --- /dev/null +++ b/include/netlink/route/link/inet6.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2014 Dan Williams + */ + +#ifndef NETLINK_LINK_INET6_H_ +#define NETLINK_LINK_INET6_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +const char * rtnl_link_inet6_addrgenmode2str (uint8_t mode, + char *buf, + size_t len); + +uint8_t rtnl_link_inet6_str2addrgenmode (const char *mode); + +extern int rtnl_link_inet6_get_token(struct rtnl_link *, + struct nl_addr **); + +extern int rtnl_link_inet6_set_token(struct rtnl_link *, + struct nl_addr *); + +extern int rtnl_link_inet6_get_addr_gen_mode(struct rtnl_link *, + uint8_t *); + +extern int rtnl_link_inet6_set_addr_gen_mode(struct rtnl_link *, + uint8_t); + +extern int rtnl_link_inet6_get_flags(struct rtnl_link *, + uint32_t *); + +extern int rtnl_link_inet6_set_flags(struct rtnl_link *, + uint32_t); + +extern int rtnl_link_inet6_get_conf(struct rtnl_link *, + unsigned int, + uint32_t *); + +/* Link Flags Translations */ +extern char * rtnl_link_inet6_flags2str(int, char *, size_t); +extern int rtnl_link_inet6_str2flags(const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/info-api.h b/include/netlink/route/link/info-api.h index 1087ad4..11cffcf 100644 --- a/include/netlink/route/link/info-api.h +++ b/include/netlink/route/link/info-api.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/link/info-api.h Link Modules API - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2013 Thomas Graf */ diff --git a/include/netlink/route/link/ip6gre.h b/include/netlink/route/link/ip6gre.h new file mode 100644 index 0000000..2838592 --- /dev/null +++ b/include/netlink/route/link/ip6gre.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#ifndef NETLINK_LINK_IP6GRE_H_ +#define NETLINK_LINK_IP6GRE_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + extern int rtnl_link_is_ip6gre(struct rtnl_link *link); + + extern struct rtnl_link *rtnl_link_ip6gre_alloc(void); + extern int rtnl_link_ip6gre_add(struct nl_sock *sk, const char *name); + + extern int rtnl_link_ip6gre_set_link(struct rtnl_link *link, uint32_t index); + extern int rtnl_link_ip6gre_get_link(struct rtnl_link *link, uint32_t *index); + + extern int rtnl_link_ip6gre_set_iflags(struct rtnl_link *link, uint16_t iflags); + extern int rtnl_link_ip6gre_get_iflags(struct rtnl_link *link, uint16_t *iflags); + + extern int rtnl_link_ip6gre_set_oflags(struct rtnl_link *link, uint16_t oflags); + extern int rtnl_link_ip6gre_get_oflags(struct rtnl_link *link, uint16_t *oflags); + + extern int rtnl_link_ip6gre_set_ikey(struct rtnl_link *link, uint32_t ikey); + extern int rtnl_link_ip6gre_get_ikey(struct rtnl_link *link, uint32_t *ikey); + + extern int rtnl_link_ip6gre_set_okey(struct rtnl_link *link, uint32_t okey); + extern int rtnl_link_ip6gre_get_okey(struct rtnl_link *link, uint32_t *okey); + + extern int rtnl_link_ip6gre_set_local(struct rtnl_link *link, struct in6_addr *local); + extern int rtnl_link_ip6gre_get_local(struct rtnl_link *link, struct in6_addr *local); + + extern int rtnl_link_ip6gre_set_remote(struct rtnl_link *link, struct in6_addr *remote); + extern int rtnl_link_ip6gre_get_remote(struct rtnl_link *link, struct in6_addr *remote); + + extern int rtnl_link_ip6gre_set_ttl(struct rtnl_link *link, uint8_t ttl); + extern int rtnl_link_ip6gre_get_ttl(struct rtnl_link *link, uint8_t *ttl); + + extern int rtnl_link_ip6gre_set_encaplimit(struct rtnl_link *link, uint8_t encaplimit); + extern int rtnl_link_ip6gre_get_encaplimit(struct rtnl_link *link, uint8_t *encaplimit); + + extern int rtnl_link_ip6gre_set_flowinfo(struct rtnl_link *link, uint32_t flowinfo); + extern int rtnl_link_ip6gre_get_flowinfo(struct rtnl_link *link, uint32_t *flowinfo); + + extern int rtnl_link_ip6gre_set_flags(struct rtnl_link *link, uint32_t flags); + extern int rtnl_link_ip6gre_get_flags(struct rtnl_link *link, uint32_t *flags); + + extern int rtnl_link_ip6gre_set_fwmark(struct rtnl_link *link, uint32_t fwmark); + extern int rtnl_link_ip6gre_get_fwmark(struct rtnl_link *link, uint32_t *fwmark); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/ip6tnl.h b/include/netlink/route/link/ip6tnl.h new file mode 100644 index 0000000..865d973 --- /dev/null +++ b/include/netlink/route/link/ip6tnl.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2014 Susant Sahani + */ + +#ifndef NETLINK_LINK_IP6TNL_H_ +#define NETLINK_LINK_IP6TNL_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + extern struct rtnl_link *rtnl_link_ip6_tnl_alloc(void); + extern int rtnl_link_ip6_tnl_add(struct nl_sock *sk, const char *name); + + extern int rtnl_link_is_ip6_tnl(struct rtnl_link *link); + + extern int rtnl_link_ip6_tnl_set_link(struct rtnl_link *link, uint32_t index); + extern uint32_t rtnl_link_ip6_tnl_get_link(struct rtnl_link *link); + + extern int rtnl_link_ip6_tnl_set_local(struct rtnl_link *link, struct in6_addr *); + extern int rtnl_link_ip6_tnl_get_local(struct rtnl_link *link, struct in6_addr *addr); + + extern int rtnl_link_ip6_tnl_set_remote(struct rtnl_link *link, struct in6_addr *); + extern int rtnl_link_ip6_tnl_get_remote(struct rtnl_link *link, struct in6_addr *); + + extern int rtnl_link_ip6_tnl_set_ttl(struct rtnl_link *link, uint8_t ttl); + extern uint8_t rtnl_link_ip6_tnl_get_ttl(struct rtnl_link *link); + + extern int rtnl_link_ip6_tnl_set_tos(struct rtnl_link *link, uint8_t tos); + extern uint8_t rtnl_link_ip6_tnl_get_tos(struct rtnl_link *link); + + extern int rtnl_link_ip6_tnl_set_encaplimit(struct rtnl_link *link, uint8_t encap_limit); + extern uint8_t rtnl_link_ip6_tnl_get_encaplimit(struct rtnl_link *link); + + extern int rtnl_link_ip6_tnl_set_flags(struct rtnl_link *link, uint32_t flags); + extern uint32_t rtnl_link_ip6_tnl_get_flags(struct rtnl_link *link); + + extern uint32_t rtnl_link_ip6_tnl_get_flowinfo(struct rtnl_link *link); + extern int rtnl_link_ip6_tnl_set_flowinfo(struct rtnl_link *link, uint32_t flowinfo); + + extern int rtnl_link_ip6_tnl_set_proto(struct rtnl_link *link, uint8_t proto); + extern uint8_t rtnl_link_ip6_tnl_get_proto(struct rtnl_link *link); + + extern int rtnl_link_ip6_tnl_set_fwmark(struct rtnl_link *link, uint32_t fwmark); + extern int rtnl_link_ip6_tnl_get_fwmark(struct rtnl_link *link, uint32_t *fwmark); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/ip6vti.h b/include/netlink/route/link/ip6vti.h new file mode 100644 index 0000000..bfe33d3 --- /dev/null +++ b/include/netlink/route/link/ip6vti.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#ifndef NETLINK_LINK_IP6VTI_H_ +#define NETLINK_LINK_IP6VTI_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + int rtnl_link_is_ip6vti(struct rtnl_link *link); + + extern struct rtnl_link *rtnl_link_ip6vti_alloc(void); + extern int rtnl_link_ip6vti_add(struct nl_sock *sk, const char *name); + + extern int rtnl_link_ip6vti_set_link(struct rtnl_link *link, uint32_t index); + extern int rtnl_link_ip6vti_get_link(struct rtnl_link *link, uint32_t *index); + + extern int rtnl_link_ip6vti_set_ikey(struct rtnl_link *link, uint32_t ikey); + extern int rtnl_link_ip6vti_get_ikey(struct rtnl_link *link, uint32_t *ikey); + + extern int rtnl_link_ip6vti_set_okey(struct rtnl_link *link, uint32_t okey); + extern int rtnl_link_ip6vti_get_okey(struct rtnl_link *link, uint32_t *okey); + + extern int rtnl_link_ip6vti_set_local(struct rtnl_link *link, struct in6_addr *local); + extern int rtnl_link_ip6vti_get_local(struct rtnl_link *link, struct in6_addr *remote); + + extern int rtnl_link_ip6vti_set_remote(struct rtnl_link *link, struct in6_addr *remote); + extern int rtnl_link_ip6vti_get_remote(struct rtnl_link *link, struct in6_addr *remote); + + extern int rtnl_link_ip6vti_set_fwmark(struct rtnl_link *link, uint32_t fwmark); + extern int rtnl_link_ip6vti_get_fwmark(struct rtnl_link *link, uint32_t *fwmark); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/ipgre.h b/include/netlink/route/link/ipgre.h new file mode 100644 index 0000000..09a4957 --- /dev/null +++ b/include/netlink/route/link/ipgre.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2014 Susant Sahani + */ + +#ifndef NETLINK_LINK_IPGRE_H_ +#define NETLINK_LINK_IPGRE_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + extern int rtnl_link_is_ipgre(struct rtnl_link *link); + extern int rtnl_link_is_ipgretap(struct rtnl_link *link); + + extern struct rtnl_link *rtnl_link_ipgre_alloc(void); + extern struct rtnl_link *rtnl_link_ipgretap_alloc(void); + extern int rtnl_link_ipgre_add(struct nl_sock *sk, const char *name); + extern int rtnl_link_ipgretap_add(struct nl_sock *sk, const char *name); + + extern int rtnl_link_ipgre_set_link(struct rtnl_link *link, uint32_t index); + extern uint32_t rtnl_link_ipgre_get_link(struct rtnl_link *link); + + extern int rtnl_link_ipgre_set_iflags(struct rtnl_link *link, uint16_t iflags); + extern uint16_t rtnl_link_ipgre_get_iflags(struct rtnl_link *link); + + extern int rtnl_link_ipgre_set_oflags(struct rtnl_link *link, uint16_t oflags); + extern uint16_t rtnl_link_ipgre_get_oflags(struct rtnl_link *link); + + extern int rtnl_link_ipgre_set_ikey(struct rtnl_link *link, uint32_t ikey); + extern uint32_t rtnl_link_ipgre_get_ikey(struct rtnl_link *link); + + extern int rtnl_link_ipgre_set_okey(struct rtnl_link *link, uint32_t okey); + extern uint32_t rtnl_link_ipgre_get_okey(struct rtnl_link *link); + + extern int rtnl_link_ipgre_set_local(struct rtnl_link *link, uint32_t addr); + extern uint32_t rtnl_link_ipgre_get_local(struct rtnl_link *link); + + extern int rtnl_link_ipgre_set_remote(struct rtnl_link *link, uint32_t addr); + extern uint32_t rtnl_link_ipgre_get_remote(struct rtnl_link *link); + + extern int rtnl_link_ipgre_set_ttl(struct rtnl_link *link, uint8_t ttl); + extern uint8_t rtnl_link_ipgre_get_ttl(struct rtnl_link *link); + + extern int rtnl_link_ipgre_set_tos(struct rtnl_link *link, uint8_t tos); + extern uint8_t rtnl_link_ipgre_get_tos(struct rtnl_link *link); + + extern int rtnl_link_ipgre_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc); + extern uint8_t rtnl_link_ipgre_get_pmtudisc(struct rtnl_link *link); + + extern int rtnl_link_ipgre_set_fwmark(struct rtnl_link *link, uint32_t fwmark); + extern int rtnl_link_ipgre_get_fwmark(struct rtnl_link *link, uint32_t *fwmark); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/ipip.h b/include/netlink/route/link/ipip.h new file mode 100644 index 0000000..65d9f18 --- /dev/null +++ b/include/netlink/route/link/ipip.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2014 Susant Sahani + */ + +#ifndef NETLINK_LINK_IPIP_H_ +#define NETLINK_LINK_IPIP_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + extern struct rtnl_link *rtnl_link_ipip_alloc(void); + extern int rtnl_link_ipip_add(struct nl_sock *sk, const char *name); + + extern int rtnl_link_is_ipip(struct rtnl_link *link); + + extern uint32_t rtnl_link_ipip_get_link(struct rtnl_link *link); + extern int rtnl_link_ipip_set_link(struct rtnl_link *link, uint32_t index); + + extern int rtnl_link_ipip_set_local(struct rtnl_link *link, uint32_t addr); + extern uint32_t rtnl_link_ipip_get_local(struct rtnl_link *link); + + extern int rtnl_link_ipip_set_remote(struct rtnl_link *link, uint32_t addr); + extern uint32_t rtnl_link_ipip_get_remote(struct rtnl_link *link); + + extern int rtnl_link_ipip_set_ttl(struct rtnl_link *link, uint8_t ttl); + extern uint8_t rtnl_link_ipip_get_ttl(struct rtnl_link *link); + + extern int rtnl_link_ipip_set_tos(struct rtnl_link *link, uint8_t tos); + extern uint8_t rtnl_link_ipip_get_tos(struct rtnl_link *link); + + extern int rtnl_link_ipip_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc); + extern uint8_t rtnl_link_ipip_get_pmtudisc(struct rtnl_link *link); + + extern int rtnl_link_ipip_set_fwmark(struct rtnl_link *link, uint32_t fwmark); + extern int rtnl_link_ipip_get_fwmark(struct rtnl_link *link, uint32_t *fwmark); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/ipvlan.h b/include/netlink/route/link/ipvlan.h new file mode 100644 index 0000000..09b1d2d --- /dev/null +++ b/include/netlink/route/link/ipvlan.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2015 Cong Wang + */ + +#ifndef NETLINK_LINK_IPVLAN_H_ +#define NETLINK_LINK_IPVLAN_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct rtnl_link *rtnl_link_ipvlan_alloc(void); + +extern int rtnl_link_is_ipvlan(struct rtnl_link *); + +extern char * rtnl_link_ipvlan_mode2str(int, char *, size_t); +extern int rtnl_link_ipvlan_str2mode(const char *); + +extern int rtnl_link_ipvlan_set_mode(struct rtnl_link *, + uint16_t); +extern int rtnl_link_ipvlan_get_mode(struct rtnl_link *, uint16_t *out_mode); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/ipvti.h b/include/netlink/route/link/ipvti.h new file mode 100644 index 0000000..8e31dab --- /dev/null +++ b/include/netlink/route/link/ipvti.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2014 Susant Sahani + */ + +#ifndef NETLINK_LINK_IPVTI_H_ +#define NETLINK_LINK_IPVTI_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + extern struct rtnl_link *rtnl_link_ipvti_alloc(void); + extern int rtnl_link_ipvti_add(struct nl_sock *sk, const char *name); + + extern int rtnl_link_is_ipvti(struct rtnl_link *link); + + extern int rtnl_link_ipvti_set_link(struct rtnl_link *link, uint32_t index); + extern uint32_t rtnl_link_ipvti_get_link(struct rtnl_link *link); + + extern int rtnl_link_ipvti_set_ikey(struct rtnl_link *link, uint32_t ikey); + extern uint32_t rtnl_link_ipvti_get_ikey(struct rtnl_link *link); + + extern int rtnl_link_ipvti_set_okey(struct rtnl_link *link, uint32_t okey); + extern uint32_t rtnl_link_ipvti_get_okey(struct rtnl_link *link); + + extern int rtnl_link_ipvti_set_local(struct rtnl_link *link, uint32_t addr); + extern uint32_t rtnl_link_ipvti_get_local(struct rtnl_link *link); + + extern int rtnl_link_ipvti_set_remote(struct rtnl_link *link, uint32_t addr); + extern uint32_t rtnl_link_ipvti_get_remote(struct rtnl_link *link); + + extern int rtnl_link_ipvti_set_fwmark(struct rtnl_link *link, uint32_t fwmark); + extern int rtnl_link_ipvti_get_fwmark(struct rtnl_link *link, uint32_t *fwmark); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/macsec.h b/include/netlink/route/link/macsec.h new file mode 100644 index 0000000..3139b47 --- /dev/null +++ b/include/netlink/route/link/macsec.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2016 Sabrina Dubroca + */ + +#ifndef NETLINK_LINK_MACSEC_H_ +#define NETLINK_LINK_MACSEC_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum macsec_validation_type; + +struct rtnl_link *rtnl_link_macsec_alloc(void); + +int rtnl_link_macsec_set_sci(struct rtnl_link *, uint64_t); +int rtnl_link_macsec_get_sci(struct rtnl_link *, uint64_t *); + +int rtnl_link_macsec_set_port(struct rtnl_link *, uint16_t); +int rtnl_link_macsec_get_port(struct rtnl_link *, uint16_t *); + +int rtnl_link_macsec_set_cipher_suite(struct rtnl_link *, uint64_t); +int rtnl_link_macsec_get_cipher_suite(struct rtnl_link *, uint64_t *); + +int rtnl_link_macsec_set_icv_len(struct rtnl_link *, uint16_t); +int rtnl_link_macsec_get_icv_len(struct rtnl_link *, uint16_t *); + +int rtnl_link_macsec_set_protect(struct rtnl_link *, uint8_t); +int rtnl_link_macsec_get_protect(struct rtnl_link *, uint8_t *); + +int rtnl_link_macsec_set_encrypt(struct rtnl_link *, uint8_t); +int rtnl_link_macsec_get_encrypt(struct rtnl_link *, uint8_t *); + +int rtnl_link_macsec_set_offload(struct rtnl_link *, uint8_t); +int rtnl_link_macsec_get_offload(struct rtnl_link *, uint8_t *); + +int rtnl_link_macsec_set_encoding_sa(struct rtnl_link *, uint8_t); +int rtnl_link_macsec_get_encoding_sa(struct rtnl_link *, uint8_t *); + +int rtnl_link_macsec_set_validation_type(struct rtnl_link *, + enum macsec_validation_type); +int rtnl_link_macsec_get_validation_type(struct rtnl_link *, + enum macsec_validation_type *); + +int rtnl_link_macsec_set_replay_protect(struct rtnl_link *, uint8_t); +int rtnl_link_macsec_get_replay_protect(struct rtnl_link *, uint8_t *); + +int rtnl_link_macsec_set_window(struct rtnl_link *, uint32_t); +int rtnl_link_macsec_get_window(struct rtnl_link *, uint32_t *); + +int rtnl_link_macsec_set_send_sci(struct rtnl_link *, uint8_t); +int rtnl_link_macsec_get_send_sci(struct rtnl_link *, uint8_t *); + +int rtnl_link_macsec_set_end_station(struct rtnl_link *, uint8_t); +int rtnl_link_macsec_get_end_station(struct rtnl_link *, uint8_t *); + +int rtnl_link_macsec_set_scb(struct rtnl_link *, uint8_t); +int rtnl_link_macsec_get_scb(struct rtnl_link *, uint8_t *); + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/macvlan.h b/include/netlink/route/link/macvlan.h new file mode 100644 index 0000000..7c133cb --- /dev/null +++ b/include/netlink/route/link/macvlan.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Michael Braun + */ + +#ifndef NETLINK_LINK_MACVLAN_H_ +#define NETLINK_LINK_MACVLAN_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct rtnl_link *rtnl_link_macvlan_alloc(void); + +extern int rtnl_link_is_macvlan(struct rtnl_link *); + +extern char * rtnl_link_macvlan_mode2str(int, char *, size_t); +extern int rtnl_link_macvlan_str2mode(const char *); + +extern char * rtnl_link_macvlan_flags2str(int, char *, size_t); +extern int rtnl_link_macvlan_str2flags(const char *); + +extern char * rtnl_link_macvlan_macmode2str(int, char *, size_t); +extern int rtnl_link_macvlan_str2macmode(const char *); + +extern int rtnl_link_macvlan_set_mode(struct rtnl_link *, + uint32_t); +extern uint32_t rtnl_link_macvlan_get_mode(struct rtnl_link *); + +extern int rtnl_link_macvlan_set_flags(struct rtnl_link *, + uint16_t); +extern int rtnl_link_macvlan_unset_flags(struct rtnl_link *, + uint16_t); +extern uint16_t rtnl_link_macvlan_get_flags(struct rtnl_link *); + +extern int rtnl_link_macvlan_set_macmode(struct rtnl_link *, + uint32_t); +extern int rtnl_link_macvlan_get_macmode(struct rtnl_link *link, + uint32_t *out_macmode); + +extern int rtnl_link_macvlan_count_macaddr(struct rtnl_link *link, + uint32_t *out_count); +extern int rtnl_link_macvlan_get_macaddr(struct rtnl_link *link, + uint32_t idx, + const struct nl_addr **addr); +extern int rtnl_link_macvlan_add_macaddr(struct rtnl_link *link, + struct nl_addr *addr); +extern int rtnl_link_macvlan_del_macaddr(struct rtnl_link *link, + struct nl_addr *addr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/macvtap.h b/include/netlink/route/link/macvtap.h new file mode 100644 index 0000000..6fff30d --- /dev/null +++ b/include/netlink/route/link/macvtap.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2015 Beniamino Galvani + */ + +#ifndef NETLINK_LINK_MACVTAP_H_ +#define NETLINK_LINK_MACVTAP_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct rtnl_link *rtnl_link_macvtap_alloc(void); + +extern int rtnl_link_is_macvtap(struct rtnl_link *); + +extern char * rtnl_link_macvtap_mode2str(int, char *, size_t); +extern int rtnl_link_macvtap_str2mode(const char *); + +extern char * rtnl_link_macvtap_flags2str(int, char *, size_t); +extern int rtnl_link_macvtap_str2flags(const char *); + +extern int rtnl_link_macvtap_set_mode(struct rtnl_link *, + uint32_t); +extern uint32_t rtnl_link_macvtap_get_mode(struct rtnl_link *); + +extern int rtnl_link_macvtap_set_flags(struct rtnl_link *, + uint16_t); +extern int rtnl_link_macvtap_unset_flags(struct rtnl_link *, + uint16_t); +extern uint16_t rtnl_link_macvtap_get_flags(struct rtnl_link *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/ppp.h b/include/netlink/route/link/ppp.h new file mode 100644 index 0000000..d65582a --- /dev/null +++ b/include/netlink/route/link/ppp.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2016 Jonas Johansson + */ + +#ifndef NETLINK_LINK_PPP_H_ +#define NETLINK_LINK_PPP_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct rtnl_link *rtnl_link_ppp_alloc(void); +extern int rtnl_link_ppp_set_fd(struct rtnl_link *, int32_t); +extern int rtnl_link_ppp_get_fd(struct rtnl_link *, int32_t *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/sit.h b/include/netlink/route/link/sit.h new file mode 100644 index 0000000..f41e101 --- /dev/null +++ b/include/netlink/route/link/sit.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2014 Susant Sahani + */ + +#ifndef NETLINK_LINK_SIT_H_ +#define NETLINK_LINK_SIT_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + extern struct rtnl_link *rtnl_link_sit_alloc(void); + extern int rtnl_link_sit_add(struct nl_sock *sk, const char *name); + + extern int rtnl_link_is_sit(struct rtnl_link *link); + + extern int rtnl_link_sit_set_link(struct rtnl_link *link, uint32_t index); + extern uint32_t rtnl_link_sit_get_link(struct rtnl_link *link); + + extern int rtnl_link_sit_set_local(struct rtnl_link *link, uint32_t addr); + extern uint32_t rtnl_link_sit_get_local(struct rtnl_link *link); + + extern int rtnl_link_sit_set_remote(struct rtnl_link *link, uint32_t addr); + extern uint32_t rtnl_link_sit_get_remote(struct rtnl_link *link); + + extern int rtnl_link_sit_set_ttl(struct rtnl_link *link, uint8_t ttl); + extern uint8_t rtnl_link_sit_get_ttl(struct rtnl_link *link); + + extern int rtnl_link_sit_set_tos(struct rtnl_link *link, uint8_t tos); + extern uint8_t rtnl_link_sit_get_tos(struct rtnl_link *link); + + extern int rtnl_link_sit_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc); + extern uint8_t rtnl_link_sit_get_pmtudisc(struct rtnl_link *link); + + extern int rtnl_link_sit_set_flags(struct rtnl_link *link, uint16_t flags); + extern uint16_t rtnl_link_sit_get_flags(struct rtnl_link *link); + + int rtnl_link_sit_set_proto(struct rtnl_link *link, uint8_t proto); + uint8_t rtnl_link_sit_get_proto(struct rtnl_link *link); + + int rtnl_link_sit_set_ip6rd_prefix(struct rtnl_link *link, const struct in6_addr *prefix); + int rtnl_link_sit_get_ip6rd_prefix(const struct rtnl_link *link, struct in6_addr *prefix); + + int rtnl_link_sit_set_ip6rd_prefixlen(struct rtnl_link *link, uint16_t prefixlen); + int rtnl_link_sit_get_ip6rd_prefixlen(struct rtnl_link *link, uint16_t *prefixlen); + + int rtnl_link_sit_set_ip6rd_relay_prefix(struct rtnl_link *link, uint32_t prefix); + int rtnl_link_sit_get_ip6rd_relay_prefix(const struct rtnl_link *link, uint32_t *prefix); + + int rtnl_link_sit_set_ip6rd_relay_prefixlen(struct rtnl_link *link, uint16_t prefix); + int rtnl_link_sit_get_ip6rd_relay_prefixlen(struct rtnl_link *link, uint16_t *prefix); + + extern int rtnl_link_sit_set_fwmark(struct rtnl_link *link, uint32_t fwmark); + extern int rtnl_link_sit_get_fwmark(struct rtnl_link *link, uint32_t *fwmark); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/sriov.h b/include/netlink/route/link/sriov.h new file mode 100644 index 0000000..36d66bf --- /dev/null +++ b/include/netlink/route/link/sriov.h @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2016 Intel Corp. All rights reserved. + * Copyright (c) 2016 Jef Oliver + */ + +#ifndef NETLINK_LINK_SRIOV_H_ +#define NETLINK_LINK_SRIOV_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define RTNL_VF_GUID_STR_LEN 23 + +/** + * @ingroup sriov + */ +typedef enum { + RTNL_LINK_VF_RATE_API_UNSPEC, /*!< Unspecified API type */ + RTNL_LINK_VF_RATE_API_OLD, /*!< Old Rate setting API */ + RTNL_LINK_VF_RATE_API_NEW, /*!< New Rate setting API */ + __RTNL_LINK_VF_RATE_API_MAX, +} rtnl_link_rate_api_t; + +#define RTNL_LINK_VF_RATE_API_MAX (__RTNL_LINK_VF_RATE_API_MAX - 1) + +/** + * @ingroup sriov + */ +typedef enum { + RTNL_LINK_VF_STATS_RX_PACKETS, /*!< Packets Received */ + RTNL_LINK_VF_STATS_TX_PACKETS, /*!< Packets Sent */ + RTNL_LINK_VF_STATS_RX_BYTES, /*!< Bytes Recieved */ + RTNL_LINK_VF_STATS_TX_BYTES, /*!< Bytes Sent */ + RTNL_LINK_VF_STATS_BROADCAST, /*!< Broadcast packets received */ + RTNL_LINK_VF_STATS_MULTICAST, /*!< Multicast packets received */ + __RTNL_LINK_VF_STATS_MAX, +} rtnl_link_vf_stats_t; + +#define RTNL_LINK_VF_STATS_MAX (__RTNL_LINK_VF_STATS_MAX - 1) + +/** + * @struct rtnl_link_vf sriov.h "netlink/route/link/sriov.h" + * @brief SRIOV VF object + * @ingroup sriov + * + * @copydoc private_struct + */ +struct rtnl_link_vf; + +/** + * @brief SRIOV VF VFLAN settings + * @ingroup sriov + */ +typedef struct nl_vf_vlan_info { + uint32_t vf_vlan; /*!< VLAN number */ + uint32_t vf_vlan_qos; /*!< VLAN QOS value */ + uint16_t vf_vlan_proto; /*!< VLAN protocol */ +} nl_vf_vlan_info_t; + +/** + * @brief SRIOV VF VLANs information + * @ingroup sriov + */ +typedef struct nl_vf_vlans { + int ce_refcnt; /*!< Reference counter. Don't change this value */ + int size; /*!< Number of VLANs on the SRIOV VF */ + nl_vf_vlan_info_t * vlans; /*!< nl_vf_vlan_info_t array of SRIOV VF VLANs */ +} nl_vf_vlans_t; + +/** + * @brief VF Rate information structure + * @ingroup sriov + */ +struct nl_vf_rate { + int api; /*!< rtnl_link_rate_api_t API Version to use */ + uint32_t rate; /*!< Old API Max Rate in Mbps */ + uint32_t max_tx_rate; /*!< New API Max Rate in Mbps */ + uint32_t min_tx_rate; /*!< New API Mix Rate in Mbps */ +}; + +extern int rtnl_link_vf_add(struct rtnl_link *, struct rtnl_link_vf *); +extern struct rtnl_link_vf *rtnl_link_vf_alloc(void); +extern void rtnl_link_vf_free(struct rtnl_link_vf *); +extern struct rtnl_link_vf *rtnl_link_vf_get(struct rtnl_link *, uint32_t); +extern void rtnl_link_vf_put(struct rtnl_link_vf *); + +extern int rtnl_link_vf_get_addr(struct rtnl_link_vf *, struct nl_addr **); +extern void rtnl_link_vf_set_addr(struct rtnl_link_vf *, struct nl_addr *); + +extern void rtnl_link_vf_set_ib_node_guid(struct rtnl_link_vf *, uint64_t); +extern void rtnl_link_vf_set_ib_port_guid(struct rtnl_link_vf *, uint64_t); + +extern int rtnl_link_vf_get_index(struct rtnl_link_vf *, uint32_t *); +extern void rtnl_link_vf_set_index(struct rtnl_link_vf *, uint32_t); + +extern int rtnl_link_vf_get_linkstate(struct rtnl_link_vf *, uint32_t *); +extern void rtnl_link_vf_set_linkstate(struct rtnl_link_vf *, uint32_t); + +extern int rtnl_link_vf_get_rate(struct rtnl_link_vf *, struct nl_vf_rate *); +extern void rtnl_link_vf_set_rate(struct rtnl_link_vf *, struct nl_vf_rate *); + +extern int rtnl_link_vf_get_rss_query_en(struct rtnl_link_vf *, uint32_t *); +extern void rtnl_link_vf_set_rss_query_en(struct rtnl_link_vf *, uint32_t); + +extern int rtnl_link_vf_get_spoofchk(struct rtnl_link_vf *, uint32_t *); +extern void rtnl_link_vf_set_spoofchk(struct rtnl_link_vf *, uint32_t); + +extern int rtnl_link_vf_get_stat(struct rtnl_link_vf *, rtnl_link_vf_stats_t, + uint64_t *); + +extern int rtnl_link_vf_get_trust(struct rtnl_link_vf *, uint32_t *); +extern void rtnl_link_vf_set_trust(struct rtnl_link_vf *, uint32_t); + +extern int rtnl_link_vf_get_vlans(struct rtnl_link_vf *, nl_vf_vlans_t **); +extern void rtnl_link_vf_set_vlans(struct rtnl_link_vf *, nl_vf_vlans_t *); + +extern int rtnl_link_vf_vlan_alloc(nl_vf_vlans_t **, int); +extern void rtnl_link_vf_vlan_free(nl_vf_vlans_t *vf_vlans); +extern void rtnl_link_vf_vlan_put(nl_vf_vlans_t *); + +/* Utility functions */ +extern char *rtnl_link_vf_linkstate2str(uint32_t, char *, size_t); +extern int rtnl_link_vf_str2linkstate(const char *); + +extern char *rtnl_link_vf_vlanproto2str(uint16_t, char *, size_t); +extern int rtnl_link_vf_str2vlanproto(const char *); + +extern int rtnl_link_vf_str2guid(uint64_t *, const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/team.h b/include/netlink/route/link/team.h new file mode 100644 index 0000000..a55cdf9 --- /dev/null +++ b/include/netlink/route/link/team.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2015 Jonas Johansson + */ + +#ifndef NETLINK_LINK_TEAM_H_ +#define NETLINK_LINK_TEAM_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct rtnl_link *rtnl_link_team_alloc(void); + +extern int rtnl_link_team_add(struct nl_sock *, const char *, + struct rtnl_link *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/netlink/route/link/veth.h b/include/netlink/route/link/veth.h new file mode 100644 index 0000000..66a0d93 --- /dev/null +++ b/include/netlink/route/link/veth.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Cong Wang + */ + +#ifndef NETLINK_LINK_VETH_H_ +#define NETLINK_LINK_VETH_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct rtnl_link *rtnl_link_veth_alloc(void); +extern void rtnl_link_veth_release(struct rtnl_link *); + +extern int rtnl_link_is_veth(struct rtnl_link *); + +extern struct rtnl_link *rtnl_link_veth_get_peer(struct rtnl_link *); +extern int rtnl_link_veth_add(struct nl_sock *sock, const char *name, + const char *peer, pid_t pid); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/vlan.h b/include/netlink/route/link/vlan.h index f274163..2729d6e 100644 --- a/include/netlink/route/link/vlan.h +++ b/include/netlink/route/link/vlan.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/link/vlan.h VLAN interface - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2013 Thomas Graf */ @@ -34,6 +28,9 @@ extern int rtnl_link_is_vlan(struct rtnl_link *); extern char * rtnl_link_vlan_flags2str(int, char *, size_t); extern int rtnl_link_vlan_str2flags(const char *); +extern int rtnl_link_vlan_set_protocol(struct rtnl_link *link, uint16_t); +extern int rtnl_link_vlan_get_protocol(struct rtnl_link *link); + extern int rtnl_link_vlan_set_id(struct rtnl_link *, uint16_t); extern int rtnl_link_vlan_get_id(struct rtnl_link *); diff --git a/include/netlink/route/link/vrf.h b/include/netlink/route/link/vrf.h new file mode 100644 index 0000000..5d49437 --- /dev/null +++ b/include/netlink/route/link/vrf.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2015 Cumulus Networks. All rights reserved. + * Copyright (c) 2015 David Ahern + */ + +#ifndef NETLINK_LINK_VRF_H_ +#define NETLINK_LINK_VRF_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct rtnl_link *rtnl_link_vrf_alloc(void); +extern int rtnl_link_is_vrf(struct rtnl_link *link); +extern int rtnl_link_vrf_get_tableid(struct rtnl_link *link, uint32_t *id); +extern int rtnl_link_vrf_set_tableid(struct rtnl_link *link, uint32_t id); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/vxlan.h b/include/netlink/route/link/vxlan.h new file mode 100644 index 0000000..6321b09 --- /dev/null +++ b/include/netlink/route/link/vxlan.h @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Yasunobu Chiba + */ + +#ifndef NETLINK_LINK_VXLAN_H_ +#define NETLINK_LINK_VXLAN_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct ifla_vxlan_port_range; + +#define VXLAN_ID_MAX 16777215 + +enum { + RTNL_LINK_VXLAN_F_GBP = 1 << 0, +#define RTNL_LINK_VXLAN_F_GBP RTNL_LINK_VXLAN_F_GBP + RTNL_LINK_VXLAN_F_GPE = 1 << 1, +#define RTNL_LINK_VXLAN_F_GPE RTNL_LINK_VXLAN_F_GPE + RTNL_LINK_VXLAN_F_REMCSUM_NOPARTIAL = 1 << 2, +#define RTNL_LINK_VXLAN_F_REMCSUM_NOPARTIAL RTNL_LINK_VXLAN_F_REMCSUM_NOPARTIAL +}; + +extern struct rtnl_link *rtnl_link_vxlan_alloc(void); + +extern int rtnl_link_is_vxlan(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_id(struct rtnl_link *, uint32_t); +extern int rtnl_link_vxlan_get_id(struct rtnl_link *, uint32_t *); + +extern int rtnl_link_vxlan_set_group(struct rtnl_link *, struct nl_addr *); +extern int rtnl_link_vxlan_get_group(struct rtnl_link *, struct nl_addr **); + +extern int rtnl_link_vxlan_set_link(struct rtnl_link *, uint32_t); +extern int rtnl_link_vxlan_get_link(struct rtnl_link *, uint32_t *); + +extern int rtnl_link_vxlan_set_local(struct rtnl_link *, struct nl_addr *); +extern int rtnl_link_vxlan_get_local(struct rtnl_link *, struct nl_addr **); + +extern int rtnl_link_vxlan_set_ttl(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_ttl(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_tos(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_tos(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_learning(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_learning(struct rtnl_link *); +extern int rtnl_link_vxlan_enable_learning(struct rtnl_link *); +extern int rtnl_link_vxlan_disable_learning(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_ageing(struct rtnl_link *, uint32_t); +extern int rtnl_link_vxlan_get_ageing(struct rtnl_link *, uint32_t *); + +extern int rtnl_link_vxlan_set_limit(struct rtnl_link *, uint32_t); +extern int rtnl_link_vxlan_get_limit(struct rtnl_link *, uint32_t *); + +extern int rtnl_link_vxlan_set_port_range(struct rtnl_link *, + struct ifla_vxlan_port_range *); +extern int rtnl_link_vxlan_get_port_range(struct rtnl_link *, + struct ifla_vxlan_port_range *); + +extern int rtnl_link_vxlan_set_proxy(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_proxy(struct rtnl_link *); +extern int rtnl_link_vxlan_enable_proxy(struct rtnl_link *); +extern int rtnl_link_vxlan_disable_proxy(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_rsc(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_rsc(struct rtnl_link *); +extern int rtnl_link_vxlan_enable_rsc(struct rtnl_link *); +extern int rtnl_link_vxlan_disable_rsc(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_l2miss(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_l2miss(struct rtnl_link *); +extern int rtnl_link_vxlan_enable_l2miss(struct rtnl_link *); +extern int rtnl_link_vxlan_disable_l2miss(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_l3miss(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_l3miss(struct rtnl_link *); +extern int rtnl_link_vxlan_enable_l3miss(struct rtnl_link *); +extern int rtnl_link_vxlan_disable_l3miss(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_port(struct rtnl_link *, uint32_t); +extern int rtnl_link_vxlan_get_port(struct rtnl_link *, uint32_t *); + +extern int rtnl_link_vxlan_set_udp_csum(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_udp_csum(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_udp_zero_csum6_tx(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_udp_zero_csum6_tx(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_udp_zero_csum6_rx(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_udp_zero_csum6_rx(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_remcsum_tx(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_remcsum_tx(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_remcsum_rx(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_remcsum_rx(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_flags(struct rtnl_link *, uint32_t flags, int enable); +extern int rtnl_link_vxlan_get_flags(struct rtnl_link *, uint32_t *out_flags); + +extern int rtnl_link_vxlan_set_collect_metadata(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_collect_metadata(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_label(struct rtnl_link *, uint32_t); +extern int rtnl_link_vxlan_get_label(struct rtnl_link *, uint32_t *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/link/xfrmi.h b/include/netlink/route/link/xfrmi.h new file mode 100644 index 0000000..094ea11 --- /dev/null +++ b/include/netlink/route/link/xfrmi.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2019 Eyal Birger + * + * Based on netlink/route/link/ipvti.h + */ + +#ifndef NETLINK_LINK_XFRMI_H_ +#define NETLINK_LINK_XFRMI_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + extern struct rtnl_link *rtnl_link_xfrmi_alloc(void); + + extern int rtnl_link_is_xfrmi(struct rtnl_link *link); + + extern int rtnl_link_xfrmi_set_link(struct rtnl_link *link, uint32_t index); + extern int rtnl_link_xfrmi_get_link(struct rtnl_link *link, uint32_t *out_link); + + extern int rtnl_link_xfrmi_set_if_id(struct rtnl_link *link, uint32_t if_id); + extern int rtnl_link_xfrmi_get_if_id(struct rtnl_link *link, uint32_t *out_if_id); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/mdb.h b/include/netlink/route/mdb.h new file mode 100644 index 0000000..a65ea84 --- /dev/null +++ b/include/netlink/route/mdb.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#ifndef NETLINK_MDB_H_ +#define NETLINK_MDB_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct rtnl_mdb; +struct rtnl_mdb_entry; + +struct rtnl_mdb *rtnl_mdb_alloc(void); +void rtnl_mdb_put(struct rtnl_mdb *mdb); + +int rtnl_mdb_alloc_cache(struct nl_sock *sk, struct nl_cache **result); +int rtnl_mdb_alloc_cache_flags(struct nl_sock *sock, + struct nl_cache **result, + unsigned int flags); + +uint32_t rtnl_mdb_get_ifindex(struct rtnl_mdb *mdb); +void rtnl_mdb_add_entry(struct rtnl_mdb *mdb, + struct rtnl_mdb_entry *_entry); + +void rtnl_mdb_foreach_entry(struct rtnl_mdb *mdb, + void (*cb)(struct rtnl_mdb_entry *, void *), + void *arg); + +int rtnl_mdb_entry_get_ifindex(struct rtnl_mdb_entry *mdb_entry); +int rtnl_mdb_entry_get_vid(struct rtnl_mdb_entry *mdb_entry); +int rtnl_mdb_entry_get_state(struct rtnl_mdb_entry *mdb_entry); +struct nl_addr *rtnl_mdb_entry_get_addr(struct rtnl_mdb_entry + *mdb_entry); +uint16_t rtnl_mdb_entry_get_proto(struct rtnl_mdb_entry *mdb_entry); +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/netlink/route/neighbour.h b/include/netlink/route/neighbour.h index 1d1179b..657db53 100644 --- a/include/netlink/route/neighbour.h +++ b/include/netlink/route/neighbour.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/neighbour.h Neighbours - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf */ @@ -26,8 +20,13 @@ extern struct rtnl_neigh *rtnl_neigh_alloc(void); extern void rtnl_neigh_put(struct rtnl_neigh *); extern int rtnl_neigh_alloc_cache(struct nl_sock *, struct nl_cache **); +extern int rtnl_neigh_alloc_cache_flags(struct nl_sock *, + struct nl_cache **, + unsigned int); extern struct rtnl_neigh *rtnl_neigh_get(struct nl_cache *, int, struct nl_addr *); +extern struct rtnl_neigh *rtnl_neigh_get_by_vlan(struct nl_cache *, int, + struct nl_addr *, int); extern int rtnl_neigh_parse(struct nlmsghdr *, struct rtnl_neigh **); @@ -74,6 +73,15 @@ extern int rtnl_neigh_get_type(struct rtnl_neigh *); extern void rtnl_neigh_set_family(struct rtnl_neigh *, int); extern int rtnl_neigh_get_family(struct rtnl_neigh *); +extern void rtnl_neigh_set_vlan(struct rtnl_neigh *, int); +extern int rtnl_neigh_get_vlan(struct rtnl_neigh *); + +extern void rtnl_neigh_set_master(struct rtnl_neigh *, int); +extern int rtnl_neigh_get_master(struct rtnl_neigh *); + +extern void rtnl_neigh_set_nhid(struct rtnl_neigh *, uint32_t); +extern int rtnl_neigh_get_nhid(struct rtnl_neigh *, uint32_t *); + #ifdef __cplusplus } #endif diff --git a/include/netlink/route/neightbl.h b/include/netlink/route/neightbl.h index 412c3e9..8bcdab2 100644 --- a/include/netlink/route/neightbl.h +++ b/include/netlink/route/neightbl.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/neightbl.h Neighbour Tables - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf */ @@ -41,6 +35,7 @@ extern void rtnl_neightbl_set_family(struct rtnl_neightbl *, int); extern void rtnl_neightbl_set_gc_tresh1(struct rtnl_neightbl *, int); extern void rtnl_neightbl_set_gc_tresh2(struct rtnl_neightbl *, int); extern void rtnl_neightbl_set_gc_tresh3(struct rtnl_neightbl *, int); +extern void rtnl_neightbl_set_gc_interval(struct rtnl_neightbl *, uint64_t); extern void rtnl_neightbl_set_name(struct rtnl_neightbl *, const char *); extern void rtnl_neightbl_set_dev(struct rtnl_neightbl *, int); extern void rtnl_neightbl_set_queue_len(struct rtnl_neightbl *, int); diff --git a/include/netlink/route/netconf.h b/include/netlink/route/netconf.h new file mode 100644 index 0000000..a6b1f89 --- /dev/null +++ b/include/netlink/route/netconf.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2017 David Ahern + */ + +#ifndef NETCONF_H_ +#define NETCONF_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct nl_sock; +struct nl_cache; +struct rtnl_netconf; + +int rtnl_netconf_alloc_cache(struct nl_sock *sk, struct nl_cache **result); + +struct rtnl_netconf *rtnl_netconf_get_by_idx(struct nl_cache *cache, int family, + int ifindex); +struct rtnl_netconf *rtnl_netconf_get_all(struct nl_cache *cache, + int family); +struct rtnl_netconf *rtnl_netconf_get_default(struct nl_cache *cache, + int family); +void rtnl_netconf_put(struct rtnl_netconf *nc); + +int rtnl_netconf_get_family(struct rtnl_netconf *nc, int *val); +int rtnl_netconf_get_ifindex(struct rtnl_netconf *nc, int *val); +int rtnl_netconf_get_forwarding(struct rtnl_netconf *nc, int *val); +int rtnl_netconf_get_mc_forwarding(struct rtnl_netconf *nc, int *val); +int rtnl_netconf_get_rp_filter(struct rtnl_netconf *nc, int *val); +int rtnl_netconf_get_proxy_neigh(struct rtnl_netconf *nc, int *val); +int rtnl_netconf_get_ignore_routes_linkdown(struct rtnl_netconf *nc, int *val); +int rtnl_netconf_get_input(struct rtnl_netconf *nc, int *val); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/nexthop.h b/include/netlink/route/nexthop.h index 2aa44dc..c4a2604 100644 --- a/include/netlink/route/nexthop.h +++ b/include/netlink/route/nexthop.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/nexthop.h Routing Nexthop - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf */ @@ -55,9 +49,23 @@ extern void rtnl_route_nh_set_realms(struct rtnl_nexthop *, uint32_t); extern uint32_t rtnl_route_nh_get_realms(struct rtnl_nexthop *); +extern int rtnl_route_nh_set_newdst(struct rtnl_nexthop *, + struct nl_addr *); +extern struct nl_addr * rtnl_route_nh_get_newdst(struct rtnl_nexthop *); +extern int rtnl_route_nh_set_via(struct rtnl_nexthop *, + struct nl_addr *); +extern struct nl_addr * rtnl_route_nh_get_via(struct rtnl_nexthop *); extern char * rtnl_route_nh_flags2str(int, char *, size_t); extern int rtnl_route_nh_str2flags(const char *); +/* + * nexthop encapsulations + */ +extern int rtnl_route_nh_encap_mpls(struct rtnl_nexthop *nh, + struct nl_addr *addr, + uint8_t ttl); +extern struct nl_addr * rtnl_route_nh_get_encap_mpls_dst(struct rtnl_nexthop *); +extern uint8_t rtnl_route_nh_get_encap_mpls_ttl(struct rtnl_nexthop *); #ifdef __cplusplus } #endif diff --git a/include/netlink/route/nh.h b/include/netlink/route/nh.h new file mode 100644 index 0000000..3edbad7 --- /dev/null +++ b/include/netlink/route/nh.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2022 Stanislav Zaikin + */ + +#ifndef NETLINK_ROUTE_NEXTHOP2_H_ +#define NETLINK_ROUTE_NEXTHOP2_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct rtnl_nh; + +typedef struct nl_nh_group_info { + uint32_t nh_id; /*!< nexthop id */ + uint8_t weight; /*!< weight in nexthop group */ +} nl_nh_group_info_t; + +typedef struct nl_nh_group { + int ce_refcnt; + unsigned size; + nl_nh_group_info_t *entries; +} nl_nh_group_t; + +extern int rtnl_nh_alloc_cache(struct nl_sock *sk, int family, + struct nl_cache **result); +extern struct rtnl_nh *rtnl_nh_alloc(void); +extern void rtnl_nh_put(struct rtnl_nh *); + +extern struct rtnl_nh *rtnl_nh_get(struct nl_cache *cache, int nhid); + +extern int rtnl_nh_set_gateway(struct rtnl_nh *, struct nl_addr *); +extern struct nl_addr *rtnl_nh_get_gateway(struct rtnl_nh *); + +extern int rtnl_nh_set_fdb(struct rtnl_nh *, int value); +extern int rtnl_nh_get_fdb(struct rtnl_nh *); + +extern int rtnl_nh_get_group_entry(struct rtnl_nh *, int n); +extern int rtnl_nh_get_group_size(struct rtnl_nh *); + +extern int rtnl_nh_get_id(struct rtnl_nh *); +extern int rtnl_nh_get_oif(struct rtnl_nh *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/pktloc.h b/include/netlink/route/pktloc.h index c3768ce..ab83821 100644 --- a/include/netlink/route/pktloc.h +++ b/include/netlink/route/pktloc.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/pktloc.h Packet Location Aliasing - * - * 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 */ diff --git a/include/netlink/route/qdisc.h b/include/netlink/route/qdisc.h index 10b85c5..7d963a5 100644 --- a/include/netlink/route/qdisc.h +++ b/include/netlink/route/qdisc.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/qdisc.h 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-2011 Thomas Graf */ @@ -33,6 +27,8 @@ extern struct rtnl_qdisc * extern struct rtnl_qdisc * rtnl_qdisc_get_by_parent(struct nl_cache *, int, uint32_t); +extern struct rtnl_qdisc *rtnl_qdisc_get_by_kind(struct nl_cache *cache, + int ifindex, char *kind); extern int rtnl_qdisc_build_add_request(struct rtnl_qdisc *, int, struct nl_msg **); diff --git a/include/netlink/route/qdisc/cbq.h b/include/netlink/route/qdisc/cbq.h index 3dbdd2d..3af6d88 100644 --- a/include/netlink/route/qdisc/cbq.h +++ b/include/netlink/route/qdisc/cbq.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/sch/cbq.h Class Based Queueing - * - * 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 */ diff --git a/include/netlink/route/qdisc/dsmark.h b/include/netlink/route/qdisc/dsmark.h index 06bd9d3..b8c358f 100644 --- a/include/netlink/route/qdisc/dsmark.h +++ b/include/netlink/route/qdisc/dsmark.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/sch/dsmark.h DSMARK - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf */ diff --git a/include/netlink/route/qdisc/fifo.h b/include/netlink/route/qdisc/fifo.h index c033427..291aac5 100644 --- a/include/netlink/route/qdisc/fifo.h +++ b/include/netlink/route/qdisc/fifo.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/sch/fifo.c FIFO Qdisc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2006 Thomas Graf */ diff --git a/include/netlink/route/qdisc/fq_codel.h b/include/netlink/route/qdisc/fq_codel.h new file mode 100644 index 0000000..1a69cd8 --- /dev/null +++ b/include/netlink/route/qdisc/fq_codel.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Cong Wang + */ + +#ifndef NETLINK_FQ_CODEL_H_ +#define NETLINK_FQ_CODEL_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_qdisc_fq_codel_set_limit(struct rtnl_qdisc *, int); +extern int rtnl_qdisc_fq_codel_get_limit(struct rtnl_qdisc *); + +extern int rtnl_qdisc_fq_codel_set_target(struct rtnl_qdisc *, uint32_t); +extern uint32_t rtnl_qdisc_fq_codel_get_target(struct rtnl_qdisc *); + +extern int rtnl_qdisc_fq_codel_set_interval(struct rtnl_qdisc *, uint32_t); +extern uint32_t rtnl_qdisc_fq_codel_get_interval(struct rtnl_qdisc *); + +extern int rtnl_qdisc_fq_codel_set_quantum(struct rtnl_qdisc *, uint32_t); +extern uint32_t rtnl_qdisc_fq_codel_get_quantum(struct rtnl_qdisc *); + +extern int rtnl_qdisc_fq_codel_set_flows(struct rtnl_qdisc *, int); +extern int rtnl_qdisc_fq_codel_get_flows(struct rtnl_qdisc *); + +extern int rtnl_qdisc_fq_codel_set_ecn(struct rtnl_qdisc *, int); +extern int rtnl_qdisc_fq_codel_get_ecn(struct rtnl_qdisc *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/qdisc/hfsc.h b/include/netlink/route/qdisc/hfsc.h new file mode 100644 index 0000000..d6a6417 --- /dev/null +++ b/include/netlink/route/qdisc/hfsc.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2014 Cong Wang + */ + +#ifndef NETLINK_HFSC_H_ +#define NETLINK_HFSC_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct tc_service_curve; + +extern uint32_t rtnl_qdisc_hfsc_get_defcls(const struct rtnl_qdisc *); +extern int rtnl_qdisc_hfsc_set_defcls(struct rtnl_qdisc *, uint32_t); + +extern int rtnl_class_hfsc_get_rsc(const struct rtnl_class *cls, struct tc_service_curve *tsc); +extern int rtnl_class_hfsc_set_rsc(struct rtnl_class *cls, const struct tc_service_curve *tsc); +extern int rtnl_class_hfsc_get_fsc(const struct rtnl_class *cls, struct tc_service_curve *tsc); +extern int rtnl_class_hfsc_set_fsc(struct rtnl_class *cls, const struct tc_service_curve *tsc); +extern int rtnl_class_hfsc_get_usc(const struct rtnl_class *cls, struct tc_service_curve *tsc); +extern int rtnl_class_hfsc_set_usc(struct rtnl_class *cls, const struct tc_service_curve *tsc); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/route/qdisc/htb.h b/include/netlink/route/qdisc/htb.h index c909f84..b751855 100644 --- a/include/netlink/route/qdisc/htb.h +++ b/include/netlink/route/qdisc/htb.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/sch/htb.h HTB Qdisc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf * Copyright (c) 2005 Petr Gotthard * Copyright (c) 2005 Siemens AG Oesterreich @@ -30,16 +24,24 @@ extern int rtnl_htb_set_defcls(struct rtnl_qdisc *, uint32_t); extern uint32_t rtnl_htb_get_prio(struct rtnl_class *); extern int rtnl_htb_set_prio(struct rtnl_class *, uint32_t); -extern uint32_t rtnl_htb_get_rate(struct rtnl_class *); -extern int rtnl_htb_set_rate(struct rtnl_class *, uint32_t); -extern uint32_t rtnl_htb_get_ceil(struct rtnl_class *); -extern int rtnl_htb_set_ceil(struct rtnl_class *, uint32_t); + +extern uint32_t rtnl_htb_get_rate(struct rtnl_class *); +extern int rtnl_htb_set_rate(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_ceil(struct rtnl_class *); +extern int rtnl_htb_set_ceil(struct rtnl_class *, uint32_t); + +extern int rtnl_htb_get_rate64(struct rtnl_class *, uint64_t *); +extern int rtnl_htb_set_rate64(struct rtnl_class *, uint64_t); +extern int rtnl_htb_get_ceil64(struct rtnl_class *, uint64_t *); +extern int rtnl_htb_set_ceil64(struct rtnl_class *, uint64_t); + extern uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *); extern int rtnl_htb_set_rbuffer(struct rtnl_class *, uint32_t); extern uint32_t rtnl_htb_get_cbuffer(struct rtnl_class *); extern int rtnl_htb_set_cbuffer(struct rtnl_class *, uint32_t); extern uint32_t rtnl_htb_get_quantum(struct rtnl_class *); extern int rtnl_htb_set_quantum(struct rtnl_class *, uint32_t); +extern int rtnl_htb_set_level(struct rtnl_class *, int); extern int rtnl_htb_get_level(struct rtnl_class *); #ifdef __cplusplus diff --git a/include/netlink/route/qdisc/mqprio.h b/include/netlink/route/qdisc/mqprio.h new file mode 100644 index 0000000..0b26fdb --- /dev/null +++ b/include/netlink/route/qdisc/mqprio.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2018 Volodymyr Bendiuga + */ + +#ifndef NETLINK_MQPRIO_H_ +#define NETLINK_MQPRIO_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_qdisc_mqprio_set_num_tc(struct rtnl_qdisc *qdisc, int num_tc); +extern int rtnl_qdisc_mqprio_get_num_tc(struct rtnl_qdisc *qdisc); +extern int rtnl_qdisc_mqprio_set_priomap(struct rtnl_qdisc *qdisc, uint8_t priomap[], + int len); +extern uint8_t *rtnl_qdisc_mqprio_get_priomap(struct rtnl_qdisc *qdisc); +extern int rtnl_qdisc_mqprio_hw_offload(struct rtnl_qdisc *qdisc, int offload); +extern int rtnl_qdisc_mqprio_get_hw_offload(struct rtnl_qdisc *qdisc); +extern int rtnl_qdisc_mqprio_set_queue(struct rtnl_qdisc *qdisc, uint16_t count[], + uint16_t offset[], int len); +extern int rtnl_qdisc_mqprio_get_queue(struct rtnl_qdisc *qdisc, uint16_t *count, + uint16_t *offset); +extern int rtnl_qdisc_mqprio_set_mode(struct rtnl_qdisc *qdisc, uint16_t mode); +extern int rtnl_qdisc_mqprio_get_mode(struct rtnl_qdisc *qdisc); +extern int rtnl_qdisc_mqprio_set_shaper(struct rtnl_qdisc *qdisc, uint16_t shaper); +extern int rtnl_qdisc_mqprio_get_shaper(struct rtnl_qdisc *qdisc); +extern int rtnl_qdisc_mqprio_set_min_rate(struct rtnl_qdisc *qdisc, uint64_t min[], + int len); +extern int rtnl_qdisc_mqprio_get_min_rate(struct rtnl_qdisc *qdisc, uint64_t *min); +extern int rtnl_qdisc_mqprio_set_max_rate(struct rtnl_qdisc *qdisc, uint64_t max[], + int len); +extern int rtnl_qdisc_mqprio_get_max_rate(struct rtnl_qdisc *qdisc, uint64_t *max); + +#ifdef __cplusplus +} +#endif + +#endif /* NETLINK_MQPRIO_H_ */ diff --git a/include/netlink/route/qdisc/netem.h b/include/netlink/route/qdisc/netem.h index 4b071bf..5012ef5 100644 --- a/include/netlink/route/qdisc/netem.h +++ b/include/netlink/route/qdisc/netem.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/sch/netem.h Network Emulator Qdisc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2006 Thomas Graf */ @@ -66,6 +60,7 @@ extern int rtnl_netem_get_delay_correlation(struct rtnl_qdisc *); /* Delay Distribution */ #define MAXDIST 65536 extern int rtnl_netem_set_delay_distribution(struct rtnl_qdisc *, const char *); +extern int rtnl_netem_set_delay_distribution_data(struct rtnl_qdisc *, const int16_t *, size_t len); extern int rtnl_netem_get_delay_distribution_size(struct rtnl_qdisc *); extern int rtnl_netem_get_delay_distribution(struct rtnl_qdisc *, int16_t **); diff --git a/include/netlink/route/qdisc/plug.h b/include/netlink/route/qdisc/plug.h index 40f7e53..f14c043 100644 --- a/include/netlink/route/qdisc/plug.h +++ b/include/netlink/route/qdisc/plug.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/qdisc/plug.c PLUG Qdisc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2012 Shriram Rajagopalan */ diff --git a/include/netlink/route/qdisc/prio.h b/include/netlink/route/qdisc/prio.h index 636a8f9..28bcc1b 100644 --- a/include/netlink/route/qdisc/prio.h +++ b/include/netlink/route/qdisc/prio.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/sch/prio.c PRIO Qdisc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf */ diff --git a/include/netlink/route/qdisc/red.h b/include/netlink/route/qdisc/red.h index a4e8642..f74ad80 100644 --- a/include/netlink/route/qdisc/red.h +++ b/include/netlink/route/qdisc/red.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/sch/red.h RED Qdisc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2006 Thomas Graf */ @@ -13,5 +7,17 @@ #define NETLINK_RED_H_ #include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern void rtnl_red_set_limit(struct rtnl_qdisc *qdisc, int limit); +extern int rtnl_red_get_limit(struct rtnl_qdisc *qdisc); + +#ifdef __cplusplus +} +#endif #endif diff --git a/include/netlink/route/qdisc/sfq.h b/include/netlink/route/qdisc/sfq.h index 77d2e29..38ee0ce 100644 --- a/include/netlink/route/qdisc/sfq.h +++ b/include/netlink/route/qdisc/sfq.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/sch/sfq.c SFQ Qdisc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf */ diff --git a/include/netlink/route/qdisc/tbf.h b/include/netlink/route/qdisc/tbf.h index ce31c54..b6c4f3d 100644 --- a/include/netlink/route/qdisc/tbf.h +++ b/include/netlink/route/qdisc/tbf.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/sch/tbf.h TBF Qdisc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf */ diff --git a/include/netlink/route/route.h b/include/netlink/route/route.h index 477250d..3824762 100644 --- a/include/netlink/route/route.h +++ b/include/netlink/route/route.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/route.h Routes - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -58,6 +52,9 @@ extern void rtnl_route_get(struct rtnl_route *); extern int rtnl_route_parse(struct nlmsghdr *, struct rtnl_route **); extern int rtnl_route_build_msg(struct nl_msg *, struct rtnl_route *); +extern int rtnl_route_lookup(struct nl_sock *sk, struct nl_addr *dst, + struct rtnl_route **result); + extern int rtnl_route_build_add_request(struct rtnl_route *, int, struct nl_msg **); extern int rtnl_route_add(struct nl_sock *, struct rtnl_route *, int); @@ -94,6 +91,9 @@ extern struct nl_addr *rtnl_route_get_pref_src(struct rtnl_route *); extern void rtnl_route_set_iif(struct rtnl_route *, int); extern int rtnl_route_get_iif(struct rtnl_route *); extern int rtnl_route_get_src_len(struct rtnl_route *); +extern void rtnl_route_set_ttl_propagate(struct rtnl_route *route, + uint8_t ttl_prop); +extern int rtnl_route_get_ttl_propagate(struct rtnl_route *route); extern void rtnl_route_add_nexthop(struct rtnl_route *, struct rtnl_nexthop *); diff --git a/include/netlink/route/rtnl.h b/include/netlink/route/rtnl.h index f551a5d..6cae88f 100644 --- a/include/netlink/route/rtnl.h +++ b/include/netlink/route/rtnl.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/rtnl.h Routing Netlink - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf */ diff --git a/include/netlink/route/rule.h b/include/netlink/route/rule.h index 760b782..26f5b52 100644 --- a/include/netlink/route/rule.h +++ b/include/netlink/route/rule.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/rule.h Rules - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2010 Thomas Graf */ @@ -67,6 +61,24 @@ extern void rtnl_rule_set_realms(struct rtnl_rule *, uint32_t); extern uint32_t rtnl_rule_get_realms(struct rtnl_rule *); extern void rtnl_rule_set_goto(struct rtnl_rule *, uint32_t); extern uint32_t rtnl_rule_get_goto(struct rtnl_rule *); +extern void rtnl_rule_set_l3mdev(struct rtnl_rule *, int); +extern int rtnl_rule_get_l3mdev(struct rtnl_rule *); +extern int rtnl_rule_set_protocol(struct rtnl_rule *, uint8_t); +extern int rtnl_rule_get_protocol(struct rtnl_rule *, uint8_t *); +extern int rtnl_rule_set_ipproto(struct rtnl_rule *, uint8_t); +extern int rtnl_rule_get_ipproto(struct rtnl_rule *, uint8_t *); +extern int rtnl_rule_set_sport(struct rtnl_rule *, uint16_t start); +extern int rtnl_rule_set_sport_range(struct rtnl_rule *, + uint16_t start, + uint16_t end); +extern int rtnl_rule_get_sport(struct rtnl_rule *, uint16_t *start, + uint16_t *end); +extern int rtnl_rule_set_dport(struct rtnl_rule *, uint16_t start); +extern int rtnl_rule_set_dport_range(struct rtnl_rule *, + uint16_t start, + uint16_t end); +extern int rtnl_rule_get_dport(struct rtnl_rule *, uint16_t *start, + uint16_t *end); #ifdef __cplusplus } diff --git a/include/netlink/route/tc-api.h b/include/netlink/route/tc-api.h index b7771b5..3f400ba 100644 --- a/include/netlink/route/tc-api.h +++ b/include/netlink/route/tc-api.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/tc-api.h Traffic Control API - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2013 Thomas Graf */ diff --git a/include/netlink/route/tc.h b/include/netlink/route/tc.h index 836f7b1..ee55555 100644 --- a/include/netlink/route/tc.h +++ b/include/netlink/route/tc.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/route/tc.h Traffic Control - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf */ @@ -27,6 +21,7 @@ enum rtnl_tc_type { RTNL_TC_TYPE_QDISC, RTNL_TC_TYPE_CLASS, RTNL_TC_TYPE_CLS, + RTNL_TC_TYPE_ACT, __RTNL_TC_TYPE_MAX, }; @@ -96,6 +91,8 @@ extern uint32_t rtnl_tc_get_parent(struct rtnl_tc *); extern int rtnl_tc_set_kind(struct rtnl_tc *, const char *); extern char * rtnl_tc_get_kind(struct rtnl_tc *); extern uint64_t rtnl_tc_get_stat(struct rtnl_tc *, enum rtnl_tc_stat); +extern char * rtnl_tc_stat2str(enum rtnl_tc_stat, char *, size_t); +extern int rtnl_tc_str2stat(const char *); extern int rtnl_tc_calc_txtime(int, int); extern int rtnl_tc_calc_bufsize(int, int); @@ -106,6 +103,8 @@ extern char * rtnl_tc_handle2str(uint32_t, char *, size_t); extern int rtnl_tc_str2handle(const char *, uint32_t *); extern int rtnl_classid_generate(const char *, uint32_t *, uint32_t); +extern void rtnl_tc_set_chain(struct rtnl_tc *, uint32_t); +extern int rtnl_tc_get_chain(struct rtnl_tc *, uint32_t *); #ifdef __cplusplus } diff --git a/include/netlink/socket.h b/include/netlink/socket.h index 1007eba..2bd98c3 100644 --- a/include/netlink/socket.h +++ b/include/netlink/socket.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/socket.h Netlink Socket - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf */ @@ -60,6 +54,7 @@ extern void nl_socket_disable_auto_ack(struct nl_sock *); extern void nl_socket_enable_auto_ack(struct nl_sock *); extern int nl_socket_get_fd(const struct nl_sock *); +extern int nl_socket_set_fd(struct nl_sock *sk, int protocol, int fd); extern int nl_socket_set_nonblocking(const struct nl_sock *); extern void nl_socket_enable_msg_peek(struct nl_sock *); extern void nl_socket_disable_msg_peek(struct nl_sock *); diff --git a/include/netlink/types.h b/include/netlink/types.h index 09cc5bd..a3a28fd 100644 --- a/include/netlink/types.h +++ b/include/netlink/types.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/types.h Definition of public types - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -14,6 +8,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /** * @ingroup utils * Enumeration of dumping variations (dp_type) @@ -107,4 +105,8 @@ struct nl_dump_params unsigned int dp_line; }; +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/netlink/utils.h b/include/netlink/utils.h index 502341a..11a6b93 100644 --- a/include/netlink/utils.h +++ b/include/netlink/utils.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/utils.h Utility Functions - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -19,6 +13,12 @@ extern "C" { #endif +#if defined(__GNUC__) && __GNUC__ > 5 +#define _nl_attribute_printf(a, b) __attribute__((__format__(printf, a, b))) +#else +#define _nl_attribute_printf(a, b) +#endif + /** * @name Probability Constants * @{ @@ -76,8 +76,272 @@ extern int nl_str2ip_proto(const char *); /* Dumping helpers */ extern void nl_new_line(struct nl_dump_params *); -extern void nl_dump(struct nl_dump_params *, const char *, ...); -extern void nl_dump_line(struct nl_dump_params *, const char *, ...); +extern void nl_dump(struct nl_dump_params *, const char *, ...) _nl_attribute_printf(2, 3); +extern void nl_dump_line(struct nl_dump_params *, const char *, ...) _nl_attribute_printf(2, 3); + +enum { + NL_CAPABILITY_NONE, + + /** + * rtnl_route_build_msg() no longer guesses the route scope + * if explicitly set to RT_SCOPE_NOWHERE. + * @ingroup utils + */ + NL_CAPABILITY_ROUTE_BUILD_MSG_SET_SCOPE = 1, +#define NL_CAPABILITY_ROUTE_BUILD_MSG_SET_SCOPE NL_CAPABILITY_ROUTE_BUILD_MSG_SET_SCOPE + + /** + * rtnl_link_veth_get_peer() now returns a reference that is owned by the + * caller and must be released by the caller with rtnl_link_put(). + */ + NL_CAPABILITY_ROUTE_LINK_VETH_GET_PEER_OWN_REFERENCE = 2, +#define NL_CAPABILITY_ROUTE_LINK_VETH_GET_PEER_OWN_REFERENCE NL_CAPABILITY_ROUTE_LINK_VETH_GET_PEER_OWN_REFERENCE + + /** + * rtnl_u32_add_action() and rtnl_basic_add_action() now grab a reference to act + * caller are free to release its own + */ + NL_CAPABILITY_ROUTE_LINK_CLS_ADD_ACT_OWN_REFERENCE = 3, +#define NL_CAPABILITY_ROUTE_LINK_CLS_ADD_ACT_OWN_REFERENCE NL_CAPABILITY_ROUTE_LINK_CLS_ADD_ACT_OWN_REFERENCE + + /** + * Indicate that the local port is unspecified until the user accesses + * it (via nl_socket_get_local_port()) or until nl_connect(). More importantly, + * if the port is left unspecified, nl_connect() will retry generating another + * port when bind() fails with ADDRINUSE. + */ + NL_CAPABILITY_NL_CONNECT_RETRY_GENERATE_PORT_ON_ADDRINUSE = 4, +#define NL_CAPABILITY_NL_CONNECT_RETRY_GENERATE_PORT_ON_ADDRINUSE NL_CAPABILITY_NL_CONNECT_RETRY_GENERATE_PORT_ON_ADDRINUSE + + /** + * Indicate that rtnl_link_get_kernel() fails with -NLE_OPNOTSUPP in case + * of older kernals not supporting lookup by ifname. This changes behavior + * from returning -NLE_INVAL to return -NLE_OPNOTSUPP. + */ + NL_CAPABILITY_ROUTE_LINK_GET_KERNEL_FAIL_OPNOTSUPP = 5, +#define NL_CAPABILITY_ROUTE_LINK_GET_KERNEL_FAIL_OPNOTSUPP NL_CAPABILITY_ROUTE_LINK_GET_KERNEL_FAIL_OPNOTSUPP + + /** + * Also consider the a_cacheinfo field (ADDR_ATTR_CACHEINFO) that contains the + * address timestamps and expiry when comparing struct rtnl_addr objects with + * nl_object_diff(). + */ + NL_CAPABILITY_ROUTE_ADDR_COMPARE_CACHEINFO = 6, +#define NL_CAPABILITY_ROUTE_ADDR_COMPARE_CACHEINFO NL_CAPABILITY_ROUTE_ADDR_COMPARE_CACHEINFO + + /** + * The library version is libnl3 3.2.26 or newer. This capability should never be backported. + */ + NL_CAPABILITY_VERSION_3_2_26 = 7, +#define NL_CAPABILITY_VERSION_3_2_26 NL_CAPABILITY_VERSION_3_2_26 + + /** + * nl_recv() fails with NLE_MSG_TRUNC if a message got truncated + * with NL_MSG_PEEK disabled. Previously, the failed message was wrongly + * discarded and the next message received. + */ + NL_CAPABILITY_NL_RECV_FAIL_TRUNC_NO_PEEK = 8, +#define NL_CAPABILITY_NL_RECV_FAIL_TRUNC_NO_PEEK NL_CAPABILITY_NL_RECV_FAIL_TRUNC_NO_PEEK + + /** + * rtnl_link_build_change_request() and rtnl_link_change() would set ifi.ifi_flags but leave + * ifi.ifi_change at zero. This was later fixed to set ifi.ifi_change to the flags that are actually + * set in changes. + */ + NL_CAPABILITY_LINK_BUILD_CHANGE_REQUEST_SET_CHANGE = 9, +#define NL_CAPABILITY_LINK_BUILD_CHANGE_REQUEST_SET_CHANGE NL_CAPABILITY_LINK_BUILD_CHANGE_REQUEST_SET_CHANGE + + /** + * Between 3.2.14 (64fcb47a36ec12d7e7f00605f6a8952ce985dd08) and 3.2.22 (8571f58f23763d8db7365d02c9b27832ad3d7005), + * rtnl_neigh_get() behaved differently and only returned objects with family AF_UNSPEC. + * This capability indicates, that the function was fixed. The absense of the capability, + * doesn't indicate however which behavior the function will have. So beware. */ + NL_CAPABILITY_RTNL_NEIGH_GET_FILTER_AF_UNSPEC_FIX = 10, +#define NL_CAPABILITY_RTNL_NEIGH_GET_FILTER_AF_UNSPEC_FIX NL_CAPABILITY_RTNL_NEIGH_GET_FILTER_AF_UNSPEC_FIX + + /** + * The library version is libnl3 3.2.27 or newer. This capability should never be backported. + */ + NL_CAPABILITY_VERSION_3_2_27 = 11, +#define NL_CAPABILITY_VERSION_3_2_27 NL_CAPABILITY_VERSION_3_2_27 + + /** + * Properly serialize vlan protocol IFLA_VLAN_PROTOCOL. + */ + NL_CAPABILITY_RTNL_LINK_VLAN_PROTOCOL_SERIALZE = 12, +#define NL_CAPABILITY_RTNL_LINK_VLAN_PROTOCOL_SERIALZE NL_CAPABILITY_RTNL_LINK_VLAN_PROTOCOL_SERIALZE + + /** + * Properly read gre REMOTE port. + */ + NL_CAPABILITY_RTNL_LINK_PARSE_GRE_REMOTE = 13, +#define NL_CAPABILITY_RTNL_LINK_PARSE_GRE_REMOTE NL_CAPABILITY_RTNL_LINK_PARSE_GRE_REMOTE + + /** + * Don't skip over vlan ingress-map entries with "to" field zero when serializing + * a netlink message. Previously such entires would be ignored which inhibits the + * user from clearing ingress map entries. + */ + NL_CAPABILITY_RTNL_LINK_VLAN_INGRESS_MAP_CLEAR = 14, +#define NL_CAPABILITY_RTNL_LINK_VLAN_INGRESS_MAP_CLEAR NL_CAPABILITY_RTNL_LINK_VLAN_INGRESS_MAP_CLEAR + + /** + * Consider vxlan link info for nl_object_diff(). + */ + NL_CAPABILITY_RTNL_LINK_VXLAN_IO_COMPARE = 15, +#define NL_CAPABILITY_RTNL_LINK_VXLAN_IO_COMPARE NL_CAPABILITY_RTNL_LINK_VXLAN_IO_COMPARE + + /** + * Support 64 bit attributes for nl_object_diff(). + */ + NL_CAPABILITY_NL_OBJECT_DIFF64 = 16, +#define NL_CAPABILITY_NL_OBJECT_DIFF64 NL_CAPABILITY_NL_OBJECT_DIFF64 + + /** + * Support omitting @key argument to xfrmnl_sa_get_*_params() to check + * for required buffer size for key. + */ + NL_CAPABILITY_XFRM_SA_KEY_SIZE = 17, +#define NL_CAPABILITY_XFRM_SA_KEY_SIZE NL_CAPABILITY_XFRM_SA_KEY_SIZE + + /** + * Properly handle nl_object_identity() for AF_INET and AF_INET6 addresses + * and properly handle the peer/IFA_ADDRESS for IPv4 addresses. + */ + NL_CAPABILITY_RTNL_ADDR_PEER_FIX = 18, +#define NL_CAPABILITY_RTNL_ADDR_PEER_FIX NL_CAPABILITY_RTNL_ADDR_PEER_FIX + + /** + * The library version is libnl3 3.2.28 or newer. This capability should never be backported. + */ + NL_CAPABILITY_VERSION_3_2_28 = 19, +#define NL_CAPABILITY_VERSION_3_2_28 NL_CAPABILITY_VERSION_3_2_28 + + /** + * After NL_CAPABILITY_RTNL_ADDR_PEER_FIX, a follow up regression to lookup + * IPv4 addresses in the cache was fixed (PR#105). + */ + NL_CAPABILITY_RTNL_ADDR_PEER_ID_FIX = 20, +#define NL_CAPABILITY_RTNL_ADDR_PEER_ID_FIX NL_CAPABILITY_RTNL_ADDR_PEER_ID_FIX + + /** + * nl_addr_fill_sockaddr() properly checks that the provided address to + * avoid read-out-of-bounds for invalid addresses. + */ + NL_CAPABILITY_NL_ADDR_FILL_SOCKADDR = 21, +#define NL_CAPABILITY_NL_ADDR_FILL_SOCKADDR NL_CAPABILITY_NL_ADDR_FILL_SOCKADDR + + /** + * Support omitting @ctx_str argument to xfrmnl_sa_get_sec_ctx() to check + * for required buffer size for context string. + */ + NL_CAPABILITY_XFRM_SEC_CTX_LEN = 22, +#define NL_CAPABILITY_XFRM_SEC_CTX_LEN NL_CAPABILITY_XFRM_SEC_CTX_LEN + + /** + * rtnl_link_build_add_request() would set ifi.ifi_flags but leave ifi.ifi_change at zero. + * This was later fixed to set ifi.ifi_change to the flags that are actually + * set + */ + NL_CAPABILITY_LINK_BUILD_ADD_REQUEST_SET_CHANGE = 23, +#define NL_CAPABILITY_LINK_BUILD_ADD_REQUEST_SET_CHANGE NL_CAPABILITY_LINK_BUILD_ADD_REQUEST_SET_CHANGE + + /* Older versions of libnl3 would not use MSG_PEEK for nl_recvmsgs() unless calling + * nl_socket_enable_msg_peek(). Instead, the user had to specify the buffer size via + * nl_socket_set_msg_buf_size(), which in turn would default to 4*getpagesize(). + * + * The default value might not be large enough, so users who were not aware of the + * problem easily ended up using a too small receive buffer. Usually, one wants to + * avoid MSG_PEEK for recvmsg() because it requires an additional syscall. + * + * Now, as indicated by this capability, nl_recvmsgs() would use MSG_PEEK by default. The + * user still can explicitly disable MSG_PEEK by calling nl_socket_disable_msg_peek() or + * by setting the nl_socket_set_msg_buf_size() to a non-zero value. + */ + NL_CAPABILITY_NL_RECVMSGS_PEEK_BY_DEFAULT = 24, +#define NL_CAPABILITY_NL_RECVMSGS_PEEK_BY_DEFAULT NL_CAPABILITY_NL_RECVMSGS_PEEK_BY_DEFAULT + + /** + * The library version is libnl3 3.2.29 or newer. This capability should never be backported. + */ + NL_CAPABILITY_VERSION_3_2_29 = 25, +#define NL_CAPABILITY_VERSION_3_2_29 NL_CAPABILITY_VERSION_3_2_29 + + /** + * Support omitting @ctx_str argument to xfrmnl_sp_get_sec_ctx() to check + * for required buffer size for context string. + */ + NL_CAPABILITY_XFRM_SP_SEC_CTX_LEN = 26, +#define NL_CAPABILITY_XFRM_SP_SEC_CTX_LEN NL_CAPABILITY_XFRM_SP_SEC_CTX_LEN + + /** + * The library version is libnl3 3.3.0 or newer. This capability should never be backported. + */ + NL_CAPABILITY_VERSION_3_3_0 = 27, +#define NL_CAPABILITY_VERSION_3_3_0 NL_CAPABILITY_VERSION_3_3_0 + + /** + * The library version is libnl3 3.4.0 or newer. This capability should never be backported. + */ + NL_CAPABILITY_VERSION_3_4_0 = 28, +#define NL_CAPABILITY_VERSION_3_4_0 NL_CAPABILITY_VERSION_3_4_0 + + /** + * Fixed memory corruption in rtnl_link_vlan_set_egress_map(). Previously, if you tried + * to add more then 4 mappings, a buffer overflow occured. Also fixed nl_object_clone() + * for VLAN links. + */ + NL_CAPABILITY_ROUTE_FIX_VLAN_SET_EGRESS_MAP = 29, +#define NL_CAPABILITY_ROUTE_FIX_VLAN_SET_EGRESS_MAP NL_CAPABILITY_ROUTE_FIX_VLAN_SET_EGRESS_MAP + + /** + * The library version is libnl3 3.5.0 or newer. This capability should never be backported. + */ + NL_CAPABILITY_VERSION_3_5_0 = 30, +#define NL_CAPABILITY_VERSION_3_5_0 NL_CAPABILITY_VERSION_3_5_0 + + /** + * nl_object_identical() can consider objects identical, if they both lack the same + * set of ID attributes. + */ + NL_CAPABILITY_NL_OBJECT_IDENTICAL_PARTIAL = 31, +#define NL_CAPABILITY_NL_OBJECT_IDENTICAL_PARTIAL NL_CAPABILITY_NL_OBJECT_IDENTICAL_PARTIAL + + /** + * The library version is libnl3 3.6.0 or newer. This capability should never be backported. + */ + NL_CAPABILITY_VERSION_3_6_0 = 32, +#define NL_CAPABILITY_VERSION_3_6_0 NL_CAPABILITY_VERSION_3_6_0 + + /** + * The library version is libnl3 3.7.0 or newer. This capability should never be backported. + */ + NL_CAPABILITY_VERSION_3_7_0 = 33, +#define NL_CAPABILITY_VERSION_3_7_0 NL_CAPABILITY_VERSION_3_7_0 + + /** + * The library version is libnl3 3.8.0 or newer. This capability should never be backported. + */ + NL_CAPABILITY_VERSION_3_8_0 = 34, +#define NL_CAPABILITY_VERSION_3_8_0 NL_CAPABILITY_VERSION_3_8_0 + + /** + * The library version is libnl3 3.9.0 or newer. This capability should never be backported. + */ + NL_CAPABILITY_VERSION_3_9_0 = 35, +#define NL_CAPABILITY_VERSION_3_9_0 NL_CAPABILITY_VERSION_3_9_0 + + __NL_CAPABILITY_MAX, + NL_CAPABILITY_MAX = (__NL_CAPABILITY_MAX - 1), +#define NL_CAPABILITY_MAX NL_CAPABILITY_MAX + + /** + * The range 0x7000 to 0x7FFF is reserved for private capabilities. Upstream libnl3 will + * not register capabilities in this range. However, instead of adding private capabilities, + * better register their number with upstream libnl3. */ +#define NL_CAPABILITY_IS_USER_RESERVED(cap) ( ((cap) & ~0x0FFF) == 0x7000 ) +}; +int nl_has_capability (int capability); #ifdef __cplusplus } diff --git a/include/netlink/version.h b/include/netlink/version.h index ccb8bed..f3d5d36 100644 --- a/include/netlink/version.h +++ b/include/netlink/version.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/version.h Versioning Information - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2008-2011 Thomas Graf */ @@ -14,18 +8,22 @@ /* Compile Time Versioning Information */ -#define LIBNL_STRING "libnl 3.2.22" -#define LIBNL_VERSION "3.2.22" +#ifdef __cplusplus +extern "C" { +#endif + +#define LIBNL_STRING "libnl 3.9.0" +#define LIBNL_VERSION "3.9.0" #define LIBNL_VER_MAJ 3 -#define LIBNL_VER_MIN 2 -#define LIBNL_VER_MIC 22 +#define LIBNL_VER_MIN 9 +#define LIBNL_VER_MIC 0 #define LIBNL_VER(maj,min) ((maj) << 8 | (min)) #define LIBNL_VER_NUM LIBNL_VER(LIBNL_VER_MAJ, LIBNL_VER_MIN) -#define LIBNL_CURRENT 217 +#define LIBNL_CURRENT 226 #define LIBNL_REVISION 0 -#define LIBNL_AGE 17 +#define LIBNL_AGE 26 /* Run-time version information */ @@ -34,4 +32,8 @@ extern const int nl_ver_maj; extern const int nl_ver_min; extern const int nl_ver_mic; +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/netlink/version.h.in b/include/netlink/version.h.in index 35bf2aa..3c43355 100644 --- a/include/netlink/version.h.in +++ b/include/netlink/version.h.in @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/version.h Versioning Information - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2008-2011 Thomas Graf */ @@ -14,6 +8,10 @@ /* Compile Time Versioning Information */ +#ifdef __cplusplus +extern "C" { +#endif + #define LIBNL_STRING "@PACKAGE_STRING@" #define LIBNL_VERSION "@PACKAGE_VERSION@" @@ -34,4 +32,8 @@ extern const int nl_ver_maj; extern const int nl_ver_min; extern const int nl_ver_mic; +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/netlink/xfrm/ae.h b/include/netlink/xfrm/ae.h new file mode 100644 index 0000000..95112dd --- /dev/null +++ b/include/netlink/xfrm/ae.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * +*/ +#ifndef NETLINK_XFRM_AE_H_ +#define NETLINK_XFRM_AE_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct xfrmnl_ae; + +extern struct xfrmnl_ae*xfrmnl_ae_alloc(void); +extern void xfrmnl_ae_put(struct xfrmnl_ae *); + +extern int xfrmnl_ae_get_kernel(struct nl_sock*, struct nl_addr*, unsigned int, unsigned int, + unsigned int, unsigned int, struct xfrmnl_ae**); +extern int xfrmnl_ae_set(struct nl_sock*, struct xfrmnl_ae*, int); + +extern int xfrmnl_ae_parse(struct nlmsghdr*, struct xfrmnl_ae **); +extern int xfrmnl_ae_build_get_request(struct nl_addr*, unsigned int, unsigned int, + unsigned int, unsigned int, struct nl_msg **); + +extern struct nl_addr* xfrmnl_ae_get_daddr (struct xfrmnl_ae*); +extern int xfrmnl_ae_set_daddr (struct xfrmnl_ae*, struct nl_addr*); + +extern int xfrmnl_ae_get_spi (struct xfrmnl_ae*); +extern int xfrmnl_ae_set_spi (struct xfrmnl_ae*, unsigned int); + +extern int xfrmnl_ae_get_family (struct xfrmnl_ae*); +extern int xfrmnl_ae_set_family (struct xfrmnl_ae*, unsigned int); + +extern int xfrmnl_ae_get_proto (struct xfrmnl_ae*); +extern int xfrmnl_ae_set_proto (struct xfrmnl_ae*, unsigned int); + +extern struct nl_addr* xfrmnl_ae_get_saddr (struct xfrmnl_ae*); +extern int xfrmnl_ae_set_saddr (struct xfrmnl_ae*, struct nl_addr*); + +extern int xfrmnl_ae_get_flags (struct xfrmnl_ae*); +extern int xfrmnl_ae_set_flags (struct xfrmnl_ae*, unsigned int); + +extern int xfrmnl_ae_get_reqid (struct xfrmnl_ae*); +extern int xfrmnl_ae_set_reqid (struct xfrmnl_ae*, unsigned int); + +extern int xfrmnl_ae_get_mark (struct xfrmnl_ae*, unsigned int*, unsigned int*); +extern int xfrmnl_ae_set_mark (struct xfrmnl_ae*, unsigned int, unsigned int); + +extern int xfrmnl_ae_get_curlifetime (struct xfrmnl_ae*, unsigned long long int*, + unsigned long long int*, unsigned long long int*, + unsigned long long int*); +extern int xfrmnl_ae_set_curlifetime (struct xfrmnl_ae*, unsigned long long int, + unsigned long long int, unsigned long long int, + unsigned long long int); + +extern int xfrmnl_ae_get_replay_maxage (struct xfrmnl_ae*); +extern int xfrmnl_ae_set_replay_maxage (struct xfrmnl_ae*, unsigned int); + +extern int xfrmnl_ae_get_replay_maxdiff (struct xfrmnl_ae*); +extern int xfrmnl_ae_set_replay_maxdiff (struct xfrmnl_ae*, unsigned int); + +extern int xfrmnl_ae_get_replay_state (struct xfrmnl_ae*, unsigned int*, unsigned int*, unsigned int*); +extern int xfrmnl_ae_set_replay_state (struct xfrmnl_ae*, unsigned int, unsigned int, unsigned int); + +extern int xfrmnl_ae_get_replay_state_esn (struct xfrmnl_ae*, unsigned int*, unsigned int*, unsigned int*, + unsigned int*, unsigned int*, unsigned int*, unsigned int*); +extern int xfrmnl_ae_set_replay_state_esn (struct xfrmnl_ae*, unsigned int, unsigned int, unsigned int, + unsigned int, unsigned int, unsigned int, unsigned int*); + +extern char* xfrmnl_ae_flags2str(int, char *, size_t); +extern int xfrmnl_ae_str2flag(const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/xfrm/lifetime.h b/include/netlink/xfrm/lifetime.h new file mode 100644 index 0000000..a5d5955 --- /dev/null +++ b/include/netlink/xfrm/lifetime.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * +*/ +#ifndef NETLINK_XFRM_LTIME_H_ +#define NETLINK_XFRM_LTIME_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct xfrmnl_ltime_cfg; + +/* Creation */ +extern struct xfrmnl_ltime_cfg* xfrmnl_ltime_cfg_alloc(void); +extern struct xfrmnl_ltime_cfg* xfrmnl_ltime_cfg_clone(struct xfrmnl_ltime_cfg*); + +/* Usage Management */ +extern struct xfrmnl_ltime_cfg* xfrmnl_ltime_cfg_get(struct xfrmnl_ltime_cfg*); +extern void xfrmnl_ltime_cfg_put(struct xfrmnl_ltime_cfg*); +extern int xfrmnl_ltime_cfg_shared(struct xfrmnl_ltime_cfg*); +extern int xfrmnl_ltime_cfg_cmp(struct xfrmnl_ltime_cfg*, struct xfrmnl_ltime_cfg*); + +/* Access Functions */ +extern unsigned long long xfrmnl_ltime_cfg_get_soft_bytelimit (struct xfrmnl_ltime_cfg*); +extern int xfrmnl_ltime_cfg_set_soft_bytelimit (struct xfrmnl_ltime_cfg*, unsigned long long); + +extern unsigned long long xfrmnl_ltime_cfg_get_hard_bytelimit (struct xfrmnl_ltime_cfg*); +extern int xfrmnl_ltime_cfg_set_hard_bytelimit (struct xfrmnl_ltime_cfg*, unsigned long long); + +extern unsigned long long xfrmnl_ltime_cfg_get_soft_packetlimit (struct xfrmnl_ltime_cfg*); +extern int xfrmnl_ltime_cfg_set_soft_packetlimit (struct xfrmnl_ltime_cfg*, unsigned long long); + +extern unsigned long long xfrmnl_ltime_cfg_get_hard_packetlimit (struct xfrmnl_ltime_cfg*); +extern int xfrmnl_ltime_cfg_set_hard_packetlimit (struct xfrmnl_ltime_cfg*, unsigned long long); + +extern unsigned long long xfrmnl_ltime_cfg_get_soft_addexpires (struct xfrmnl_ltime_cfg*); +extern int xfrmnl_ltime_cfg_set_soft_addexpires (struct xfrmnl_ltime_cfg*, unsigned long long); + +extern unsigned long long xfrmnl_ltime_cfg_get_hard_addexpires (struct xfrmnl_ltime_cfg*); +extern int xfrmnl_ltime_cfg_set_hard_addexpires (struct xfrmnl_ltime_cfg*, unsigned long long); + +extern unsigned long long xfrmnl_ltime_cfg_get_soft_useexpires (struct xfrmnl_ltime_cfg*); +extern int xfrmnl_ltime_cfg_set_soft_useexpires (struct xfrmnl_ltime_cfg*, unsigned long long); + +extern unsigned long long xfrmnl_ltime_cfg_get_hard_useexpires (struct xfrmnl_ltime_cfg*); +extern int xfrmnl_ltime_cfg_set_hard_useexpires (struct xfrmnl_ltime_cfg*, unsigned long long); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/xfrm/sa.h b/include/netlink/xfrm/sa.h new file mode 100644 index 0000000..cd5e552 --- /dev/null +++ b/include/netlink/xfrm/sa.h @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * +*/ +#ifndef NETLINK_XFRM_SA_H_ +#define NETLINK_XFRM_SA_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct xfrmnl_sa; + +extern struct xfrmnl_sa* xfrmnl_sa_alloc(void); +extern void xfrmnl_sa_put(struct xfrmnl_sa *); + +extern int xfrmnl_sa_alloc_cache(struct nl_sock *, struct nl_cache **); +extern struct xfrmnl_sa* xfrmnl_sa_get(struct nl_cache*, struct nl_addr*, unsigned int, unsigned int); + +extern int xfrmnl_sa_parse(struct nlmsghdr *n, struct xfrmnl_sa **result); + +extern int xfrmnl_sa_build_get_request(struct nl_addr*, unsigned int, unsigned int, + unsigned int, unsigned int, struct nl_msg **); +extern int xfrmnl_sa_get_kernel(struct nl_sock*, struct nl_addr*, unsigned int, + unsigned int, unsigned int, unsigned int, struct xfrmnl_sa**); + +extern int xfrmnl_sa_build_add_request(struct xfrmnl_sa*, int, struct nl_msg **); +extern int xfrmnl_sa_add(struct nl_sock*, struct xfrmnl_sa*, int); + +extern int xfrmnl_sa_build_update_request(struct xfrmnl_sa*, int, struct nl_msg **); +extern int xfrmnl_sa_update(struct nl_sock*, struct xfrmnl_sa*, int); + +extern int xfrmnl_sa_build_delete_request(struct xfrmnl_sa*, int, struct nl_msg **); +extern int xfrmnl_sa_delete(struct nl_sock*, struct xfrmnl_sa*, int); + +extern struct xfrmnl_sel* xfrmnl_sa_get_sel (struct xfrmnl_sa*); +extern int xfrmnl_sa_set_sel (struct xfrmnl_sa*, struct xfrmnl_sel*); + +extern struct nl_addr* xfrmnl_sa_get_daddr (struct xfrmnl_sa*); +extern int xfrmnl_sa_set_daddr (struct xfrmnl_sa*, struct nl_addr*); + +extern int xfrmnl_sa_get_spi (struct xfrmnl_sa*); +extern int xfrmnl_sa_set_spi (struct xfrmnl_sa*, unsigned int); + +extern int xfrmnl_sa_get_proto (struct xfrmnl_sa*); +extern int xfrmnl_sa_set_proto (struct xfrmnl_sa*, unsigned int); + +extern struct nl_addr* xfrmnl_sa_get_saddr (struct xfrmnl_sa*); +extern int xfrmnl_sa_set_saddr (struct xfrmnl_sa*, struct nl_addr*); + +extern struct xfrmnl_ltime_cfg* xfrmnl_sa_get_lifetime_cfg (struct xfrmnl_sa*); +extern int xfrmnl_sa_set_lifetime_cfg (struct xfrmnl_sa*, struct xfrmnl_ltime_cfg*); + +extern int xfrmnl_sa_get_curlifetime (struct xfrmnl_sa*, unsigned long long int*, + unsigned long long int*, unsigned long long int*, + unsigned long long int*); + +extern int xfrmnl_sa_get_stats (struct xfrmnl_sa*, unsigned long long int*, + unsigned long long int*, unsigned long long int*); + +extern int xfrmnl_sa_get_seq (struct xfrmnl_sa*); + +extern int xfrmnl_sa_get_reqid (struct xfrmnl_sa*); +extern int xfrmnl_sa_set_reqid (struct xfrmnl_sa*, unsigned int); + +extern int xfrmnl_sa_get_family (struct xfrmnl_sa*); +extern int xfrmnl_sa_set_family (struct xfrmnl_sa*, unsigned int); + +extern int xfrmnl_sa_get_mode (struct xfrmnl_sa*); +extern int xfrmnl_sa_set_mode (struct xfrmnl_sa*, unsigned int); + +extern int xfrmnl_sa_get_replay_window (struct xfrmnl_sa*); +extern int xfrmnl_sa_set_replay_window (struct xfrmnl_sa*, unsigned int); + +extern int xfrmnl_sa_get_flags (struct xfrmnl_sa*); +extern int xfrmnl_sa_set_flags (struct xfrmnl_sa*, unsigned int); + +extern int xfrmnl_sa_get_aead_params (struct xfrmnl_sa*, char*, unsigned int*, + unsigned int*, char*); +extern int xfrmnl_sa_set_aead_params (struct xfrmnl_sa*, const char*, unsigned int, + unsigned int, const char*); + +extern int xfrmnl_sa_get_auth_params (struct xfrmnl_sa*, char*, unsigned int*, + unsigned int*, char*); +extern int xfrmnl_sa_set_auth_params (struct xfrmnl_sa*, const char*, unsigned int, + unsigned int, const char*); + +extern int xfrmnl_sa_get_crypto_params (struct xfrmnl_sa*, char*, unsigned int*, char*); +extern int xfrmnl_sa_set_crypto_params (struct xfrmnl_sa*, const char*, unsigned int, + const char*); + +extern int xfrmnl_sa_get_comp_params (struct xfrmnl_sa*, char*, unsigned int*, char*); +extern int xfrmnl_sa_set_comp_params (struct xfrmnl_sa*, const char*, unsigned int, + const char*); + +extern int xfrmnl_sa_get_encap_tmpl (struct xfrmnl_sa*, unsigned int*, unsigned int*, + unsigned int*, struct nl_addr**); +extern int xfrmnl_sa_set_encap_tmpl (struct xfrmnl_sa*, unsigned int, unsigned int, + unsigned int, struct nl_addr*); + +extern int xfrmnl_sa_get_tfcpad (struct xfrmnl_sa*); +extern int xfrmnl_sa_set_tfcpad (struct xfrmnl_sa*, unsigned int); + +extern struct nl_addr* xfrmnl_sa_get_coaddr (struct xfrmnl_sa*); +extern int xfrmnl_sa_set_coaddr (struct xfrmnl_sa*, struct nl_addr*); + +extern int xfrmnl_sa_get_mark (struct xfrmnl_sa*, unsigned int*, unsigned int*); +extern int xfrmnl_sa_set_mark (struct xfrmnl_sa*, unsigned int, unsigned int); + +extern int xfrmnl_sa_get_sec_ctx (struct xfrmnl_sa*, unsigned int*, unsigned int*, + unsigned int*, unsigned int*, char*); +extern int xfrmnl_sa_set_sec_ctx (struct xfrmnl_sa*, unsigned int, unsigned int, + unsigned int, unsigned int, const char*); + +extern int xfrmnl_sa_get_replay_maxage (struct xfrmnl_sa*); +extern int xfrmnl_sa_set_replay_maxage (struct xfrmnl_sa*, unsigned int); + +extern int xfrmnl_sa_get_replay_maxdiff (struct xfrmnl_sa*); +extern int xfrmnl_sa_set_replay_maxdiff (struct xfrmnl_sa*, unsigned int); + +extern int xfrmnl_sa_get_replay_state (struct xfrmnl_sa*, unsigned int*, + unsigned int*, unsigned int*); +extern int xfrmnl_sa_set_replay_state (struct xfrmnl_sa*, unsigned int, + unsigned int, unsigned int); + +extern int xfrmnl_sa_get_replay_state_esn (struct xfrmnl_sa*, unsigned int*, unsigned int*, + unsigned int*, unsigned int*, unsigned int*, + unsigned int*, unsigned int*); +extern int xfrmnl_sa_set_replay_state_esn (struct xfrmnl_sa*, unsigned int, unsigned int, + unsigned int, unsigned int, unsigned int, + unsigned int, unsigned int*); + +extern int xfrmnl_sa_get_user_offload (struct xfrmnl_sa*, int*, uint8_t *); +extern int xfrmnl_sa_set_user_offload (struct xfrmnl_sa*, int, uint8_t); + +extern int xfrmnl_sa_is_expiry_reached (struct xfrmnl_sa*); +extern int xfrmnl_sa_is_hardexpiry_reached (struct xfrmnl_sa*); + +extern char* xfrmnl_sa_flags2str(int, char *, size_t); +extern int xfrmnl_sa_str2flag(const char *); + +extern char* xfrmnl_sa_mode2str(int, char *, size_t); +extern int xfrmnl_sa_str2mode(const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/xfrm/selector.h b/include/netlink/xfrm/selector.h new file mode 100644 index 0000000..2ee6842 --- /dev/null +++ b/include/netlink/xfrm/selector.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * +*/ +#ifndef NETLINK_XFRM_SEL_H_ +#define NETLINK_XFRM_SEL_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct xfrmnl_sel; + +/* Creation */ +extern struct xfrmnl_sel* xfrmnl_sel_alloc(void); +extern struct xfrmnl_sel* xfrmnl_sel_clone(struct xfrmnl_sel*); + +/* Usage Management */ +extern struct xfrmnl_sel* xfrmnl_sel_get(struct xfrmnl_sel*); +extern void xfrmnl_sel_put(struct xfrmnl_sel*); +extern int xfrmnl_sel_shared(struct xfrmnl_sel*); +extern int xfrmnl_sel_cmp(struct xfrmnl_sel*, struct xfrmnl_sel*); +extern void xfrmnl_sel_dump(struct xfrmnl_sel*, struct nl_dump_params *); + +/* Access Functions */ +extern struct nl_addr* xfrmnl_sel_get_daddr (struct xfrmnl_sel*); +extern int xfrmnl_sel_set_daddr (struct xfrmnl_sel*, struct nl_addr*); + +extern struct nl_addr* xfrmnl_sel_get_saddr (struct xfrmnl_sel*); +extern int xfrmnl_sel_set_saddr (struct xfrmnl_sel*, struct nl_addr*); + +extern int xfrmnl_sel_get_dport (struct xfrmnl_sel*); +extern int xfrmnl_sel_set_dport (struct xfrmnl_sel*, unsigned int); + +extern int xfrmnl_sel_get_dportmask (struct xfrmnl_sel*); +extern int xfrmnl_sel_set_dportmask (struct xfrmnl_sel*, unsigned int); + +extern int xfrmnl_sel_get_sport (struct xfrmnl_sel*); +extern int xfrmnl_sel_set_sport (struct xfrmnl_sel*, unsigned int); + +extern int xfrmnl_sel_get_sportmask (struct xfrmnl_sel*); +extern int xfrmnl_sel_set_sportmask (struct xfrmnl_sel*, unsigned int); + +extern int xfrmnl_sel_get_family (struct xfrmnl_sel*); +extern int xfrmnl_sel_set_family (struct xfrmnl_sel*, unsigned int); + +extern int xfrmnl_sel_get_prefixlen_d (struct xfrmnl_sel*); +extern int xfrmnl_sel_set_prefixlen_d (struct xfrmnl_sel*, unsigned int); + +extern int xfrmnl_sel_get_prefixlen_s (struct xfrmnl_sel*); +extern int xfrmnl_sel_set_prefixlen_s (struct xfrmnl_sel*, unsigned int); + +extern int xfrmnl_sel_get_proto (struct xfrmnl_sel*); +extern int xfrmnl_sel_set_proto (struct xfrmnl_sel*, unsigned int); + +extern int xfrmnl_sel_get_ifindex (struct xfrmnl_sel*); +extern int xfrmnl_sel_set_ifindex (struct xfrmnl_sel*, unsigned int); + +extern int xfrmnl_sel_get_userid (struct xfrmnl_sel*); +extern int xfrmnl_sel_set_userid (struct xfrmnl_sel*, unsigned int); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/xfrm/sp.h b/include/netlink/xfrm/sp.h new file mode 100644 index 0000000..84cbfb2 --- /dev/null +++ b/include/netlink/xfrm/sp.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * +*/ +#ifndef NETLINK_XFRM_SP_H_ +#define NETLINK_XFRM_SP_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct xfrmnl_sp; + +extern struct xfrmnl_sp* xfrmnl_sp_alloc(void); +extern void xfrmnl_sp_put(struct xfrmnl_sp *); + +extern int xfrmnl_sp_alloc_cache(struct nl_sock *, struct nl_cache **); +extern struct xfrmnl_sp* xfrmnl_sp_get(struct nl_cache*, unsigned int, unsigned int); + +extern int xfrmnl_sp_parse(struct nlmsghdr *n, struct xfrmnl_sp **result); + +extern int xfrmnl_sp_build_get_request(unsigned int, unsigned int, unsigned int, + unsigned int, struct nl_msg **); +extern int xfrmnl_sp_get_kernel(struct nl_sock*, unsigned int, unsigned int, + unsigned int, unsigned int, struct xfrmnl_sp**); + +extern int xfrmnl_sp_add(struct nl_sock*, struct xfrmnl_sp*, int); +extern int xfrmnl_sp_build_add_request(struct xfrmnl_sp*, int, struct nl_msg **); + +extern int xfrmnl_sp_update(struct nl_sock*, struct xfrmnl_sp*, int); +extern int xfrmnl_sp_build_update_request(struct xfrmnl_sp*, int, struct nl_msg **); + +extern int xfrmnl_sp_delete(struct nl_sock*, struct xfrmnl_sp*, int); +extern int xfrmnl_sp_build_delete_request(struct xfrmnl_sp*, int, struct nl_msg **); + +extern struct xfrmnl_sel* xfrmnl_sp_get_sel (struct xfrmnl_sp*); +extern int xfrmnl_sp_set_sel (struct xfrmnl_sp*, struct xfrmnl_sel*); + +extern struct xfrmnl_ltime_cfg* xfrmnl_sp_get_lifetime_cfg (struct xfrmnl_sp*); +extern int xfrmnl_sp_set_lifetime_cfg (struct xfrmnl_sp*, struct xfrmnl_ltime_cfg*); + +extern int xfrmnl_sp_get_curlifetime (struct xfrmnl_sp*, unsigned long long int*, + unsigned long long int*, unsigned long long int*, + unsigned long long int*); + +extern int xfrmnl_sp_get_priority (struct xfrmnl_sp*); +extern int xfrmnl_sp_set_priority (struct xfrmnl_sp*, unsigned int); + +extern int xfrmnl_sp_get_index (struct xfrmnl_sp*); +extern int xfrmnl_sp_set_index (struct xfrmnl_sp*, unsigned int); + +extern int xfrmnl_sp_get_dir (struct xfrmnl_sp*); +extern int xfrmnl_sp_set_dir (struct xfrmnl_sp*, unsigned int); + +extern int xfrmnl_sp_get_action (struct xfrmnl_sp*); +extern int xfrmnl_sp_set_action (struct xfrmnl_sp*, unsigned int); + +extern int xfrmnl_sp_get_flags (struct xfrmnl_sp*); +extern int xfrmnl_sp_set_flags (struct xfrmnl_sp*, unsigned int); + +extern int xfrmnl_sp_get_share (struct xfrmnl_sp*); +extern int xfrmnl_sp_set_share (struct xfrmnl_sp*, unsigned int); + +extern int xfrmnl_sp_get_sec_ctx (struct xfrmnl_sp*, unsigned int*, unsigned int*, + unsigned int*, unsigned int*, unsigned int*, char*); +extern int xfrmnl_sp_set_sec_ctx (struct xfrmnl_sp*, unsigned int, unsigned int, + unsigned int, unsigned int, unsigned int, char*); + +extern int xfrmnl_sp_get_userpolicy_type (struct xfrmnl_sp*); +extern int xfrmnl_sp_set_userpolicy_type (struct xfrmnl_sp*, unsigned int); + +extern void xfrmnl_sp_add_usertemplate(struct xfrmnl_sp*, struct xfrmnl_user_tmpl*); +extern void xfrmnl_sp_remove_usertemplate(struct xfrmnl_sp*, struct xfrmnl_user_tmpl*); +extern struct nl_list_head* xfrmnl_sp_get_usertemplates(struct xfrmnl_sp*); +extern int xfrmnl_sp_get_nusertemplates(struct xfrmnl_sp*); +extern void xfrmnl_sp_foreach_usertemplate(struct xfrmnl_sp*, + void (*cb)(struct xfrmnl_user_tmpl*, void *), + void *arg); +extern struct xfrmnl_user_tmpl* xfrmnl_sp_usertemplate_n(struct xfrmnl_sp*, int); + +extern int xfrmnl_sp_get_mark (struct xfrmnl_sp*, unsigned int*, unsigned int*); +extern int xfrmnl_sp_set_mark (struct xfrmnl_sp*, unsigned int, unsigned int); + +extern char* xfrmnl_sp_action2str(int, char *, size_t); +extern int xfrmnl_sp_str2action(const char *); + +extern char* xfrmnl_sp_flags2str(int, char *, size_t); +extern int xfrmnl_sp_str2flag(const char *); + +extern char* xfrmnl_sp_type2str(int, char *, size_t); +extern int xfrmnl_sp_str2type(const char *); + +extern char* xfrmnl_sp_dir2str(int, char *, size_t); +extern int xfrmnl_sp_str2dir(const char *); + +extern char* xfrmnl_sp_share2str(int, char *, size_t); +extern int xfrmnl_sp_str2share(const char *); + +extern int xfrmnl_sp_index2dir (unsigned int); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/netlink/xfrm/template.h b/include/netlink/xfrm/template.h new file mode 100644 index 0000000..da51e7d --- /dev/null +++ b/include/netlink/xfrm/template.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * +*/ +#ifndef NETLINK_XFRM_TEMPL_H_ +#define NETLINK_XFRM_TEMPL_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct xfrmnl_user_tmpl; + +/* Creation */ +extern struct xfrmnl_user_tmpl* xfrmnl_user_tmpl_alloc(void); +extern struct xfrmnl_user_tmpl* xfrmnl_user_tmpl_clone(struct xfrmnl_user_tmpl*); +extern void xfrmnl_user_tmpl_free(struct xfrmnl_user_tmpl* utmpl); + +/* Utility functions */ +extern int xfrmnl_user_tmpl_cmp(struct xfrmnl_user_tmpl*, struct xfrmnl_user_tmpl*); +extern void xfrmnl_user_tmpl_dump(struct xfrmnl_user_tmpl*, struct nl_dump_params*); + +/* Access Functions */ +extern struct nl_addr* xfrmnl_user_tmpl_get_daddr (struct xfrmnl_user_tmpl*); +extern int xfrmnl_user_tmpl_set_daddr (struct xfrmnl_user_tmpl*, struct nl_addr*); + +extern int xfrmnl_user_tmpl_get_spi (struct xfrmnl_user_tmpl*); +extern int xfrmnl_user_tmpl_set_spi (struct xfrmnl_user_tmpl*, unsigned int); + +extern int xfrmnl_user_tmpl_get_proto (struct xfrmnl_user_tmpl*); +extern int xfrmnl_user_tmpl_set_proto (struct xfrmnl_user_tmpl*, unsigned int); + +extern int xfrmnl_user_tmpl_get_family (struct xfrmnl_user_tmpl*); +extern int xfrmnl_user_tmpl_set_family (struct xfrmnl_user_tmpl*, unsigned int); + +extern struct nl_addr* xfrmnl_user_tmpl_get_saddr (struct xfrmnl_user_tmpl*); +extern int xfrmnl_user_tmpl_set_saddr (struct xfrmnl_user_tmpl*, struct nl_addr*); + +extern int xfrmnl_user_tmpl_get_reqid (struct xfrmnl_user_tmpl*); +extern int xfrmnl_user_tmpl_set_reqid (struct xfrmnl_user_tmpl*, unsigned int); + +extern int xfrmnl_user_tmpl_get_mode (struct xfrmnl_user_tmpl*); +extern int xfrmnl_user_tmpl_set_mode (struct xfrmnl_user_tmpl*, unsigned int); + +extern int xfrmnl_user_tmpl_get_share (struct xfrmnl_user_tmpl*); +extern int xfrmnl_user_tmpl_set_share (struct xfrmnl_user_tmpl*, unsigned int); + +extern int xfrmnl_user_tmpl_get_optional (struct xfrmnl_user_tmpl*); +extern int xfrmnl_user_tmpl_set_optional (struct xfrmnl_user_tmpl*, unsigned int); + +extern int xfrmnl_user_tmpl_get_aalgos (struct xfrmnl_user_tmpl*); +extern int xfrmnl_user_tmpl_set_aalgos (struct xfrmnl_user_tmpl*, unsigned int); + +extern int xfrmnl_user_tmpl_get_ealgos (struct xfrmnl_user_tmpl*); +extern int xfrmnl_user_tmpl_set_ealgos (struct xfrmnl_user_tmpl*, unsigned int); + +extern int xfrmnl_user_tmpl_get_calgos (struct xfrmnl_user_tmpl*); +extern int xfrmnl_user_tmpl_set_calgos (struct xfrmnl_user_tmpl*, unsigned int); + +extern char* xfrmnl_user_tmpl_mode2str(int, char *, size_t); +extern int xfrmnl_user_tmpl_str2mode(const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/nl-aux-core/nl-core.h b/include/nl-aux-core/nl-core.h new file mode 100644 index 0000000..5b34bcb --- /dev/null +++ b/include/nl-aux-core/nl-core.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#ifndef NETLINK_NL_AUTO_H_ +#define NETLINK_NL_AUTO_H_ + +#include "base/nl-base-utils.h" + +#ifdef NL_DEBUG +#define NL_DBG(LVL, FMT, ARG...) \ + do { \ + if (LVL <= nl_debug) { \ + int _errsv = errno; \ + fprintf(stderr, "DBG<" #LVL ">%20s:%-4u %s: " FMT, \ + __FILE__, __LINE__, __func__, ##ARG); \ + errno = _errsv; \ + } \ + } while (0) +#else /* NL_DEBUG */ +#define NL_DBG(LVL, FMT, ARG...) \ + do { \ + } while (0) +#endif /* NL_DEBUG */ + +struct nl_addr; +void nl_addr_put(struct nl_addr *); +#define _nl_auto_nl_addr _nl_auto(_nl_auto_nl_addr_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct nl_addr *, _nl_auto_nl_addr_fcn, nl_addr_put); + +struct nl_data; +void nl_data_free(struct nl_data *data); +#define _nl_auto_nl_data _nl_auto(_nl_auto_nl_data_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct nl_data *, _nl_auto_nl_data_fcn, + nl_data_free); + +struct nl_msg; +void nlmsg_free(struct nl_msg *); +#define _nl_auto_nl_msg _nl_auto(_nl_auto_nl_msg_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct nl_msg *, _nl_auto_nl_msg_fcn, nlmsg_free); + +struct nl_cache; +void nl_cache_put(struct nl_cache *); +#define _nl_auto_nl_cache _nl_auto(_nl_auto_nl_cache_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct nl_cache *, _nl_auto_nl_cache_fcn, + nl_cache_put); + +struct nl_sock; +void nl_socket_free(struct nl_sock *); +#define _nl_auto_nl_socket _nl_auto(_nl_auto_nl_socket_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct nl_sock *, _nl_auto_nl_socket_fcn, + nl_socket_free); + +struct nl_addr *nl_addr_build(int, const void *, size_t); + +static inline struct nl_addr *_nl_addr_build(int family, const void *buf) +{ + return nl_addr_build(family, buf, _nl_addr_family_to_size(family)); +} + +#endif /* NETLINK_NL_AUTO_H_ */ diff --git a/include/nl-aux-route/nl-route.h b/include/nl-aux-route/nl-route.h new file mode 100644 index 0000000..9c85337 --- /dev/null +++ b/include/nl-aux-route/nl-route.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#ifndef __NETLINK_NL_AUX_ROUTE_NL_ROUTE_H__ +#define __NETLINK_NL_AUX_ROUTE_NL_ROUTE_H__ + +#include "base/nl-base-utils.h" + +#include + +struct rtnl_link; +void rtnl_link_put(struct rtnl_link *); +#define _nl_auto_rtnl_link _nl_auto(_nl_auto_rtnl_link_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_link *, _nl_auto_rtnl_link_fcn, + rtnl_link_put); + +struct rtnl_route; +void rtnl_route_put(struct rtnl_route *); +#define _nl_auto_rtnl_route _nl_auto(_nl_auto_rtnl_route_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_route *, _nl_auto_rtnl_route_fcn, + rtnl_route_put); + +struct rtnl_mdb; +void rtnl_mdb_put(struct rtnl_mdb *); +#define _nl_auto_rtnl_mdb _nl_auto(_nl_auto_rtnl_mdb_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_mdb *, _nl_auto_rtnl_mdb_fcn, + rtnl_mdb_put); + +struct rtnl_nexthop; +void rtnl_route_nh_free(struct rtnl_nexthop *); +#define _nl_auto_rtnl_nexthop _nl_auto(_nl_auto_rtnl_nexthop_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_nexthop *, _nl_auto_rtnl_nexthop_fcn, + rtnl_route_nh_free); + +struct rtnl_nh; +void rtnl_nh_put(struct rtnl_nh *); +#define _nl_auto_rtnl_nh _nl_auto(_nl_auto_rtnl_nh_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_nh *, _nl_auto_rtnl_nh_fcn, rtnl_nh_put); + +struct rtnl_link_af_ops; +void rtnl_link_af_ops_put(struct rtnl_link_af_ops *); +#define _nl_auto_rtnl_link_af_ops _nl_auto(_nl_auto_rtnl_link_af_ops_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_link_af_ops *, + _nl_auto_rtnl_link_af_ops_fcn, rtnl_link_af_ops_put); + +#define _nl_auto_rtnl_act _nl_auto(_nl_auto_rtnl_act_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_act *, _nl_auto_rtnl_act_fcn, + rtnl_act_put); + +#define _nl_auto_rtnl_act_all _nl_auto(_nl_auto_rtnl_act_fcn_all) +_NL_AUTO_DEFINE_FCN_INDIRECT0(struct rtnl_act *, _nl_auto_rtnl_act_fcn_all, + rtnl_act_put_all); + +struct rtnl_ematch_tree; +void rtnl_ematch_tree_free(struct rtnl_ematch_tree *); +#define _nl_auto_rtnl_ematch_tree _nl_auto(_nl_auto_rtnl_ematch_tree_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_ematch_tree *, + _nl_auto_rtnl_ematch_tree_fcn, + rtnl_ematch_tree_free); + +struct rtnl_cls; +void rtnl_cls_put(struct rtnl_cls *); +#define _nl_auto_rtnl_cls _nl_auto(_nl_auto_rtnl_cls_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_cls *, _nl_auto_rtnl_cls_fcn, + rtnl_cls_put); + +/*****************************************************************************/ + +static inline int _rtnl_act_append_get(struct rtnl_act **head, + struct rtnl_act *new) +{ + int r; + + r = rtnl_act_append(head, new); + if (r >= 0) + rtnl_act_get(new); + return r; +} + +static inline int _rtnl_act_append_take(struct rtnl_act **head, + struct rtnl_act *new) +{ + int r; + + r = rtnl_act_append(head, new); + if (r < 0) + rtnl_act_put(new); + return r; +} + +#endif /* __NETLINK_NL_AUX_ROUTE_NL_ROUTE_H__ */ diff --git a/include/nl-aux-xfrm/nl-xfrm.h b/include/nl-aux-xfrm/nl-xfrm.h new file mode 100644 index 0000000..9c5c46a --- /dev/null +++ b/include/nl-aux-xfrm/nl-xfrm.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#ifndef __NETLINK_NL_AUX_XFRM_NL_XFRM_H__ +#define __NETLINK_NL_AUX_XFRM_NL_XFRM_H__ + +#include "base/nl-base-utils.h" + +struct xfrmnl_sp; +void xfrmnl_sp_put(struct xfrmnl_sp *sp); +#define _nl_auto_xfrmnl_sp _nl_auto(_nl_auto_xfrmnl_sp_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct xfrmnl_sp *, _nl_auto_xfrmnl_sp_fcn, + xfrmnl_sp_put); + +struct xfrmnl_sa; +void xfrmnl_sa_put(struct xfrmnl_sa *sa); +#define _nl_auto_xfrmnl_sa _nl_auto(_nl_auto_xfrmnl_sa_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct xfrmnl_sa *, _nl_auto_xfrmnl_sa_fcn, + xfrmnl_sa_put); + +struct xfrmnl_ae; +void xfrmnl_ae_put(struct xfrmnl_ae *ae); +#define _nl_auto_xfrmnl_ae _nl_auto(_nl_auto_xfrmnl_ae_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct xfrmnl_ae *, _nl_auto_xfrmnl_ae_fcn, + xfrmnl_ae_put); + +struct xfrmnl_user_tmpl; +void xfrmnl_user_tmpl_free(struct xfrmnl_user_tmpl *utmpl); +#define _nl_auto_xfrmnl_user_tmpl _nl_auto(_nl_auto_xfrmnl_user_tmpl_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(struct xfrmnl_user_tmpl *, + _nl_auto_xfrmnl_user_tmpl_fcn, + xfrmnl_user_tmpl_free); + +#endif /* __NETLINK_NL_AUX_XFRM_NL_XFRM_H__ */ diff --git a/include/nl-default.h b/include/nl-default.h new file mode 100644 index 0000000..83dbcb4 --- /dev/null +++ b/include/nl-default.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#ifndef __NL_DEFAULT_H__ +#define __NL_DEFAULT_H__ + +#include "config.h" + +#include "base/nl-base-utils.h" + +#endif /* __NL_DEFAULT_H__ */ diff --git a/include/netlink-private/cache-api.h b/include/nl-priv-dynamic-core/cache-api.h similarity index 92% rename from include/netlink-private/cache-api.h rename to include/nl-priv-dynamic-core/cache-api.h index f3d9f01..2ddc30c 100644 --- a/include/netlink-private/cache-api.h +++ b/include/nl-priv-dynamic-core/cache-api.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink-private/cache-api.h Caching API - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2013 Thomas Graf */ @@ -15,10 +9,6 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif - /** * @ingroup cache * @defgroup cache_api Cache Implementation @@ -237,7 +227,8 @@ struct nl_cache_ops * @see nl_cache_include() */ int (*co_include_event)(struct nl_cache *cache, struct nl_object *obj, - change_func_t change_cb, void *data); + change_func_t change_cb, change_func_v2_t change_cb_v2, + void *data); void (*reserved_1)(void); void (*reserved_2)(void); @@ -263,8 +254,27 @@ struct nl_cache_ops /** @} */ -#ifdef __cplusplus +struct nl_cache { + struct nl_list_head c_items; + int c_nitems; + int c_iarg1; + int c_iarg2; + int c_refcnt; + unsigned int c_flags; + struct nl_hash_table *hashtable; + struct nl_cache_ops *c_ops; +}; + +static inline const char *nl_cache_name(struct nl_cache *cache) +{ + return cache->c_ops ? cache->c_ops->co_name : "unknown"; } -#endif + +struct nl_cache_assoc { + struct nl_cache *ca_cache; + change_func_t ca_change; + change_func_v2_t ca_change_v2; + void *ca_change_data; +}; #endif diff --git a/include/nl-priv-dynamic-core/nl-core.h b/include/nl-priv-dynamic-core/nl-core.h new file mode 100644 index 0000000..33ebfa1 --- /dev/null +++ b/include/nl-priv-dynamic-core/nl-core.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2003-2013 Thomas Graf + */ + +#ifndef __NL_SHARED_CORE_NL_CORE_H__ +#define __NL_SHARED_CORE_NL_CORE_H__ + +#define NL_SOCK_PASSCRED (1 << 1) +#define NL_OWN_PORT (1 << 2) +#define NL_MSG_PEEK (1 << 3) +#define NL_MSG_PEEK_EXPLICIT (1 << 4) +#define NL_NO_AUTO_ACK (1 << 5) + +struct nl_sock { + struct sockaddr_nl s_local; + struct sockaddr_nl s_peer; + int s_fd; + int s_proto; + unsigned int s_seq_next; + unsigned int s_seq_expect; + int s_flags; + struct nl_cb *s_cb; + size_t s_bufsize; +}; + +static inline int wait_for_ack(struct nl_sock *sk) +{ + if (sk->s_flags & NL_NO_AUTO_ACK) + return 0; + else + return nl_wait_for_ack(sk); +} + +#define LOOSE_COMPARISON 1 +#define ID_COMPARISON 2 + +#define NL_OBJ_MARK 1 + +struct nl_data { + size_t d_size; + void *d_data; +}; + +struct nl_addr { + int a_family; + unsigned int a_maxsize; + unsigned int a_len; + int a_prefixlen; + int a_refcnt; + char a_addr[0]; +}; + +#define NL_MSG_CRED_PRESENT 1 + +struct nl_msg { + int nm_protocol; + int nm_flags; + struct sockaddr_nl nm_src; + struct sockaddr_nl nm_dst; + struct ucred nm_creds; + struct nlmsghdr *nm_nlh; + size_t nm_size; + int nm_refcnt; +}; + +/*****************************************************************************/ + +int nl_getprotobyname(const char *name); + +bool nl_getprotobynumber(int proto, char *out_name, size_t name_len); + +extern const char *nl_strerror_l(int err); + +extern int __nl_read_num_str_file(const char *path, + int (*cb)(long, const char *)); + +extern int __trans_list_add(int, const char *, struct nl_list_head *); +extern void __trans_list_clear(struct nl_list_head *); + +extern char *__type2str(int, char *, size_t, const struct trans_tbl *, size_t); +extern int __str2type(const char *, const struct trans_tbl *, size_t); + +extern char *__list_type2str(int, char *, size_t, struct nl_list_head *); +extern int __list_str2type(const char *, struct nl_list_head *); + +extern char *__flags2str(int, char *, size_t, const struct trans_tbl *, size_t); +extern int __str2flags(const char *, const struct trans_tbl *, size_t); + +#endif /* __NL_SHARED_CORE_NL_CORE_H__ */ diff --git a/include/netlink-private/object-api.h b/include/nl-priv-dynamic-core/object-api.h similarity index 94% rename from include/netlink-private/object-api.h rename to include/nl-priv-dynamic-core/object-api.h index f4fd71e..a20a9d5 100644 --- a/include/netlink-private/object-api.h +++ b/include/nl-priv-dynamic-core/object-api.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink-private/object-api.c Object API - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2013 Thomas Graf */ @@ -16,10 +10,6 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif - /** * @ingroup object * @defgroup object_api Object API @@ -126,6 +116,8 @@ extern "C" { * #define MY_ATTR_FOO (1<<0) * #define MY_ATTR_BAR (1<<1) * + * // Bit 31 for attributes is reserved for 32-bit API. + * * // When assigning an optional attribute to the object, make sure * // to mark its availability. * my_obj->foo = 123123; @@ -153,12 +145,12 @@ extern "C" { * // We help ourselves in defining our own DIFF macro which will * // call ATTR_DIFF() on both objects which will make sure to only * // compare the attributes if required. - * #define MY_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MY_ATTR_##ATTR, a, b, EXPR) + * #define MY_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) * * // Call our own diff macro for each attribute to build a bitmask * // representing the attributes which mismatch. - * diff |= MY_DIFF(FOO, a->foo != b->foo) - * diff |= MY_DIFF(BAR, strcmp(a->bar, b->bar)) + * diff |= MY_DIFF(MY_ATTR_FOO, a->foo != b->foo) + * diff |= MY_DIFF(MY_ATTR_BAR, strcmp(a->bar, b->bar)) * * return diff; * } @@ -189,7 +181,7 @@ extern "C" { struct nl_list_head ce_list; \ int ce_msgtype; \ int ce_flags; \ - uint32_t ce_mask; + uint64_t ce_mask; struct nl_object { @@ -258,7 +250,7 @@ struct nl_object * @endcode */ #define ATTR_DIFF(LIST, ATTR, A, B, EXPR) \ -({ int diff = 0; \ +({ uint64_t diff = 0; \ if (((LIST) & (ATTR)) && ATTR_MISMATCH(A, B, ATTR, EXPR)) \ diff = ATTR; \ diff; }) @@ -333,8 +325,8 @@ struct nl_object_ops * The function must return a bitmask with the relevant bit * set for each attribute that mismatches. */ - int (*oo_compare)(struct nl_object *, struct nl_object *, - uint32_t, int); + uint64_t (*oo_compare)(struct nl_object *, struct nl_object *, + uint64_t, int); /** @@ -369,8 +361,4 @@ struct nl_object_ops /** @} */ -#ifdef __cplusplus -} -#endif - #endif diff --git a/include/nl-priv-dynamic-route/nl-priv-dynamic-route.h b/include/nl-priv-dynamic-route/nl-priv-dynamic-route.h new file mode 100644 index 0000000..c8168a3 --- /dev/null +++ b/include/nl-priv-dynamic-route/nl-priv-dynamic-route.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2003-2013 Thomas Graf + * Copyright (c) 2013 Sassano Systems LLC + */ + +#ifndef __NL_PRIVATE_TYPES_NL_ROUTE_H__ +#define __NL_PRIVATE_TYPES_NL_ROUTE_H__ + +struct rtnl_ematch { + uint16_t e_id; + uint16_t e_kind; + uint16_t e_flags; + uint16_t e_index; + size_t e_datalen; + + struct nl_list_head e_childs; + struct nl_list_head e_list; + struct rtnl_ematch_ops *e_ops; + + void *e_data; +}; + +struct rtnl_ematch_tree { + uint16_t et_progid; + struct nl_list_head et_list; +}; + +/*****************************************************************************/ + +/** + * Traffic control object operations + * @ingroup tc + * + * This structure holds function pointers and settings implementing + * the features of each traffic control object implementation. + */ +struct rtnl_tc_ops { + /** + * Name of traffic control module + */ + char *to_kind; + + /** + * Type of traffic control object + */ + enum rtnl_tc_type to_type; + + /** + * Size of private data + */ + size_t to_size; + + /** + * Dump callbacks + */ + void (*to_dump[NL_DUMP_MAX + 1])(struct rtnl_tc *, void *, + struct nl_dump_params *); + /** + * Used to fill the contents of TCA_OPTIONS + */ + int (*to_msg_fill)(struct rtnl_tc *, void *, struct nl_msg *); + + /** + * Uesd to to fill tc related messages, unlike with to_msg_fill, + * the contents is not encapsulated with a TCA_OPTIONS nested + * attribute. + */ + int (*to_msg_fill_raw)(struct rtnl_tc *, void *, struct nl_msg *); + + /** + * TCA_OPTIONS message parser + */ + int (*to_msg_parser)(struct rtnl_tc *, void *); + + /** + * Called before a tc object is destroyed + */ + void (*to_free_data)(struct rtnl_tc *, void *); + + /** + * Called whenever a classifier object needs to be cloned + */ + int (*to_clone)(void *, void *); + + /** + * Internal, don't touch + */ + struct nl_list_head to_list; +}; + +extern struct rtnl_tc_ops *rtnl_tc_lookup_ops(enum rtnl_tc_type, const char *); + +struct rtnl_tc_ops *rtnl_tc_get_ops(struct rtnl_tc *); + +#endif /* __NL_PRIVATE_TYPES_NL_ROUTE_H__ */ diff --git a/include/nl-priv-static-route/nl-priv-static-route.h b/include/nl-priv-static-route/nl-priv-static-route.h new file mode 100644 index 0000000..65ff531 --- /dev/null +++ b/include/nl-priv-static-route/nl-priv-static-route.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#ifndef NETLINK_ROUTE_UTILS_PRIV_H_ +#define NETLINK_ROUTE_UTILS_PRIV_H_ + +extern const uint8_t *const _nltst_map_stat_id_from_IPSTATS_MIB_v2; + +#endif diff --git a/lib/Makefile.am b/lib/Makefile.am deleted file mode 100644 index 677a89c..0000000 --- a/lib/Makefile.am +++ /dev/null @@ -1,118 +0,0 @@ -# -*- Makefile -*- - -AM_CPPFLAGS = \ - -Wall \ - -I${top_srcdir}/include \ - -I${top_builddir}/include \ - -I${builddir}/route \ - -I${builddir}/route/cls \ - -D_GNU_SOURCE \ - -DSYSCONFDIR=\"$(sysconfdir)/libnl\" - -AM_LDFLAGS = \ - -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) - -lib_LTLIBRARIES = \ - libnl-3.la libnl-genl-3.la libnl-route-3.la libnl-nf-3.la - -libnl_3_la_SOURCES = \ - addr.c attr.c cache.c cache_mngr.c cache_mngt.c data.c \ - error.c handlers.c msg.c nl.c object.c socket.c utils.c \ - version.c hash.c hashtable.c - -libnl_genl_3_la_LIBADD = libnl-3.la -libnl_genl_3_la_SOURCES = \ - genl/ctrl.c genl/family.c genl/genl.c genl/mngt.c - -libnl_nf_3_la_LIBADD = libnl-route-3.la -libnl_nf_3_la_SOURCES = \ - netfilter/ct.c netfilter/ct_obj.c netfilter/log.c \ - netfilter/log_msg.c netfilter/log_msg_obj.c netfilter/log_obj.c \ - netfilter/netfilter.c netfilter/nfnl.c netfilter/queue.c \ - netfilter/queue_msg.c netfilter/queue_msg_obj.c netfilter/queue_obj.c \ - netfilter/exp.c netfilter/exp_obj.c - -CLEANFILES = \ - route/pktloc_grammar.c route/pktloc_grammar.h \ - route/pktloc_syntax.c route/pktloc_syntax.h \ - route/cls/ematch_grammar.c route/cls/ematch_grammar.h \ - route/cls/ematch_syntax.c route/cls/ematch_syntax.h - -# Hack to avoid using ylwrap. It does not function correctly in combination -# with --header-file= -route/pktloc_grammar.c: route/pktloc_grammar.l - $(AM_V_GEN) $(FLEX) --header-file=route/pktloc_grammar.h $(LFLAGS) -o $@ $^ - -route/pktloc_syntax.c: route/pktloc_syntax.y - $(AM_V_GEN) $(YACC) -d $(YFLAGS) -o $@ $^ - -route/cls/ematch_grammar.c: route/cls/ematch_grammar.l - $(AM_V_GEN) $(FLEX) --header-file=route/cls/ematch_grammar.h $(LFLAGS) -o $@ $^ - -route/cls/ematch_syntax.c: route/cls/ematch_syntax.y - $(AM_V_GEN) $(YACC) -d $(YFLAGS) -o $@ $^ - -libnl_route_3_la_LIBADD = libnl-3.la -libnl_route_3_la_SOURCES = \ - route/addr.c route/class.c route/cls.c route/link.c \ - route/neigh.c route/neightbl.c route/nexthop.c route/qdisc.c \ - route/route.c route/route_obj.c route/route_utils.c route/rtnl.c \ - route/rule.c route/tc.c route/classid.c \ - \ - route/cls/fw.c route/cls/police.c route/cls/u32.c route/cls/basic.c \ - route/cls/cgroup.c \ - \ - route/cls/ematch.c \ - route/cls/ematch/container.c route/cls/ematch/cmp.c \ - route/cls/ematch/nbyte.c route/cls/ematch/text.c \ - route/cls/ematch/meta.c \ - \ - route/link/api.c route/link/vlan.c route/link/dummy.c \ - route/link/bridge.c route/link/inet6.c route/link/inet.c \ - route/link/bonding.c route/link/can.c \ - \ - route/qdisc/blackhole.c route/qdisc/cbq.c route/qdisc/dsmark.c \ - route/qdisc/fifo.c route/qdisc/htb.c route/qdisc/netem.c \ - route/qdisc/prio.c route/qdisc/red.c route/qdisc/sfq.c \ - route/qdisc/tbf.c route/qdisc/plug.c \ - \ - fib_lookup/lookup.c fib_lookup/request.c \ - \ - route/pktloc.c - -nodist_libnl_route_3_la_SOURCES = \ - route/pktloc_syntax.c route/pktloc_syntax.h \ - route/pktloc_grammar.c route/pktloc_grammar.h \ - route/cls/ematch_syntax.c route/cls/ematch_syntax.h \ - route/cls/ematch_grammar.c route/cls/ematch_grammar.h - -BUILT_SOURCES = \ - route/cls/ematch_grammar.c \ - route/cls/ematch_syntax.c \ - route/pktloc_grammar.c \ - route/pktloc_syntax.c - -EXTRA_DIST = \ - route/pktloc_grammar.l \ - route/pktloc_syntax.y \ - route/cls/ematch_grammar.l \ - route/cls/ematch_syntax.y - -if ENABLE_CLI -nobase_pkglib_LTLIBRARIES = \ - cli/qdisc/htb.la \ - cli/qdisc/blackhole.la \ - cli/qdisc/pfifo.la \ - cli/qdisc/plug.la \ - cli/qdisc/bfifo.la \ - cli/cls/basic.la \ - cli/cls/cgroup.la - -cli_qdisc_htb_la_LDFLAGS = -module -avoid-version -cli_qdisc_blackhole_la_LDFLAGS = -module -avoid-version -cli_qdisc_pfifo_la_LDFLAGS = -module -avoid-version -cli_qdisc_plug_la_LDFLAGS = -module -avoid-version -cli_qdisc_bfifo_la_LDFLAGS = -module -avoid-version -cli_cls_basic_la_LDFLAGS = -module -avoid-version -cli_cls_cgroup_la_LDFLAGS = -module -avoid-version -endif diff --git a/lib/Makefile.in b/lib/Makefile.in deleted file mode 100644 index bf6a68e..0000000 --- a/lib/Makefile.in +++ /dev/null @@ -1,1370 +0,0 @@ -# Makefile.in generated by automake 1.11.6 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -# -*- Makefile -*- - -VPATH = @srcdir@ -am__make_dryrun = \ - { \ - am__dry=no; \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ - esac; \ - test $$am__dry = yes; \ - } -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = lib -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(srcdir)/defs.h.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = defs.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkglibdir)" -LTLIBRARIES = $(lib_LTLIBRARIES) $(nobase_pkglib_LTLIBRARIES) -cli_cls_basic_la_LIBADD = -cli_cls_basic_la_SOURCES = cli/cls/basic.c -am__dirstamp = $(am__leading_dot)dirstamp -cli_cls_basic_la_OBJECTS = cli/cls/basic.lo -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -cli_cls_basic_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ - $(AM_CFLAGS) $(CFLAGS) $(cli_cls_basic_la_LDFLAGS) $(LDFLAGS) \ - -o $@ -@ENABLE_CLI_TRUE@am_cli_cls_basic_la_rpath = -rpath \ -@ENABLE_CLI_TRUE@ $(pkglibdir)/cli/cls -cli_cls_cgroup_la_LIBADD = -cli_cls_cgroup_la_SOURCES = cli/cls/cgroup.c -cli_cls_cgroup_la_OBJECTS = cli/cls/cgroup.lo -cli_cls_cgroup_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ - $(AM_CFLAGS) $(CFLAGS) $(cli_cls_cgroup_la_LDFLAGS) $(LDFLAGS) \ - -o $@ -@ENABLE_CLI_TRUE@am_cli_cls_cgroup_la_rpath = -rpath \ -@ENABLE_CLI_TRUE@ $(pkglibdir)/cli/cls -cli_qdisc_bfifo_la_LIBADD = -cli_qdisc_bfifo_la_SOURCES = cli/qdisc/bfifo.c -cli_qdisc_bfifo_la_OBJECTS = cli/qdisc/bfifo.lo -cli_qdisc_bfifo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ - $(AM_CFLAGS) $(CFLAGS) $(cli_qdisc_bfifo_la_LDFLAGS) \ - $(LDFLAGS) -o $@ -@ENABLE_CLI_TRUE@am_cli_qdisc_bfifo_la_rpath = -rpath \ -@ENABLE_CLI_TRUE@ $(pkglibdir)/cli/qdisc -cli_qdisc_blackhole_la_LIBADD = -cli_qdisc_blackhole_la_SOURCES = cli/qdisc/blackhole.c -cli_qdisc_blackhole_la_OBJECTS = cli/qdisc/blackhole.lo -cli_qdisc_blackhole_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ - $(AM_CFLAGS) $(CFLAGS) $(cli_qdisc_blackhole_la_LDFLAGS) \ - $(LDFLAGS) -o $@ -@ENABLE_CLI_TRUE@am_cli_qdisc_blackhole_la_rpath = -rpath \ -@ENABLE_CLI_TRUE@ $(pkglibdir)/cli/qdisc -cli_qdisc_htb_la_LIBADD = -cli_qdisc_htb_la_SOURCES = cli/qdisc/htb.c -cli_qdisc_htb_la_OBJECTS = cli/qdisc/htb.lo -cli_qdisc_htb_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ - $(AM_CFLAGS) $(CFLAGS) $(cli_qdisc_htb_la_LDFLAGS) $(LDFLAGS) \ - -o $@ -@ENABLE_CLI_TRUE@am_cli_qdisc_htb_la_rpath = -rpath \ -@ENABLE_CLI_TRUE@ $(pkglibdir)/cli/qdisc -cli_qdisc_pfifo_la_LIBADD = -cli_qdisc_pfifo_la_SOURCES = cli/qdisc/pfifo.c -cli_qdisc_pfifo_la_OBJECTS = cli/qdisc/pfifo.lo -cli_qdisc_pfifo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ - $(AM_CFLAGS) $(CFLAGS) $(cli_qdisc_pfifo_la_LDFLAGS) \ - $(LDFLAGS) -o $@ -@ENABLE_CLI_TRUE@am_cli_qdisc_pfifo_la_rpath = -rpath \ -@ENABLE_CLI_TRUE@ $(pkglibdir)/cli/qdisc -cli_qdisc_plug_la_LIBADD = -cli_qdisc_plug_la_SOURCES = cli/qdisc/plug.c -cli_qdisc_plug_la_OBJECTS = cli/qdisc/plug.lo -cli_qdisc_plug_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ - $(AM_CFLAGS) $(CFLAGS) $(cli_qdisc_plug_la_LDFLAGS) $(LDFLAGS) \ - -o $@ -@ENABLE_CLI_TRUE@am_cli_qdisc_plug_la_rpath = -rpath \ -@ENABLE_CLI_TRUE@ $(pkglibdir)/cli/qdisc -libnl_3_la_LIBADD = -am_libnl_3_la_OBJECTS = addr.lo attr.lo cache.lo cache_mngr.lo \ - cache_mngt.lo data.lo error.lo handlers.lo msg.lo nl.lo \ - object.lo socket.lo utils.lo version.lo hash.lo hashtable.lo -libnl_3_la_OBJECTS = $(am_libnl_3_la_OBJECTS) -libnl_genl_3_la_DEPENDENCIES = libnl-3.la -am_libnl_genl_3_la_OBJECTS = genl/ctrl.lo genl/family.lo genl/genl.lo \ - genl/mngt.lo -libnl_genl_3_la_OBJECTS = $(am_libnl_genl_3_la_OBJECTS) -libnl_nf_3_la_DEPENDENCIES = libnl-route-3.la -am_libnl_nf_3_la_OBJECTS = netfilter/ct.lo netfilter/ct_obj.lo \ - netfilter/log.lo netfilter/log_msg.lo netfilter/log_msg_obj.lo \ - netfilter/log_obj.lo netfilter/netfilter.lo netfilter/nfnl.lo \ - netfilter/queue.lo netfilter/queue_msg.lo \ - netfilter/queue_msg_obj.lo netfilter/queue_obj.lo \ - netfilter/exp.lo netfilter/exp_obj.lo -libnl_nf_3_la_OBJECTS = $(am_libnl_nf_3_la_OBJECTS) -libnl_route_3_la_DEPENDENCIES = libnl-3.la -am_libnl_route_3_la_OBJECTS = route/addr.lo route/class.lo \ - route/cls.lo route/link.lo route/neigh.lo route/neightbl.lo \ - route/nexthop.lo route/qdisc.lo route/route.lo \ - route/route_obj.lo route/route_utils.lo route/rtnl.lo \ - route/rule.lo route/tc.lo route/classid.lo route/cls/fw.lo \ - route/cls/police.lo route/cls/u32.lo route/cls/basic.lo \ - route/cls/cgroup.lo route/cls/ematch.lo \ - route/cls/ematch/container.lo route/cls/ematch/cmp.lo \ - route/cls/ematch/nbyte.lo route/cls/ematch/text.lo \ - route/cls/ematch/meta.lo route/link/api.lo route/link/vlan.lo \ - route/link/dummy.lo route/link/bridge.lo route/link/inet6.lo \ - route/link/inet.lo route/link/bonding.lo route/link/can.lo \ - route/qdisc/blackhole.lo route/qdisc/cbq.lo \ - route/qdisc/dsmark.lo route/qdisc/fifo.lo route/qdisc/htb.lo \ - route/qdisc/netem.lo route/qdisc/prio.lo route/qdisc/red.lo \ - route/qdisc/sfq.lo route/qdisc/tbf.lo route/qdisc/plug.lo \ - fib_lookup/lookup.lo fib_lookup/request.lo route/pktloc.lo -nodist_libnl_route_3_la_OBJECTS = route/pktloc_syntax.lo \ - route/pktloc_grammar.lo route/cls/ematch_syntax.lo \ - route/cls/ematch_grammar.lo -libnl_route_3_la_OBJECTS = $(am_libnl_route_3_la_OBJECTS) \ - $(nodist_libnl_route_3_la_OBJECTS) -DEFAULT_INCLUDES = -I.@am__isrc@ -depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -SOURCES = cli/cls/basic.c cli/cls/cgroup.c cli/qdisc/bfifo.c \ - cli/qdisc/blackhole.c cli/qdisc/htb.c cli/qdisc/pfifo.c \ - cli/qdisc/plug.c $(libnl_3_la_SOURCES) \ - $(libnl_genl_3_la_SOURCES) $(libnl_nf_3_la_SOURCES) \ - $(libnl_route_3_la_SOURCES) $(nodist_libnl_route_3_la_SOURCES) -DIST_SOURCES = cli/cls/basic.c cli/cls/cgroup.c cli/qdisc/bfifo.c \ - cli/qdisc/blackhole.c cli/qdisc/htb.c cli/qdisc/pfifo.c \ - cli/qdisc/plug.c $(libnl_3_la_SOURCES) \ - $(libnl_genl_3_la_SOURCES) $(libnl_nf_3_la_SOURCES) \ - $(libnl_route_3_la_SOURCES) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CHECK_CFLAGS = @CHECK_CFLAGS@ -CHECK_LIBS = @CHECK_LIBS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -FLEX = @FLEX@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBNL_VERSION = @LIBNL_VERSION@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_AGE = @LT_AGE@ -LT_CURRENT = @LT_CURRENT@ -LT_REVISION = @LT_REVISION@ -MAJ_VERSION = @MAJ_VERSION@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MIC_VERSION = @MIC_VERSION@ -MIN_VERSION = @MIN_VERSION@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -YACC = @YACC@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgconfigdir = @pkgconfigdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -subdirs = @subdirs@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -AM_CPPFLAGS = \ - -Wall \ - -I${top_srcdir}/include \ - -I${top_builddir}/include \ - -I${builddir}/route \ - -I${builddir}/route/cls \ - -D_GNU_SOURCE \ - -DSYSCONFDIR=\"$(sysconfdir)/libnl\" - -AM_LDFLAGS = \ - -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) - -lib_LTLIBRARIES = \ - libnl-3.la libnl-genl-3.la libnl-route-3.la libnl-nf-3.la - -libnl_3_la_SOURCES = \ - addr.c attr.c cache.c cache_mngr.c cache_mngt.c data.c \ - error.c handlers.c msg.c nl.c object.c socket.c utils.c \ - version.c hash.c hashtable.c - -libnl_genl_3_la_LIBADD = libnl-3.la -libnl_genl_3_la_SOURCES = \ - genl/ctrl.c genl/family.c genl/genl.c genl/mngt.c - -libnl_nf_3_la_LIBADD = libnl-route-3.la -libnl_nf_3_la_SOURCES = \ - netfilter/ct.c netfilter/ct_obj.c netfilter/log.c \ - netfilter/log_msg.c netfilter/log_msg_obj.c netfilter/log_obj.c \ - netfilter/netfilter.c netfilter/nfnl.c netfilter/queue.c \ - netfilter/queue_msg.c netfilter/queue_msg_obj.c netfilter/queue_obj.c \ - netfilter/exp.c netfilter/exp_obj.c - -CLEANFILES = \ - route/pktloc_grammar.c route/pktloc_grammar.h \ - route/pktloc_syntax.c route/pktloc_syntax.h \ - route/cls/ematch_grammar.c route/cls/ematch_grammar.h \ - route/cls/ematch_syntax.c route/cls/ematch_syntax.h - -libnl_route_3_la_LIBADD = libnl-3.la -libnl_route_3_la_SOURCES = \ - route/addr.c route/class.c route/cls.c route/link.c \ - route/neigh.c route/neightbl.c route/nexthop.c route/qdisc.c \ - route/route.c route/route_obj.c route/route_utils.c route/rtnl.c \ - route/rule.c route/tc.c route/classid.c \ - \ - route/cls/fw.c route/cls/police.c route/cls/u32.c route/cls/basic.c \ - route/cls/cgroup.c \ - \ - route/cls/ematch.c \ - route/cls/ematch/container.c route/cls/ematch/cmp.c \ - route/cls/ematch/nbyte.c route/cls/ematch/text.c \ - route/cls/ematch/meta.c \ - \ - route/link/api.c route/link/vlan.c route/link/dummy.c \ - route/link/bridge.c route/link/inet6.c route/link/inet.c \ - route/link/bonding.c route/link/can.c \ - \ - route/qdisc/blackhole.c route/qdisc/cbq.c route/qdisc/dsmark.c \ - route/qdisc/fifo.c route/qdisc/htb.c route/qdisc/netem.c \ - route/qdisc/prio.c route/qdisc/red.c route/qdisc/sfq.c \ - route/qdisc/tbf.c route/qdisc/plug.c \ - \ - fib_lookup/lookup.c fib_lookup/request.c \ - \ - route/pktloc.c - -nodist_libnl_route_3_la_SOURCES = \ - route/pktloc_syntax.c route/pktloc_syntax.h \ - route/pktloc_grammar.c route/pktloc_grammar.h \ - route/cls/ematch_syntax.c route/cls/ematch_syntax.h \ - route/cls/ematch_grammar.c route/cls/ematch_grammar.h - -BUILT_SOURCES = \ - route/cls/ematch_grammar.c \ - route/cls/ematch_syntax.c \ - route/pktloc_grammar.c \ - route/pktloc_syntax.c - -EXTRA_DIST = \ - route/pktloc_grammar.l \ - route/pktloc_syntax.y \ - route/cls/ematch_grammar.l \ - route/cls/ematch_syntax.y - -@ENABLE_CLI_TRUE@nobase_pkglib_LTLIBRARIES = \ -@ENABLE_CLI_TRUE@ cli/qdisc/htb.la \ -@ENABLE_CLI_TRUE@ cli/qdisc/blackhole.la \ -@ENABLE_CLI_TRUE@ cli/qdisc/pfifo.la \ -@ENABLE_CLI_TRUE@ cli/qdisc/plug.la \ -@ENABLE_CLI_TRUE@ cli/qdisc/bfifo.la \ -@ENABLE_CLI_TRUE@ cli/cls/basic.la \ -@ENABLE_CLI_TRUE@ cli/cls/cgroup.la - -@ENABLE_CLI_TRUE@cli_qdisc_htb_la_LDFLAGS = -module -avoid-version -@ENABLE_CLI_TRUE@cli_qdisc_blackhole_la_LDFLAGS = -module -avoid-version -@ENABLE_CLI_TRUE@cli_qdisc_pfifo_la_LDFLAGS = -module -avoid-version -@ENABLE_CLI_TRUE@cli_qdisc_plug_la_LDFLAGS = -module -avoid-version -@ENABLE_CLI_TRUE@cli_qdisc_bfifo_la_LDFLAGS = -module -avoid-version -@ENABLE_CLI_TRUE@cli_cls_basic_la_LDFLAGS = -module -avoid-version -@ENABLE_CLI_TRUE@cli_cls_cgroup_la_LDFLAGS = -module -avoid-version -all: $(BUILT_SOURCES) defs.h - $(MAKE) $(AM_MAKEFLAGS) all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign lib/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -defs.h: stamp-h1 - @if test ! -f $@; then rm -f stamp-h1; else :; fi - @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi - -stamp-h1: $(srcdir)/defs.h.in $(top_builddir)/config.status - @rm -f stamp-h1 - cd $(top_builddir) && $(SHELL) ./config.status lib/defs.h -$(srcdir)/defs.h.in: $(am__configure_deps) - ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) - rm -f stamp-h1 - touch $@ - -distclean-hdr: - -rm -f defs.h stamp-h1 -install-libLTLIBRARIES: $(lib_LTLIBRARIES) - @$(NORMAL_INSTALL) - @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ - list2=; for p in $$list; do \ - if test -f $$p; then \ - list2="$$list2 $$p"; \ - else :; fi; \ - done; \ - test -z "$$list2" || { \ - echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ - } - -uninstall-libLTLIBRARIES: - @$(NORMAL_UNINSTALL) - @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ - for p in $$list; do \ - $(am__strip_dir) \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ - done - -clean-libLTLIBRARIES: - -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) - @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ - dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ - test "$$dir" != "$$p" || dir=.; \ - echo "rm -f \"$${dir}/so_locations\""; \ - rm -f "$${dir}/so_locations"; \ - done -install-nobase_pkglibLTLIBRARIES: $(nobase_pkglib_LTLIBRARIES) - @$(NORMAL_INSTALL) - @list='$(nobase_pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ - fi; \ - for p in $$list; do if test -f "$$p"; then echo "$$p $$p"; else :; fi; done | \ - sed '/ .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { cur = "." } \ - { if ($$2 == cur) { files = files " " $$1 } \ - else { print cur, files; files = $$1; cur = $$2 } } \ - END { print cur, files }' | \ - while read dir files; do \ - test -z "$$files" || { \ - test "x$$dir" = x. || { \ - echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)/$$dir'"; \ - $(MKDIR_P) "$(DESTDIR)$(pkglibdir)/$$dir"; }; \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$files '$(DESTDIR)$(pkglibdir)/$$dir'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$files "$(DESTDIR)$(pkglibdir)/$$dir" || exit $$?; \ - }; \ - done - -uninstall-nobase_pkglibLTLIBRARIES: - @$(NORMAL_UNINSTALL) - @list='$(nobase_pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ - for p in $$list; do \ - f=$$p; \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ - done - -clean-nobase_pkglibLTLIBRARIES: - -test -z "$(nobase_pkglib_LTLIBRARIES)" || rm -f $(nobase_pkglib_LTLIBRARIES) - @list='$(nobase_pkglib_LTLIBRARIES)'; for p in $$list; do \ - dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ - test "$$dir" != "$$p" || dir=.; \ - echo "rm -f \"$${dir}/so_locations\""; \ - rm -f "$${dir}/so_locations"; \ - done -cli/cls/$(am__dirstamp): - @$(MKDIR_P) cli/cls - @: > cli/cls/$(am__dirstamp) -cli/cls/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) cli/cls/$(DEPDIR) - @: > cli/cls/$(DEPDIR)/$(am__dirstamp) -cli/cls/basic.lo: cli/cls/$(am__dirstamp) \ - cli/cls/$(DEPDIR)/$(am__dirstamp) -cli/cls/basic.la: $(cli_cls_basic_la_OBJECTS) $(cli_cls_basic_la_DEPENDENCIES) $(EXTRA_cli_cls_basic_la_DEPENDENCIES) cli/cls/$(am__dirstamp) - $(AM_V_CCLD)$(cli_cls_basic_la_LINK) $(am_cli_cls_basic_la_rpath) $(cli_cls_basic_la_OBJECTS) $(cli_cls_basic_la_LIBADD) $(LIBS) -cli/cls/cgroup.lo: cli/cls/$(am__dirstamp) \ - cli/cls/$(DEPDIR)/$(am__dirstamp) -cli/cls/cgroup.la: $(cli_cls_cgroup_la_OBJECTS) $(cli_cls_cgroup_la_DEPENDENCIES) $(EXTRA_cli_cls_cgroup_la_DEPENDENCIES) cli/cls/$(am__dirstamp) - $(AM_V_CCLD)$(cli_cls_cgroup_la_LINK) $(am_cli_cls_cgroup_la_rpath) $(cli_cls_cgroup_la_OBJECTS) $(cli_cls_cgroup_la_LIBADD) $(LIBS) -cli/qdisc/$(am__dirstamp): - @$(MKDIR_P) cli/qdisc - @: > cli/qdisc/$(am__dirstamp) -cli/qdisc/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) cli/qdisc/$(DEPDIR) - @: > cli/qdisc/$(DEPDIR)/$(am__dirstamp) -cli/qdisc/bfifo.lo: cli/qdisc/$(am__dirstamp) \ - cli/qdisc/$(DEPDIR)/$(am__dirstamp) -cli/qdisc/bfifo.la: $(cli_qdisc_bfifo_la_OBJECTS) $(cli_qdisc_bfifo_la_DEPENDENCIES) $(EXTRA_cli_qdisc_bfifo_la_DEPENDENCIES) cli/qdisc/$(am__dirstamp) - $(AM_V_CCLD)$(cli_qdisc_bfifo_la_LINK) $(am_cli_qdisc_bfifo_la_rpath) $(cli_qdisc_bfifo_la_OBJECTS) $(cli_qdisc_bfifo_la_LIBADD) $(LIBS) -cli/qdisc/blackhole.lo: cli/qdisc/$(am__dirstamp) \ - cli/qdisc/$(DEPDIR)/$(am__dirstamp) -cli/qdisc/blackhole.la: $(cli_qdisc_blackhole_la_OBJECTS) $(cli_qdisc_blackhole_la_DEPENDENCIES) $(EXTRA_cli_qdisc_blackhole_la_DEPENDENCIES) cli/qdisc/$(am__dirstamp) - $(AM_V_CCLD)$(cli_qdisc_blackhole_la_LINK) $(am_cli_qdisc_blackhole_la_rpath) $(cli_qdisc_blackhole_la_OBJECTS) $(cli_qdisc_blackhole_la_LIBADD) $(LIBS) -cli/qdisc/htb.lo: cli/qdisc/$(am__dirstamp) \ - cli/qdisc/$(DEPDIR)/$(am__dirstamp) -cli/qdisc/htb.la: $(cli_qdisc_htb_la_OBJECTS) $(cli_qdisc_htb_la_DEPENDENCIES) $(EXTRA_cli_qdisc_htb_la_DEPENDENCIES) cli/qdisc/$(am__dirstamp) - $(AM_V_CCLD)$(cli_qdisc_htb_la_LINK) $(am_cli_qdisc_htb_la_rpath) $(cli_qdisc_htb_la_OBJECTS) $(cli_qdisc_htb_la_LIBADD) $(LIBS) -cli/qdisc/pfifo.lo: cli/qdisc/$(am__dirstamp) \ - cli/qdisc/$(DEPDIR)/$(am__dirstamp) -cli/qdisc/pfifo.la: $(cli_qdisc_pfifo_la_OBJECTS) $(cli_qdisc_pfifo_la_DEPENDENCIES) $(EXTRA_cli_qdisc_pfifo_la_DEPENDENCIES) cli/qdisc/$(am__dirstamp) - $(AM_V_CCLD)$(cli_qdisc_pfifo_la_LINK) $(am_cli_qdisc_pfifo_la_rpath) $(cli_qdisc_pfifo_la_OBJECTS) $(cli_qdisc_pfifo_la_LIBADD) $(LIBS) -cli/qdisc/plug.lo: cli/qdisc/$(am__dirstamp) \ - cli/qdisc/$(DEPDIR)/$(am__dirstamp) -cli/qdisc/plug.la: $(cli_qdisc_plug_la_OBJECTS) $(cli_qdisc_plug_la_DEPENDENCIES) $(EXTRA_cli_qdisc_plug_la_DEPENDENCIES) cli/qdisc/$(am__dirstamp) - $(AM_V_CCLD)$(cli_qdisc_plug_la_LINK) $(am_cli_qdisc_plug_la_rpath) $(cli_qdisc_plug_la_OBJECTS) $(cli_qdisc_plug_la_LIBADD) $(LIBS) -libnl-3.la: $(libnl_3_la_OBJECTS) $(libnl_3_la_DEPENDENCIES) $(EXTRA_libnl_3_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) -rpath $(libdir) $(libnl_3_la_OBJECTS) $(libnl_3_la_LIBADD) $(LIBS) -genl/$(am__dirstamp): - @$(MKDIR_P) genl - @: > genl/$(am__dirstamp) -genl/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) genl/$(DEPDIR) - @: > genl/$(DEPDIR)/$(am__dirstamp) -genl/ctrl.lo: genl/$(am__dirstamp) genl/$(DEPDIR)/$(am__dirstamp) -genl/family.lo: genl/$(am__dirstamp) genl/$(DEPDIR)/$(am__dirstamp) -genl/genl.lo: genl/$(am__dirstamp) genl/$(DEPDIR)/$(am__dirstamp) -genl/mngt.lo: genl/$(am__dirstamp) genl/$(DEPDIR)/$(am__dirstamp) -libnl-genl-3.la: $(libnl_genl_3_la_OBJECTS) $(libnl_genl_3_la_DEPENDENCIES) $(EXTRA_libnl_genl_3_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) -rpath $(libdir) $(libnl_genl_3_la_OBJECTS) $(libnl_genl_3_la_LIBADD) $(LIBS) -netfilter/$(am__dirstamp): - @$(MKDIR_P) netfilter - @: > netfilter/$(am__dirstamp) -netfilter/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) netfilter/$(DEPDIR) - @: > netfilter/$(DEPDIR)/$(am__dirstamp) -netfilter/ct.lo: netfilter/$(am__dirstamp) \ - netfilter/$(DEPDIR)/$(am__dirstamp) -netfilter/ct_obj.lo: netfilter/$(am__dirstamp) \ - netfilter/$(DEPDIR)/$(am__dirstamp) -netfilter/log.lo: netfilter/$(am__dirstamp) \ - netfilter/$(DEPDIR)/$(am__dirstamp) -netfilter/log_msg.lo: netfilter/$(am__dirstamp) \ - netfilter/$(DEPDIR)/$(am__dirstamp) -netfilter/log_msg_obj.lo: netfilter/$(am__dirstamp) \ - netfilter/$(DEPDIR)/$(am__dirstamp) -netfilter/log_obj.lo: netfilter/$(am__dirstamp) \ - netfilter/$(DEPDIR)/$(am__dirstamp) -netfilter/netfilter.lo: netfilter/$(am__dirstamp) \ - netfilter/$(DEPDIR)/$(am__dirstamp) -netfilter/nfnl.lo: netfilter/$(am__dirstamp) \ - netfilter/$(DEPDIR)/$(am__dirstamp) -netfilter/queue.lo: netfilter/$(am__dirstamp) \ - netfilter/$(DEPDIR)/$(am__dirstamp) -netfilter/queue_msg.lo: netfilter/$(am__dirstamp) \ - netfilter/$(DEPDIR)/$(am__dirstamp) -netfilter/queue_msg_obj.lo: netfilter/$(am__dirstamp) \ - netfilter/$(DEPDIR)/$(am__dirstamp) -netfilter/queue_obj.lo: netfilter/$(am__dirstamp) \ - netfilter/$(DEPDIR)/$(am__dirstamp) -netfilter/exp.lo: netfilter/$(am__dirstamp) \ - netfilter/$(DEPDIR)/$(am__dirstamp) -netfilter/exp_obj.lo: netfilter/$(am__dirstamp) \ - netfilter/$(DEPDIR)/$(am__dirstamp) -libnl-nf-3.la: $(libnl_nf_3_la_OBJECTS) $(libnl_nf_3_la_DEPENDENCIES) $(EXTRA_libnl_nf_3_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) -rpath $(libdir) $(libnl_nf_3_la_OBJECTS) $(libnl_nf_3_la_LIBADD) $(LIBS) -route/$(am__dirstamp): - @$(MKDIR_P) route - @: > route/$(am__dirstamp) -route/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) route/$(DEPDIR) - @: > route/$(DEPDIR)/$(am__dirstamp) -route/addr.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) -route/class.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) -route/cls.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) -route/link.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) -route/neigh.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) -route/neightbl.lo: route/$(am__dirstamp) \ - route/$(DEPDIR)/$(am__dirstamp) -route/nexthop.lo: route/$(am__dirstamp) \ - route/$(DEPDIR)/$(am__dirstamp) -route/qdisc.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) -route/route.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) -route/route_obj.lo: route/$(am__dirstamp) \ - route/$(DEPDIR)/$(am__dirstamp) -route/route_utils.lo: route/$(am__dirstamp) \ - route/$(DEPDIR)/$(am__dirstamp) -route/rtnl.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) -route/rule.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) -route/tc.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) -route/classid.lo: route/$(am__dirstamp) \ - route/$(DEPDIR)/$(am__dirstamp) -route/cls/$(am__dirstamp): - @$(MKDIR_P) route/cls - @: > route/cls/$(am__dirstamp) -route/cls/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) route/cls/$(DEPDIR) - @: > route/cls/$(DEPDIR)/$(am__dirstamp) -route/cls/fw.lo: route/cls/$(am__dirstamp) \ - route/cls/$(DEPDIR)/$(am__dirstamp) -route/cls/police.lo: route/cls/$(am__dirstamp) \ - route/cls/$(DEPDIR)/$(am__dirstamp) -route/cls/u32.lo: route/cls/$(am__dirstamp) \ - route/cls/$(DEPDIR)/$(am__dirstamp) -route/cls/basic.lo: route/cls/$(am__dirstamp) \ - route/cls/$(DEPDIR)/$(am__dirstamp) -route/cls/cgroup.lo: route/cls/$(am__dirstamp) \ - route/cls/$(DEPDIR)/$(am__dirstamp) -route/cls/ematch.lo: route/cls/$(am__dirstamp) \ - route/cls/$(DEPDIR)/$(am__dirstamp) -route/cls/ematch/$(am__dirstamp): - @$(MKDIR_P) route/cls/ematch - @: > route/cls/ematch/$(am__dirstamp) -route/cls/ematch/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) route/cls/ematch/$(DEPDIR) - @: > route/cls/ematch/$(DEPDIR)/$(am__dirstamp) -route/cls/ematch/container.lo: route/cls/ematch/$(am__dirstamp) \ - route/cls/ematch/$(DEPDIR)/$(am__dirstamp) -route/cls/ematch/cmp.lo: route/cls/ematch/$(am__dirstamp) \ - route/cls/ematch/$(DEPDIR)/$(am__dirstamp) -route/cls/ematch/nbyte.lo: route/cls/ematch/$(am__dirstamp) \ - route/cls/ematch/$(DEPDIR)/$(am__dirstamp) -route/cls/ematch/text.lo: route/cls/ematch/$(am__dirstamp) \ - route/cls/ematch/$(DEPDIR)/$(am__dirstamp) -route/cls/ematch/meta.lo: route/cls/ematch/$(am__dirstamp) \ - route/cls/ematch/$(DEPDIR)/$(am__dirstamp) -route/link/$(am__dirstamp): - @$(MKDIR_P) route/link - @: > route/link/$(am__dirstamp) -route/link/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) route/link/$(DEPDIR) - @: > route/link/$(DEPDIR)/$(am__dirstamp) -route/link/api.lo: route/link/$(am__dirstamp) \ - route/link/$(DEPDIR)/$(am__dirstamp) -route/link/vlan.lo: route/link/$(am__dirstamp) \ - route/link/$(DEPDIR)/$(am__dirstamp) -route/link/dummy.lo: route/link/$(am__dirstamp) \ - route/link/$(DEPDIR)/$(am__dirstamp) -route/link/bridge.lo: route/link/$(am__dirstamp) \ - route/link/$(DEPDIR)/$(am__dirstamp) -route/link/inet6.lo: route/link/$(am__dirstamp) \ - route/link/$(DEPDIR)/$(am__dirstamp) -route/link/inet.lo: route/link/$(am__dirstamp) \ - route/link/$(DEPDIR)/$(am__dirstamp) -route/link/bonding.lo: route/link/$(am__dirstamp) \ - route/link/$(DEPDIR)/$(am__dirstamp) -route/link/can.lo: route/link/$(am__dirstamp) \ - route/link/$(DEPDIR)/$(am__dirstamp) -route/qdisc/$(am__dirstamp): - @$(MKDIR_P) route/qdisc - @: > route/qdisc/$(am__dirstamp) -route/qdisc/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) route/qdisc/$(DEPDIR) - @: > route/qdisc/$(DEPDIR)/$(am__dirstamp) -route/qdisc/blackhole.lo: route/qdisc/$(am__dirstamp) \ - route/qdisc/$(DEPDIR)/$(am__dirstamp) -route/qdisc/cbq.lo: route/qdisc/$(am__dirstamp) \ - route/qdisc/$(DEPDIR)/$(am__dirstamp) -route/qdisc/dsmark.lo: route/qdisc/$(am__dirstamp) \ - route/qdisc/$(DEPDIR)/$(am__dirstamp) -route/qdisc/fifo.lo: route/qdisc/$(am__dirstamp) \ - route/qdisc/$(DEPDIR)/$(am__dirstamp) -route/qdisc/htb.lo: route/qdisc/$(am__dirstamp) \ - route/qdisc/$(DEPDIR)/$(am__dirstamp) -route/qdisc/netem.lo: route/qdisc/$(am__dirstamp) \ - route/qdisc/$(DEPDIR)/$(am__dirstamp) -route/qdisc/prio.lo: route/qdisc/$(am__dirstamp) \ - route/qdisc/$(DEPDIR)/$(am__dirstamp) -route/qdisc/red.lo: route/qdisc/$(am__dirstamp) \ - route/qdisc/$(DEPDIR)/$(am__dirstamp) -route/qdisc/sfq.lo: route/qdisc/$(am__dirstamp) \ - route/qdisc/$(DEPDIR)/$(am__dirstamp) -route/qdisc/tbf.lo: route/qdisc/$(am__dirstamp) \ - route/qdisc/$(DEPDIR)/$(am__dirstamp) -route/qdisc/plug.lo: route/qdisc/$(am__dirstamp) \ - route/qdisc/$(DEPDIR)/$(am__dirstamp) -fib_lookup/$(am__dirstamp): - @$(MKDIR_P) fib_lookup - @: > fib_lookup/$(am__dirstamp) -fib_lookup/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) fib_lookup/$(DEPDIR) - @: > fib_lookup/$(DEPDIR)/$(am__dirstamp) -fib_lookup/lookup.lo: fib_lookup/$(am__dirstamp) \ - fib_lookup/$(DEPDIR)/$(am__dirstamp) -fib_lookup/request.lo: fib_lookup/$(am__dirstamp) \ - fib_lookup/$(DEPDIR)/$(am__dirstamp) -route/pktloc.lo: route/$(am__dirstamp) route/$(DEPDIR)/$(am__dirstamp) -route/pktloc_syntax.lo: route/$(am__dirstamp) \ - route/$(DEPDIR)/$(am__dirstamp) -route/pktloc_grammar.lo: route/$(am__dirstamp) \ - route/$(DEPDIR)/$(am__dirstamp) -route/cls/ematch_syntax.lo: route/cls/$(am__dirstamp) \ - route/cls/$(DEPDIR)/$(am__dirstamp) -route/cls/ematch_grammar.lo: route/cls/$(am__dirstamp) \ - route/cls/$(DEPDIR)/$(am__dirstamp) -libnl-route-3.la: $(libnl_route_3_la_OBJECTS) $(libnl_route_3_la_DEPENDENCIES) $(EXTRA_libnl_route_3_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) -rpath $(libdir) $(libnl_route_3_la_OBJECTS) $(libnl_route_3_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -rm -f cli/cls/basic.$(OBJEXT) - -rm -f cli/cls/basic.lo - -rm -f cli/cls/cgroup.$(OBJEXT) - -rm -f cli/cls/cgroup.lo - -rm -f cli/qdisc/bfifo.$(OBJEXT) - -rm -f cli/qdisc/bfifo.lo - -rm -f cli/qdisc/blackhole.$(OBJEXT) - -rm -f cli/qdisc/blackhole.lo - -rm -f cli/qdisc/htb.$(OBJEXT) - -rm -f cli/qdisc/htb.lo - -rm -f cli/qdisc/pfifo.$(OBJEXT) - -rm -f cli/qdisc/pfifo.lo - -rm -f cli/qdisc/plug.$(OBJEXT) - -rm -f cli/qdisc/plug.lo - -rm -f fib_lookup/lookup.$(OBJEXT) - -rm -f fib_lookup/lookup.lo - -rm -f fib_lookup/request.$(OBJEXT) - -rm -f fib_lookup/request.lo - -rm -f genl/ctrl.$(OBJEXT) - -rm -f genl/ctrl.lo - -rm -f genl/family.$(OBJEXT) - -rm -f genl/family.lo - -rm -f genl/genl.$(OBJEXT) - -rm -f genl/genl.lo - -rm -f genl/mngt.$(OBJEXT) - -rm -f genl/mngt.lo - -rm -f netfilter/ct.$(OBJEXT) - -rm -f netfilter/ct.lo - -rm -f netfilter/ct_obj.$(OBJEXT) - -rm -f netfilter/ct_obj.lo - -rm -f netfilter/exp.$(OBJEXT) - -rm -f netfilter/exp.lo - -rm -f netfilter/exp_obj.$(OBJEXT) - -rm -f netfilter/exp_obj.lo - -rm -f netfilter/log.$(OBJEXT) - -rm -f netfilter/log.lo - -rm -f netfilter/log_msg.$(OBJEXT) - -rm -f netfilter/log_msg.lo - -rm -f netfilter/log_msg_obj.$(OBJEXT) - -rm -f netfilter/log_msg_obj.lo - -rm -f netfilter/log_obj.$(OBJEXT) - -rm -f netfilter/log_obj.lo - -rm -f netfilter/netfilter.$(OBJEXT) - -rm -f netfilter/netfilter.lo - -rm -f netfilter/nfnl.$(OBJEXT) - -rm -f netfilter/nfnl.lo - -rm -f netfilter/queue.$(OBJEXT) - -rm -f netfilter/queue.lo - -rm -f netfilter/queue_msg.$(OBJEXT) - -rm -f netfilter/queue_msg.lo - -rm -f netfilter/queue_msg_obj.$(OBJEXT) - -rm -f netfilter/queue_msg_obj.lo - -rm -f netfilter/queue_obj.$(OBJEXT) - -rm -f netfilter/queue_obj.lo - -rm -f route/addr.$(OBJEXT) - -rm -f route/addr.lo - -rm -f route/class.$(OBJEXT) - -rm -f route/class.lo - -rm -f route/classid.$(OBJEXT) - -rm -f route/classid.lo - -rm -f route/cls.$(OBJEXT) - -rm -f route/cls.lo - -rm -f route/cls/basic.$(OBJEXT) - -rm -f route/cls/basic.lo - -rm -f route/cls/cgroup.$(OBJEXT) - -rm -f route/cls/cgroup.lo - -rm -f route/cls/ematch.$(OBJEXT) - -rm -f route/cls/ematch.lo - -rm -f route/cls/ematch/cmp.$(OBJEXT) - -rm -f route/cls/ematch/cmp.lo - -rm -f route/cls/ematch/container.$(OBJEXT) - -rm -f route/cls/ematch/container.lo - -rm -f route/cls/ematch/meta.$(OBJEXT) - -rm -f route/cls/ematch/meta.lo - -rm -f route/cls/ematch/nbyte.$(OBJEXT) - -rm -f route/cls/ematch/nbyte.lo - -rm -f route/cls/ematch/text.$(OBJEXT) - -rm -f route/cls/ematch/text.lo - -rm -f route/cls/ematch_grammar.$(OBJEXT) - -rm -f route/cls/ematch_grammar.lo - -rm -f route/cls/ematch_syntax.$(OBJEXT) - -rm -f route/cls/ematch_syntax.lo - -rm -f route/cls/fw.$(OBJEXT) - -rm -f route/cls/fw.lo - -rm -f route/cls/police.$(OBJEXT) - -rm -f route/cls/police.lo - -rm -f route/cls/u32.$(OBJEXT) - -rm -f route/cls/u32.lo - -rm -f route/link.$(OBJEXT) - -rm -f route/link.lo - -rm -f route/link/api.$(OBJEXT) - -rm -f route/link/api.lo - -rm -f route/link/bonding.$(OBJEXT) - -rm -f route/link/bonding.lo - -rm -f route/link/bridge.$(OBJEXT) - -rm -f route/link/bridge.lo - -rm -f route/link/can.$(OBJEXT) - -rm -f route/link/can.lo - -rm -f route/link/dummy.$(OBJEXT) - -rm -f route/link/dummy.lo - -rm -f route/link/inet.$(OBJEXT) - -rm -f route/link/inet.lo - -rm -f route/link/inet6.$(OBJEXT) - -rm -f route/link/inet6.lo - -rm -f route/link/vlan.$(OBJEXT) - -rm -f route/link/vlan.lo - -rm -f route/neigh.$(OBJEXT) - -rm -f route/neigh.lo - -rm -f route/neightbl.$(OBJEXT) - -rm -f route/neightbl.lo - -rm -f route/nexthop.$(OBJEXT) - -rm -f route/nexthop.lo - -rm -f route/pktloc.$(OBJEXT) - -rm -f route/pktloc.lo - -rm -f route/pktloc_grammar.$(OBJEXT) - -rm -f route/pktloc_grammar.lo - -rm -f route/pktloc_syntax.$(OBJEXT) - -rm -f route/pktloc_syntax.lo - -rm -f route/qdisc.$(OBJEXT) - -rm -f route/qdisc.lo - -rm -f route/qdisc/blackhole.$(OBJEXT) - -rm -f route/qdisc/blackhole.lo - -rm -f route/qdisc/cbq.$(OBJEXT) - -rm -f route/qdisc/cbq.lo - -rm -f route/qdisc/dsmark.$(OBJEXT) - -rm -f route/qdisc/dsmark.lo - -rm -f route/qdisc/fifo.$(OBJEXT) - -rm -f route/qdisc/fifo.lo - -rm -f route/qdisc/htb.$(OBJEXT) - -rm -f route/qdisc/htb.lo - -rm -f route/qdisc/netem.$(OBJEXT) - -rm -f route/qdisc/netem.lo - -rm -f route/qdisc/plug.$(OBJEXT) - -rm -f route/qdisc/plug.lo - -rm -f route/qdisc/prio.$(OBJEXT) - -rm -f route/qdisc/prio.lo - -rm -f route/qdisc/red.$(OBJEXT) - -rm -f route/qdisc/red.lo - -rm -f route/qdisc/sfq.$(OBJEXT) - -rm -f route/qdisc/sfq.lo - -rm -f route/qdisc/tbf.$(OBJEXT) - -rm -f route/qdisc/tbf.lo - -rm -f route/route.$(OBJEXT) - -rm -f route/route.lo - -rm -f route/route_obj.$(OBJEXT) - -rm -f route/route_obj.lo - -rm -f route/route_utils.$(OBJEXT) - -rm -f route/route_utils.lo - -rm -f route/rtnl.$(OBJEXT) - -rm -f route/rtnl.lo - -rm -f route/rule.$(OBJEXT) - -rm -f route/rule.lo - -rm -f route/tc.$(OBJEXT) - -rm -f route/tc.lo - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addr.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attr.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cache.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cache_mngr.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cache_mngt.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/data.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/handlers.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hashtable.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@cli/cls/$(DEPDIR)/basic.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@cli/cls/$(DEPDIR)/cgroup.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@cli/qdisc/$(DEPDIR)/bfifo.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@cli/qdisc/$(DEPDIR)/blackhole.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@cli/qdisc/$(DEPDIR)/htb.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@cli/qdisc/$(DEPDIR)/pfifo.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@cli/qdisc/$(DEPDIR)/plug.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@fib_lookup/$(DEPDIR)/lookup.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@fib_lookup/$(DEPDIR)/request.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@genl/$(DEPDIR)/ctrl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@genl/$(DEPDIR)/family.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@genl/$(DEPDIR)/genl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@genl/$(DEPDIR)/mngt.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/ct.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/ct_obj.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/exp.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/exp_obj.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/log.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/log_msg.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/log_msg_obj.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/log_obj.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/netfilter.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/nfnl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/queue.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/queue_msg.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/queue_msg_obj.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@netfilter/$(DEPDIR)/queue_obj.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/addr.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/class.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/classid.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/cls.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/link.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/neigh.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/neightbl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/nexthop.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/pktloc.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/pktloc_grammar.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/pktloc_syntax.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/qdisc.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/route.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/route_obj.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/route_utils.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/rtnl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/rule.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/$(DEPDIR)/tc.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/cls/$(DEPDIR)/basic.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/cls/$(DEPDIR)/cgroup.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/cls/$(DEPDIR)/ematch.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/cls/$(DEPDIR)/ematch_grammar.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/cls/$(DEPDIR)/ematch_syntax.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/cls/$(DEPDIR)/fw.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/cls/$(DEPDIR)/police.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/cls/$(DEPDIR)/u32.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/cls/ematch/$(DEPDIR)/cmp.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/cls/ematch/$(DEPDIR)/container.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/cls/ematch/$(DEPDIR)/meta.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/cls/ematch/$(DEPDIR)/nbyte.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/cls/ematch/$(DEPDIR)/text.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/link/$(DEPDIR)/api.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/link/$(DEPDIR)/bonding.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/link/$(DEPDIR)/bridge.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/link/$(DEPDIR)/can.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/link/$(DEPDIR)/dummy.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/link/$(DEPDIR)/inet.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/link/$(DEPDIR)/inet6.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/link/$(DEPDIR)/vlan.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/blackhole.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/cbq.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/dsmark.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/fifo.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/htb.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/netem.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/plug.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/prio.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/red.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/sfq.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@route/qdisc/$(DEPDIR)/tbf.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ -@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ -@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -rm -rf cli/cls/.libs cli/cls/_libs - -rm -rf cli/qdisc/.libs cli/qdisc/_libs - -rm -rf fib_lookup/.libs fib_lookup/_libs - -rm -rf genl/.libs genl/_libs - -rm -rf netfilter/.libs netfilter/_libs - -rm -rf route/.libs route/_libs - -rm -rf route/cls/.libs route/cls/_libs - -rm -rf route/cls/ematch/.libs route/cls/ematch/_libs - -rm -rf route/link/.libs route/link/_libs - -rm -rf route/qdisc/.libs route/qdisc/_libs - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) defs.h.in $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - set x; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) defs.h.in $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) defs.h.in $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) defs.h.in $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) check-am -all-am: Makefile $(LTLIBRARIES) defs.h -installdirs: - for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkglibdir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -rm -f cli/cls/$(DEPDIR)/$(am__dirstamp) - -rm -f cli/cls/$(am__dirstamp) - -rm -f cli/qdisc/$(DEPDIR)/$(am__dirstamp) - -rm -f cli/qdisc/$(am__dirstamp) - -rm -f fib_lookup/$(DEPDIR)/$(am__dirstamp) - -rm -f fib_lookup/$(am__dirstamp) - -rm -f genl/$(DEPDIR)/$(am__dirstamp) - -rm -f genl/$(am__dirstamp) - -rm -f netfilter/$(DEPDIR)/$(am__dirstamp) - -rm -f netfilter/$(am__dirstamp) - -rm -f route/$(DEPDIR)/$(am__dirstamp) - -rm -f route/$(am__dirstamp) - -rm -f route/cls/$(DEPDIR)/$(am__dirstamp) - -rm -f route/cls/$(am__dirstamp) - -rm -f route/cls/ematch/$(DEPDIR)/$(am__dirstamp) - -rm -f route/cls/ematch/$(am__dirstamp) - -rm -f route/link/$(DEPDIR)/$(am__dirstamp) - -rm -f route/link/$(am__dirstamp) - -rm -f route/qdisc/$(DEPDIR)/$(am__dirstamp) - -rm -f route/qdisc/$(am__dirstamp) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." - -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) -clean: clean-am - -clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ - clean-nobase_pkglibLTLIBRARIES mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) cli/cls/$(DEPDIR) cli/qdisc/$(DEPDIR) fib_lookup/$(DEPDIR) genl/$(DEPDIR) netfilter/$(DEPDIR) route/$(DEPDIR) route/cls/$(DEPDIR) route/cls/ematch/$(DEPDIR) route/link/$(DEPDIR) route/qdisc/$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-hdr distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: install-libLTLIBRARIES \ - install-nobase_pkglibLTLIBRARIES - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) cli/cls/$(DEPDIR) cli/qdisc/$(DEPDIR) fib_lookup/$(DEPDIR) genl/$(DEPDIR) netfilter/$(DEPDIR) route/$(DEPDIR) route/cls/$(DEPDIR) route/cls/ematch/$(DEPDIR) route/link/$(DEPDIR) route/qdisc/$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-libLTLIBRARIES \ - uninstall-nobase_pkglibLTLIBRARIES - -.MAKE: all check install install-am install-strip - -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ - clean-libLTLIBRARIES clean-libtool \ - clean-nobase_pkglibLTLIBRARIES ctags distclean \ - distclean-compile distclean-generic distclean-hdr \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-libLTLIBRARIES install-man \ - install-nobase_pkglibLTLIBRARIES install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags uninstall uninstall-am uninstall-libLTLIBRARIES \ - uninstall-nobase_pkglibLTLIBRARIES - - -# Hack to avoid using ylwrap. It does not function correctly in combination -# with --header-file= -route/pktloc_grammar.c: route/pktloc_grammar.l - $(AM_V_GEN) $(FLEX) --header-file=route/pktloc_grammar.h $(LFLAGS) -o $@ $^ - -route/pktloc_syntax.c: route/pktloc_syntax.y - $(AM_V_GEN) $(YACC) -d $(YFLAGS) -o $@ $^ - -route/cls/ematch_grammar.c: route/cls/ematch_grammar.l - $(AM_V_GEN) $(FLEX) --header-file=route/cls/ematch_grammar.h $(LFLAGS) -o $@ $^ - -route/cls/ematch_syntax.c: route/cls/ematch_syntax.y - $(AM_V_GEN) $(YACC) -d $(YFLAGS) -o $@ $^ - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/lib/addr.c b/lib/addr.c index 86e7e58..89a3b38 100644 --- a/lib/addr.c +++ b/lib/addr.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/addr.c Network Address - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2013 Thomas Graf */ @@ -27,11 +21,17 @@ * ~~~~ */ -#include +#include "nl-default.h" + +#include + #include #include #include -#include +#include + +#include "mpls.h" +#include "nl-priv-dynamic-core/nl-core.h" /* All this DECnet stuff is stolen from iproute2, thanks to whoever wrote * this, probably Alexey. */ @@ -65,7 +65,7 @@ static inline int do_digit(char *str, uint16_t *addr, uint16_t scale, return 0; } -static const char *dnet_ntop(char *addrbuf, size_t addrlen, char *str, +static const char *dnet_ntop(const char *addrbuf, size_t addrlen, char *str, size_t len) { uint16_t addr = dn_ntohs(*(uint16_t *)addrbuf); @@ -213,7 +213,7 @@ struct nl_addr *nl_addr_alloc(size_t maxsize) * * @return Allocated address object or NULL upon failure. */ -struct nl_addr *nl_addr_build(int family, void *buf, size_t size) +struct nl_addr *nl_addr_build(int family, const void *buf, size_t size) { struct nl_addr *addr; @@ -223,9 +223,15 @@ struct nl_addr *nl_addr_build(int family, void *buf, size_t size) addr->a_family = family; addr->a_len = size; - addr->a_prefixlen = size*8; + switch(family) { + case AF_MPLS: + addr->a_prefixlen = 20; /* MPLS address is a 20-bit label */ + break; + default: + addr->a_prefixlen = size*8; + } - if (size) + if (size && buf) memcpy(addr->a_addr, buf, size); return addr; @@ -252,7 +258,7 @@ struct nl_addr *nl_addr_build(int family, void *buf, size_t size) * * @return Allocated address object or NULL upon failure. */ -struct nl_addr *nl_addr_alloc_attr(struct nlattr *nla, int family) +struct nl_addr *nl_addr_alloc_attr(const struct nlattr *nla, int family) { return nl_addr_build(family, nla_data(nla), nla_len(nla)); } @@ -290,8 +296,8 @@ struct nl_addr *nl_addr_alloc_attr(struct nlattr *nla, int family) */ int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result) { - int err, copy = 0, len = 0, family = AF_UNSPEC; - char *str, *prefix, buf[32]; + int err, copy = 0, len = 0, family = AF_UNSPEC, plen = 0; + char *str, *prefix = NULL, buf[256]; struct nl_addr *addr = NULL; /* gcc ain't that smart */ str = strdup(addrstr); @@ -300,9 +306,11 @@ int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result) goto errout; } - prefix = strchr(str, '/'); - if (prefix) - *prefix = '\0'; + if (hint != AF_MPLS) { + prefix = strchr(str, '/'); + if (prefix) + *prefix = '\0'; + } if (!strcasecmp(str, "none")) { family = hint; @@ -313,8 +321,6 @@ int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result) !strcasecmp(str, "all") || !strcasecmp(str, "any")) { - len = 0; - switch (hint) { case AF_INET: case AF_UNSPEC: @@ -322,14 +328,17 @@ int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result) * no hint given the user wants to have a IPv4 * address given back. */ family = AF_INET; + len = 4; goto prefix; case AF_INET6: family = AF_INET6; + len = 16; goto prefix; case AF_LLC: family = AF_LLC; + len = 6; goto prefix; default: @@ -399,6 +408,17 @@ int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result) } } + if (hint == AF_MPLS) { + len = mpls_pton(AF_MPLS, str, buf, sizeof(buf)); + if (len <= 0) { + err = -NLE_INVAL; + goto errout; + } + family = AF_MPLS; + plen = 20; + goto prefix; + } + if (hint == AF_UNSPEC && strchr(str, ':')) { size_t i = 0; char *s = str, *p; @@ -435,6 +455,8 @@ prefix: if (copy) nl_addr_set_binary_addr(addr, buf, len); + else + addr->a_len = len; if (prefix) { char *p; @@ -445,9 +467,11 @@ prefix: goto errout; } nl_addr_set_prefixlen(addr, pl); - } else - nl_addr_set_prefixlen(addr, len * 8); - + } else { + if (copy && !plen) + plen = len * 8; + nl_addr_set_prefixlen(addr, plen); + } *result = addr; err = 0; errout: @@ -468,7 +492,7 @@ errout: * * @return Allocated abstract address or NULL upon failure. */ -struct nl_addr *nl_addr_clone(struct nl_addr *addr) +struct nl_addr *nl_addr_clone(const struct nl_addr *addr) { struct nl_addr *new; @@ -531,7 +555,7 @@ void nl_addr_put(struct nl_addr *addr) * * @return Non-zero if the abstract address is shared, otherwise 0. */ -int nl_addr_shared(struct nl_addr *addr) +int nl_addr_shared(const struct nl_addr *addr) { return addr->a_refcnt > 1; } @@ -560,10 +584,18 @@ int nl_addr_shared(struct nl_addr *addr) * @return Integer less than, equal to or greather than zero if the two * addresses match. */ -int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b) +int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b) { - int d = a->a_family - b->a_family; + int d; + if (a == b) + return 0; + if (!a) + return -1; + if (!b) + return 1; + + d = a->a_family - b->a_family; if (d == 0) { d = a->a_len - b->a_len; @@ -591,12 +623,12 @@ int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b) * @return Integer less than, equal to or greather than zero if the two * addresses match. */ -int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b) +int nl_addr_cmp_prefix(const struct nl_addr *a, const struct nl_addr *b) { int d = a->a_family - b->a_family; if (d == 0) { - int len = min(a->a_prefixlen, b->a_prefixlen); + int len = _NL_MIN(a->a_prefixlen, b->a_prefixlen); int bytes = len / 8; d = memcmp(a->a_addr, b->a_addr, bytes); @@ -617,7 +649,7 @@ int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b) * * @return 1 if the binary address consists of all zeros, 0 otherwise. */ -int nl_addr_iszero(struct nl_addr *addr) +int nl_addr_iszero(const struct nl_addr *addr) { unsigned int i; @@ -636,10 +668,10 @@ int nl_addr_iszero(struct nl_addr *addr) * @return 1 if the address is parseable assuming the specified address family, * otherwise 0 is returned. */ -int nl_addr_valid(char *addr, int family) +int nl_addr_valid(const char *addr, int family) { int ret; - char buf[32]; + char buf[256]; /* MPLS has N-labels at 4-bytes / label */ switch (family) { case AF_INET: @@ -649,6 +681,12 @@ int nl_addr_valid(char *addr, int family) return 0; break; + case AF_MPLS: + ret = mpls_pton(family, addr, buf, sizeof(buf)); + if (ret <= 0) + return 0; + break; + case AF_DECnet: ret = dnet_pton(addr, buf); if (ret <= 0) @@ -670,7 +708,7 @@ int nl_addr_valid(char *addr, int family) * * @return Numeric address family or AF_UNSPEC */ -int nl_addr_guess_family(struct nl_addr *addr) +int nl_addr_guess_family(const struct nl_addr *addr) { switch (addr->a_len) { case 4: @@ -697,7 +735,7 @@ int nl_addr_guess_family(struct nl_addr *addr) * * @return 0 on success or a negative error code */ -int nl_addr_fill_sockaddr(struct nl_addr *addr, struct sockaddr *sa, +int nl_addr_fill_sockaddr(const struct nl_addr *addr, struct sockaddr *sa, socklen_t *salen) { switch (addr->a_family) { @@ -707,8 +745,14 @@ int nl_addr_fill_sockaddr(struct nl_addr *addr, struct sockaddr *sa, if (*salen < sizeof(*sai)) return -NLE_INVAL; + if (addr->a_len == 4) + memcpy(&sai->sin_addr, addr->a_addr, 4); + else if (addr->a_len != 0) + return -NLE_INVAL; + else + memset(&sai->sin_addr, 0, 4); + sai->sin_family = addr->a_family; - memcpy(&sai->sin_addr, addr->a_addr, 4); *salen = sizeof(*sai); } break; @@ -719,8 +763,14 @@ int nl_addr_fill_sockaddr(struct nl_addr *addr, struct sockaddr *sa, if (*salen < sizeof(*sa6)) return -NLE_INVAL; + if (addr->a_len == 16) + memcpy(&sa6->sin6_addr, addr->a_addr, 16); + else if (addr->a_len != 0) + return -NLE_INVAL; + else + memset(&sa6->sin6_addr, 0, 16); + sa6->sin6_family = addr->a_family; - memcpy(&sa6->sin6_addr, addr->a_addr, 16); *salen = sizeof(*sa6); } break; @@ -753,7 +803,7 @@ int nl_addr_fill_sockaddr(struct nl_addr *addr, struct sockaddr *sa, * * @return 0 on success or a negative error code. */ -int nl_addr_info(struct nl_addr *addr, struct addrinfo **result) +int nl_addr_info(const struct nl_addr *addr, struct addrinfo **result) { int err; char buf[INET6_ADDRSTRLEN+5]; @@ -797,7 +847,7 @@ int nl_addr_info(struct nl_addr *addr, struct addrinfo **result) * * @return 0 on success or a negative error code. */ -int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen) +int nl_addr_resolve(const struct nl_addr *addr, char *host, size_t hostlen) { int err; struct sockaddr_in6 buf; @@ -842,7 +892,7 @@ void nl_addr_set_family(struct nl_addr *addr, int family) * * @return The numeric address family or `AF_UNSPEC` */ -int nl_addr_get_family(struct nl_addr *addr) +int nl_addr_get_family(const struct nl_addr *addr) { return addr->a_family; } @@ -867,7 +917,7 @@ int nl_addr_get_family(struct nl_addr *addr) * * @return 0 on success or a negative error code. */ -int nl_addr_set_binary_addr(struct nl_addr *addr, void *buf, size_t len) +int nl_addr_set_binary_addr(struct nl_addr *addr, const void *buf, size_t len) { if (len > addr->a_maxsize) return -NLE_RANGE; @@ -890,9 +940,9 @@ int nl_addr_set_binary_addr(struct nl_addr *addr, void *buf, size_t len) * * @return Pointer to binary address of length nl_addr_get_len() */ -void *nl_addr_get_binary_addr(struct nl_addr *addr) +void *nl_addr_get_binary_addr(const struct nl_addr *addr) { - return addr->a_addr; + return (void*)addr->a_addr; } /** @@ -902,7 +952,7 @@ void *nl_addr_get_binary_addr(struct nl_addr *addr) * @see nl_addr_get_binary_addr() * @see nl_addr_set_binary_addr() */ -unsigned int nl_addr_get_len(struct nl_addr *addr) +unsigned int nl_addr_get_len(const struct nl_addr *addr) { return addr->a_len; } @@ -925,7 +975,7 @@ void nl_addr_set_prefixlen(struct nl_addr *addr, int prefixlen) * * @see nl_addr_set_prefixlen() */ -unsigned int nl_addr_get_prefixlen(struct nl_addr *addr) +unsigned int nl_addr_get_prefixlen(const struct nl_addr *addr) { return addr->a_prefixlen; } @@ -948,7 +998,7 @@ unsigned int nl_addr_get_prefixlen(struct nl_addr *addr) * * @return Address represented in ASCII stored in destination buffer. */ -char *nl_addr2str(struct nl_addr *addr, char *buf, size_t size) +char *nl_addr2str(const struct nl_addr *addr, char *buf, size_t size) { unsigned int i; char tmp[16]; @@ -970,6 +1020,10 @@ char *nl_addr2str(struct nl_addr *addr, char *buf, size_t size) inet_ntop(AF_INET6, addr->a_addr, buf, size); break; + case AF_MPLS: + mpls_ntop(AF_MPLS, addr->a_addr, buf, size); + break; + case AF_DECnet: dnet_ntop(addr->a_addr, addr->a_len, buf, size); break; @@ -987,7 +1041,8 @@ char *nl_addr2str(struct nl_addr *addr, char *buf, size_t size) } prefix: - if (addr->a_prefixlen != (8 * addr->a_len)) { + if (addr->a_family != AF_MPLS && + addr->a_prefixlen != (8 * addr->a_len)) { snprintf(tmp, sizeof(tmp), "/%u", addr->a_prefixlen); strncat(buf, tmp, size - strlen(buf) - 1); } @@ -1003,52 +1058,70 @@ prefix: */ static const struct trans_tbl afs[] = { - __ADD(AF_UNSPEC,unspec) - __ADD(AF_UNIX,unix) - __ADD(AF_INET,inet) - __ADD(AF_AX25,ax25) - __ADD(AF_IPX,ipx) - __ADD(AF_APPLETALK,appletalk) - __ADD(AF_NETROM,netrom) - __ADD(AF_BRIDGE,bridge) - __ADD(AF_ATMPVC,atmpvc) - __ADD(AF_X25,x25) - __ADD(AF_INET6,inet6) - __ADD(AF_ROSE,rose) - __ADD(AF_DECnet,decnet) - __ADD(AF_NETBEUI,netbeui) - __ADD(AF_SECURITY,security) - __ADD(AF_KEY,key) - __ADD(AF_NETLINK,netlink) - __ADD(AF_PACKET,packet) - __ADD(AF_ASH,ash) - __ADD(AF_ECONET,econet) - __ADD(AF_ATMSVC,atmsvc) - __ADD(AF_RDS,rds) - __ADD(AF_SNA,sna) - __ADD(AF_IRDA,irda) - __ADD(AF_PPPOX,pppox) - __ADD(AF_WANPIPE,wanpipe) - __ADD(AF_LLC,llc) - __ADD(AF_CAN,can) - __ADD(AF_TIPC,tipc) - __ADD(AF_BLUETOOTH,bluetooth) - __ADD(AF_IUCV,iucv) - __ADD(AF_RXRPC,rxrpc) - __ADD(AF_ISDN,isdn) - __ADD(AF_PHONET,phonet) + __ADD(AF_UNSPEC,unspec), + __ADD(AF_UNIX,unix), + __ADD(AF_INET,inet), + __ADD(AF_AX25,ax25), + __ADD(AF_IPX,ipx), + __ADD(AF_APPLETALK,appletalk), + __ADD(AF_NETROM,netrom), + __ADD(AF_BRIDGE,bridge), + __ADD(AF_ATMPVC,atmpvc), + __ADD(AF_X25,x25), + __ADD(AF_INET6,inet6), + __ADD(AF_ROSE,rose), + __ADD(AF_DECnet,decnet), + __ADD(AF_NETBEUI,netbeui), + __ADD(AF_SECURITY,security), + __ADD(AF_KEY,key), + __ADD(AF_NETLINK,netlink), + __ADD(AF_PACKET,packet), + __ADD(AF_ASH,ash), + __ADD(AF_ECONET,econet), + __ADD(AF_ATMSVC,atmsvc), +#ifdef AF_RDS + __ADD(AF_RDS,rds), +#endif + __ADD(AF_SNA,sna), + __ADD(AF_IRDA,irda), + __ADD(AF_PPPOX,pppox), + __ADD(AF_WANPIPE,wanpipe), + __ADD(AF_LLC,llc), +#ifdef AF_CAN + __ADD(AF_CAN,can), +#endif +#ifdef AF_TIPC + __ADD(AF_TIPC,tipc), +#endif + __ADD(AF_BLUETOOTH,bluetooth), +#ifdef AF_IUCV + __ADD(AF_IUCV,iucv), +#endif +#ifdef AF_RXRPC + __ADD(AF_RXRPC,rxrpc), +#endif +#ifdef AF_ISDN + __ADD(AF_ISDN,isdn), +#endif +#ifdef AF_PHONET + __ADD(AF_PHONET,phonet), +#endif #ifdef AF_IEEE802154 - __ADD(AF_IEEE802154,ieee802154) + __ADD(AF_IEEE802154,ieee802154), #endif #ifdef AF_CAIF - __ADD(AF_CAIF,caif) + __ADD(AF_CAIF,caif), #endif #ifdef AF_ALG - __ADD(AF_ALG,alg) + __ADD(AF_ALG,alg), #endif #ifdef AF_NFC - __ADD(AF_NFC,nfc) + __ADD(AF_NFC,nfc), +#endif +#ifdef AF_VSOCK + __ADD(AF_VSOCK,vsock), #endif + __ADD(AF_MPLS,mpls), }; char *nl_af2str(int family, char *buf, size_t size) diff --git a/lib/attr.c b/lib/attr.c index 535f10c..b8b9837 100644 --- a/lib/attr.c +++ b/lib/attr.c @@ -1,21 +1,20 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/attr.c Netlink 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-2013 Thomas Graf */ -#include +#include "nl-default.h" + +#include + #include #include #include #include #include -#include + +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-aux-core/nl-core.h" /** * @ingroup msg @@ -147,7 +146,7 @@ int nla_len(const struct nlattr *nla) */ int nla_ok(const struct nlattr *nla, int remaining) { - return remaining >= sizeof(*nla) && + return remaining >= (int) sizeof(*nla) && nla->nla_len >= sizeof(*nla) && nla->nla_len <= remaining; } @@ -185,14 +184,14 @@ static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = { [NLA_FLAG] = 0, }; -static int validate_nla(struct nlattr *nla, int maxtype, - struct nla_policy *policy) +static int validate_nla(const struct nlattr *nla, int maxtype, + const struct nla_policy *policy) { - struct nla_policy *pt; + const struct nla_policy *pt; unsigned int minlen = 0; int type = nla_type(nla); - if (type <= 0 || type > maxtype) + if (type < 0 || type > maxtype) return 0; pt = &policy[type]; @@ -212,7 +211,7 @@ static int validate_nla(struct nlattr *nla, int maxtype, return -NLE_RANGE; if (pt->type == NLA_STRING) { - char *data = nla_data(nla); + const char *data = nla_data(nla); if (data[nla_len(nla) - 1] != '\0') return -NLE_INVAL; } @@ -240,7 +239,7 @@ static int validate_nla(struct nlattr *nla, int maxtype, * @return 0 on success or a negative error code. */ int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, - struct nla_policy *policy) + const struct nla_policy *policy) { struct nlattr *nla; int rem, err; @@ -250,17 +249,13 @@ int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, nla_for_each_attr(nla, head, len, rem) { int type = nla_type(nla); - /* Padding attributes */ - if (type == 0) - continue; - if (type > maxtype) continue; if (policy) { err = validate_nla(nla, maxtype, policy); if (err < 0) - goto errout; + return err; } if (tb[type]) @@ -270,13 +265,12 @@ int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, tb[type] = nla; } - if (rem > 0) + if (rem > 0) { NL_DBG(1, "netlink: %d bytes leftover after parsing " "attributes.\n", rem); + } - err = 0; -errout: - return err; + return 0; } /** @@ -295,10 +289,10 @@ errout: * * @return 0 on success or a negative error code. */ -int nla_validate(struct nlattr *head, int len, int maxtype, - struct nla_policy *policy) +int nla_validate(const struct nlattr *head, int len, int maxtype, + const struct nla_policy *policy) { - struct nlattr *nla; + const struct nlattr *nla; int rem, err; nla_for_each_attr(nla, head, len, rem) { @@ -324,14 +318,14 @@ errout: * * @return Pointer to attribute found or NULL. */ -struct nlattr *nla_find(struct nlattr *head, int len, int attrtype) +struct nlattr *nla_find(const struct nlattr *head, int len, int attrtype) { - struct nlattr *nla; + const struct nlattr *nla; int rem; nla_for_each_attr(nla, head, len, rem) if (nla_type(nla) == attrtype) - return nla; + return (struct nlattr*)nla; return NULL; } @@ -354,16 +348,19 @@ struct nlattr *nla_find(struct nlattr *head, int len, int attrtype) * * @return The number of bytes copied to dest. */ -int nla_memcpy(void *dest, struct nlattr *src, int count) +int nla_memcpy(void *dest, const struct nlattr *src, int count) { int minlen; if (!src) return 0; - - minlen = min_t(int, count, nla_len(src)); - memcpy(dest, nla_data(src), minlen); + minlen = _NL_MIN(count, nla_len(src)); + + if (minlen <= 0) + return 0; + + memcpy(dest, nla_data(src), minlen); return minlen; } @@ -382,7 +379,7 @@ int nla_memcpy(void *dest, struct nlattr *src, int count) size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize) { size_t srclen = nla_len(nla); - char *src = nla_data(nla); + const char *src = nla_data(nla); if (srclen > 0 && src[srclen - 1] == '\0') srclen--; @@ -461,7 +458,10 @@ struct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int attrlen) { struct nlattr *nla; int tlen; - + + if (attrlen < 0) + return NULL; + tlen = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) + nla_total_size(attrlen); if (tlen > msg->nm_size) @@ -478,7 +478,7 @@ struct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int attrlen) NL_DBG(2, "msg %p: attr <%p> %d: Reserved %d (%d) bytes at offset +%td " "nlmsg_len=%d\n", msg, nla, nla->nla_type, nla_total_size(attrlen), attrlen, - (void *) nla - nlmsg_data(msg->nm_nlh), + (char *) nla - (char *) nlmsg_data(msg->nm_nlh), msg->nm_nlh->nlmsg_len); return nla; @@ -503,14 +503,18 @@ int nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data) struct nlattr *nla; nla = nla_reserve(msg, attrtype, datalen); - if (!nla) + if (!nla) { + if (datalen < 0) + return -NLE_INVAL; + return -NLE_NOMEM; + } if (datalen > 0) { memcpy(nla_data(nla), data, datalen); NL_DBG(2, "msg %p: attr <%p> %d: Wrote %d bytes at offset +%td\n", msg, nla, nla->nla_type, datalen, - (void *) nla - nlmsg_data(msg->nm_nlh)); + (char *) nla - (char *) nlmsg_data(msg->nm_nlh)); } return 0; @@ -528,7 +532,7 @@ int nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data) * @see nla_put * @return 0 on success or a negative error code. */ -int nla_put_data(struct nl_msg *msg, int attrtype, struct nl_data *data) +int nla_put_data(struct nl_msg *msg, int attrtype, const struct nl_data *data) { return nla_put(msg, attrtype, nl_data_get_size(data), nl_data_get(data)); @@ -545,6 +549,9 @@ int nla_put_data(struct nl_msg *msg, int attrtype, struct nl_data *data) */ int nla_put_addr(struct nl_msg *msg, int attrtype, struct nl_addr *addr) { + if (nl_addr_get_len(addr) == 0) + return -NLE_INVAL; + return nla_put(msg, attrtype, nl_addr_get_len(addr), nl_addr_get_binary_addr(addr)); } @@ -556,6 +563,31 @@ int nla_put_addr(struct nl_msg *msg, int attrtype, struct nl_addr *addr) */ /** + * Add 8 bit signed integer attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg value Numeric value to store as payload. + * + * @see nla_put + * @return 0 on success or a negative error code. + */ +int nla_put_s8(struct nl_msg *msg, int attrtype, int8_t value) +{ + return nla_put(msg, attrtype, sizeof(int8_t), &value); +} + +/** + * Return value of 8 bit signed integer attribute. + * @arg nla 8 bit integer attribute + * + * @return Payload as 8 bit integer. + */ +int8_t nla_get_s8(const struct nlattr *nla) +{ + return *(const int8_t *) nla_data(nla); +} + +/** * Add 8 bit integer attribute to netlink message. * @arg msg Netlink message. * @arg attrtype Attribute type. @@ -575,9 +607,34 @@ int nla_put_u8(struct nl_msg *msg, int attrtype, uint8_t value) * * @return Payload as 8 bit integer. */ -uint8_t nla_get_u8(struct nlattr *nla) +uint8_t nla_get_u8(const struct nlattr *nla) +{ + return *(const uint8_t *) nla_data(nla); +} + +/** + * Add 16 bit signed integer attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg value Numeric value to store as payload. + * + * @see nla_put + * @return 0 on success or a negative error code. + */ +int nla_put_s16(struct nl_msg *msg, int attrtype, int16_t value) +{ + return nla_put(msg, attrtype, sizeof(int16_t), &value); +} + +/** + * Return payload of 16 bit signed integer attribute. + * @arg nla 16 bit integer attribute + * + * @return Payload as 16 bit integer. + */ +int16_t nla_get_s16(const struct nlattr *nla) { - return *(uint8_t *) nla_data(nla); + return *(const int16_t *) nla_data(nla); } /** @@ -600,9 +657,34 @@ int nla_put_u16(struct nl_msg *msg, int attrtype, uint16_t value) * * @return Payload as 16 bit integer. */ -uint16_t nla_get_u16(struct nlattr *nla) +uint16_t nla_get_u16(const struct nlattr *nla) { - return *(uint16_t *) nla_data(nla); + return *(const uint16_t *) nla_data(nla); +} + +/** + * Add 32 bit signed integer attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg value Numeric value to store as payload. + * + * @see nla_put + * @return 0 on success or a negative error code. + */ +int nla_put_s32(struct nl_msg *msg, int attrtype, int32_t value) +{ + return nla_put(msg, attrtype, sizeof(int32_t), &value); +} + +/** + * Return payload of 32 bit signed integer attribute. + * @arg nla 32 bit integer attribute. + * + * @return Payload as 32 bit integer. + */ +int32_t nla_get_s32(const struct nlattr *nla) +{ + return *(const int32_t *) nla_data(nla); } /** @@ -625,9 +707,39 @@ int nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value) * * @return Payload as 32 bit integer. */ -uint32_t nla_get_u32(struct nlattr *nla) +uint32_t nla_get_u32(const struct nlattr *nla) +{ + return *(const uint32_t *) nla_data(nla); +} + +/** + * Add 64 bit signed integer attribute to netlink message. + * @arg msg Netlink message. + * @arg attrtype Attribute type. + * @arg value Numeric value to store as payload. + * + * @see nla_put + * @return 0 on success or a negative error code. + */ +int nla_put_s64(struct nl_msg *msg, int attrtype, int64_t value) +{ + return nla_put(msg, attrtype, sizeof(int64_t), &value); +} + +/** + * Return payload of s64 attribute + * @arg nla s64 netlink attribute + * + * @return Payload as 64 bit integer. + */ +int64_t nla_get_s64(const struct nlattr *nla) { - return *(uint32_t *) nla_data(nla); + int64_t tmp = 0; + + if (nla && nla_len(nla) >= sizeof(tmp)) + memcpy(&tmp, nla_data(nla), sizeof(tmp)); + + return tmp; } /** @@ -650,11 +762,12 @@ int nla_put_u64(struct nl_msg *msg, int attrtype, uint64_t value) * * @return Payload as 64 bit integer. */ -uint64_t nla_get_u64(struct nlattr *nla) +uint64_t nla_get_u64(const struct nlattr *nla) { - uint64_t tmp; + uint64_t tmp = 0; - nla_memcpy(&tmp, nla, sizeof(tmp)); + if (nla && nla_len(nla) >= sizeof(tmp)) + memcpy(&tmp, nla_data(nla), sizeof(tmp)); return tmp; } @@ -685,12 +798,12 @@ int nla_put_string(struct nl_msg *msg, int attrtype, const char *str) * * @return Pointer to attribute payload. */ -char *nla_get_string(struct nlattr *nla) +char *nla_get_string(const struct nlattr *nla) { return (char *) nla_data(nla); } -char *nla_strdup(struct nlattr *nla) +char *nla_strdup(const struct nlattr *nla) { return strdup(nla_get_string(nla)); } @@ -720,7 +833,7 @@ int nla_put_flag(struct nl_msg *msg, int attrtype) * * @return True if flag is set, otherwise false. */ -int nla_get_flag(struct nlattr *nla) +int nla_get_flag(const struct nlattr *nla) { return !!nla; } @@ -748,7 +861,7 @@ int nla_put_msecs(struct nl_msg *n, int attrtype, unsigned long msecs) * * @return the number of milliseconds. */ -unsigned long nla_get_msecs(struct nlattr *nla) +unsigned long nla_get_msecs(const struct nlattr *nla) { return nla_get_u64(nla); } @@ -772,7 +885,8 @@ unsigned long nla_get_msecs(struct nlattr *nla) * @see nla_put * @return 0 on success or a negative error code. */ -int nla_put_nested(struct nl_msg *msg, int attrtype, struct nl_msg *nested) +int nla_put_nested(struct nl_msg *msg, int attrtype, + const struct nl_msg *nested) { NL_DBG(2, "msg %p: attr <> %d: adding msg %p as nested attribute\n", msg, attrtype, nested); @@ -793,7 +907,7 @@ struct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype) { struct nlattr *start = (struct nlattr *) nlmsg_tail(msg->nm_nlh); - if (nla_put(msg, attrtype, 0, NULL) < 0) + if (nla_put(msg, NLA_F_NESTED | attrtype, 0, NULL) < 0) return NULL; NL_DBG(2, "msg %p: attr <%p> %d: starting nesting\n", @@ -802,29 +916,22 @@ struct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype) return start; } -/** - * Finalize nesting of attributes. - * @arg msg Netlink message. - * @arg start Container attribute as returned from nla_nest_start(). - * - * Corrects the container attribute header to include the appeneded attributes. - * - * @return 0 - */ -int nla_nest_end(struct nl_msg *msg, struct nlattr *start) +static int _nest_end(struct nl_msg *msg, struct nlattr *start, int keep_empty) { size_t pad, len; - len = (void *) nlmsg_tail(msg->nm_nlh) - (void *) start; + len = (char *) nlmsg_tail(msg->nm_nlh) - (char *) start; - if (len == NLA_HDRLEN) { + if ( len > USHRT_MAX + || (!keep_empty && len == NLA_HDRLEN)) { /* - * Kernel can't handle empty nested attributes, trim the + * Max nlattr size exceeded or empty nested attribute, trim the * attribute header again */ nla_nest_cancel(msg, start); - return 0; + /* Return error only if nlattr size was exceeded */ + return (len == NLA_HDRLEN) ? 0 : -NLE_ATTRSIZE; } start->nla_len = len; @@ -851,6 +958,35 @@ int nla_nest_end(struct nl_msg *msg, struct nlattr *start) } /** + * Finalize nesting of attributes. + * @arg msg Netlink message. + * @arg start Container attribute as returned from nla_nest_start(). + * + * Corrects the container attribute header to include the appeneded attributes. + * + * @return 0 on success or a negative error code. + */ +int nla_nest_end(struct nl_msg *msg, struct nlattr *start) +{ + return _nest_end (msg, start, 0); +} + +/** + * Finalize nesting of attributes without stripping off empty attributes. + * @arg msg Netlink message. + * @arg start Container attribute as returned from nla_nest_start(). + * + * Corrects the container attribute header to include the appeneded attributes. + * Keep empty attribute if NO actual attribute payload exists. + * + * @return 0 on success or a negative error code. + */ +int nla_nest_end_keep_empty(struct nl_msg *msg, struct nlattr *start) +{ + return _nest_end (msg, start, 1); +} + +/** * Cancel the addition of a nested attribute * @arg msg Netlink message * @arg attr Nested netlink attribute @@ -859,11 +995,20 @@ int nla_nest_end(struct nl_msg *msg, struct nlattr *start) * by resetting the message to the size before the call to nla_nest_start() * and by overwriting any potentially touched message segments with 0. */ -void nla_nest_cancel(struct nl_msg *msg, struct nlattr *attr) +void nla_nest_cancel(struct nl_msg *msg, const struct nlattr *attr) { ssize_t len; - len = (void *) nlmsg_tail(msg->nm_nlh) - (void *) attr; + if (!attr) { + /* For robustness, allow a NULL attr to do nothing. NULL is also + * what nla_nest_start() when out of buffer space. + * + * Warning, before libnl-3.8, the function did not accept NULL! + * If you care, catch NULL yourself. */ + return; + } + + len = (char *) nlmsg_tail(msg->nm_nlh) - (char *) attr; if (len < 0) BUG(); else if (len > 0) { @@ -886,7 +1031,7 @@ void nla_nest_cancel(struct nl_msg *msg, struct nlattr *attr) * @return 0 on success or a negative error code. */ int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, - struct nla_policy *policy) + const struct nla_policy *policy) { return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy); } @@ -897,7 +1042,7 @@ int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, * * @return True if attribute has NLA_F_NESTED flag set, oterhwise False. */ -int nla_is_nested(struct nlattr *attr) +int nla_is_nested(const struct nlattr *attr) { return !!(attr->nla_type & NLA_F_NESTED); } diff --git a/lib/cache.c b/lib/cache.c index e99e9d2..dd059c1 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/cache.c Caching Module - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -49,13 +43,20 @@ * ~~~~ */ -#include +#include "nl-default.h" + #include #include #include #include #include +#include "nl-core.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-priv-dynamic-core/cache-api.h" +#include "nl-aux-core/nl-core.h" + /** * @name Access Functions * @{ @@ -235,7 +236,7 @@ int nl_cache_alloc_and_fill(struct nl_cache_ops *ops, struct nl_sock *sock, { struct nl_cache *cache; int err; - + if (!(cache = nl_cache_alloc(ops))) return -NLE_NOMEM; @@ -421,7 +422,7 @@ void nl_cache_free(struct nl_cache *cache) void nl_cache_put(struct nl_cache *cache) { - return nl_cache_free(cache); + nl_cache_free(cache); } /** @} */ @@ -527,7 +528,7 @@ int nl_cache_move(struct nl_cache *cache, struct nl_object *obj) NL_DBG(3, "Moving object %p from cache %p to cache %p\n", obj, obj->ce_cache, cache); - + /* Acquire reference, if already in a cache this will be * reverted during removal */ nl_object_get(obj); @@ -589,7 +590,7 @@ void nl_cache_remove(struct nl_object *obj) */ void nl_cache_set_arg1(struct nl_cache *cache, int arg) { - cache->c_iarg1 = arg; + cache->c_iarg1 = arg; } /** @@ -602,7 +603,7 @@ void nl_cache_set_arg1(struct nl_cache *cache, int arg) */ void nl_cache_set_arg2(struct nl_cache *cache, int arg) { - cache->c_iarg2 = arg; + cache->c_iarg2 = arg; } /** @@ -637,11 +638,16 @@ void nl_cache_set_flags(struct nl_cache *cache, unsigned int flags) * * @see nl_cache_pickup(), nl_cache_resync() * - * @return 0 on success or a negative error code. + * @return 0 on success or a negative error code. Some implementations + * of co_request_update() return a positive number on success that is + * the number of bytes sent. Treat any non-negative number as success too. */ static int nl_cache_request_full_dump(struct nl_sock *sk, struct nl_cache *cache) { + if (sk->s_proto != cache->c_ops->co_protocol) + return -NLE_PROTO_MISMATCH; + if (cache->c_ops->co_request_update == NULL) return -NLE_OPNOTSUPP; @@ -705,7 +711,7 @@ static int __cache_pickup(struct nl_sock *sk, struct nl_cache *cache, return err; } -static int pickup_cb(struct nl_object *c, struct nl_parser_param *p) +static int pickup_checkdup_cb(struct nl_object *c, struct nl_parser_param *p) { struct nl_cache *cache = (struct nl_cache *)p->pp_arg; struct nl_object *old; @@ -724,6 +730,27 @@ static int pickup_cb(struct nl_object *c, struct nl_parser_param *p) return nl_cache_add(cache, c); } +static int pickup_cb(struct nl_object *c, struct nl_parser_param *p) +{ + struct nl_cache *cache = p->pp_arg; + + return nl_cache_add(cache, c); +} + +static int __nl_cache_pickup(struct nl_sock *sk, struct nl_cache *cache, + int checkdup) +{ + struct nl_parser_param p; + + p.pp_cb = checkdup ? pickup_checkdup_cb : pickup_cb; + p.pp_arg = cache; + + if (sk->s_proto != cache->c_ops->co_protocol) + return -NLE_PROTO_MISMATCH; + + return __cache_pickup(sk, cache, &p); +} + /** * Pickup a netlink dump response and put it into a cache. * @arg sk Netlink socket. @@ -737,41 +764,66 @@ static int pickup_cb(struct nl_object *c, struct nl_parser_param *p) * * @return 0 on success or a negative error code. */ -int nl_cache_pickup(struct nl_sock *sk, struct nl_cache *cache) +int nl_cache_pickup_checkdup(struct nl_sock *sk, struct nl_cache *cache) { - struct nl_parser_param p = { - .pp_cb = pickup_cb, - .pp_arg = cache, - }; + return __nl_cache_pickup(sk, cache, 1); +} - return __cache_pickup(sk, cache, &p); +/** + * Pickup a netlink dump response and put it into a cache. + * @arg sk Netlink socket. + * @arg cache Cache to put items into. + * + * Waits for netlink messages to arrive, parses them and puts them into + * the specified cache. + * + * @return 0 on success or a negative error code. + */ +int nl_cache_pickup(struct nl_sock *sk, struct nl_cache *cache) +{ + return __nl_cache_pickup(sk, cache, 0); } static int cache_include(struct nl_cache *cache, struct nl_object *obj, - struct nl_msgtype *type, change_func_t cb, void *data) + struct nl_msgtype *type, change_func_t cb, + change_func_v2_t cb_v2, void *data) { struct nl_object *old; + struct nl_object *clone = NULL; + uint64_t diff = 0; switch (type->mt_act) { case NL_ACT_NEW: case NL_ACT_DEL: old = nl_cache_search(cache, obj); if (old) { + if (cb_v2 && old->ce_ops->oo_update) { + clone = nl_object_clone(old); + diff = nl_object_diff64(old, obj); + } /* * Some objects types might support merging the new * object with the old existing cache object. * Handle them first. */ if (nl_object_update(old, obj) == 0) { - if (cb) + if (cb_v2) { + cb_v2(cache, clone, obj, diff, + NL_ACT_CHANGE, data); + nl_object_put(clone); + } else if (cb) cb(cache, old, NL_ACT_CHANGE, data); nl_object_put(old); return 0; } + nl_object_put(clone); nl_cache_remove(old); if (type->mt_act == NL_ACT_DEL) { - if (cb) + if (cb_v2) + cb_v2(cache, old, NULL, 0, NL_ACT_DEL, + data); + else if (cb) cb(cache, old, NL_ACT_DEL, data); nl_object_put(old); } @@ -779,10 +831,20 @@ static int cache_include(struct nl_cache *cache, struct nl_object *obj, if (type->mt_act == NL_ACT_NEW) { nl_cache_move(cache, obj); - if (old == NULL && cb) - cb(cache, obj, NL_ACT_NEW, data); - else if (old) { - if (nl_object_diff(old, obj) && cb) + if (old == NULL) { + if (cb_v2) { + cb_v2(cache, NULL, obj, 0, NL_ACT_NEW, + data); + } else if (cb) + cb(cache, obj, NL_ACT_NEW, data); + } else if (old) { + diff = 0; + if (cb || cb_v2) + diff = nl_object_diff64(old, obj); + if (diff && cb_v2) { + cb_v2(cache, old, obj, diff, NL_ACT_CHANGE, + data); + } else if (diff && cb) cb(cache, obj, NL_ACT_CHANGE, data); nl_object_put(old); @@ -809,7 +871,27 @@ int nl_cache_include(struct nl_cache *cache, struct nl_object *obj, for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) if (ops->co_msgtypes[i].mt_id == obj->ce_msgtype) return cache_include(cache, obj, &ops->co_msgtypes[i], - change_cb, data); + change_cb, NULL, data); + + NL_DBG(3, "Object %p does not seem to belong to cache %p <%s>\n", + obj, cache, nl_cache_name(cache)); + + return -NLE_MSGTYPE_NOSUPPORT; +} + +int nl_cache_include_v2(struct nl_cache *cache, struct nl_object *obj, + change_func_v2_t change_cb, void *data) +{ + struct nl_cache_ops *ops = cache->c_ops; + int i; + + if (ops->co_obj_ops != obj->ce_ops) + return -NLE_OBJ_MISMATCH; + + for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) + if (ops->co_msgtypes[i].mt_id == obj->ce_msgtype) + return cache_include(cache, obj, &ops->co_msgtypes[i], + NULL, change_cb, data); NL_DBG(3, "Object %p does not seem to belong to cache %p <%s>\n", obj, cache, nl_cache_name(cache)); @@ -821,7 +903,12 @@ static int resync_cb(struct nl_object *c, struct nl_parser_param *p) { struct nl_cache_assoc *ca = p->pp_arg; - return nl_cache_include(ca->ca_cache, c, ca->ca_change, ca->ca_change_data); + if (ca->ca_change_v2) + return nl_cache_include_v2(ca->ca_cache, c, ca->ca_change_v2, + ca->ca_change_data); + else + return nl_cache_include(ca->ca_cache, c, ca->ca_change, + ca->ca_change_data); } int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache, @@ -840,6 +927,9 @@ int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache, }; int err; + if (sk->s_proto != cache->c_ops->co_protocol) + return -NLE_PROTO_MISMATCH; + NL_DBG(1, "Resyncing cache %p <%s>...\n", cache, nl_cache_name(cache)); /* Mark all objects so we can see if some of them are obsolete */ @@ -953,6 +1043,9 @@ int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache) struct nl_af_group *grp; int err; + if (sk->s_proto != cache->c_ops->co_protocol) + return -NLE_PROTO_MISMATCH; + nl_cache_clear(cache); grp = cache->c_ops->co_groups; do { @@ -996,8 +1089,8 @@ static struct nl_object *__cache_fast_lookup(struct nl_cache *cache, obj = nl_hash_table_lookup(cache->hashtable, needle); if (obj) { - nl_object_get(obj); - return obj; + nl_object_get(obj); + return obj; } return NULL; @@ -1115,7 +1208,7 @@ void nl_cache_dump(struct nl_cache *cache, struct nl_dump_params *params) /** * Dump all elements of a cache (filtered). * @arg cache cache to dump - * @arg params dumping parameters (optional) + * @arg params dumping parameters * @arg filter filter object * * Dumps all elements of the \a cache to the file descriptor \a fd @@ -1125,13 +1218,30 @@ void nl_cache_dump_filter(struct nl_cache *cache, struct nl_dump_params *params, struct nl_object *filter) { - int type = params ? params->dp_type : NL_DUMP_DETAILS; + struct nl_dump_params params_copy; struct nl_object_ops *ops; struct nl_object *obj; + int type; NL_DBG(2, "Dumping cache %p <%s> with filter %p\n", cache, nl_cache_name(cache), filter); + if (!params) { + /* It doesn't really make sense that @params is an optional parameter. In the + * past, nl_cache_dump() was documented that the @params would be optional, so + * try to save it. + * + * Note that this still isn't useful, because we don't set any dump option. + * It only exists not to crash applications that wrongly pass %NULL here. */ + _nl_assert_not_reached (); + params_copy = (struct nl_dump_params) { + .dp_type = NL_DUMP_DETAILS, + }; + params = ¶ms_copy; + } + + type = params->dp_type; + if (type > NL_DUMP_MAX || type < 0) BUG(); diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index f8a65e3..f16882f 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/cache_mngr.c Cache Manager - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -32,12 +26,28 @@ * ~~~~ */ -#include +#include "nl-default.h" + #include #include #include +#include "nl-core.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" +#include "nl-aux-core/nl-core.h" + /** @cond SKIP */ +struct nl_cache_mngr +{ + int cm_protocol; + int cm_flags; + int cm_nassocs; + struct nl_sock * cm_sock; + struct nl_sock * cm_sync_sock; + struct nl_cache_assoc * cm_assocs; +}; + #define NASSOC_INIT 16 #define NASSOC_EXPAND 8 /** @endcond */ @@ -59,9 +69,15 @@ static int include_cb(struct nl_object *obj, struct nl_parser_param *p) if (ops->co_include_event) return ops->co_include_event(ca->ca_cache, obj, ca->ca_change, + ca->ca_change_v2, ca->ca_change_data); - else - return nl_cache_include(ca->ca_cache, obj, ca->ca_change, ca->ca_change_data); + else { + if (ca->ca_change_v2) + return nl_cache_include_v2(ca->ca_cache, obj, ca->ca_change_v2, ca->ca_change_data); + else + return nl_cache_include(ca->ca_cache, obj, ca->ca_change, ca->ca_change_data); + } + } static int event_input(struct nl_msg *msg, void *arg) @@ -165,16 +181,18 @@ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags, /* Required to receive async event notifications */ nl_socket_disable_seq_check(mngr->cm_sock); - if ((err = nl_connect(mngr->cm_sock, protocol) < 0)) + if ((err = nl_connect(mngr->cm_sock, protocol)) < 0) goto errout; - if ((err = nl_socket_set_nonblocking(mngr->cm_sock) < 0)) + if ((err = nl_socket_set_nonblocking(mngr->cm_sock)) < 0) goto errout; /* Create and allocate socket for sync cache fills */ mngr->cm_sync_sock = nl_socket_alloc(); - if (!mngr->cm_sync_sock) + if (!mngr->cm_sync_sock) { + err = -NLE_NOMEM; goto errout; + } if ((err = nl_connect(mngr->cm_sync_sock, protocol)) < 0) goto errout_free_sync_sock; @@ -192,6 +210,70 @@ errout: } /** + * Set change_func_v2 for cache manager + * @arg mngr Cache manager. + * @arg cache Cache associated with the callback + * @arg cb Function to be called upon changes. + * @arg data Argument passed on to change callback + * + * Adds callback change_func_v2 to a registered cache. This callback provides + * in like the standard change_func the added or remove netlink object. In case + * of a change the old and the new object is provided as well as the according + * diff. If this callback is registered this has a higher priority then the + * change_func registered during cache registration. Hence only one callback is + * executed. + * + * The first netlink object in the callback is refering to the old object and + * the second to the new. This means on NL_ACT_CHANGE the first is the previous + * object in the cache and the second the updated version. On NL_ACT_DEL the + * first is the deleted object the second is NULL. On NL_ACT_NEW the first is + * NULL and the second the new netlink object. + * + * The user is responsible for calling nl_cache_mngr_poll() or monitor + * the socket and call nl_cache_mngr_data_ready() to allow the library + * to process netlink notification events. + * + * @see nl_cache_mngr_poll() + * @see nl_cache_mngr_data_ready() + * + * @return 0 on success or a negative error code. + * @return -NLE_PROTO_MISMATCH Protocol mismatch between cache manager and + * cache type + * @return -NLE_OPNOTSUPP Cache type does not support updates + * @return -NLE_RANGE Cache of this type is not registered + */ +static int nl_cache_mngr_set_change_func_v2(struct nl_cache_mngr *mngr, + struct nl_cache *cache, + change_func_v2_t cb, void *data) +{ + struct nl_cache_ops *ops; + int i; + + ops = cache->c_ops; + if (!ops) + return -NLE_INVAL; + + if (ops->co_protocol != mngr->cm_protocol) + return -NLE_PROTO_MISMATCH; + + if (ops->co_groups == NULL) + return -NLE_OPNOTSUPP; + + for (i = 0; i < mngr->cm_nassocs; i++) + if (mngr->cm_assocs[i].ca_cache == cache) + break; + + if (i >= mngr->cm_nassocs) { + return -NLE_RANGE; + } + + mngr->cm_assocs[i].ca_change_v2 = cb; + mngr->cm_assocs[i].ca_change_data = data; + + return 0; +} + +/** * Add cache to cache manager * @arg mngr Cache manager. * @arg cache Cache to be added to cache manager @@ -238,25 +320,26 @@ int nl_cache_mngr_add_cache(struct nl_cache_mngr *mngr, struct nl_cache *cache, mngr->cm_assocs[i].ca_cache->c_ops == ops) return -NLE_EXIST; -retry: for (i = 0; i < mngr->cm_nassocs; i++) if (!mngr->cm_assocs[i].ca_cache) break; if (i >= mngr->cm_nassocs) { - mngr->cm_nassocs += NASSOC_EXPAND; - mngr->cm_assocs = realloc(mngr->cm_assocs, - mngr->cm_nassocs * - sizeof(struct nl_cache_assoc)); - if (mngr->cm_assocs == NULL) + struct nl_cache_assoc *cm_assocs; + int cm_nassocs = mngr->cm_nassocs + NASSOC_EXPAND; + + cm_assocs = realloc(mngr->cm_assocs, + cm_nassocs * sizeof(struct nl_cache_assoc)); + if (cm_assocs == NULL) return -NLE_NOMEM; - memset(mngr->cm_assocs + (mngr->cm_nassocs - NASSOC_EXPAND), 0, + memset(cm_assocs + mngr->cm_nassocs, 0, NASSOC_EXPAND * sizeof(struct nl_cache_assoc)); + mngr->cm_assocs = cm_assocs; + mngr->cm_nassocs = cm_nassocs; NL_DBG(1, "Increased capacity of cache manager %p " \ "to %d\n", mngr, mngr->cm_nassocs); - goto retry; } for (grp = ops->co_groups; grp->ag_group; grp++) { @@ -291,6 +374,41 @@ errout_drop_membership: /** * Add cache to cache manager * @arg mngr Cache manager. + * @arg cache Cache to be added to cache manager + * @arg cb V2 function to be called upon changes. + * @arg data Argument passed on to change callback + * + * Adds cache to the manager. The operation will trigger a full + * dump request from the kernel to initially fill the contents + * of the cache. The manager will subscribe to the notification group + * of the cache and keep track of any further changes. + * + * The user is responsible for calling nl_cache_mngr_poll() or monitor + * the socket and call nl_cache_mngr_data_ready() to allow the library + * to process netlink notification events. + * + * @see nl_cache_mngr_poll() + * @see nl_cache_mngr_data_ready() + * + * @return 0 on success or a negative error code. + * @return -NLE_PROTO_MISMATCH Protocol mismatch between cache manager and + * cache type + * @return -NLE_OPNOTSUPP Cache type does not support updates + * @return -NLE_EXIST Cache of this type already being managed + */ +int nl_cache_mngr_add_cache_v2(struct nl_cache_mngr *mngr, struct nl_cache *cache, + change_func_v2_t cb, void *data) { + int err; + err = nl_cache_mngr_add_cache(mngr, cache, NULL, NULL); + if (err < 0) + return err; + + return nl_cache_mngr_set_change_func_v2(mngr, cache, cb, data); +} + +/** + * Add cache to cache manager + * @arg mngr Cache manager. * @arg name Name of cache to keep track of * @arg cb Function to be called upon changes. * @arg data Argument passed on to change callback @@ -306,6 +424,9 @@ errout_drop_membership: * the socket and call nl_cache_mngr_data_ready() to allow the library * to process netlink notification events. * + * @note Versions up to 3.4.0 actually required the result argument, preventing + * NULL to be passed. + * * @see nl_cache_mngr_poll() * @see nl_cache_mngr_data_ready() * @@ -336,7 +457,8 @@ int nl_cache_mngr_add(struct nl_cache_mngr *mngr, const char *name, if (err < 0) goto errout_free_cache; - *result = cache; + if (result) + *result = cache; return 0; errout_free_cache: @@ -389,8 +511,11 @@ int nl_cache_mngr_poll(struct nl_cache_mngr *mngr, int timeout) NL_DBG(3, "Cache manager %p, poll() fd %d\n", mngr, fds.fd); ret = poll(&fds, 1, timeout); NL_DBG(3, "Cache manager %p, poll() returned %d\n", mngr, ret); - if (ret < 0) + if (ret < 0) { + NL_DBG(4, "nl_cache_mngr_poll(%p): poll() failed with %d (%s)\n", + mngr, errno, nl_strerror_l(errno)); return -nl_syserr2nlerr(errno); + } /* No events, return */ if (ret == 0) @@ -435,7 +560,7 @@ int nl_cache_mngr_data_ready(struct nl_cache_mngr *mngr) } nl_cb_put(cb); - if (err < 0) + if (err < 0 && err != -NLE_AGAIN) return err; return nread; @@ -515,9 +640,10 @@ void nl_cache_mngr_free(struct nl_cache_mngr *mngr) } free(mngr->cm_assocs); - free(mngr); NL_DBG(1, "Cache manager %p freed\n", mngr); + + free(mngr); } /** @} */ diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c index 4d3d6ff..7969d35 100644 --- a/lib/cache_mngt.c +++ b/lib/cache_mngt.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/cache_mngt.c Cache Management - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -25,11 +19,17 @@ * ~~~~ */ -#include +#include "nl-default.h" + #include #include #include +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-priv-dynamic-core/cache-api.h" +#include "nl-aux-core/nl-core.h" + static struct nl_cache_ops *cache_ops; static NL_RW_LOCK(cache_ops_lock); @@ -38,7 +38,7 @@ static NL_RW_LOCK(cache_ops_lock); * @{ */ -struct nl_cache_ops *__nl_cache_ops_lookup(const char *name) +static struct nl_cache_ops *__nl_cache_ops_lookup(const char *name) { struct nl_cache_ops *ops; @@ -254,6 +254,9 @@ int nl_cache_mngt_register(struct nl_cache_ops *ops) if (!ops->co_name || !ops->co_obj_ops) return -NLE_INVAL; + /* oo_keygen() also needs oo_compare() */ + BUG_ON (ops->co_obj_ops->oo_keygen && !ops->co_obj_ops->oo_compare); + nl_write_lock(&cache_ops_lock); if (__nl_cache_ops_lookup(ops->co_name)) { nl_write_unlock(&cache_ops_lock); diff --git a/lib/cli/cls/basic.c b/lib/cli/cls/basic.c index 1939988..5d33e89 100644 --- a/lib/cli/cls/basic.c +++ b/lib/cli/cls/basic.c @@ -1,19 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/cli/cls/basic.c basic classifier module for CLI lib - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2010-2011 Thomas Graf */ +#include "nl-default.h" + #include #include #include #include +#include "base/nl-base-utils.h" + static void print_usage(void) { printf( @@ -49,7 +47,7 @@ static void parse_argv(struct rtnl_tc *tc, int argc, char **argv) { "ematch", 1, 0, 'e' }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "ht:e:", long_opts, &optidx); if (c == -1) break; @@ -72,7 +70,7 @@ static void parse_argv(struct rtnl_tc *tc, int argc, char **argv) rtnl_basic_set_ematch(cls, tree); break; } - } + } } static struct nl_cli_tc_module basic_module = @@ -82,12 +80,12 @@ static struct nl_cli_tc_module basic_module = .tm_parse_argv = parse_argv, }; -static void __init basic_init(void) +static void _nl_init basic_init(void) { nl_cli_tc_register(&basic_module); } -static void __exit basic_exit(void) +static void _nl_exit basic_exit(void) { nl_cli_tc_unregister(&basic_module); } diff --git a/lib/cli/cls/cgroup.c b/lib/cli/cls/cgroup.c index fae6208..296df69 100644 --- a/lib/cli/cls/cgroup.c +++ b/lib/cli/cls/cgroup.c @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/cli/cls/cgroup.c cgroup classifier module for CLI lib - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2010-2011 Thomas Graf */ +#include "nl-default.h" + #include #include #include @@ -39,7 +35,7 @@ static void parse_argv(struct rtnl_tc *tc, int argc, char **argv) { "ematch", 1, 0, 'e' }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "he:", long_opts, &optidx); if (c == -1) break; @@ -54,7 +50,7 @@ static void parse_argv(struct rtnl_tc *tc, int argc, char **argv) rtnl_cgroup_set_ematch(cls, tree); break; } - } + } } static struct nl_cli_tc_module cgroup_module = @@ -64,12 +60,12 @@ static struct nl_cli_tc_module cgroup_module = .tm_parse_argv = parse_argv, }; -static void __init cgroup_init(void) +static void _nl_init cgroup_init(void) { nl_cli_tc_register(&cgroup_module); } -static void __exit cgroup_exit(void) +static void _nl_exit cgroup_exit(void) { nl_cli_tc_unregister(&cgroup_module); } diff --git a/lib/cli/qdisc/bfifo.c b/lib/cli/qdisc/bfifo.c index 1ee4777..30db045 100644 --- a/lib/cli/qdisc/bfifo.c +++ b/lib/cli/qdisc/bfifo.c @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/lib/bfifo.c bfifo module for CLI lib - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2010-2011 Thomas Graf */ +#include "nl-default.h" + #include #include #include @@ -42,7 +38,7 @@ static void bfifo_parse_argv(struct rtnl_tc *tc, int argc, char **argv) { "limit", 1, 0, ARG_LIMIT }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "h", long_opts, &optidx); if (c == -1) break; @@ -62,7 +58,7 @@ static void bfifo_parse_argv(struct rtnl_tc *tc, int argc, char **argv) rtnl_qdisc_fifo_set_limit(qdisc, limit); break; } - } + } } static struct nl_cli_tc_module bfifo_module = @@ -72,12 +68,12 @@ static struct nl_cli_tc_module bfifo_module = .tm_parse_argv = bfifo_parse_argv, }; -static void __init bfifo_init(void) +static void _nl_init bfifo_init(void) { nl_cli_tc_register(&bfifo_module); } -static void __exit bfifo_exit(void) +static void _nl_exit bfifo_exit(void) { nl_cli_tc_unregister(&bfifo_module); } diff --git a/lib/cli/qdisc/blackhole.c b/lib/cli/qdisc/blackhole.c index af9dc6d..0ae0a53 100644 --- a/lib/cli/qdisc/blackhole.c +++ b/lib/cli/qdisc/blackhole.c @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/lib/blackhole.c Blackhole module for CLI lib - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2010-2011 Thomas Graf */ +#include "nl-default.h" + #include #include @@ -33,7 +29,7 @@ static void blackhole_parse_argv(struct rtnl_tc *tc, int argc, char **argv) { "help", 0, 0, 'h' }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "h", long_opts, &optidx); if (c == -1) break; @@ -43,7 +39,7 @@ static void blackhole_parse_argv(struct rtnl_tc *tc, int argc, char **argv) print_usage(); return; } - } + } } static struct nl_cli_tc_module blackhole_module = @@ -53,12 +49,12 @@ static struct nl_cli_tc_module blackhole_module = .tm_parse_argv = blackhole_parse_argv, }; -static void __init blackhole_init(void) +static void _nl_init blackhole_init(void) { nl_cli_tc_register(&blackhole_module); } -static void __exit blackhole_exit(void) +static void _nl_exit blackhole_exit(void) { nl_cli_tc_unregister(&blackhole_module); } diff --git a/lib/cli/qdisc/fq_codel.c b/lib/cli/qdisc/fq_codel.c new file mode 100644 index 0000000..83e409a --- /dev/null +++ b/lib/cli/qdisc/fq_codel.c @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Cong Wang + */ + +#include "nl-default.h" + +#include +#include +#include + +static void print_usage(void) +{ + printf( +"Usage: nl-qdisc-add [...] fq_codel [OPTIONS]...\n" +"\n" +"OPTIONS\n" +" --help Show this help text.\n" +" --limit=LIMIT Maximum queue length in number of bytes.\n" +" --quantum=SIZE Amount of bytes to serve at once.\n" +" --flows=N Number of flows.\n" +" --interval=N The interval in usec.\n" +" --target=N The minimum delay in usec.\n" +"\n" +"EXAMPLE" +" # Attach fq_codel with a 4096 packets limit to eth1\n" +" nl-qdisc-add --dev=eth1 --parent=root fq_codel --limit=4096\n"); +} + +static void fq_codel_parse_argv(struct rtnl_tc *tc, int argc, char **argv) +{ + struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc; + int limit, flows; + uint32_t quantum, target, interval; + + for (;;) { + int c, optidx = 0; + enum { + ARG_LIMIT = 257, + ARG_QUANTUM = 258, + ARG_FLOWS, + ARG_INTERVAL, + ARG_TARGET, + }; + static struct option long_opts[] = { + { "help", 0, 0, 'h' }, + { "limit", 1, 0, ARG_LIMIT }, + { "quantum", 1, 0, ARG_QUANTUM }, + { "flows", 1, 0, ARG_FLOWS}, + { "interval", 1, 0, ARG_INTERVAL}, + { "target", 1, 0, ARG_TARGET}, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "h", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'h': + print_usage(); + return; + + case ARG_LIMIT: + limit = nl_cli_parse_u32(optarg); + rtnl_qdisc_fq_codel_set_limit(qdisc, limit); + break; + + case ARG_QUANTUM: + quantum = nl_cli_parse_u32(optarg); + rtnl_qdisc_fq_codel_set_quantum(qdisc, quantum); + break; + + case ARG_FLOWS: + flows = nl_cli_parse_u32(optarg); + rtnl_qdisc_fq_codel_set_flows(qdisc, flows); + break; + + case ARG_INTERVAL: + interval = nl_cli_parse_u32(optarg); + rtnl_qdisc_fq_codel_set_interval(qdisc, interval); + break; + + case ARG_TARGET: + target = nl_cli_parse_u32(optarg); + rtnl_qdisc_fq_codel_set_target(qdisc, target); + break; + + } + } +} + +static struct nl_cli_tc_module fq_codel_module = +{ + .tm_name = "fq_codel", + .tm_type = RTNL_TC_TYPE_QDISC, + .tm_parse_argv = fq_codel_parse_argv, +}; + +static void _nl_init fq_codel_init(void) +{ + nl_cli_tc_register(&fq_codel_module); +} + +static void _nl_exit fq_codel_exit(void) +{ + nl_cli_tc_unregister(&fq_codel_module); +} diff --git a/lib/cli/qdisc/hfsc.c b/lib/cli/qdisc/hfsc.c new file mode 100644 index 0000000..9ab7f7e --- /dev/null +++ b/lib/cli/qdisc/hfsc.c @@ -0,0 +1,249 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2014 Cong Wang + */ + +#include "nl-default.h" + +#include + +#include +#include +#include + +static void print_qdisc_usage(void) +{ + printf( +"Usage: nl-qdisc-add [...] hfsc [OPTIONS]...\n" +"\n" +"OPTIONS\n" +" --help Show this help text.\n" +" --default=ID Default class for unclassified traffic.\n" +"\n" +"EXAMPLE" +" # Create hfsc root qdisc 1: and direct unclassified traffic to class 1:10\n" +" nl-qdisc-add --dev=eth1 --parent=root --handle=1: hfsc --default=10\n"); +} + +static void hfsc_parse_qdisc_argv(struct rtnl_tc *tc, int argc, char **argv) +{ + struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc; + + for (;;) { + int c, optidx = 0; + enum { + ARG_DEFAULT = 257, + }; + static struct option long_opts[] = { + { "help", 0, 0, 'h' }, + { "default", 1, 0, ARG_DEFAULT }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "hv", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'h': + print_qdisc_usage(); + return; + + case ARG_DEFAULT: + rtnl_qdisc_hfsc_set_defcls(qdisc, nl_cli_parse_u32(optarg)); + break; + } + } +} + +static void print_class_usage(void) +{ + printf( +"Usage: nl-class-add [...] hfsc [OPTIONS]...\n" +"\n" +"OPTIONS\n" +" --help Show this help text.\n" +" --ls=SC Link-sharing service curve\n" +" --rt=SC Real-time service curve\n" +" --sc=SC Specifiy both of the above\n" +" --ul=SC Upper limit\n" +" where SC := [ [ m1 bits ] d usec ] m2 bits\n" +"\n" +"EXAMPLE" +" # Attach class 1:1 to hfsc qdisc 1: and use rt and ls curve\n" +" nl-class-add --dev=eth1 --parent=1: --classid=1:1 hfsc --sc=m1:250,d:8,m2:100\n"); +} + +static int +hfsc_get_sc(char *optarg, struct tc_service_curve *sc) +{ + unsigned int m1 = 0, d = 0, m2 = 0; + char *tmp = strdup(optarg); + char *p, *endptr; + char *pp = tmp; + + if (!tmp) + return -ENOMEM; + + p = strstr(pp, "m1:"); + if (p) { + char *q; + p += 3; + if (*p == 0) + goto err; + q = strchr(p, ','); + if (!q) + goto err; + *q = 0; + m1 = strtoul(p, &endptr, 10); + if (endptr == p) + goto err; + pp = q + 1; + } + + p = strstr(pp, "d:"); + if (p) { + char *q; + p += 2; + if (*p == 0) + goto err; + q = strchr(p, ','); + if (!q) + goto err; + *q = 0; + d = strtoul(p, &endptr, 10); + if (endptr == p) + goto err; + pp = q + 1; + } + + p = strstr(pp, "m2:"); + if (p) { + p += 3; + if (*p == 0) + goto err; + m2 = strtoul(p, &endptr, 10); + if (endptr == p) + goto err; + } else + goto err; + + free(tmp); + sc->m1 = m1; + sc->d = d; + sc->m2 = m2; + return 0; + +err: + free(tmp); + return -EINVAL; +} + +static void hfsc_parse_class_argv(struct rtnl_tc *tc, int argc, char **argv) +{ + struct rtnl_class *class = (struct rtnl_class *) tc; + int arg_ok = 0, ret = -EINVAL; + + for (;;) { + int c, optidx = 0; + enum { + ARG_RT = 257, + ARG_LS = 258, + ARG_SC, + ARG_UL, + }; + static struct option long_opts[] = { + { "help", 0, 0, 'h' }, + { "rt", 1, 0, ARG_RT }, + { "ls", 1, 0, ARG_LS }, + { "sc", 1, 0, ARG_SC }, + { "ul", 1, 0, ARG_UL }, + { 0, 0, 0, 0 } + }; + struct tc_service_curve tsc; + + c = getopt_long(argc, argv, "h", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'h': + print_class_usage(); + return; + + case ARG_RT: + ret = hfsc_get_sc(optarg, &tsc); + if (ret < 0) { + nl_cli_fatal(ret, "Unable to parse sc " + "\"%s\": Invalid format.", optarg); + } + + rtnl_class_hfsc_set_rsc(class, &tsc); + arg_ok++; + break; + + case ARG_LS: + ret = hfsc_get_sc(optarg, &tsc); + if (ret < 0) { + nl_cli_fatal(ret, "Unable to parse sc " + "\"%s\": Invalid format.", optarg); + } + + rtnl_class_hfsc_set_fsc(class, &tsc); + arg_ok++; + break; + + case ARG_SC: + ret = hfsc_get_sc(optarg, &tsc); + if (ret < 0) { + nl_cli_fatal(ret, "Unable to parse sc " + "\"%s\": Invalid format.", optarg); + } + + rtnl_class_hfsc_set_rsc(class, &tsc); + rtnl_class_hfsc_set_fsc(class, &tsc); + arg_ok++; + break; + + case ARG_UL: + ret = hfsc_get_sc(optarg, &tsc); + if (ret < 0) { + nl_cli_fatal(ret, "Unable to parse sc " + "\"%s\": Invalid format.", optarg); + } + + rtnl_class_hfsc_set_usc(class, &tsc); + arg_ok++; + break; + } + } + + if (!arg_ok) + nl_cli_fatal(ret, "Invalid arguments"); +} + +static struct nl_cli_tc_module hfsc_qdisc_module = +{ + .tm_name = "hfsc", + .tm_type = RTNL_TC_TYPE_QDISC, + .tm_parse_argv = hfsc_parse_qdisc_argv, +}; + +static struct nl_cli_tc_module hfsc_class_module = +{ + .tm_name = "hfsc", + .tm_type = RTNL_TC_TYPE_CLASS, + .tm_parse_argv = hfsc_parse_class_argv, +}; + +static void _nl_init hfsc_init(void) +{ + nl_cli_tc_register(&hfsc_qdisc_module); + nl_cli_tc_register(&hfsc_class_module); +} + +static void _nl_exit hfsc_exit(void) +{ + nl_cli_tc_unregister(&hfsc_class_module); + nl_cli_tc_unregister(&hfsc_qdisc_module); +} diff --git a/lib/cli/qdisc/htb.c b/lib/cli/qdisc/htb.c index 1751595..5ca6ae5 100644 --- a/lib/cli/qdisc/htb.c +++ b/lib/cli/qdisc/htb.c @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/lib/htb.c HTB module for CLI lib - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2010-2011 Thomas Graf */ +#include "nl-default.h" + #include #include #include @@ -44,7 +40,7 @@ static void htb_parse_qdisc_argv(struct rtnl_tc *tc, int argc, char **argv) { "default", 1, 0, ARG_DEFAULT }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "hv", long_opts, &optidx); if (c == -1) break; @@ -62,7 +58,7 @@ static void htb_parse_qdisc_argv(struct rtnl_tc *tc, int argc, char **argv) rtnl_htb_set_defcls(qdisc, nl_cli_parse_u32(optarg)); break; } - } + } } static void print_class_usage(void) @@ -109,7 +105,7 @@ static void htb_parse_class_argv(struct rtnl_tc *tc, int argc, char **argv) { "cburst", 1, 0, ARG_CBURST }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "h", long_opts, &optidx); if (c == -1) break; @@ -173,7 +169,7 @@ static void htb_parse_class_argv(struct rtnl_tc *tc, int argc, char **argv) rtnl_htb_set_cbuffer(class, rate); break; } - } + } } static struct nl_cli_tc_module htb_qdisc_module = @@ -190,13 +186,13 @@ static struct nl_cli_tc_module htb_class_module = .tm_parse_argv = htb_parse_class_argv, }; -static void __init htb_init(void) +static void _nl_init htb_init(void) { nl_cli_tc_register(&htb_qdisc_module); nl_cli_tc_register(&htb_class_module); } -static void __exit htb_exit(void) +static void _nl_exit htb_exit(void) { nl_cli_tc_unregister(&htb_class_module); nl_cli_tc_unregister(&htb_qdisc_module); diff --git a/lib/cli/qdisc/ingress.c b/lib/cli/qdisc/ingress.c new file mode 100644 index 0000000..9c09c4f --- /dev/null +++ b/lib/cli/qdisc/ingress.c @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Cong Wang + */ + +#include "nl-default.h" + +#include +#include + +static void print_usage(void) +{ + printf( +"Usage: nl-qdisc-add [...] ingress\n" +"\n" +"OPTIONS\n" +" --help Show this help text.\n" +"\n" +"EXAMPLE" +" # Attach ingress to eth1\n" +" nl-qdisc-add --dev=eth1 --parent=root ingress\n"); +} + +static void ingress_parse_argv(struct rtnl_tc *tc, int argc, char **argv) +{ + for (;;) { + int c, optidx = 0; + static struct option long_opts[] = { + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "h", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'h': + print_usage(); + return; + } + } +} + +static struct nl_cli_tc_module ingress_module = +{ + .tm_name = "ingress", + .tm_type = RTNL_TC_TYPE_QDISC, + .tm_parse_argv = ingress_parse_argv, +}; + +static void _nl_init ingress_init(void) +{ + nl_cli_tc_register(&ingress_module); +} + +static void _nl_exit ingress_exit(void) +{ + nl_cli_tc_unregister(&ingress_module); +} diff --git a/lib/cli/qdisc/pfifo.c b/lib/cli/qdisc/pfifo.c index 02c4d22..fbaa872 100644 --- a/lib/cli/qdisc/pfifo.c +++ b/lib/cli/qdisc/pfifo.c @@ -1,15 +1,10 @@ - +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/lib/pfifo.c pfifo module for CLI lib - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2010-2011 Thomas Graf */ +#include "nl-default.h" + #include #include #include @@ -42,7 +37,7 @@ static void pfifo_parse_argv(struct rtnl_tc *tc, int argc, char **argv) { "limit", 1, 0, ARG_LIMIT }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "h", long_opts, &optidx); if (c == -1) break; @@ -56,7 +51,7 @@ static void pfifo_parse_argv(struct rtnl_tc *tc, int argc, char **argv) rtnl_qdisc_fifo_set_limit(qdisc, nl_cli_parse_u32(optarg)); break; } - } + } } static struct nl_cli_tc_module pfifo_module = @@ -66,12 +61,12 @@ static struct nl_cli_tc_module pfifo_module = .tm_parse_argv = pfifo_parse_argv, }; -static void __init pfifo_init(void) +static void _nl_init pfifo_init(void) { nl_cli_tc_register(&pfifo_module); } -static void __exit pfifo_exit(void) +static void _nl_exit pfifo_exit(void) { nl_cli_tc_unregister(&pfifo_module); } diff --git a/lib/cli/qdisc/plug.c b/lib/cli/qdisc/plug.c index 2b8d5d6..212a6cf 100644 --- a/lib/cli/qdisc/plug.c +++ b/lib/cli/qdisc/plug.c @@ -1,15 +1,10 @@ - +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/lib/cli/qdisc/plug.c plug module for CLI lib - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2012 Shriram Rajagopalan */ +#include "nl-default.h" + #include #include #include @@ -66,7 +61,7 @@ static void plug_parse_argv(struct rtnl_tc *tc, int argc, char **argv) { "release-indefinite", 0, 0, ARG_RELEASE_INDEFINITE }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "h", long_opts, &optidx); if (c == -1) break; @@ -85,14 +80,14 @@ static void plug_parse_argv(struct rtnl_tc *tc, int argc, char **argv) break; case ARG_RELEASE_ONE: - rtnl_qdisc_plug_release_one(qdisc); + rtnl_qdisc_plug_release_one(qdisc); break; case ARG_RELEASE_INDEFINITE: rtnl_qdisc_plug_release_indefinite(qdisc); break; } - } + } } static struct nl_cli_tc_module plug_module = @@ -102,12 +97,12 @@ static struct nl_cli_tc_module plug_module = .tm_parse_argv = plug_parse_argv, }; -static void __init plug_init(void) +static void _nl_init plug_init(void) { nl_cli_tc_register(&plug_module); } -static void __exit plug_exit(void) +static void _nl_exit plug_exit(void) { nl_cli_tc_unregister(&plug_module); } diff --git a/lib/data.c b/lib/data.c index 1a3a3fb..1052578 100644 --- a/lib/data.c +++ b/lib/data.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/data.c Abstract Data - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -27,10 +21,16 @@ * ~~~~ */ -#include +#include "nl-default.h" + +#include + #include +#include +#include #include -#include + +#include "nl-priv-dynamic-core/nl-core.h" /** * @name General @@ -47,7 +47,7 @@ * * @return Newly allocated data handle or NULL */ -struct nl_data *nl_data_alloc(void *buf, size_t size) +struct nl_data *nl_data_alloc(const void *buf, size_t size) { struct nl_data *data; @@ -81,7 +81,7 @@ errout: * @see nla_data_alloc * @return Newly allocated data handle or NULL */ -struct nl_data *nl_data_alloc_attr(struct nlattr *nla) +struct nl_data *nl_data_alloc_attr(const struct nlattr *nla) { return nl_data_alloc(nla_data(nla), nla_len(nla)); } @@ -92,7 +92,7 @@ struct nl_data *nl_data_alloc_attr(struct nlattr *nla) * * @return Cloned object or NULL */ -struct nl_data *nl_data_clone(struct nl_data *src) +struct nl_data *nl_data_clone(const struct nl_data *src) { return nl_data_alloc(src->d_data, src->d_size); } @@ -108,18 +108,19 @@ struct nl_data *nl_data_clone(struct nl_data *src) * * @return 0 on success or a negative error code */ -int nl_data_append(struct nl_data *data, void *buf, size_t size) +int nl_data_append(struct nl_data *data, const void *buf, size_t size) { if (size > 0) { - data->d_data = realloc(data->d_data, data->d_size + size); - if (!data->d_data) + char *d_data = realloc(data->d_data, data->d_size + size); + if (!d_data) return -NLE_NOMEM; if (buf) - memcpy(data->d_data + data->d_size, buf, size); + memcpy(d_data + data->d_size, buf, size); else - memset(data->d_data + data->d_size, 0, size); + memset(d_data + data->d_size, 0, size); + data->d_data = d_data; data->d_size += size; } @@ -150,9 +151,11 @@ void nl_data_free(struct nl_data *data) * @arg data Abstract data object. * @return Data buffer or NULL if empty. */ -void *nl_data_get(struct nl_data *data) +void *nl_data_get(const struct nl_data *data) { - return data->d_size > 0 ? data->d_data : NULL; + if (data->d_size > 0) + return (void*)data->d_data; + return NULL; } /** @@ -160,7 +163,7 @@ void *nl_data_get(struct nl_data *data) * @arg data Abstract data object. * @return Size of data buffer. */ -size_t nl_data_get_size(struct nl_data *data) +size_t nl_data_get_size(const struct nl_data *data) { return data->d_size; } @@ -180,10 +183,10 @@ size_t nl_data_get_size(struct nl_data *data) * a is found, respectively, to be less than, to match, or * be greater than b. */ -int nl_data_cmp(struct nl_data *a, struct nl_data *b) +int nl_data_cmp(const struct nl_data *a, const struct nl_data *b) { - void *a_ = nl_data_get(a); - void *b_ = nl_data_get(b); + const void *a_ = nl_data_get(a); + const void *b_ = nl_data_get(b); if (a_ && b_) return memcmp(a_, b_, nl_data_get_size(a)); diff --git a/lib/error.c b/lib/error.c index f30b9a5..9b6d806 100644 --- a/lib/error.c +++ b/lib/error.c @@ -1,15 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/error.c Error Handling - * - * 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 Thomas Graf */ -#include +#include "nl-default.h" + #include static const char *errmsg[NLE_MAX+1] = { @@ -47,6 +42,7 @@ static const char *errmsg[NLE_MAX+1] = { [NLE_NODEV] = "No such device", [NLE_IMMUTABLE] = "Immutable attribute", [NLE_DUMP_INTR] = "Dump inconsistency detected, interrupted", +[NLE_ATTRSIZE] = "Attribute max length exceeded", }; /** diff --git a/lib/fib_lookup/lookup.c b/lib/fib_lookup/lookup.c index 3d07317..7ff2684 100644 --- a/lib/fib_lookup/lookup.c +++ b/lib/fib_lookup/lookup.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/fib_lookup/lookup.c FIB Lookup - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -16,7 +10,8 @@ * @{ */ -#include +#include "nl-default.h" + #include #include #include @@ -26,7 +21,24 @@ #include #include +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-priv-dynamic-core/cache-api.h" +#include "nl-priv-dynamic-core/nl-core.h" + /** @cond SKIP */ +struct flnl_result +{ + NLHDR_COMMON + + struct flnl_request * fr_req; + uint8_t fr_table_id; + uint8_t fr_prefixlen; + uint8_t fr_nh_sel; + uint8_t fr_type; + uint8_t fr_scope; + uint32_t fr_error; +}; + static struct nl_cache_ops fib_lookup_ops; static struct nl_object_ops result_obj_ops; @@ -60,11 +72,13 @@ static int result_clone(struct nl_object *_dst, struct nl_object *_src) struct flnl_result *dst = nl_object_priv(_dst); struct flnl_result *src = nl_object_priv(_src); - if (src->fr_req) - if (!(dst->fr_req = (struct flnl_request *) - nl_object_clone(OBJ_CAST(src->fr_req)))) + dst->fr_req = NULL; + + if (src->fr_req) { + if (!(dst->fr_req = (struct flnl_request *) nl_object_clone(OBJ_CAST(src->fr_req)))) return -NLE_NOMEM; - + } + return 0; } @@ -133,7 +147,7 @@ static void result_dump_line(struct nl_object *obj, struct nl_dump_params *p) nl_rtntype2str(res->fr_type, buf, sizeof(buf))); nl_dump(p, "scope %s error %s (%d)\n", rtnl_scope2str(res->fr_scope, buf, sizeof(buf)), - strerror_r(-res->fr_error, buf, sizeof(buf)), res->fr_error); + nl_strerror_l(-res->fr_error), res->fr_error); } static void result_dump_details(struct nl_object *obj, struct nl_dump_params *p) @@ -141,8 +155,8 @@ static void result_dump_details(struct nl_object *obj, struct nl_dump_params *p) result_dump_line(obj, p); } -static int result_compare(struct nl_object *_a, struct nl_object *_b, - uint32_t attrs, int flags) +static uint64_t result_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) { return 0; } @@ -270,7 +284,7 @@ int flnl_lookup(struct nl_sock *sk, struct flnl_request *req, if (err < 0) return err; - return nl_cache_pickup(sk, cache); + return nl_cache_pickup_checkdup(sk, cache); } /** @} */ @@ -336,12 +350,12 @@ static struct nl_cache_ops fib_lookup_ops = { .co_obj_ops = &result_obj_ops, }; -static void __init fib_lookup_init(void) +static void _nl_init fib_lookup_init(void) { nl_cache_mngt_register(&fib_lookup_ops); } -static void __exit fib_lookup_exit(void) +static void _nl_exit fib_lookup_exit(void) { nl_cache_mngt_unregister(&fib_lookup_ops); } diff --git a/lib/fib_lookup/request.c b/lib/fib_lookup/request.c index 1b021b6..81b7ba2 100644 --- a/lib/fib_lookup/request.c +++ b/lib/fib_lookup/request.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/fib_lookup/request.c FIB Lookup Request - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf */ @@ -16,16 +10,31 @@ * @{ */ -#include +#include "nl-default.h" + #include #include #include #include #include +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/object-api.h" + static struct nl_object_ops request_obj_ops; /** @cond SKIP */ +struct flnl_request +{ + NLHDR_COMMON + + struct nl_addr * lr_addr; + uint32_t lr_fwmark; + uint8_t lr_tos; + uint8_t lr_scope; + uint8_t lr_table; +}; + #define REQUEST_ATTR_ADDR 0x01 #define REQUEST_ATTR_FWMARK 0x02 #define REQUEST_ATTR_TOS 0x04 @@ -46,29 +55,30 @@ static int request_clone(struct nl_object *_dst, struct nl_object *_src) struct flnl_request *dst = nl_object_priv(_dst); struct flnl_request *src = nl_object_priv(_src); - if (src->lr_addr) + dst->lr_addr = NULL; + + if (src->lr_addr) { if (!(dst->lr_addr = nl_addr_clone(src->lr_addr))) return -NLE_NOMEM; + } return 0; } -static int request_compare(struct nl_object *_a, struct nl_object *_b, - uint32_t attrs, int flags) +static uint64_t request_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) { struct flnl_request *a = (struct flnl_request *) _a; struct flnl_request *b = (struct flnl_request *) _b; - int diff = 0; - -#define REQ_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, REQUEST_ATTR_##ATTR, a, b, EXPR) - - diff |= REQ_DIFF(FWMARK, a->lr_fwmark != b->lr_fwmark); - diff |= REQ_DIFF(TOS, a->lr_tos != b->lr_tos); - diff |= REQ_DIFF(SCOPE, a->lr_scope != b->lr_scope); - diff |= REQ_DIFF(TABLE, a->lr_table != b->lr_table); - diff |= REQ_DIFF(ADDR, nl_addr_cmp(a->lr_addr, b->lr_addr)); - -#undef REQ_DIFF + uint64_t diff = 0; + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(REQUEST_ATTR_FWMARK, a->lr_fwmark != b->lr_fwmark); + diff |= _DIFF(REQUEST_ATTR_TOS, a->lr_tos != b->lr_tos); + diff |= _DIFF(REQUEST_ATTR_SCOPE, a->lr_scope != b->lr_scope); + diff |= _DIFF(REQUEST_ATTR_TABLE, a->lr_table != b->lr_table); + diff |= _DIFF(REQUEST_ATTR_ADDR, nl_addr_cmp(a->lr_addr, b->lr_addr)); +#undef _DIFF return diff; } diff --git a/lib/genl/ctrl.c b/lib/genl/ctrl.c index ce07f1d..1747076 100644 --- a/lib/genl/ctrl.c +++ b/lib/genl/ctrl.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/genl/ctrl.c Generic Netlink Controller - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -21,7 +15,8 @@ * @{ */ -#include +#include "nl-default.h" + #include #include #include @@ -29,6 +24,10 @@ #include #include +#include "nl-genl.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/object-api.h" + /** @cond SKIP */ #define CTRL_VERSION 0x0001 @@ -523,6 +522,12 @@ static struct genl_ops genl_ops = { extern struct nl_object_ops genl_family_ops; +#define GENL_FAMILY(id, name) \ + { \ + { id, NL_ACT_UNSPEC, name }, \ + END_OF_MSGTYPES_LIST, \ + } + static struct nl_cache_ops genl_ctrl_ops = { .co_name = "genl/family", .co_hdrsize = GENL_HDRSIZE(0), @@ -533,12 +538,12 @@ static struct nl_cache_ops genl_ctrl_ops = { .co_obj_ops = &genl_family_ops, }; -static void __init ctrl_init(void) +static void _nl_init ctrl_init(void) { genl_register(&genl_ctrl_ops); } -static void __exit ctrl_exit(void) +static void _nl_exit ctrl_exit(void) { genl_unregister(&genl_ctrl_ops); } diff --git a/lib/genl/family.c b/lib/genl/family.c index 897c809..1749472 100644 --- a/lib/genl/family.c +++ b/lib/genl/family.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/genl/family.c Generic Netlink Family - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -18,13 +12,26 @@ * @{ */ -#include +#include "nl-default.h" + #include #include #include #include +#include "nl-genl.h" +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-priv-dynamic-core/nl-core.h" + /** @cond SKIP */ +struct genl_family_op +{ + uint32_t o_id; + uint32_t o_flags; + + struct nl_list_head o_list; +}; + #define FAMILY_ATTR_ID 0x01 #define FAMILY_ATTR_NAME 0x02 #define FAMILY_ATTR_VERSION 0x04 @@ -71,6 +78,9 @@ static int family_clone(struct nl_object *_dst, struct nl_object *_src) struct genl_family_grp *grp; int err; + nl_init_list_head(&dst->gf_ops); + nl_init_list_head(&dst->gf_mc_grps); + nl_list_for_each_entry(ops, &src->gf_ops, o_list) { err = genl_family_add_op(dst, ops->o_id, ops->o_flags); if (err < 0) @@ -96,10 +106,10 @@ static void family_dump_line(struct nl_object *obj, struct nl_dump_params *p) } static const struct trans_tbl ops_flags[] = { - __ADD(GENL_ADMIN_PERM, admin_perm) - __ADD(GENL_CMD_CAP_DO, has_doit) - __ADD(GENL_CMD_CAP_DUMP, has_dump) - __ADD(GENL_CMD_CAP_HASPOL, has_policy) + __ADD(GENL_ADMIN_PERM, admin_perm), + __ADD(GENL_CMD_CAP_DO, has_doit), + __ADD(GENL_CMD_CAP_DUMP, has_dump), + __ADD(GENL_CMD_CAP_HASPOL, has_policy), }; static char *ops_flags2str(int flags, char *buf, size_t len) @@ -147,22 +157,20 @@ static void family_dump_stats(struct nl_object *obj, struct nl_dump_params *p) family_dump_details(obj, p); } -static int family_compare(struct nl_object *_a, struct nl_object *_b, - uint32_t attrs, int flags) +static uint64_t family_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) { struct genl_family *a = (struct genl_family *) _a; struct genl_family *b = (struct genl_family *) _b; - int diff = 0; - -#define FAM_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, FAMILY_ATTR_##ATTR, a, b, EXPR) + uint64_t diff = 0; - diff |= FAM_DIFF(ID, a->gf_id != b->gf_id); - diff |= FAM_DIFF(VERSION, a->gf_version != b->gf_version); - diff |= FAM_DIFF(HDRSIZE, a->gf_hdrsize != b->gf_hdrsize); - diff |= FAM_DIFF(MAXATTR, a->gf_maxattr != b->gf_maxattr); - diff |= FAM_DIFF(NAME, strcmp(a->gf_name, b->gf_name)); - -#undef FAM_DIFF +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(FAMILY_ATTR_ID, a->gf_id != b->gf_id); + diff |= _DIFF(FAMILY_ATTR_VERSION, a->gf_version != b->gf_version); + diff |= _DIFF(FAMILY_ATTR_HDRSIZE, a->gf_hdrsize != b->gf_hdrsize); + diff |= _DIFF(FAMILY_ATTR_MAXATTR, a->gf_maxattr != b->gf_maxattr); + diff |= _DIFF(FAMILY_ATTR_NAME, strcmp(a->gf_name, b->gf_name)); +#undef _DIFF return diff; } @@ -215,7 +223,7 @@ unsigned int genl_family_get_id(struct genl_family *family) if (family->ce_mask & FAMILY_ATTR_ID) return family->gf_id; else - return GENL_ID_GENERATE; + return 0; } /** @@ -257,7 +265,7 @@ char *genl_family_get_name(struct genl_family *family) */ void genl_family_set_name(struct genl_family *family, const char *name) { - strncpy(family->gf_name, name, GENL_NAMSIZ-1); + _nl_strncpy_trunc(family->gf_name, name, GENL_NAMSIZ); family->ce_mask |= FAMILY_ATTR_NAME; } @@ -330,7 +338,7 @@ uint32_t genl_family_get_maxattr(struct genl_family *family) if (family->ce_mask & FAMILY_ATTR_MAXATTR) return family->gf_maxattr; else - return family->gf_maxattr; + return 0; } void genl_family_set_maxattr(struct genl_family *family, uint32_t maxattr) @@ -364,16 +372,20 @@ int genl_family_add_op(struct genl_family *family, int id, int flags) } int genl_family_add_grp(struct genl_family *family, uint32_t id, - const char *name) + const char *name) { - struct genl_family_grp *grp; + struct genl_family_grp *grp; + + if ( !name + || strlen (name) >= GENL_NAMSIZ) + return -NLE_INVAL; grp = calloc(1, sizeof(*grp)); if (grp == NULL) return -NLE_NOMEM; grp->id = id; - strncpy(grp->name, name, GENL_NAMSIZ - 1); + _nl_strncpy_assert(grp->name, name, GENL_NAMSIZ); nl_list_add_tail(&grp->list, &family->gf_mc_grps); diff --git a/lib/genl/genl.c b/lib/genl/genl.c index 0c9b11e..2e52aae 100644 --- a/lib/genl/genl.c +++ b/lib/genl/genl.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/genl/genl.c Generic Netlink - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -15,11 +9,15 @@ * @{ */ -#include +#include "nl-default.h" + #include #include #include +#include "nl-genl.h" +#include "nl-aux-core/nl-core.h" + /** * @name Generic Netlink Socket * @{ @@ -79,7 +77,8 @@ int genl_connect(struct nl_sock *sk) * * @see nl_send_simple() * - * @return 0 on success or a negative error code. + * @return 0 on success or a negative error code. Due to a bug, this function + * returns the number of bytes sent. Treat any non-negative number as success. */ int genl_send_simple(struct nl_sock *sk, int family, int cmd, int version, int flags) @@ -149,7 +148,7 @@ int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen) * @return 0 on success or a negative error code. */ int genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype, - struct nla_policy *policy) + const struct nla_policy *policy) { struct genlmsghdr *ghdr; @@ -177,7 +176,7 @@ int genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype, * @code * struct nlattr *attrs[MY_TYPE_MAX+1]; * - * if ((err = genlsmg_parse(nlmsg_nlh(msg), sizeof(struct my_hdr), attrs, + * if ((err = genlmsg_parse(nlmsg_hdr(msg), sizeof(struct my_hdr), attrs, * MY_TYPE_MAX, attr_policy)) < 0) * // ERROR * @endcode @@ -189,7 +188,7 @@ int genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype, * @return 0 on success or a negative error code. */ int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], - int maxtype, struct nla_policy *policy) + int maxtype, const struct nla_policy *policy) { struct genlmsghdr *ghdr; @@ -258,7 +257,7 @@ void *genlmsg_user_hdr(const struct genlmsghdr *gnlh) */ void *genlmsg_user_data(const struct genlmsghdr *gnlh, const int hdrlen) { - return genlmsg_user_hdr(gnlh) + NLMSG_ALIGN(hdrlen); + return (char *) genlmsg_user_hdr(gnlh) + NLMSG_ALIGN(hdrlen); } /** @@ -362,7 +361,7 @@ void *genlmsg_put(struct nl_msg *msg, uint32_t port, uint32_t seq, int family, NL_DBG(2, "msg %p: Added generic netlink header cmd=%d version=%d\n", msg, cmd, version); - return nlmsg_data(nlh) + GENL_HDRLEN; + return (char *) nlmsg_data(nlh) + GENL_HDRLEN; } /** @} */ diff --git a/lib/genl/mngt.c b/lib/genl/mngt.c index 3648663..e55256c 100644 --- a/lib/genl/mngt.c +++ b/lib/genl/mngt.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/genl/mngt.c Generic Netlink Management - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -18,7 +12,8 @@ * @{ */ -#include +#include "nl-default.h" + #include #include #include @@ -26,6 +21,8 @@ #include #include +#include "nl-genl.h" + /** @cond SKIP */ static NL_LIST_HEAD(genl_ops_list); @@ -45,41 +42,45 @@ static struct genl_cmd *lookup_cmd(struct genl_ops *ops, int cmd_id) } static int cmd_msg_parser(struct sockaddr_nl *who, struct nlmsghdr *nlh, - struct genl_ops *ops, struct nl_cache_ops *cache_ops, void *arg) + struct genl_ops *ops, struct nl_cache_ops *cache_ops, void *arg) { + _nl_auto_free struct nlattr **tb_free = NULL; int err; struct genlmsghdr *ghdr; struct genl_cmd *cmd; + struct nlattr **tb; ghdr = genlmsg_hdr(nlh); - if (!(cmd = lookup_cmd(ops, ghdr->cmd))) { - err = -NLE_MSGTYPE_NOSUPPORT; - goto errout; - } + if (!(cmd = lookup_cmd(ops, ghdr->cmd))) + return -NLE_MSGTYPE_NOSUPPORT; if (cmd->c_msg_parser == NULL) - err = -NLE_OPNOTSUPP; - else { - struct nlattr *tb[cmd->c_maxattr + 1]; + return -NLE_OPNOTSUPP; + + tb = _nl_malloc_maybe_a (300, (((size_t) cmd->c_maxattr) + 1u) * sizeof (struct nlattr *), &tb_free); + if (!tb) + return -NLE_NOMEM; + + err = nlmsg_parse(nlh, + GENL_HDRSIZE(ops->o_hdrsize), + tb, + cmd->c_maxattr, + cmd->c_attr_policy); + if (err < 0) + return err; + + { struct genl_info info = { - .who = who, - .nlh = nlh, + .who = who, + .nlh = nlh, .genlhdr = ghdr, .userhdr = genlmsg_user_hdr(ghdr), - .attrs = tb, + .attrs = tb, }; - err = nlmsg_parse(nlh, GENL_HDRSIZE(ops->o_hdrsize), tb, cmd->c_maxattr, - cmd->c_attr_policy); - if (err < 0) - goto errout; - - err = cmd->c_msg_parser(cache_ops, cmd, &info, arg); + return cmd->c_msg_parser(cache_ops, cmd, &info, arg); } -errout: - return err; - } static int genl_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, @@ -126,13 +127,13 @@ char *genl_op2name(int family, int op, char *buf, size_t len) cmd = &ops->o_cmds[i]; if (cmd->c_id == op) { - strncpy(buf, cmd->c_name, len - 1); + _nl_strncpy_trunc(buf, cmd->c_name, len); return buf; } } } - strncpy(buf, "unknown", len - 1); + _nl_strncpy_trunc(buf, "unknown", len); return NULL; } @@ -307,13 +308,14 @@ static int __genl_ops_resolve(struct nl_cache *ctrl, struct genl_ops *ops) return -NLE_OBJ_NOTFOUND; } +/* WARNING: this symbol is wrongly exported in libnl-genl-3.sym. */ int genl_resolve_id(struct genl_ops *ops) { struct nl_sock *sk; int err = 0; /* Check if resolved already */ - if (ops->o_id != GENL_ID_GENERATE) + if (ops->o_id != 0) return 0; if (!ops->o_name) diff --git a/lib/genl/nl-genl.h b/lib/genl/nl-genl.h new file mode 100644 index 0000000..2ad7cd0 --- /dev/null +++ b/lib/genl/nl-genl.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2003-2013 Thomas Graf + */ + +#ifndef NETLINK_GENL_PRIV_H_ +#define NETLINK_GENL_PRIV_H_ + +#include + +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-priv-dynamic-core/cache-api.h" + +#define GENL_HDRSIZE(hdrlen) (GENL_HDRLEN + (hdrlen)) + +/*****************************************************************************/ + +/* WARNING: this symbol is wrongly exported in libnl-genl-3.sym. */ +extern int genl_resolve_id(struct genl_ops *ops); + +/*****************************************************************************/ + +#define GENL_OP_HAS_POLICY 1 +#define GENL_OP_HAS_DOIT 2 +#define GENL_OP_HAS_DUMPIT 4 + +struct genl_family_grp { + struct genl_family *family; /* private */ + struct nl_list_head list; /* private */ + char name[GENL_NAMSIZ]; + u_int32_t id; +}; + +struct genl_family +{ + NLHDR_COMMON + + uint16_t gf_id; + char gf_name[GENL_NAMSIZ]; + uint32_t gf_version; + uint32_t gf_hdrsize; + uint32_t gf_maxattr; + + struct nl_list_head gf_ops; + struct nl_list_head gf_mc_grps; +}; + +#endif diff --git a/lib/handlers.c b/lib/handlers.c index e52c850..14dffba 100644 --- a/lib/handlers.c +++ b/lib/handlers.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/handlers.c default netlink message handlers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf */ @@ -25,17 +19,21 @@ * ~~~~ */ -#include +#include "nl-default.h" + #include #include #include #include +#include "nl-core.h" +#include "nl-priv-dynamic-core/nl-core.h" + static void print_header_content(FILE *ofd, struct nlmsghdr *n) { char flags[128]; char type[32]; - + fprintf(ofd, "type=%s length=%u flags=<%s> sequence-nr=%u pid=%u", nl_nlmsgtype2str(n->nlmsg_type, type, sizeof(type)), n->nlmsg_len, nl_nlmsg_flags2str(n->nlmsg_flags, flags, @@ -71,7 +69,7 @@ static int nl_overrun_handler_verbose(struct nl_msg *msg, void *arg) fprintf(ofd, "-- Error: Netlink Overrun: "); print_header_content(ofd, nlmsg_hdr(msg)); fprintf(ofd, "\n"); - + return NL_STOP; } @@ -79,10 +77,9 @@ static int nl_error_handler_verbose(struct sockaddr_nl *who, struct nlmsgerr *e, void *arg) { FILE *ofd = arg ? arg : stderr; - char buf[256]; fprintf(ofd, "-- Error received: %s\n-- Original message: ", - strerror_r(-e->error, buf, sizeof(buf))); + nl_strerror_l(-e->error)); print_header_content(ofd, &e->msg); fprintf(ofd, "\n"); @@ -107,7 +104,7 @@ static int nl_finish_handler_debug(struct nl_msg *msg, void *arg) fprintf(ofd, "-- Debug: End of multipart message block: "); print_header_content(ofd, nlmsg_hdr(msg)); fprintf(ofd, "\n"); - + return NL_STOP; } @@ -117,7 +114,7 @@ static int nl_msg_in_handler_debug(struct nl_msg *msg, void *arg) fprintf(ofd, "-- Debug: Received Message:\n"); nl_msg_dump(msg, ofd); - + return NL_OK; } @@ -203,7 +200,7 @@ struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind) int i; struct nl_cb *cb; - if (kind < 0 || kind > NL_CB_KIND_MAX) + if ((unsigned int) kind > NL_CB_KIND_MAX) return NULL; cb = calloc(1, sizeof(*cb)); @@ -211,6 +208,7 @@ struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind) return NULL; cb->cb_refcnt = 1; + cb->cb_active = NL_CB_TYPE_MAX + 1; for (i = 0; i <= NL_CB_TYPE_MAX; i++) nl_cb_set(cb, i, kind, NULL, NULL); @@ -229,7 +227,7 @@ struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind) struct nl_cb *nl_cb_clone(struct nl_cb *orig) { struct nl_cb *cb; - + cb = nl_cb_alloc(NL_CB_DEFAULT); if (!cb) return NULL; @@ -261,6 +259,17 @@ void nl_cb_put(struct nl_cb *cb) free(cb); } +/** + * Obtain type of current active callback + * @arg cb callback to query + * + * @return type or __NL_CB_TYPE_MAX if none active + */ +enum nl_cb_type nl_cb_active_type(struct nl_cb *cb) +{ + return cb->cb_active; +} + /** @} */ /** @@ -269,7 +278,7 @@ void nl_cb_put(struct nl_cb *cb) */ /** - * Set up a callback + * Set up a callback * @arg cb callback set * @arg type callback to modify * @arg kind kind of implementation @@ -281,10 +290,10 @@ void nl_cb_put(struct nl_cb *cb) int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func, void *arg) { - if (type < 0 || type > NL_CB_TYPE_MAX) + if ((unsigned int) type > NL_CB_TYPE_MAX) return -NLE_RANGE; - if (kind < 0 || kind > NL_CB_KIND_MAX) + if ((unsigned int) kind > NL_CB_KIND_MAX) return -NLE_RANGE; if (kind == NL_CB_CUSTOM) { @@ -331,7 +340,7 @@ int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind, int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind, nl_recvmsg_err_cb_t func, void *arg) { - if (kind < 0 || kind > NL_CB_KIND_MAX) + if ((unsigned int) kind > NL_CB_KIND_MAX) return -NLE_RANGE; if (kind == NL_CB_CUSTOM) { diff --git a/lib/hash.c b/lib/hash.c index 47c938b..94a73f8 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* * This code was taken from http://ccodearchive.net/info/hash.html * The original file was modified to remove unwanted code @@ -38,6 +39,8 @@ mixing with 12*3 instructions on 3 integers than you can with 3 instructions on 1 byte), but shoehorning those bytes into integers efficiently is messy. ------------------------------------------------------------------------------- */ +#include "nl-default.h" + #include #if HAVE_LITTLE_ENDIAN @@ -321,17 +324,17 @@ static uint32_t hashlittle( const void *key, size_t length, uint32_t *val2 ) /*-------------------------------- last block: affect all 32 bits of (c) */ switch(length) /* all the case statements fall through */ { - case 12: c+=((uint32_t)k[11])<<24; - case 11: c+=((uint32_t)k[10])<<16; - case 10: c+=((uint32_t)k[9])<<8; - case 9 : c+=k[8]; - case 8 : b+=((uint32_t)k[7])<<24; - case 7 : b+=((uint32_t)k[6])<<16; - case 6 : b+=((uint32_t)k[5])<<8; - case 5 : b+=k[4]; - case 4 : a+=((uint32_t)k[3])<<24; - case 3 : a+=((uint32_t)k[2])<<16; - case 2 : a+=((uint32_t)k[1])<<8; + case 12: c+=((uint32_t)k[11])<<24; /* fall through */ + case 11: c+=((uint32_t)k[10])<<16; /* fall through */ + case 10: c+=((uint32_t)k[9])<<8; /* fall through */ + case 9 : c+=k[8]; /* fall through */ + case 8 : b+=((uint32_t)k[7])<<24; /* fall through */ + case 7 : b+=((uint32_t)k[6])<<16; /* fall through */ + case 6 : b+=((uint32_t)k[5])<<8; /* fall through */ + case 5 : b+=k[4]; /* fall through */ + case 4 : a+=((uint32_t)k[3])<<24; /* fall through */ + case 3 : a+=((uint32_t)k[2])<<16; /* fall through */ + case 2 : a+=((uint32_t)k[1])<<8; /* fall through */ case 1 : a+=k[0]; break; case 0 : return c; @@ -451,18 +454,18 @@ static uint32_t hashbig( const void *key, size_t length, uint32_t *val2) /*-------------------------------- last block: affect all 32 bits of (c) */ switch(length) /* all the case statements fall through */ { - case 12: c+=k[11]; - case 11: c+=((uint32_t)k[10])<<8; - case 10: c+=((uint32_t)k[9])<<16; - case 9 : c+=((uint32_t)k[8])<<24; - case 8 : b+=k[7]; - case 7 : b+=((uint32_t)k[6])<<8; - case 6 : b+=((uint32_t)k[5])<<16; - case 5 : b+=((uint32_t)k[4])<<24; - case 4 : a+=k[3]; - case 3 : a+=((uint32_t)k[2])<<8; - case 2 : a+=((uint32_t)k[1])<<16; - case 1 : a+=((uint32_t)k[0])<<24; + case 12: c+=k[11]; /* fall through */ + case 11: c+=((uint32_t)k[10])<<8; /* fall through */ + case 10: c+=((uint32_t)k[9])<<16; /* fall through */ + case 9 : c+=((uint32_t)k[8])<<24; /* fall through */ + case 8 : b+=k[7]; /* fall through */ + case 7 : b+=((uint32_t)k[6])<<8; /* fall through */ + case 6 : b+=((uint32_t)k[5])<<16; /* fall through */ + case 5 : b+=((uint32_t)k[4])<<24; /* fall through */ + case 4 : a+=k[3]; /* fall through */ + case 3 : a+=((uint32_t)k[2])<<8; /* fall through */ + case 2 : a+=((uint32_t)k[1])<<16; /* fall through */ + case 1 : a+=((uint32_t)k[0])<<24; /* fall through */ break; case 0 : return c; } diff --git a/lib/hashtable.c b/lib/hashtable.c index 8b15925..7cb6984 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -1,19 +1,16 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink/hashtable.c Netlink hashtable Utilities - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2012 Cumulus Networks, Inc */ -#include -#include + +#include "nl-default.h" + #include #include #include +#include "nl-aux-core/nl-core.h" + /** * @ingroup core_types * @defgroup hashtable Hashtable @@ -58,15 +55,15 @@ void nl_hash_table_free(nl_hash_table_t *ht) int i; for(i = 0; i < ht->size; i++) { - nl_hash_node_t *node = ht->nodes[i]; - nl_hash_node_t *saved_node; - - while (node) { - saved_node = node; - node = node->next; - nl_object_put(saved_node->obj); - free(saved_node); - } + nl_hash_node_t *node = ht->nodes[i]; + nl_hash_node_t *saved_node; + + while (node) { + saved_node = node; + node = node->next; + nl_object_put(saved_node->obj); + free(saved_node); + } } free(ht->nodes); @@ -93,9 +90,9 @@ struct nl_object* nl_hash_table_lookup(nl_hash_table_t *ht, node = ht->nodes[key_hash]; while (node) { - if (nl_object_identical(node->obj, obj)) - return node->obj; - node = node->next; + if (nl_object_identical(node->obj, obj)) + return node->obj; + node = node->next; } return NULL; @@ -123,11 +120,11 @@ int nl_hash_table_add(nl_hash_table_t *ht, struct nl_object *obj) node = ht->nodes[key_hash]; while (node) { - if (nl_object_identical(node->obj, obj)) { - NL_DBG(2, "Warning: Add to hashtable found duplicate...\n"); - return -NLE_EXIST; - } - node = node->next; + if (nl_object_identical(node->obj, obj)) { + NL_DBG(2, "Warning: Add to hashtable found duplicate...\n"); + return -NLE_EXIST; + } + node = node->next; } NL_DBG (5, "adding cache entry of obj %p in table %p, with hash 0x%x\n", @@ -167,20 +164,20 @@ int nl_hash_table_del(nl_hash_table_t *ht, struct nl_object *obj) prev = node = ht->nodes[key_hash]; while (node) { - if (nl_object_identical(node->obj, obj)) { - nl_object_put(obj); + if (nl_object_identical(node->obj, obj)) { + nl_object_put(obj); - NL_DBG (5, "deleting cache entry of obj %p in table %p, with" - " hash 0x%x\n", obj, ht, key_hash); + NL_DBG (5, "deleting cache entry of obj %p in table %p, with" + " hash 0x%x\n", obj, ht, key_hash); - if (node == ht->nodes[key_hash]) - ht->nodes[key_hash] = node->next; - else - prev->next = node->next; + if (node == ht->nodes[key_hash]) + ht->nodes[key_hash] = node->next; + else + prev->next = node->next; - free(node); + free(node); - return 0; + return 0; } prev = node; node = node->next; @@ -191,7 +188,7 @@ int nl_hash_table_del(nl_hash_table_t *ht, struct nl_object *obj) uint32_t nl_hash(void *k, size_t length, uint32_t initval) { - return(__nl_hash(k, length, initval)); + return(__nl_hash((char *) k, length, initval)); } /** @} */ diff --git a/lib/idiag/idiag.c b/lib/idiag/idiag.c new file mode 100644 index 0000000..4f5d9f9 --- /dev/null +++ b/lib/idiag/idiag.c @@ -0,0 +1,276 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Sassano Systems LLC + */ + +/** + * @defgroup idiag Inet Diag library (libnl-idiag) + * @brief + * @{ + */ + +#include "nl-default.h" + +#include + +#include +#include +#include + +#include "nl-priv-dynamic-core/nl-core.h" + +/** + * @name Socket Creation + * @{ + */ + +/** + * Create and connect idiag netlink socket. + * @arg sk Netlink socket. + * + * Creates a NETLINK_INET_DIAG socket, binds the socket, and issues a connection + * attemp. + * + * @see nl_connect() + * + * @return 0 on success or a negative error code. + */ +int idiagnl_connect(struct nl_sock *sk) +{ + return nl_connect(sk, NETLINK_INET_DIAG); +} + +/** @} */ + +/** + * @name Sending + * @{ + */ + +/** + * Send trivial idiag netlink message + * @arg sk Netlink socket. + * @arg flags Message flags + * @arg family Address family + * @arg states Socket states to query + * @arg ext Inet Diag attribute extensions to query. Note that this only supports + * 8 bit arguments. Flags outside uint8_t range are silently ignored. + * + * @return 0 on success or a negative error code. Due to a bug, this function + * returns the number of bytes sent. Treat any non-negative number as success. + */ +int idiagnl_send_simple(struct nl_sock *sk, int flags, uint8_t family, + uint16_t states, uint16_t ext) +{ + struct inet_diag_req req; + memset(&req, 0, sizeof(req)); + + flags |= NLM_F_ROOT; + + req.idiag_family = family; + req.idiag_states = states; + req.idiag_ext = ext; + + return nl_send_simple(sk, TCPDIAG_GETSOCK, flags, &req, sizeof(req)); +} + +/** @} */ + +/** + * @name Inet Diag flag and attribute conversions + * @{ + */ + +static const struct trans_tbl idiag_states[] = { + __ADD(TCP_ESTABLISHED, established), + __ADD(TCP_SYN_SENT, syn_sent), + __ADD(TCP_SYN_RECV, syn_recv), + __ADD(TCP_FIN_WAIT1, fin_wait), + __ADD(TCP_FIN_WAIT2, fin_wait2), + __ADD(TCP_TIME_WAIT, time_wait), + __ADD(TCP_CLOSE, close), + __ADD(TCP_CLOSE_WAIT, close_wait), + __ADD(TCP_LAST_ACK, last_ack), + __ADD(TCP_LISTEN, listen), + __ADD(TCP_CLOSING, closing), +}; + +/** + * Convert inet diag socket states to strings. + * @arg state inetdiag socket state (e.g., TCP_ESTABLISHED) + * @arg buf output buffer which will hold string result + * @arg len length in bytes of the output buffer + * + * @return string representation of the inetdiag socket state or an empty + * string. + */ +char * idiagnl_state2str(int state, char *buf, size_t len) +{ + return __type2str(state, buf, len, idiag_states, + ARRAY_SIZE(idiag_states)); +} + +/** + * Convert inet diag socket state string to int. + * @arg name inetdiag socket state string + * + * @return the int representation of the socket state strign or a negative error + * code. + */ +int idiagnl_str2state(const char *name) +{ + return __str2type(name, idiag_states, ARRAY_SIZE(idiag_states)); +} + +static const struct trans_tbl idiag_timers[] = { + __ADD(IDIAGNL_TIMER_OFF, off), + __ADD(IDIAGNL_TIMER_ON, on), + __ADD(IDIAGNL_TIMER_KEEPALIVE, keepalive), + __ADD(IDIAGNL_TIMER_TIMEWAIT, timewait), + __ADD(IDIAGNL_TIMER_PERSIST, persist), + __ADD(IDIAGNL_TIMER_UNKNOWN, unknown), +}; + +/** + * Convert inet diag timer types to strings. + * @arg timer inetdiag timer (e.g., IDIAGNL_TIMER_ON) + * @arg buf output buffer which will hold string result + * @arg len length in bytes of the output buffer + * + * @return string representation of the inetdiag timer type or an empty string. + */ +char * idiagnl_timer2str(int timer, char *buf, size_t len) +{ + return __type2str(timer, buf, len, idiag_timers, + ARRAY_SIZE(idiag_timers)); +} + +/** + * Convert inet diag timer string to int. + * @arg name inetdiag timer string + * + * @return the int representation of the timer string or a negative error code. + */ +int idiagnl_str2timer(const char *name) +{ + return __str2type(name, idiag_timers, ARRAY_SIZE(idiag_timers)); +} + +static const struct trans_tbl idiag_attrs[] = { + __ADD(INET_DIAG_NONE, none), + __ADD(INET_DIAG_MEMINFO, meminfo), + __ADD(INET_DIAG_INFO, info), + __ADD(INET_DIAG_VEGASINFO, vegasinfo), + __ADD(INET_DIAG_CONG, congestion), + __ADD(INET_DIAG_TOS, tos), + __ADD(INET_DIAG_TCLASS, tclass), + __ADD(INET_DIAG_SKMEMINFO, skmeminfo), + __ADD(INET_DIAG_SHUTDOWN, shutdown), +}; + +/** + * Convert inet diag extension type to a string. + * @arg attrs inet diag extension type (e.g. INET_DIAG_MEMINFO) + * @arg buf output buffer which will hold string result + * @arg len length in bytes of the output buffer + * + * @return string representation of inet diag extension type or an empty string. + * @deprecated: don't use this function. It is not very useful and should + * never have been exposed as public API. + */ +char *idiagnl_attrs2str(int attrs, char *buf, size_t len) +{ + return __type2str(attrs, buf, len, idiag_attrs, ARRAY_SIZE(idiag_attrs)); +} + +static const struct trans_tbl idiag_exts[] = { + __ADD((1 << (INET_DIAG_MEMINFO - 1)), meminfo), + __ADD((1 << (INET_DIAG_INFO - 1)), info), + __ADD((1 << (INET_DIAG_VEGASINFO - 1)), vegasinfo), + __ADD((1 << (INET_DIAG_CONG - 1)), congestion), + __ADD((1 << (INET_DIAG_TOS - 1)), tos), + __ADD((1 << (INET_DIAG_TCLASS - 1)), tclass), + __ADD((1 << (INET_DIAG_SKMEMINFO - 1)), skmeminfo), + __ADD((1 << (INET_DIAG_SHUTDOWN - 1)), shutdown), +}; + +/** + * Convert inet diag extension flags to a string. + * @arg attrs inet diag extension flags (e.g. + * ( (1<<(INET_DIAG_MEMINFO-1)) | (1<<(INET_DIAG_CONG-1)) | (1<<(INET_DIAG_TOS-1)) ) ) + * @arg buf Output buffer to hold string representation + * @arg len length in bytes of the output buffer + */ +char *idiagnl_exts2str(uint8_t attrs, char *buf, size_t len) +{ + return __flags2str(attrs, buf, len, idiag_exts, ARRAY_SIZE(idiag_exts)); +} + +static const struct trans_tbl idiagnl_tcpstates[] = { + __ADD(TCP_CA_Open, open), + __ADD(TCP_CA_Disorder, disorder), + __ADD(TCP_CA_CWR, cwr), + __ADD(TCP_CA_Recovery, recovery), + __ADD(TCP_CA_Loss, loss), +}; + +/** + * Convert inetdiag tcp states to strings. + * @arg state TCP state (e.g., TCP_CA_Open) + * @arg buf output buffer which will hold string result + * @arg len length in bytes of the output buffer + */ +char *idiagnl_tcpstate2str(uint8_t state, char *buf, size_t len) +{ + return __type2str(state, buf, len, idiagnl_tcpstates, + ARRAY_SIZE(idiagnl_tcpstates)); +} + +static const struct trans_tbl idiagnl_tcpopt_attrs[] = { + __ADD(TCPI_OPT_TIMESTAMPS, timestamps), + __ADD(TCPI_OPT_SACK, sACK), + __ADD(TCPI_OPT_WSCALE, wscale), + __ADD(TCPI_OPT_ECN, ecn), +}; + +/** + * Convert TCP option attributes to string + * @arg attrs TCP option attributes to convert (e.g., TCPI_OPT_SACK | + * TCPI_OPT_WSCALE) + * @arg buf Output buffer for string + * @arg len Length in bytes of output buffer + * + * @return buffer with string representation or empty string + */ +char *idiagnl_tcpopts2str(uint8_t attrs, char *buf, size_t len) +{ + return __flags2str(attrs, buf, len, idiagnl_tcpopt_attrs, + ARRAY_SIZE(idiagnl_tcpopt_attrs)); +} + +/** + * Convert shutdown state to string. + * @arg shutdown Shutdown state (e.g., idiag_msg->shutdown) + * @arg buf Ouput buffer to hold string representation + * @arg len Length in bytes of output buffer + * + * @return string representation of shutdown state or NULL + */ +char * idiagnl_shutdown2str(uint8_t shutdown, char *buf, size_t len) +{ + if (shutdown == 0) { + snprintf(buf, len, " "); + return buf; + } else if (shutdown == 1) { + snprintf(buf, len, "receive shutdown"); + return buf; + } else if (shutdown == 2) { + snprintf(buf, len, "send shutdown"); + return buf; + } + + return NULL; +} + +/** @} */ +/** @} */ diff --git a/lib/idiag/idiag_meminfo_obj.c b/lib/idiag/idiag_meminfo_obj.c new file mode 100644 index 0000000..ebb9767 --- /dev/null +++ b/lib/idiag/idiag_meminfo_obj.c @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Sassano Systems LLC + */ + +#include "nl-default.h" + +#include + +#include "nl-idiag.h" + +/** + * @ingroup idiag + * @defgroup idiagnl_meminfo Inet Diag Memory Info + * + * @details + * @idiagnl_doc{idiagnl_meminfo, Inet Diag Memory Info Documentation} + * @{ + */ +struct idiagnl_meminfo *idiagnl_meminfo_alloc(void) +{ + return (struct idiagnl_meminfo *) nl_object_alloc(&idiagnl_meminfo_obj_ops); +} + +void idiagnl_meminfo_get(struct idiagnl_meminfo *minfo) +{ + nl_object_get((struct nl_object *) minfo); +} + +void idiagnl_meminfo_put(struct idiagnl_meminfo *minfo) +{ + nl_object_put((struct nl_object *) minfo); +} + +/** + * @name Attributes + * @{ + */ +uint32_t idiagnl_meminfo_get_rmem(const struct idiagnl_meminfo *minfo) +{ + return minfo->idiag_rmem; +} + +void idiagnl_meminfo_set_rmem(struct idiagnl_meminfo *minfo, uint32_t rmem) +{ + minfo->idiag_rmem = rmem; +} + +uint32_t idiagnl_meminfo_get_wmem(const struct idiagnl_meminfo *minfo) +{ + return minfo->idiag_wmem; +} + +void idiagnl_meminfo_set_wmem(struct idiagnl_meminfo *minfo, uint32_t wmem) +{ + minfo->idiag_wmem = wmem; +} + +uint32_t idiagnl_meminfo_get_fmem(const struct idiagnl_meminfo *minfo) +{ + return minfo->idiag_fmem; +} + +void idiagnl_meminfo_set_fmem(struct idiagnl_meminfo *minfo, uint32_t fmem) +{ + minfo->idiag_fmem = fmem; +} + +uint32_t idiagnl_meminfo_get_tmem(const struct idiagnl_meminfo *minfo) +{ + return minfo->idiag_tmem; +} + +void idiagnl_meminfo_set_tmem(struct idiagnl_meminfo *minfo, uint32_t tmem) +{ + minfo->idiag_tmem = tmem; +} +/** @} */ + +/** @cond SKIP */ +static uint64_t idiagnl_meminfo_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) +{ + struct idiagnl_meminfo *a = (struct idiagnl_meminfo *) _a; + struct idiagnl_meminfo *b = (struct idiagnl_meminfo *) _b; + + /* meminfo is a very simple object. It has no attribe flags (ce_mask), + * hence compare just returns 0 or 1, not a bit mask of attributes. */ + return a->idiag_rmem != b->idiag_rmem || + a->idiag_wmem != b->idiag_wmem || + a->idiag_fmem != b->idiag_fmem || + a->idiag_tmem != b->idiag_tmem; +} + +struct nl_object_ops idiagnl_meminfo_obj_ops = { + .oo_name = "idiag/idiag_meminfo", + .oo_size = sizeof(struct idiagnl_meminfo), + .oo_compare = idiagnl_meminfo_compare, +}; +/** @endcond */ +/** @} */ diff --git a/lib/idiag/idiag_msg_obj.c b/lib/idiag/idiag_msg_obj.c new file mode 100644 index 0000000..2c78eb1 --- /dev/null +++ b/lib/idiag/idiag_msg_obj.c @@ -0,0 +1,1003 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Sassano Systems LLC + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include +#include + +#include "nl-idiag.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-aux-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" + +/** @cond SKIP */ +struct idiagnl_msg { + NLHDR_COMMON + + uint8_t idiag_family; + uint8_t idiag_state; + uint8_t idiag_timer; + uint8_t idiag_retrans; + uint16_t idiag_sport; + uint16_t idiag_dport; + struct nl_addr * idiag_src; + struct nl_addr * idiag_dst; + uint32_t idiag_ifindex; + uint32_t idiag_expires; + uint32_t idiag_rqueue; + uint32_t idiag_wqueue; + uint32_t idiag_uid; + uint32_t idiag_inode; + + uint8_t idiag_tos; + uint8_t idiag_tclass; + uint8_t idiag_shutdown; + char * idiag_cong; + struct idiagnl_meminfo * idiag_meminfo; + struct idiagnl_vegasinfo * idiag_vegasinfo; + struct tcp_info idiag_tcpinfo; + uint32_t idiag_skmeminfo[SK_MEMINFO_VARS]; +}; + +#define IDIAGNL_ATTR_FAMILY (0x1 << 1) +#define IDIAGNL_ATTR_STATE (0x1 << 2) +#define IDIAGNL_ATTR_TIMER (0x1 << 3) +#define IDIAGNL_ATTR_RETRANS (0x1 << 4) +#define IDIAGNL_ATTR_SPORT (0x1 << 5) +#define IDIAGNL_ATTR_DPORT (0x1 << 6) +#define IDIAGNL_ATTR_SRC (0x1 << 7) +#define IDIAGNL_ATTR_DST (0x1 << 8) +#define IDIAGNL_ATTR_IFINDEX (0x1 << 9) +#define IDIAGNL_ATTR_EXPIRES (0x1 << 10) +#define IDIAGNL_ATTR_RQUEUE (0x1 << 11) +#define IDIAGNL_ATTR_WQUEUE (0x1 << 12) +#define IDIAGNL_ATTR_UID (0x1 << 13) +#define IDIAGNL_ATTR_INODE (0x1 << 14) +#define IDIAGNL_ATTR_TOS (0x1 << 15) +#define IDIAGNL_ATTR_TCLASS (0x1 << 16) +#define IDIAGNL_ATTR_SHUTDOWN (0x1 << 17) +#define IDIAGNL_ATTR_CONG (0x1 << 18) +#define IDIAGNL_ATTR_MEMINFO (0x1 << 19) +#define IDIAGNL_ATTR_VEGASINFO (0x1 << 20) +#define IDIAGNL_ATTR_TCPINFO (0x1 << 21) +#define IDIAGNL_ATTR_SKMEMINFO (0x1 << 22) + +#define _INET_DIAG_ALL ((1<<(INET_DIAG_MAX+1))-1) +/** @endcond */ + +/** + * @ingroup idiag + * @defgroup idiagnl_msg Inet Diag Messages + * + * @details + * @idiagnl_doc{idiagnl_msg, Inet Diag Message Documentation} + * @{ + */ +struct idiagnl_msg *idiagnl_msg_alloc(void) +{ + return (struct idiagnl_msg *) nl_object_alloc(&idiagnl_msg_obj_ops); +} + +void idiagnl_msg_get(struct idiagnl_msg *msg) +{ + nl_object_get((struct nl_object *) msg); +} + +void idiagnl_msg_put(struct idiagnl_msg *msg) +{ + nl_object_put((struct nl_object *) msg); +} + +static struct nl_cache_ops idiagnl_msg_ops; + +static int idiagnl_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *nlh, struct nl_parser_param *pp) +{ + struct idiagnl_msg *msg = NULL; + int err = 0; + + if ((err = idiagnl_msg_parse(nlh, &msg)) < 0) + return err; + + err = pp->pp_cb((struct nl_object *) msg, pp); + idiagnl_msg_put(msg); + + return err; +} + +static int idiagnl_request_update(struct nl_cache *cache, struct nl_sock *sk) +{ + int family = cache->c_iarg1; + int states = cache->c_iarg2; + + /* idiagnl_send_simple()'s "ext" argument is u16, which is too small for _INET_DIAG_ALL, + * which is more than 16 bits on recent kernels. + * + * Actually, internally idiagnl_send_simple() sets "struct inet_diag_req"'s "idiag_ext" + * field, which is only 8 bits. So, it's even worse. + * + * FIXME: this probably should be fixed (by adding idiagnl_send_simple2() function), but for + * the moment it means we cannot request more than 0xFF. + */ + + return idiagnl_send_simple(sk, 0, family, states, (uint16_t) _INET_DIAG_ALL); +} + +static struct nl_cache_ops idiagnl_msg_ops = { + .co_name = "idiag/idiag", + .co_hdrsize = sizeof(struct inet_diag_msg), + .co_msgtypes = { + { TCPDIAG_GETSOCK, NL_ACT_NEW, "new" }, + { DCCPDIAG_GETSOCK, NL_ACT_NEW, "new" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_INET_DIAG, + .co_request_update = idiagnl_request_update, + .co_msg_parser = idiagnl_msg_parser, + .co_obj_ops = &idiagnl_msg_obj_ops, +}; + +static void _nl_init idiagnl_init(void) +{ + nl_cache_mngt_register(&idiagnl_msg_ops); +} + +static void _nl_exit idiagnl_exit(void) +{ + nl_cache_mngt_unregister(&idiagnl_msg_ops); +} + +/** + * @name Cache Management + * @{ + */ + +/** + * Build an inetdiag cache to hold socket state information. + * @arg sk Netlink socket + * @arg family The address family to query + * @arg states Socket states to query + * @arg result Result pointer + * + * @note The caller is responsible for destroying and free the cache after using + * it. + * @return 0 on success of a negative error code. + */ +int idiagnl_msg_alloc_cache(struct nl_sock *sk, int family, int states, + struct nl_cache **result) +{ + struct nl_cache *cache = NULL; + int err; + + if (!(cache = nl_cache_alloc(&idiagnl_msg_ops))) + return -NLE_NOMEM; + + cache->c_iarg1 = family; + cache->c_iarg2 = states; + + if (sk && (err = nl_cache_refill(sk, cache)) < 0) { + free(cache); + return err; + } + + *result = cache; + return 0; +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ + +uint8_t idiagnl_msg_get_family(const struct idiagnl_msg *msg) +{ + return msg->idiag_family; +} + +void idiagnl_msg_set_family(struct idiagnl_msg *msg, uint8_t family) +{ + msg->idiag_family = family; + msg->ce_mask |= IDIAGNL_ATTR_FAMILY; +} + +uint8_t idiagnl_msg_get_state(const struct idiagnl_msg *msg) +{ + return msg->idiag_state; +} + +void idiagnl_msg_set_state(struct idiagnl_msg *msg, uint8_t state) +{ + msg->idiag_state = state; + msg->ce_mask |= IDIAGNL_ATTR_STATE; +} + +uint8_t idiagnl_msg_get_timer(const struct idiagnl_msg *msg) +{ + return msg->idiag_timer; +} + +void idiagnl_msg_set_timer(struct idiagnl_msg *msg, uint8_t timer) +{ + msg->idiag_timer = timer; + msg->ce_mask |= IDIAGNL_ATTR_TIMER; +} + +uint8_t idiagnl_msg_get_retrans(const struct idiagnl_msg *msg) +{ + return msg->idiag_retrans; +} + +void idiagnl_msg_set_retrans(struct idiagnl_msg *msg, uint8_t retrans) +{ + msg->idiag_retrans = retrans; + msg->ce_mask |= IDIAGNL_ATTR_RETRANS; +} + +uint16_t idiagnl_msg_get_sport(struct idiagnl_msg *msg) +{ + return msg->idiag_sport; +} + +void idiagnl_msg_set_sport(struct idiagnl_msg *msg, uint16_t port) +{ + msg->idiag_sport = port; + msg->ce_mask |= IDIAGNL_ATTR_SPORT; +} + +uint16_t idiagnl_msg_get_dport(struct idiagnl_msg *msg) +{ + return msg->idiag_dport; +} + +void idiagnl_msg_set_dport(struct idiagnl_msg *msg, uint16_t port) +{ + msg->idiag_dport = port; + msg->ce_mask |= IDIAGNL_ATTR_DPORT; +} + +struct nl_addr *idiagnl_msg_get_src(const struct idiagnl_msg *msg) +{ + return msg->idiag_src; +} + +int idiagnl_msg_set_src(struct idiagnl_msg *msg, struct nl_addr *addr) +{ + if (msg->idiag_src) + nl_addr_put(msg->idiag_src); + + nl_addr_get(addr); + msg->idiag_src = addr; + msg->ce_mask |= IDIAGNL_ATTR_SRC; + + return 0; +} + +struct nl_addr *idiagnl_msg_get_dst(const struct idiagnl_msg *msg) +{ + return msg->idiag_dst; +} + +int idiagnl_msg_set_dst(struct idiagnl_msg *msg, struct nl_addr *addr) +{ + if (msg->idiag_dst) + nl_addr_put(msg->idiag_dst); + + nl_addr_get(addr); + msg->idiag_dst = addr; + msg->ce_mask |= IDIAGNL_ATTR_DST; + + return 0; +} + +uint32_t idiagnl_msg_get_ifindex(const struct idiagnl_msg *msg) +{ + return msg->idiag_ifindex; +} + +void idiagnl_msg_set_ifindex(struct idiagnl_msg *msg, uint32_t ifindex) +{ + msg->idiag_ifindex = ifindex; + msg->ce_mask |= IDIAGNL_ATTR_IFINDEX; +} + +uint32_t idiagnl_msg_get_expires(const struct idiagnl_msg *msg) +{ + return msg->idiag_expires; +} + +void idiagnl_msg_set_expires(struct idiagnl_msg *msg, uint32_t expires) +{ + msg->idiag_expires = expires; + msg->ce_mask |= IDIAGNL_ATTR_EXPIRES; +} + +uint32_t idiagnl_msg_get_rqueue(const struct idiagnl_msg *msg) +{ + return msg->idiag_rqueue; +} + +void idiagnl_msg_set_rqueue(struct idiagnl_msg *msg, uint32_t rqueue) +{ + msg->idiag_rqueue = rqueue; + msg->ce_mask |= IDIAGNL_ATTR_RQUEUE; +} + +uint32_t idiagnl_msg_get_wqueue(const struct idiagnl_msg *msg) +{ + return msg->idiag_wqueue; +} + +void idiagnl_msg_set_wqueue(struct idiagnl_msg *msg, uint32_t wqueue) +{ + msg->idiag_wqueue = wqueue; + msg->ce_mask |= IDIAGNL_ATTR_WQUEUE; +} + +uint32_t idiagnl_msg_get_uid(const struct idiagnl_msg *msg) +{ + return msg->idiag_uid; +} + +void idiagnl_msg_set_uid(struct idiagnl_msg *msg, uint32_t uid) +{ + msg->idiag_uid = uid; + msg->ce_mask |= IDIAGNL_ATTR_UID; +} + +uint32_t idiagnl_msg_get_inode(const struct idiagnl_msg *msg) +{ + return msg->idiag_inode; +} + +void idiagnl_msg_set_inode(struct idiagnl_msg *msg, uint32_t inode) +{ + msg->idiag_inode = inode; + msg->ce_mask |= IDIAGNL_ATTR_INODE; +} + +uint8_t idiagnl_msg_get_tos(const struct idiagnl_msg *msg) +{ + return msg->idiag_tos; +} + +void idiagnl_msg_set_tos(struct idiagnl_msg *msg, uint8_t tos) +{ + msg->idiag_tos = tos; + msg->ce_mask |= IDIAGNL_ATTR_TOS; +} + +uint8_t idiagnl_msg_get_tclass(const struct idiagnl_msg *msg) +{ + return msg->idiag_tclass; +} + +void idiagnl_msg_set_tclass(struct idiagnl_msg *msg, uint8_t tclass) +{ + msg->idiag_tclass = tclass; + msg->ce_mask |= IDIAGNL_ATTR_TCLASS; +} + +uint8_t idiagnl_msg_get_shutdown(const struct idiagnl_msg *msg) +{ + return msg->idiag_shutdown; +} + +void idiagnl_msg_set_shutdown(struct idiagnl_msg *msg, uint8_t shutdown) +{ + msg->idiag_shutdown = shutdown; + msg->ce_mask |= IDIAGNL_ATTR_SHUTDOWN; +} + +char *idiagnl_msg_get_cong(const struct idiagnl_msg *msg) +{ + return msg->idiag_cong; +} + +void idiagnl_msg_set_cong(struct idiagnl_msg *msg, char *cong) +{ + free (msg->idiag_cong); + msg->idiag_cong = strdup(cong); + msg->ce_mask |= IDIAGNL_ATTR_CONG; +} + +struct idiagnl_meminfo *idiagnl_msg_get_meminfo(const struct idiagnl_msg *msg) +{ + return msg->idiag_meminfo; +} + +void idiagnl_msg_set_meminfo(struct idiagnl_msg *msg, struct idiagnl_meminfo *minfo) +{ + if (msg->idiag_meminfo) + idiagnl_meminfo_put(msg->idiag_meminfo); + + idiagnl_meminfo_get(minfo); + msg->idiag_meminfo = minfo; + msg->ce_mask |= IDIAGNL_ATTR_MEMINFO; +} + +struct idiagnl_vegasinfo *idiagnl_msg_get_vegasinfo(const struct idiagnl_msg *msg) +{ + return msg->idiag_vegasinfo; +} + +void idiagnl_msg_set_vegasinfo(struct idiagnl_msg *msg, struct idiagnl_vegasinfo *vinfo) +{ + if (msg->idiag_vegasinfo) + idiagnl_vegasinfo_put(msg->idiag_vegasinfo); + + idiagnl_vegasinfo_get(vinfo); + msg->idiag_vegasinfo = vinfo; + msg->ce_mask |= IDIAGNL_ATTR_VEGASINFO; +} + +struct tcp_info idiagnl_msg_get_tcpinfo(const struct idiagnl_msg *msg) +{ + return msg->idiag_tcpinfo; +} + +void idiagnl_msg_set_tcpinfo(struct idiagnl_msg *msg, struct tcp_info *tinfo) +{ + memcpy(&msg->idiag_tcpinfo, tinfo, sizeof(struct tcp_info)); + msg->ce_mask |= IDIAGNL_ATTR_TCPINFO; +} + +/** @} */ + +static void idiag_msg_dump_line(struct nl_object *a, struct nl_dump_params *p) +{ + struct idiagnl_msg *msg = (struct idiagnl_msg *) a; + char buf[64] = { 0 }; + + nl_dump_line(p, "family: %s ", nl_af2str(msg->idiag_family, buf, sizeof(buf))); + nl_dump(p, "src: %s:%d ", nl_addr2str(msg->idiag_src, buf, sizeof(buf)), + ntohs(msg->idiag_sport)); + nl_dump(p, "dst: %s:%d ", nl_addr2str(msg->idiag_dst, buf, sizeof(buf)), + ntohs(msg->idiag_dport)); + nl_dump(p, "iif: %d ", msg->idiag_ifindex); + nl_dump(p, "\n"); +} + +static void idiag_msg_dump_details(struct nl_object *a, struct nl_dump_params *p) +{ + struct idiagnl_msg *msg = (struct idiagnl_msg *) a; + char buf[64], buf2[64]; + + nl_dump(p, "\nfamily: %s\n", nl_af2str(msg->idiag_family, buf, sizeof(buf))); + nl_dump(p, "state: %s\n", + idiagnl_state2str(msg->idiag_state, buf, sizeof(buf))); + nl_dump(p, "timer (%s, %s, retransmits: %d)\n", + idiagnl_timer2str(msg->idiag_timer, buf, sizeof(buf)), + nl_msec2str(msg->idiag_expires, buf2, sizeof(buf2)), + msg->idiag_retrans); + + nl_dump(p, "source: %s:%d\n", nl_addr2str(msg->idiag_src, buf, sizeof(buf)), + ntohs(msg->idiag_sport)); + nl_dump(p, "destination: %s:%d\n", nl_addr2str(msg->idiag_dst, buf, sizeof(buf)), + ntohs(msg->idiag_dport)); + + nl_dump(p, "ifindex: %d\n", msg->idiag_ifindex); + nl_dump(p, "rqueue: %-6d wqueue: %-6d\n", msg->idiag_rqueue, msg->idiag_wqueue); + nl_dump(p, "uid %d\n", msg->idiag_uid); + nl_dump(p, "inode %d\n", msg->idiag_inode); + if (msg->idiag_shutdown) { + nl_dump(p, "socket shutdown: %s\n", + idiagnl_shutdown2str(msg->idiag_shutdown, + buf, sizeof(buf))); + } + + nl_dump(p, "tos: 0x%x\n", msg->idiag_tos); + nl_dump(p, "traffic class: %d\n", msg->idiag_tclass); + nl_dump(p, "congestion algorithm: %s\n", msg->idiag_cong ? msg->idiag_cong : ""); +} + +static void idiag_msg_dump_stats(struct nl_object *obj, struct nl_dump_params *p) +{ + struct idiagnl_msg *msg = (struct idiagnl_msg *) obj; + char buf[64]; + + idiag_msg_dump_details(obj, p); + + nl_dump(p, "tcp info: [\n"); + nl_dump(p, "\tsocket state: %s\n", + idiagnl_state2str(msg->idiag_tcpinfo.tcpi_state, + buf, sizeof(buf))); + nl_dump(p, "\ttcp state: %s\n", + idiagnl_tcpstate2str(msg->idiag_tcpinfo.tcpi_ca_state, + buf, sizeof(buf))); + nl_dump(p, "\tretransmits: %d\n", + msg->idiag_tcpinfo.tcpi_retransmits); + nl_dump(p, "\tprobes: %d\n", + msg->idiag_tcpinfo.tcpi_probes); + nl_dump(p, "\tbackoff: %d\n", + msg->idiag_tcpinfo.tcpi_backoff); + nl_dump(p, "\toptions: %s\n", + idiagnl_tcpopts2str(msg->idiag_tcpinfo.tcpi_options, + buf, sizeof(buf))); + nl_dump(p, "\tsnd_wscale: %d\n", msg->idiag_tcpinfo.tcpi_snd_wscale); + nl_dump(p, "\trcv_wscale: %d\n", msg->idiag_tcpinfo.tcpi_rcv_wscale); + nl_dump(p, "\trto: %d\n", msg->idiag_tcpinfo.tcpi_rto); + nl_dump(p, "\tato: %d\n", msg->idiag_tcpinfo.tcpi_ato); + nl_dump(p, "\tsnd_mss: %s\n", nl_size2str(msg->idiag_tcpinfo.tcpi_snd_mss, + buf, sizeof(buf))); + nl_dump(p, "\trcv_mss: %s\n", nl_size2str(msg->idiag_tcpinfo.tcpi_rcv_mss, + buf, sizeof(buf))); + nl_dump(p, "\tunacked: %d\n", msg->idiag_tcpinfo.tcpi_unacked); + nl_dump(p, "\tsacked: %d\n", msg->idiag_tcpinfo.tcpi_sacked); + + nl_dump(p, "\tlost: %d\n", msg->idiag_tcpinfo.tcpi_lost); + nl_dump(p, "\tretransmit segments: %d\n", + msg->idiag_tcpinfo.tcpi_retrans); + nl_dump(p, "\tfackets: %d\n", + msg->idiag_tcpinfo.tcpi_fackets); + nl_dump(p, "\tlast data sent: %s\n", + nl_msec2str(msg->idiag_tcpinfo.tcpi_last_data_sent, buf, + sizeof(buf))); + nl_dump(p, "\tlast ack sent: %s\n", + nl_msec2str(msg->idiag_tcpinfo.tcpi_last_ack_sent, buf, sizeof(buf))); + nl_dump(p, "\tlast data recv: %s\n", + nl_msec2str(msg->idiag_tcpinfo.tcpi_last_data_recv, buf, + sizeof(buf))); + nl_dump(p, "\tlast ack recv: %s\n", + nl_msec2str(msg->idiag_tcpinfo.tcpi_last_ack_recv, buf, + sizeof(buf))); + nl_dump(p, "\tpath mtu: %s\n", + nl_size2str(msg->idiag_tcpinfo.tcpi_pmtu, buf, + sizeof(buf))); + nl_dump(p, "\trcv ss threshold: %d\n", + msg->idiag_tcpinfo.tcpi_rcv_ssthresh); + nl_dump(p, "\tsmoothed round trip time: %d\n", + msg->idiag_tcpinfo.tcpi_rtt); + nl_dump(p, "\tround trip time variation: %d\n", + msg->idiag_tcpinfo.tcpi_rttvar); + nl_dump(p, "\tsnd ss threshold: %s\n", + nl_size2str(msg->idiag_tcpinfo.tcpi_snd_ssthresh, buf, + sizeof(buf))); + nl_dump(p, "\tsend congestion window: %d\n", + msg->idiag_tcpinfo.tcpi_snd_cwnd); + nl_dump(p, "\tadvertised mss: %s\n", + nl_size2str(msg->idiag_tcpinfo.tcpi_advmss, buf, + sizeof(buf))); + nl_dump(p, "\treordering: %d\n", + msg->idiag_tcpinfo.tcpi_reordering); + nl_dump(p, "\trcv rround trip time: %d\n", + msg->idiag_tcpinfo.tcpi_rcv_rtt); + nl_dump(p, "\treceive queue space: %s\n", + nl_size2str(msg->idiag_tcpinfo.tcpi_rcv_space, buf, + sizeof(buf))); + nl_dump(p, "\ttotal retransmits: %d\n", + msg->idiag_tcpinfo.tcpi_total_retrans); + nl_dump(p, "]\n"); + + if (msg->idiag_meminfo) { + nl_dump(p, "meminfo: [\n"); + nl_dump(p, "\trmem: %s\n", + nl_size2str(msg->idiag_meminfo->idiag_rmem, + buf, + sizeof(buf))); + nl_dump(p, "\twmem: %s\n", + nl_size2str(msg->idiag_meminfo->idiag_wmem, + buf, + sizeof(buf))); + nl_dump(p, "\tfmem: %s\n", + nl_size2str(msg->idiag_meminfo->idiag_fmem, + buf, + sizeof(buf))); + nl_dump(p, "\ttmem: %s\n", + nl_size2str(msg->idiag_meminfo->idiag_tmem, + buf, + sizeof(buf))); + nl_dump(p, "]\n"); + } + + if (msg->idiag_vegasinfo) { + nl_dump(p, "vegasinfo: [\n"); + nl_dump(p, "\tvegas enabled: %d\n", + msg->idiag_vegasinfo->tcpv_enabled); + if (msg->idiag_vegasinfo->tcpv_enabled) { + nl_dump(p, "\trtt cnt: %d", + msg->idiag_vegasinfo->tcpv_rttcnt); + nl_dump(p, "\trtt (propagation delay): %d", + msg->idiag_vegasinfo->tcpv_rtt); + nl_dump(p, "\tmin rtt: %d", + msg->idiag_vegasinfo->tcpv_minrtt); + } + nl_dump(p, "]\n"); + } + + if (msg->ce_mask & IDIAGNL_ATTR_MEMINFO) { + nl_dump(p, "skmeminfo: [\n"); + nl_dump(p, "\trmem alloc: %d\n", + msg->idiag_skmeminfo[SK_MEMINFO_RMEM_ALLOC]); + nl_dump(p, "\trcv buf: %s\n", + nl_size2str(msg->idiag_skmeminfo[SK_MEMINFO_RCVBUF], + buf, sizeof(buf))); + nl_dump(p, "\twmem alloc: %d\n", + msg->idiag_skmeminfo[SK_MEMINFO_WMEM_ALLOC]); + nl_dump(p, "\tsnd buf: %s\n", + nl_size2str(msg->idiag_skmeminfo[SK_MEMINFO_SNDBUF], + buf, sizeof(buf))); + nl_dump(p, "\tfwd alloc: %d\n", + msg->idiag_skmeminfo[SK_MEMINFO_FWD_ALLOC]); + nl_dump(p, "\twmem queued: %s\n", + nl_size2str(msg->idiag_skmeminfo[SK_MEMINFO_WMEM_QUEUED], + buf, sizeof(buf))); + nl_dump(p, "\topt mem: %d\n", + msg->idiag_skmeminfo[SK_MEMINFO_OPTMEM]); + nl_dump(p, "\tbacklog: %d\n", + msg->idiag_skmeminfo[SK_MEMINFO_BACKLOG]); + nl_dump(p, "]\n\n"); + } +} + +static void idiagnl_msg_free(struct nl_object *a) +{ + struct idiagnl_msg *msg = (struct idiagnl_msg *) a; + if (a == NULL) + return; + + free(msg->idiag_cong); + nl_addr_put(msg->idiag_src); + nl_addr_put(msg->idiag_dst); + idiagnl_meminfo_put(msg->idiag_meminfo); + idiagnl_vegasinfo_put(msg->idiag_vegasinfo); +} + +static int idiagnl_msg_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct idiagnl_msg *dst = (struct idiagnl_msg *) _dst; + struct idiagnl_msg *src = (struct idiagnl_msg *) _src; + + dst->idiag_src = NULL; + dst->idiag_dst = NULL; + dst->idiag_cong = NULL; + dst->idiag_meminfo = NULL; + dst->idiag_vegasinfo = NULL; + dst->ce_mask &= ~(IDIAGNL_ATTR_CONG | + IDIAGNL_ATTR_SRC | + IDIAGNL_ATTR_DST | + IDIAGNL_ATTR_MEMINFO | + IDIAGNL_ATTR_VEGASINFO); + + if (src->idiag_cong) { + if (!(dst->idiag_cong = strdup(src->idiag_cong))) + return -NLE_NOMEM; + dst->ce_mask |= IDIAGNL_ATTR_CONG; + } + + if (src->idiag_src) { + if (!(dst->idiag_src = nl_addr_clone(src->idiag_src))) + return -NLE_NOMEM; + dst->ce_mask |= IDIAGNL_ATTR_SRC; + } + + if (src->idiag_dst) { + if (!(dst->idiag_dst = nl_addr_clone(src->idiag_dst))) + return -NLE_NOMEM; + dst->ce_mask |= IDIAGNL_ATTR_DST; + } + + if (src->idiag_meminfo) { + if (!(dst->idiag_meminfo = (struct idiagnl_meminfo *) nl_object_clone((struct nl_object *) src->idiag_meminfo))) + return -NLE_NOMEM; + dst->ce_mask |= IDIAGNL_ATTR_MEMINFO; + } + + if (src->idiag_vegasinfo) { + if (!(dst->idiag_vegasinfo = (struct idiagnl_vegasinfo *) nl_object_clone((struct nl_object *) src->idiag_vegasinfo))) + return -NLE_NOMEM; + dst->ce_mask |= IDIAGNL_ATTR_VEGASINFO; + } + + return 0; +} + +static struct nla_policy ext_policy[INET_DIAG_MAX+1] = { + [INET_DIAG_MEMINFO] = { .minlen = sizeof(struct inet_diag_meminfo) }, + [INET_DIAG_INFO] = { .minlen = sizeof(struct tcp_info) }, + [INET_DIAG_VEGASINFO] = { .minlen = sizeof(struct tcpvegas_info) }, + [INET_DIAG_CONG] = { .type = NLA_STRING }, + [INET_DIAG_TOS] = { .type = NLA_U8 }, + [INET_DIAG_TCLASS] = { .type = NLA_U8 }, + /* Older kernel doesn't have SK_MEMINFO_BACKLOG */ + [INET_DIAG_SKMEMINFO] = { .minlen = (sizeof(uint32_t) * (SK_MEMINFO_OPTMEM + 1)) }, + [INET_DIAG_SHUTDOWN] = { .type = NLA_U8 }, +}; + +int idiagnl_msg_parse(struct nlmsghdr *nlh, struct idiagnl_msg **result) +{ + struct idiagnl_msg *msg = NULL; + struct inet_diag_msg *raw_msg = NULL; + struct nl_addr *src = NULL, *dst = NULL; + struct nlattr *tb[INET_DIAG_MAX+1]; + int err = 0; + + msg = idiagnl_msg_alloc(); + if (!msg) + goto errout_nomem; + + err = nlmsg_parse(nlh, sizeof(struct inet_diag_msg), tb, INET_DIAG_MAX, + ext_policy); + if (err < 0) + goto errout; + + raw_msg = nlmsg_data(nlh); + msg->idiag_family = raw_msg->idiag_family; + msg->idiag_state = raw_msg->idiag_state; + msg->idiag_timer = raw_msg->idiag_timer; + msg->idiag_retrans = raw_msg->idiag_retrans; + msg->idiag_expires = raw_msg->idiag_expires; + msg->idiag_rqueue = raw_msg->idiag_rqueue; + msg->idiag_wqueue = raw_msg->idiag_wqueue; + msg->idiag_uid = raw_msg->idiag_uid; + msg->idiag_inode = raw_msg->idiag_inode; + msg->idiag_sport = raw_msg->id.idiag_sport; + msg->idiag_dport = raw_msg->id.idiag_dport; + msg->idiag_ifindex = raw_msg->id.idiag_if; + + msg->ce_mask = (IDIAGNL_ATTR_FAMILY | + IDIAGNL_ATTR_STATE | + IDIAGNL_ATTR_TIMER | + IDIAGNL_ATTR_RETRANS | + IDIAGNL_ATTR_EXPIRES | + IDIAGNL_ATTR_RQUEUE | + IDIAGNL_ATTR_WQUEUE | + IDIAGNL_ATTR_UID | + IDIAGNL_ATTR_INODE | + IDIAGNL_ATTR_SPORT | + IDIAGNL_ATTR_DPORT | + IDIAGNL_ATTR_IFINDEX); + + dst = nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_dst, + sizeof(raw_msg->id.idiag_dst)); + if (!dst) + goto errout_nomem; + + err = idiagnl_msg_set_dst(msg, dst); + if (err < 0) + goto errout; + + nl_addr_put(dst); + + src = nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_src, + sizeof(raw_msg->id.idiag_src)); + if (!src) + goto errout_nomem; + + err = idiagnl_msg_set_src(msg, src); + if (err < 0) + goto errout; + + nl_addr_put(src); + + if (tb[INET_DIAG_TOS]) { + msg->idiag_tos = nla_get_u8(tb[INET_DIAG_TOS]); + msg->ce_mask |= IDIAGNL_ATTR_TOS; + } + + if (tb[INET_DIAG_TCLASS]) { + msg->idiag_tclass = nla_get_u8(tb[INET_DIAG_TCLASS]); + msg->ce_mask |= IDIAGNL_ATTR_TCLASS; + } + + if (tb[INET_DIAG_SHUTDOWN]) { + msg->idiag_shutdown = nla_get_u8(tb[INET_DIAG_SHUTDOWN]); + msg->ce_mask |= IDIAGNL_ATTR_SHUTDOWN; + } + + if (tb[INET_DIAG_CONG]) { + msg->idiag_cong = nla_strdup(tb[INET_DIAG_CONG]); + msg->ce_mask |= IDIAGNL_ATTR_CONG; + } + + if (tb[INET_DIAG_INFO]) { + nla_memcpy(&msg->idiag_tcpinfo, tb[INET_DIAG_INFO], + sizeof(msg->idiag_tcpinfo)); + msg->ce_mask |= IDIAGNL_ATTR_TCPINFO; + } + + if (tb[INET_DIAG_MEMINFO]) { + struct idiagnl_meminfo *minfo = idiagnl_meminfo_alloc(); + struct inet_diag_meminfo *raw_minfo = NULL; + + if (!minfo) + goto errout_nomem; + + raw_minfo = (struct inet_diag_meminfo *) + nla_data(tb[INET_DIAG_MEMINFO]); + + idiagnl_meminfo_set_rmem(minfo, raw_minfo->idiag_rmem); + idiagnl_meminfo_set_wmem(minfo, raw_minfo->idiag_wmem); + idiagnl_meminfo_set_fmem(minfo, raw_minfo->idiag_fmem); + idiagnl_meminfo_set_tmem(minfo, raw_minfo->idiag_tmem); + + msg->idiag_meminfo = minfo; + msg->ce_mask |= IDIAGNL_ATTR_MEMINFO; + } + + if (tb[INET_DIAG_VEGASINFO]) { + struct idiagnl_vegasinfo *vinfo = idiagnl_vegasinfo_alloc(); + struct tcpvegas_info *raw_vinfo = NULL; + + if (!vinfo) + goto errout_nomem; + + raw_vinfo = (struct tcpvegas_info *) + nla_data(tb[INET_DIAG_VEGASINFO]); + + idiagnl_vegasinfo_set_enabled(vinfo, raw_vinfo->tcpv_enabled); + idiagnl_vegasinfo_set_rttcnt(vinfo, raw_vinfo->tcpv_rttcnt); + idiagnl_vegasinfo_set_rtt(vinfo, raw_vinfo->tcpv_rtt); + idiagnl_vegasinfo_set_minrtt(vinfo, raw_vinfo->tcpv_minrtt); + + msg->idiag_vegasinfo = vinfo; + msg->ce_mask |= IDIAGNL_ATTR_VEGASINFO; + } + + if (tb[INET_DIAG_SKMEMINFO]) { + nla_memcpy(&msg->idiag_skmeminfo, tb[INET_DIAG_SKMEMINFO], + sizeof(msg->idiag_skmeminfo)); + msg->ce_mask |= IDIAGNL_ATTR_SKMEMINFO; + } + + *result = msg; + return 0; + +errout: + idiagnl_msg_put(msg); + return err; + +errout_nomem: + err = -NLE_NOMEM; + goto errout; +} + +static const struct trans_tbl idiagnl_attrs[] = { + __ADD(IDIAGNL_ATTR_FAMILY, family), + __ADD(IDIAGNL_ATTR_STATE, state), + __ADD(IDIAGNL_ATTR_TIMER, timer), + __ADD(IDIAGNL_ATTR_RETRANS, retrans), + __ADD(IDIAGNL_ATTR_SPORT, sport), + __ADD(IDIAGNL_ATTR_DPORT, dport), + __ADD(IDIAGNL_ATTR_SRC, src), + __ADD(IDIAGNL_ATTR_DST, dst), + __ADD(IDIAGNL_ATTR_IFINDEX, ifindex), + __ADD(IDIAGNL_ATTR_EXPIRES, expires), + __ADD(IDIAGNL_ATTR_RQUEUE, rqueue), + __ADD(IDIAGNL_ATTR_WQUEUE, wqueue), + __ADD(IDIAGNL_ATTR_UID, uid), + __ADD(IDIAGNL_ATTR_INODE, inode), + __ADD(IDIAGNL_ATTR_TOS, tos), + __ADD(IDIAGNL_ATTR_TCLASS, tclass), + __ADD(IDIAGNL_ATTR_SHUTDOWN, shutdown), + __ADD(IDIAGNL_ATTR_CONG, cong), + __ADD(IDIAGNL_ATTR_MEMINFO, meminfo), + __ADD(IDIAGNL_ATTR_VEGASINFO, vegasinfo), + __ADD(IDIAGNL_ATTR_TCPINFO, tcpinfo), + __ADD(IDIAGNL_ATTR_SKMEMINFO, skmeminfo), +}; + +static char *_idiagnl_attrs2str(int attrs, char *buf, size_t len) +{ + return __flags2str(attrs, buf, len, idiagnl_attrs, + ARRAY_SIZE(idiagnl_attrs)); +} + +static uint64_t idiagnl_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) +{ + struct idiagnl_msg *a = (struct idiagnl_msg *) _a; + struct idiagnl_msg *b = (struct idiagnl_msg *) _b; + uint64_t diff = 0; + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(IDIAGNL_ATTR_FAMILY, a->idiag_family != b->idiag_family); + diff |= _DIFF(IDIAGNL_ATTR_STATE, a->idiag_state != b->idiag_state); + diff |= _DIFF(IDIAGNL_ATTR_TIMER, a->idiag_timer != b->idiag_timer); + diff |= _DIFF(IDIAGNL_ATTR_RETRANS, + a->idiag_retrans != b->idiag_retrans); + diff |= _DIFF(IDIAGNL_ATTR_SPORT, a->idiag_sport != b->idiag_sport); + diff |= _DIFF(IDIAGNL_ATTR_DPORT, a->idiag_dport != b->idiag_dport); + diff |= _DIFF(IDIAGNL_ATTR_SRC, + nl_addr_cmp(a->idiag_src, b->idiag_src)); + diff |= _DIFF(IDIAGNL_ATTR_DST, + nl_addr_cmp(a->idiag_dst, b->idiag_dst)); + diff |= _DIFF(IDIAGNL_ATTR_IFINDEX, + a->idiag_ifindex != b->idiag_ifindex); + diff |= _DIFF(IDIAGNL_ATTR_EXPIRES, + a->idiag_expires != b->idiag_expires); + diff |= _DIFF(IDIAGNL_ATTR_RQUEUE, a->idiag_rqueue != b->idiag_rqueue); + diff |= _DIFF(IDIAGNL_ATTR_WQUEUE, a->idiag_wqueue != b->idiag_wqueue); + diff |= _DIFF(IDIAGNL_ATTR_UID, a->idiag_uid != b->idiag_uid); + diff |= _DIFF(IDIAGNL_ATTR_INODE, a->idiag_inode != b->idiag_inode); + diff |= _DIFF(IDIAGNL_ATTR_TOS, a->idiag_tos != b->idiag_tos); + diff |= _DIFF(IDIAGNL_ATTR_TCLASS, a->idiag_tclass != b->idiag_tclass); + diff |= _DIFF(IDIAGNL_ATTR_SHUTDOWN, + a->idiag_shutdown != b->idiag_shutdown); + diff |= _DIFF(IDIAGNL_ATTR_CONG, strcmp(a->idiag_cong, b->idiag_cong)); + diff |= _DIFF(IDIAGNL_ATTR_MEMINFO, + nl_object_diff((struct nl_object *)a->idiag_meminfo, + (struct nl_object *)b->idiag_meminfo)); + diff |= _DIFF(IDIAGNL_ATTR_VEGASINFO, + nl_object_diff((struct nl_object *)a->idiag_vegasinfo, + (struct nl_object *)b->idiag_vegasinfo)); + diff |= _DIFF(IDIAGNL_ATTR_TCPINFO, + memcmp(&a->idiag_tcpinfo, &b->idiag_tcpinfo, + sizeof(a->idiag_tcpinfo))); + diff |= _DIFF(IDIAGNL_ATTR_SKMEMINFO, + memcmp(a->idiag_skmeminfo, b->idiag_skmeminfo, + sizeof(a->idiag_skmeminfo))); +#undef _DIFF + + return diff; +} + +static void idiagnl_keygen(struct nl_object *obj, uint32_t *hashkey, + uint32_t table_sz) +{ + struct idiagnl_msg *msg = (struct idiagnl_msg *)obj; + unsigned int key_sz; + struct idiagnl_hash_key { + uint8_t family; + uint32_t src_hash; + uint32_t dst_hash; + uint16_t sport; + uint16_t dport; + } _nl_packed key; + + key_sz = sizeof(key); + key.family = msg->idiag_family; + key.src_hash = 0; + key.dst_hash = 0; + key.sport = msg->idiag_sport; + key.dport = msg->idiag_dport; + + if (msg->idiag_src) { + key.src_hash = nl_hash (nl_addr_get_binary_addr(msg->idiag_src), + nl_addr_get_len(msg->idiag_src), 0); + } + if (msg->idiag_dst) { + key.dst_hash = nl_hash (nl_addr_get_binary_addr(msg->idiag_dst), + nl_addr_get_len(msg->idiag_dst), 0); + } + + *hashkey = nl_hash(&key, key_sz, 0) % table_sz; + + NL_DBG(5, "idiagnl %p key (fam %d src_hash %d dst_hash %d sport %d dport %d) keysz %d, hash 0x%x\n", + msg, key.family, key.src_hash, key.dst_hash, key.sport, key.dport, key_sz, *hashkey); + + return; +} + +/** @cond SKIP */ +struct nl_object_ops idiagnl_msg_obj_ops = { + .oo_name = "idiag/idiag_msg", + .oo_size = sizeof(struct idiagnl_msg), + .oo_free_data = idiagnl_msg_free, + .oo_clone = idiagnl_msg_clone, + .oo_dump = { + [NL_DUMP_LINE] = idiag_msg_dump_line, + [NL_DUMP_DETAILS] = idiag_msg_dump_details, + [NL_DUMP_STATS] = idiag_msg_dump_stats, + }, + .oo_compare = idiagnl_compare, + .oo_keygen = idiagnl_keygen, + .oo_attrs2str = _idiagnl_attrs2str, + .oo_id_attrs = (IDIAGNL_ATTR_FAMILY | + IDIAGNL_ATTR_SRC | + IDIAGNL_ATTR_DST | + IDIAGNL_ATTR_SPORT | + IDIAGNL_ATTR_DPORT), +}; +/** @endcond */ + +/** @} */ diff --git a/lib/idiag/idiag_req_obj.c b/lib/idiag/idiag_req_obj.c new file mode 100644 index 0000000..cc23a80 --- /dev/null +++ b/lib/idiag/idiag_req_obj.c @@ -0,0 +1,272 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Sassano Systems LLC + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include +#include + +#include "nl-priv-dynamic-core/object-api.h" + +struct idiagnl_req { + NLHDR_COMMON + + uint8_t idiag_family; + uint8_t idiag_ext; + struct nl_addr * idiag_src; + struct nl_addr * idiag_dst; + uint32_t idiag_ifindex; + uint32_t idiag_states; + uint32_t idiag_dbs; +}; + +/** + * @ingroup idiag + * @defgroup idiagnl_req Inet Diag Requests + * + * @details + * @idiagnl_doc{idiagnl_req, Inet Diag Request Documentation} + * @{ + */ +struct idiagnl_req *idiagnl_req_alloc(void) +{ + return (struct idiagnl_req *) nl_object_alloc(&idiagnl_req_obj_ops); +} + +void idiagnl_req_get(struct idiagnl_req *req) +{ + nl_object_get((struct nl_object *) req); +} + +void idiagnl_req_put(struct idiagnl_req *req) +{ + nl_object_put((struct nl_object *) req); +} + +/** + * @name Attributes + * @{ + */ + +uint8_t idiagnl_req_get_family(const struct idiagnl_req *req) +{ + return req->idiag_family; +} + +void idiagnl_req_set_family(struct idiagnl_req *req, uint8_t family) +{ + req->idiag_family = family; +} + +uint8_t idiagnl_req_get_ext(const struct idiagnl_req *req) +{ + return req->idiag_ext; +} + +void idiagnl_req_set_ext(struct idiagnl_req *req, uint8_t ext) +{ + req->idiag_ext = ext; +} + +uint32_t idiagnl_req_get_ifindex(const struct idiagnl_req *req) +{ + return req->idiag_ifindex; +} + +void idiagnl_req_set_ifindex(struct idiagnl_req *req, uint32_t ifindex) +{ + req->idiag_ifindex = ifindex; +} + +uint32_t idiagnl_req_get_states(const struct idiagnl_req *req) +{ + return req->idiag_states; +} + +void idiagnl_req_set_states(struct idiagnl_req *req, uint32_t states) +{ + req->idiag_states = states; +} + +uint32_t idiagnl_req_get_dbs(const struct idiagnl_req *req) +{ + return req->idiag_dbs; +} + +void idiagnl_req_set_dbs(struct idiagnl_req *req, uint32_t dbs) +{ + req->idiag_dbs = dbs; +} + +struct nl_addr *idiagnl_req_get_src(const struct idiagnl_req *req) +{ + return req->idiag_src; +} + +int idiagnl_req_set_src(struct idiagnl_req *req, struct nl_addr *addr) +{ + if (req->idiag_src) + nl_addr_put(req->idiag_src); + + nl_addr_get(addr); + req->idiag_src = addr; + + return 0; +} + +struct nl_addr *idiagnl_req_get_dst(const struct idiagnl_req *req) +{ + return req->idiag_dst; +} + +int idiagnl_req_set_dst(struct idiagnl_req *req, struct nl_addr *addr) +{ + if (req->idiag_dst) + nl_addr_put(req->idiag_dst); + + nl_addr_get(addr); + req->idiag_dst = addr; + + return 0; +} + +/** @} */ + +static void idiag_req_dump_line(struct nl_object *a, struct nl_dump_params *p) +{ + struct idiagnl_req *req = (struct idiagnl_req *) a; + char buf[64] = { 0 }; + + nl_dump_line(p, "%s ", nl_af2str(req->idiag_family, buf, sizeof(buf))); + nl_dump(p, "src %s ", nl_addr2str(req->idiag_src, buf, sizeof(buf))); + nl_dump(p, "dst %s ", nl_addr2str(req->idiag_dst, buf, sizeof(buf))); + nl_dump(p, "iif %d ", req->idiag_ifindex); + nl_dump(p, "\n"); +} + +static void idiag_req_dump_details(struct nl_object *a, struct nl_dump_params *p) +{ + struct idiagnl_req *req = (struct idiagnl_req *) a; + char buf[64]; + + nl_dump_line(p, " "); + nl_dump(p, "%s ", nl_af2str(req->idiag_family, buf, sizeof(buf))); + nl_dump(p, "exts %s ", + idiagnl_exts2str(req->idiag_ext, buf, sizeof(buf))); + nl_dump(p, "src %s ", nl_addr2str(req->idiag_src, buf, sizeof(buf))); + nl_dump(p, "dst %s ", nl_addr2str(req->idiag_dst, buf, sizeof(buf))); + nl_dump(p, "iif %d ", req->idiag_ifindex); + nl_dump(p, "states %s ", idiagnl_state2str(req->idiag_states, buf, + sizeof(buf))); + nl_dump(p, "dbs %d", req->idiag_dbs); + nl_dump(p, "\n"); +} + +static void idiag_req_dump_stats(struct nl_object *obj, struct nl_dump_params *p) +{ + idiag_req_dump_details(obj, p); +} + +static void idiagnl_req_free(struct nl_object *a) +{ + struct idiagnl_req *req = (struct idiagnl_req *) a; + if (a == NULL) + return; + + nl_addr_put(req->idiag_src); + nl_addr_put(req->idiag_dst); +} + +static int idiagnl_req_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct idiagnl_req *dst = (struct idiagnl_req *) _dst; + struct idiagnl_req *src = (struct idiagnl_req *) _src; + + src->idiag_src = NULL; + src->idiag_dst = NULL; + + if (src->idiag_src) + if (!(dst->idiag_src = nl_addr_clone(src->idiag_src))) + return -NLE_NOMEM; + + if (src->idiag_dst) + if (!(dst->idiag_dst = nl_addr_clone(src->idiag_dst))) + return -NLE_NOMEM; + + return 0; +} + +int idiagnl_req_parse(struct nlmsghdr *nlh, struct idiagnl_req **result) +{ + struct idiagnl_req *req = NULL; + struct inet_diag_req *raw_req = NULL; + struct nl_addr *src = NULL, *dst = NULL; + int err = 0; + + req = idiagnl_req_alloc(); + if (!req) + goto errout_nomem; + + raw_req = nlmsg_data(nlh); + req->idiag_family = raw_req->idiag_family; + req->idiag_ext = raw_req->idiag_ext; + req->idiag_states = raw_req->idiag_states; + req->idiag_dbs = raw_req->idiag_dbs; + req->idiag_ifindex = raw_req->id.idiag_if; + + dst = nl_addr_build(raw_req->idiag_family, raw_req->id.idiag_dst, + sizeof(raw_req->id.idiag_dst)); + if (!dst) + goto errout_nomem; + + err = idiagnl_req_set_dst(req, dst); + if (err < 0) + goto errout; + + nl_addr_put(dst); + + src = nl_addr_build(raw_req->idiag_family, raw_req->id.idiag_src, + sizeof(raw_req->id.idiag_src)); + if (!src) + goto errout_nomem; + + err = idiagnl_req_set_src(req, src); + if (err < 0) + goto errout; + + nl_addr_put(src); + + *result = req; + return 0; + +errout: + idiagnl_req_put(req); + return err; + +errout_nomem: + err = -NLE_NOMEM; + goto errout; +} + +/** @cond SKIP */ +struct nl_object_ops idiagnl_req_obj_ops = { + .oo_name = "idiag/idiag_req", + .oo_size = sizeof(struct idiagnl_req), + .oo_free_data = idiagnl_req_free, + .oo_clone = idiagnl_req_clone, + .oo_dump = { + [NL_DUMP_LINE] = idiag_req_dump_line, + [NL_DUMP_DETAILS] = idiag_req_dump_details, + [NL_DUMP_STATS] = idiag_req_dump_stats, + }, +}; +/** @endcond */ + +/** @} */ diff --git a/lib/idiag/idiag_vegasinfo_obj.c b/lib/idiag/idiag_vegasinfo_obj.c new file mode 100644 index 0000000..f9e9408 --- /dev/null +++ b/lib/idiag/idiag_vegasinfo_obj.c @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Sassano Systems LLC + */ + +#include "nl-default.h" + +#include + +#include "nl-idiag.h" + +/** + * @ingroup idiag + * @defgroup idiagnl_vegasinfo Inet Diag TCP Vegas Info + * + * @details + * @idiagnl_doc{idiagnl_vegasinfo, Inet Diag TCP Vegas Info Documentation} + * @{ + */ +struct idiagnl_vegasinfo *idiagnl_vegasinfo_alloc(void) +{ + return (struct idiagnl_vegasinfo *) nl_object_alloc(&idiagnl_vegasinfo_obj_ops); +} + +void idiagnl_vegasinfo_get(struct idiagnl_vegasinfo *vinfo) +{ + nl_object_get((struct nl_object *) vinfo); +} + +void idiagnl_vegasinfo_put(struct idiagnl_vegasinfo *vinfo) +{ + nl_object_put((struct nl_object *) vinfo); +} + +/** + * @name Attributes + * @{ + */ +uint32_t idiagnl_vegasinfo_get_enabled(const struct idiagnl_vegasinfo *vinfo) +{ + return vinfo->tcpv_enabled; +} + +void idiagnl_vegasinfo_set_enabled(struct idiagnl_vegasinfo *vinfo, uint32_t + enabled) +{ + vinfo->tcpv_enabled = enabled; +} + +uint32_t idiagnl_vegasinfo_get_rttcnt(const struct idiagnl_vegasinfo *vinfo) +{ + return vinfo->tcpv_rttcnt; +} + +void idiagnl_vegasinfo_set_rttcnt(struct idiagnl_vegasinfo *vinfo, uint32_t + rttcnt) +{ + vinfo->tcpv_rttcnt = rttcnt; +} + +uint32_t idiagnl_vegasinfo_get_rtt(const struct idiagnl_vegasinfo *vinfo) +{ + return vinfo->tcpv_rtt; +} + +void idiagnl_vegasinfo_set_rtt(struct idiagnl_vegasinfo *vinfo, uint32_t rtt) +{ + vinfo->tcpv_rtt = rtt; +} + +uint32_t idiagnl_vegasinfo_get_minrtt(const struct idiagnl_vegasinfo *vinfo) +{ + return vinfo->tcpv_minrtt; +} + +void idiagnl_vegasinfo_set_minrtt(struct idiagnl_vegasinfo *vinfo, uint32_t + minrtt) +{ + vinfo->tcpv_minrtt = minrtt; +} +/** @} */ + +/** @cond SKIP */ +static uint64_t idiagnl_vegasinfo_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) +{ + struct idiagnl_vegasinfo *a = (struct idiagnl_vegasinfo *) _a; + struct idiagnl_vegasinfo *b = (struct idiagnl_vegasinfo *) _b; + + /* vegasinfo is a very simple object. It has no attribe flags (ce_mask), + * hence compare just returns 0 or 1, not a bit mask of attributes. */ + return a->tcpv_enabled != b->tcpv_enabled || + a->tcpv_rttcnt != b->tcpv_rttcnt || + a->tcpv_rtt != b->tcpv_rtt || + a->tcpv_minrtt != b->tcpv_minrtt; +} + +struct nl_object_ops idiagnl_vegasinfo_obj_ops = { + .oo_name = "idiag/idiag_vegasinfo", + .oo_size = sizeof(struct idiagnl_vegasinfo), + .oo_compare = idiagnl_vegasinfo_compare, +}; +/** @endcond */ +/** @} */ diff --git a/lib/idiag/nl-idiag.h b/lib/idiag/nl-idiag.h new file mode 100644 index 0000000..3615bb3 --- /dev/null +++ b/lib/idiag/nl-idiag.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2003-2013 Thomas Graf + * Copyright (c) 2013 Sassano Systems LLC + */ + +#ifndef __LIB_IDIAG_NL_IDIAG_H__ +#define __LIB_IDIAG_NL_IDIAG_H__ + +#include "nl-priv-dynamic-core/object-api.h" + +struct idiagnl_meminfo { + NLHDR_COMMON + + uint32_t idiag_rmem; + uint32_t idiag_wmem; + uint32_t idiag_fmem; + uint32_t idiag_tmem; +}; + +struct idiagnl_vegasinfo { + NLHDR_COMMON + + uint32_t tcpv_enabled; + uint32_t tcpv_rttcnt; + uint32_t tcpv_rtt; + uint32_t tcpv_minrtt; +}; + +#endif /* __LIB_IDIAG_NL_IDIAG_H__ */ diff --git a/lib/mpls.c b/lib/mpls.c new file mode 100644 index 0000000..d0189bf --- /dev/null +++ b/lib/mpls.c @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Adapted from mpls_ntop and mpls_pton copied from iproute2, + * lib/mpls_ntop.c and lib/mpls_pton.c + */ + +#include "nl-default.h" + +#include + +#include + +#include + +#include "mpls.h" + +static const char *mpls_ntop1(const struct mpls_label *addr, + char *buf, size_t buflen) +{ + size_t destlen = buflen; + char *dest = buf; + int count = 0; + + while (1) { + uint32_t entry = ntohl(addr[count++].entry); + uint32_t label = (entry & MPLS_LS_LABEL_MASK) >> MPLS_LS_LABEL_SHIFT; + int len = snprintf(dest, destlen, "%u", label); + + if (len >= destlen) + break; + + /* Is this the end? */ + if (entry & MPLS_LS_S_MASK) + return buf; + + dest += len; + destlen -= len; + if (destlen) { + *dest = '/'; + dest++; + destlen--; + } + } + errno = E2BIG; + + return NULL; +} + +const char *mpls_ntop(int af, const void *addr, char *buf, size_t buflen) +{ + switch(af) { + case AF_MPLS: + errno = 0; + return mpls_ntop1((struct mpls_label *)addr, buf, buflen); + } + + errno = EINVAL; + return NULL; +} + +static int mpls_pton1(const char *name, struct mpls_label *addr, + unsigned int maxlabels) +{ + char *endp; + unsigned count; + + for (count = 0; count < maxlabels; count++) { + unsigned long label; + + label = strtoul(name, &endp, 0); + /* Fail when the label value is out or range */ + if (label >= (1 << 20)) + return 0; + + if (endp == name) /* no digits */ + return 0; + + addr->entry = htonl(label << MPLS_LS_LABEL_SHIFT); + if (*endp == '\0') { + addr->entry |= htonl(1 << MPLS_LS_S_SHIFT); + return (count + 1) * sizeof(struct mpls_label); + } + + /* Bad character in the address */ + if (*endp != '/') + return 0; + + name = endp + 1; + addr += 1; + } + + /* The address was too long */ + return 0; +} + +int mpls_pton(int af, const char *src, void *addr, size_t alen) +{ + unsigned int maxlabels = alen / sizeof(struct mpls_label); + int err; + + switch(af) { + case AF_MPLS: + errno = 0; + err = mpls_pton1(src, (struct mpls_label *)addr, maxlabels); + break; + default: + errno = EAFNOSUPPORT; + err = -1; + } + + return err; +} diff --git a/lib/mpls.h b/lib/mpls.h new file mode 100644 index 0000000..591b3cc --- /dev/null +++ b/lib/mpls.h @@ -0,0 +1,7 @@ +#ifndef MPLS_H_ +#define MPLS_H_ + +extern const char *mpls_ntop(int af, const void *addr, char *buf, size_t buflen); +extern int mpls_pton(int af, const char *src, void *addr, size_t alen); + +#endif diff --git a/lib/msg.c b/lib/msg.c index 6478507..0e1592a 100644 --- a/lib/msg.c +++ b/lib/msg.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/msg.c Netlink Messages Interface - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -26,16 +20,25 @@ * ~~~~ */ -#include +#include "nl-default.h" + +#include + +#include + #include #include #include #include -#include + +#include "nl-core.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" +#include "nl-aux-core/nl-core.h" static size_t default_msg_size; -static void __init init_msg_size(void) +static void _nl_init init_msg_size(void) { default_msg_size = getpagesize(); } @@ -153,7 +156,7 @@ struct nlattr *nlmsg_attrdata(const struct nlmsghdr *nlh, int hdrlen) */ int nlmsg_attrlen(const struct nlmsghdr *nlh, int hdrlen) { - return nlmsg_len(nlh) - NLMSG_ALIGN(hdrlen); + return _NL_MAX(nlmsg_len(nlh) - NLMSG_ALIGN(hdrlen), 0u); } /** @} */ @@ -211,7 +214,7 @@ struct nlmsghdr *nlmsg_next(struct nlmsghdr *nlh, int *remaining) * See nla_parse() */ int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], - int maxtype, struct nla_policy *policy) + int maxtype, const struct nla_policy *policy) { if (!nlmsg_valid_hdr(nlh, hdrlen)) return -NLE_MSG_TOOSHORT; @@ -242,7 +245,7 @@ struct nlattr *nlmsg_find_attr(struct nlmsghdr *nlh, int hdrlen, int attrtype) * @arg policy validation policy */ int nlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype, - struct nla_policy *policy) + const struct nla_policy *policy) { if (!nlmsg_valid_hdr(nlh, hdrlen)) return -NLE_MSG_TOOSHORT; @@ -275,8 +278,6 @@ static struct nl_msg *__nlmsg_alloc(size_t len) if (!nm->nm_nlh) goto errout; - memset(nm->nm_nlh, 0, sizeof(struct nlmsghdr)); - nm->nm_protocol = -1; nm->nm_size = len; nm->nm_nlh->nlmsg_len = nlmsg_total_size(0); @@ -351,6 +352,8 @@ struct nl_msg *nlmsg_alloc_simple(int nlmsgtype, int flags) struct nlmsghdr nlh = { .nlmsg_type = nlmsgtype, .nlmsg_flags = flags, + .nlmsg_seq = NL_AUTO_SEQ, + .nlmsg_pid = NL_AUTO_PID, }; msg = nlmsg_inherit(&nlh); @@ -387,14 +390,11 @@ struct nl_msg *nlmsg_convert(struct nlmsghdr *hdr) nm = __nlmsg_alloc(NLMSG_ALIGN(hdr->nlmsg_len)); if (!nm) - goto errout; + return NULL; memcpy(nm->nm_nlh, hdr, hdr->nlmsg_len); return nm; -errout: - nlmsg_free(nm); - return NULL; } /** @@ -411,10 +411,13 @@ errout: */ void *nlmsg_reserve(struct nl_msg *n, size_t len, int pad) { - void *buf = n->nm_nlh; + char *buf = (char *) n->nm_nlh; size_t nlmsg_len = n->nm_nlh->nlmsg_len; size_t tlen; + if (len > n->nm_size) + return NULL; + tlen = pad ? ((len + (pad - 1)) & ~(pad - 1)) : len; if ((tlen + nlmsg_len) > n->nm_size) @@ -574,8 +577,8 @@ void nlmsg_free(struct nl_msg *msg) if (msg->nm_refcnt <= 0) { free(msg->nm_nlh); - free(msg); NL_DBG(2, "msg %p: Freed\n", msg); + free(msg); } } @@ -642,10 +645,10 @@ struct ucred *nlmsg_get_creds(struct nl_msg *msg) */ static const struct trans_tbl nl_msgtypes[] = { - __ADD(NLMSG_NOOP,NOOP) - __ADD(NLMSG_ERROR,ERROR) - __ADD(NLMSG_DONE,DONE) - __ADD(NLMSG_OVERRUN,OVERRUN) + __ADD(NLMSG_NOOP,NOOP), + __ADD(NLMSG_ERROR,ERROR), + __ADD(NLMSG_DONE,DONE), + __ADD(NLMSG_OVERRUN,OVERRUN), }; char *nl_nlmsgtype2str(int type, char *buf, size_t size) @@ -836,7 +839,7 @@ static void print_genl_hdr(FILE *ofd, void *start) static void *print_genl_msg(struct nl_msg *msg, FILE *ofd, struct nlmsghdr *hdr, struct nl_cache_ops *ops, int *payloadlen) { - void *data = nlmsg_data(hdr); + char *data = nlmsg_data(hdr); if (*payloadlen < GENL_HDRLEN) return data; @@ -899,7 +902,7 @@ static void dump_attrs(FILE *ofd, struct nlattr *attrs, int attrlen, prefix_line(ofd, prefix); fprintf(ofd, " [PADDING] %d octets\n", padlen); - dump_hex(ofd, nla_data(nla) + alen, + dump_hex(ofd, (char *) nla_data(nla) + alen, padlen, prefix); } } @@ -918,11 +921,10 @@ static void dump_error_msg(struct nl_msg *msg, FILE *ofd) fprintf(ofd, " [ERRORMSG] %zu octets\n", sizeof(*err)); if (nlmsg_len(hdr) >= sizeof(*err)) { - char buf[256]; struct nl_msg *errmsg; fprintf(ofd, " .error = %d \"%s\"\n", err->error, - strerror_r(-err->error, buf, sizeof(buf))); + nl_strerror_l(-err->error)); fprintf(ofd, " [ORIGINAL MESSAGE] %zu octets\n", sizeof(*hdr)); errmsg = nlmsg_inherit(&err->msg); diff --git a/lib/netfilter/ct.c b/lib/netfilter/ct.c index 794932f..3a69a2d 100644 --- a/lib/netfilter/ct.c +++ b/lib/netfilter/ct.c @@ -1,15 +1,9 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/netfilter/ct.c Conntrack - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation - * Copyright (c= 2008 Patrick McHardy + * Copyright (c) 2008 Patrick McHardy */ /** @@ -19,28 +13,22 @@ * @{ */ -#include +#include "nl-default.h" + #include + #include -#include #include #include #include +#include "nl-netfilter.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" + static struct nl_cache_ops nfnl_ct_ops; -#if __BYTE_ORDER == __BIG_ENDIAN -static uint64_t ntohll(uint64_t x) -{ - return x; -} -#elif __BYTE_ORDER == __LITTLE_ENDIAN -static uint64_t ntohll(uint64_t x) -{ - return bswap_64(x); -} -#endif static struct nla_policy ct_policy[CTA_MAX+1] = { [CTA_TUPLE_ORIG] = { .type = NLA_NESTED }, @@ -55,6 +43,7 @@ static struct nla_policy ct_policy[CTA_MAX+1] = { [CTA_COUNTERS_REPLY] = { .type = NLA_NESTED }, [CTA_USE] = { .type = NLA_U32 }, [CTA_ID] = { .type = NLA_U32 }, + [CTA_ZONE] = { .type = NLA_U16 }, //[CTA_NAT_DST] }; @@ -102,13 +91,18 @@ static struct nla_policy ct_counters_policy[CTA_COUNTERS_MAX+1] = { [CTA_COUNTERS32_BYTES] = { .type = NLA_U32 }, }; +static struct nla_policy ct_timestamp_policy[CTA_TIMESTAMP_MAX + 1] = { + [CTA_TIMESTAMP_START] = { .type = NLA_U64 }, + [CTA_TIMESTAMP_STOP] = { .type = NLA_U64 }, +}; + static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr) { struct nlattr *tb[CTA_IP_MAX+1]; struct nl_addr *addr; int err; - err = nla_parse_nested(tb, CTA_IP_MAX, attr, ct_ip_policy); + err = nla_parse_nested(tb, CTA_IP_MAX, attr, ct_ip_policy); if (err < 0) goto errout; @@ -300,40 +294,43 @@ int nfnlmsg_ct_group(struct nlmsghdr *nlh) } } -int nfnlmsg_ct_parse(struct nlmsghdr *nlh, struct nfnl_ct **result) +static int ct_parse_timestamp(struct nfnl_ct *ct, struct nlattr *attr) { - struct nfnl_ct *ct; - struct nlattr *tb[CTA_MAX+1]; + struct nlattr *tb[CTA_TIMESTAMP_MAX + 1]; int err; - ct = nfnl_ct_alloc(); - if (!ct) - return -NLE_NOMEM; + err = nla_parse_nested(tb, CTA_TIMESTAMP_MAX, attr, + ct_timestamp_policy); + if (err < 0) + return err; - ct->ce_msgtype = nlh->nlmsg_type; + if (tb[CTA_TIMESTAMP_START] && tb[CTA_TIMESTAMP_STOP]) + nfnl_ct_set_timestamp(ct, + ntohll(nla_get_u64(tb[CTA_TIMESTAMP_START])), + ntohll(nla_get_u64(tb[CTA_TIMESTAMP_STOP]))); - err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_MAX, - ct_policy); - if (err < 0) - goto errout; + return 0; +} - nfnl_ct_set_family(ct, nfnlmsg_family(nlh)); +static int _nfnlmsg_ct_parse(struct nlattr **tb, struct nfnl_ct *ct) +{ + int err; if (tb[CTA_TUPLE_ORIG]) { err = ct_parse_tuple(ct, 0, tb[CTA_TUPLE_ORIG]); if (err < 0) - goto errout; + return err; } if (tb[CTA_TUPLE_REPLY]) { err = ct_parse_tuple(ct, 1, tb[CTA_TUPLE_REPLY]); if (err < 0) - goto errout; + return err; } if (tb[CTA_PROTOINFO]) { err = ct_parse_protoinfo(ct, tb[CTA_PROTOINFO]); if (err < 0) - goto errout; + return err; } if (tb[CTA_STATUS]) @@ -346,22 +343,86 @@ int nfnlmsg_ct_parse(struct nlmsghdr *nlh, struct nfnl_ct **result) nfnl_ct_set_use(ct, ntohl(nla_get_u32(tb[CTA_USE]))); if (tb[CTA_ID]) nfnl_ct_set_id(ct, ntohl(nla_get_u32(tb[CTA_ID]))); + if (tb[CTA_ZONE]) + nfnl_ct_set_zone(ct, ntohs(nla_get_u16(tb[CTA_ZONE]))); if (tb[CTA_COUNTERS_ORIG]) { err = ct_parse_counters(ct, 0, tb[CTA_COUNTERS_ORIG]); if (err < 0) - goto errout; + return err; } if (tb[CTA_COUNTERS_REPLY]) { err = ct_parse_counters(ct, 1, tb[CTA_COUNTERS_REPLY]); if (err < 0) - goto errout; + return err; + } + + if (tb[CTA_TIMESTAMP]) { + err = ct_parse_timestamp(ct, tb[CTA_TIMESTAMP]); + if (err < 0) + return err; } + return 0; +} + +int nfnlmsg_ct_parse(struct nlmsghdr *nlh, struct nfnl_ct **result) +{ + struct nfnl_ct *ct; + struct nlattr *tb[CTA_MAX+1]; + int err; + + ct = nfnl_ct_alloc(); + if (!ct) + return -NLE_NOMEM; + + ct->ce_msgtype = nlh->nlmsg_type; + + err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_MAX, + ct_policy); + if (err < 0) + goto errout; + + nfnl_ct_set_family(ct, nfnlmsg_family(nlh)); + + err = _nfnlmsg_ct_parse(tb, ct); + if (err < 0) + goto errout; + *result = ct; return 0; +errout: + nfnl_ct_put(ct); + return err; +} +int nfnlmsg_ct_parse_nested(struct nlattr *attr, struct nfnl_ct **result) +{ + struct nfnl_ct *ct; + struct nlattr *tb[CTA_MAX+1]; + int err; + + ct = nfnl_ct_alloc(); + if (!ct) + return -NLE_NOMEM; + + // msgtype not given for nested + //ct->ce_msgtype = nlh->nlmsg_type; + + err = nla_parse_nested(tb, CTA_MAX, attr, ct_policy); + if (err < 0) + goto errout; + + // family not known + //nfnl_ct_set_family(ct, nfnlmsg_family(nlh)); + + err = _nfnlmsg_ct_parse(tb, ct); + if (err < 0) + goto errout; + + *result = ct; + return 0; errout: nfnl_ct_put(ct); return err; @@ -374,14 +435,20 @@ static int ct_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, int err; if ((err = nfnlmsg_ct_parse(nlh, &ct)) < 0) - goto errout; + return err; err = pp->pp_cb((struct nl_object *) ct, pp); -errout: nfnl_ct_put(ct); return err; } +/** + * Send nfnl ct dump request + * @arg sk Netlink socket. + * + * @return 0 on success or a negative error code. Due to a bug, this function + * returns the number of bytes sent. Treat any non-negative number as success. + */ int nfnl_ct_dump_request(struct nl_sock *sk) { return nfnl_send_simple(sk, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET, @@ -479,18 +546,44 @@ static int nfnl_ct_build_message(const struct nfnl_ct *ct, int cmd, int flags, { struct nl_msg *msg; int err; + int reply = 0; msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK, cmd, flags, nfnl_ct_get_family(ct), 0); if (msg == NULL) return -NLE_NOMEM; - if ((err = nfnl_ct_build_tuple(msg, ct, 0)) < 0) - goto err_out; + /* We use REPLY || ORIG, depending on requests. */ + if (nfnl_ct_get_src(ct, 1) || nfnl_ct_get_dst(ct, 1)) { + reply = 1; + if ((err = nfnl_ct_build_tuple(msg, ct, 1)) < 0) + goto err_out; + } + + if (!reply || nfnl_ct_get_src(ct, 0) || nfnl_ct_get_dst(ct, 0)) { + if ((err = nfnl_ct_build_tuple(msg, ct, 0)) < 0) + goto err_out; + } + + if (nfnl_ct_test_status(ct)) + NLA_PUT_U32(msg, CTA_STATUS, htonl(nfnl_ct_get_status(ct))); + + if (nfnl_ct_test_timeout(ct)) + NLA_PUT_U32(msg, CTA_TIMEOUT, htonl(nfnl_ct_get_timeout(ct))); + + if (nfnl_ct_test_mark(ct)) + NLA_PUT_U32(msg, CTA_MARK, htonl(nfnl_ct_get_mark(ct))); + + if (nfnl_ct_test_id(ct)) + NLA_PUT_U32(msg, CTA_ID, htonl(nfnl_ct_get_id(ct))); + + if (nfnl_ct_test_zone(ct)) + NLA_PUT_U16(msg, CTA_ZONE, htons(nfnl_ct_get_zone(ct))); *result = msg; return 0; +nla_put_failure: err_out: nlmsg_free(msg); return err; @@ -615,12 +708,12 @@ static struct nl_cache_ops nfnl_ct_ops = { .co_obj_ops = &ct_obj_ops, }; -static void __init ct_init(void) +static void _nl_init ct_init(void) { nl_cache_mngt_register(&nfnl_ct_ops); } -static void __exit ct_exit(void) +static void _nl_exit ct_exit(void) { nl_cache_mngt_unregister(&nfnl_ct_ops); } diff --git a/lib/netfilter/ct_obj.c b/lib/netfilter/ct_obj.c index bac775b..4430400 100644 --- a/lib/netfilter/ct_obj.c +++ b/lib/netfilter/ct_obj.c @@ -1,25 +1,26 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/netfilter/ct_obj.c Conntrack Object - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation */ +#include "nl-default.h" + #include + #include #include + #include -#include #include #include +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-netfilter.h" +#include "nl-priv-dynamic-core/nl-core.h" + /** @cond SKIP */ #define CT_ATTR_FAMILY (1UL << 0) #define CT_ATTR_PROTO (1UL << 1) @@ -51,6 +52,8 @@ #define CT_ATTR_REPL_ICMP_CODE (1UL << 23) #define CT_ATTR_REPL_PACKETS (1UL << 24) #define CT_ATTR_REPL_BYTES (1UL << 25) +#define CT_ATTR_TIMESTAMP (1UL << 26) +#define CT_ATTR_ZONE (1UL << 27) /** @endcond */ static void ct_free_data(struct nl_object *c) @@ -72,6 +75,11 @@ static int ct_clone(struct nl_object *_dst, struct nl_object *_src) struct nfnl_ct *src = (struct nfnl_ct *) _src; struct nl_addr *addr; + dst->ct_orig.src = NULL; + dst->ct_orig.dst = NULL; + dst->ct_repl.src = NULL; + dst->ct_repl.dst = NULL; + if (src->ct_orig.src) { addr = nl_addr_clone(src->ct_orig.src); if (!addr) @@ -192,6 +200,20 @@ static void ct_dump_line(struct nl_object *a, struct nl_dump_params *p) if (nfnl_ct_test_mark(ct) && nfnl_ct_get_mark(ct)) nl_dump(p, "mark %u ", nfnl_ct_get_mark(ct)); + if (nfnl_ct_test_zone(ct)) + nl_dump(p, "zone %hu ", nfnl_ct_get_zone(ct)); + + if (nfnl_ct_test_timestamp(ct)) { + const struct nfnl_ct_timestamp *tstamp = nfnl_ct_get_timestamp(ct); + int64_t delta_time = tstamp->stop - tstamp->start; + + if (delta_time > 0) + delta_time /= NSEC_PER_SEC; + else + delta_time = 0; + nl_dump(p, "delta-time %llu ", (long long unsigned)delta_time); + } + nl_dump(p, "\n"); } @@ -204,8 +226,9 @@ static void ct_dump_details(struct nl_object *a, struct nl_dump_params *p) ct_dump_line(a, p); nl_dump(p, " id 0x%x ", ct->ct_id); - nl_dump_line(p, "family %s ", - nl_af2str(ct->ct_family, buf, sizeof(buf))); + if (ct->ce_mask & CT_ATTR_FAMILY) + nl_dump_line(p, "family %s ", + nl_af2str(ct->ct_family, buf, sizeof(buf))); if (nfnl_ct_test_use(ct)) nl_dump(p, "refcnt %u ", nfnl_ct_get_use(ct)); @@ -281,86 +304,84 @@ static void ct_dump_stats(struct nl_object *a, struct nl_dump_params *p) } } -static int ct_compare(struct nl_object *_a, struct nl_object *_b, - uint32_t attrs, int flags) +static uint64_t ct_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) { struct nfnl_ct *a = (struct nfnl_ct *) _a; struct nfnl_ct *b = (struct nfnl_ct *) _b; - int diff = 0; - -#define CT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, CT_ATTR_##ATTR, a, b, EXPR) -#define CT_DIFF_VAL(ATTR, FIELD) CT_DIFF(ATTR, a->FIELD != b->FIELD) -#define CT_DIFF_ADDR(ATTR, FIELD) \ - ((flags & LOOSE_COMPARISON) \ - ? CT_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \ - : CT_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD))) - - diff |= CT_DIFF_VAL(FAMILY, ct_family); - diff |= CT_DIFF_VAL(PROTO, ct_proto); - diff |= CT_DIFF_VAL(TCP_STATE, ct_protoinfo.tcp.state); - diff |= CT_DIFF_VAL(TIMEOUT, ct_timeout); - diff |= CT_DIFF_VAL(MARK, ct_mark); - diff |= CT_DIFF_VAL(USE, ct_use); - diff |= CT_DIFF_VAL(ID, ct_id); - diff |= CT_DIFF_ADDR(ORIG_SRC, ct_orig.src); - diff |= CT_DIFF_ADDR(ORIG_DST, ct_orig.dst); - diff |= CT_DIFF_VAL(ORIG_SRC_PORT, ct_orig.proto.port.src); - diff |= CT_DIFF_VAL(ORIG_DST_PORT, ct_orig.proto.port.dst); - diff |= CT_DIFF_VAL(ORIG_ICMP_ID, ct_orig.proto.icmp.id); - diff |= CT_DIFF_VAL(ORIG_ICMP_TYPE, ct_orig.proto.icmp.type); - diff |= CT_DIFF_VAL(ORIG_ICMP_CODE, ct_orig.proto.icmp.code); - diff |= CT_DIFF_VAL(ORIG_PACKETS, ct_orig.packets); - diff |= CT_DIFF_VAL(ORIG_BYTES, ct_orig.bytes); - diff |= CT_DIFF_ADDR(REPL_SRC, ct_repl.src); - diff |= CT_DIFF_ADDR(REPL_DST, ct_repl.dst); - diff |= CT_DIFF_VAL(REPL_SRC_PORT, ct_repl.proto.port.src); - diff |= CT_DIFF_VAL(REPL_DST_PORT, ct_repl.proto.port.dst); - diff |= CT_DIFF_VAL(REPL_ICMP_ID, ct_repl.proto.icmp.id); - diff |= CT_DIFF_VAL(REPL_ICMP_TYPE, ct_repl.proto.icmp.type); - diff |= CT_DIFF_VAL(REPL_ICMP_CODE, ct_repl.proto.icmp.code); - diff |= CT_DIFF_VAL(REPL_PACKETS, ct_repl.packets); - diff |= CT_DIFF_VAL(REPL_BYTES, ct_repl.bytes); + uint64_t diff = 0; + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) +#define _DIFF_VAL(ATTR, FIELD) _DIFF(ATTR, a->FIELD != b->FIELD) +#define _DIFF_ADDR(ATTR, FIELD) \ + ((flags & LOOSE_COMPARISON) ? \ + _DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) : \ + _DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD))) + diff |= _DIFF_VAL(CT_ATTR_FAMILY, ct_family); + diff |= _DIFF_VAL(CT_ATTR_PROTO, ct_proto); + diff |= _DIFF_VAL(CT_ATTR_TCP_STATE, ct_protoinfo.tcp.state); + diff |= _DIFF_VAL(CT_ATTR_TIMEOUT, ct_timeout); + diff |= _DIFF_VAL(CT_ATTR_MARK, ct_mark); + diff |= _DIFF_VAL(CT_ATTR_USE, ct_use); + diff |= _DIFF_VAL(CT_ATTR_ID, ct_id); + diff |= _DIFF_ADDR(CT_ATTR_ORIG_SRC, ct_orig.src); + diff |= _DIFF_ADDR(CT_ATTR_ORIG_DST, ct_orig.dst); + diff |= _DIFF_VAL(CT_ATTR_ORIG_SRC_PORT, ct_orig.proto.port.src); + diff |= _DIFF_VAL(CT_ATTR_ORIG_DST_PORT, ct_orig.proto.port.dst); + diff |= _DIFF_VAL(CT_ATTR_ORIG_ICMP_ID, ct_orig.proto.icmp.id); + diff |= _DIFF_VAL(CT_ATTR_ORIG_ICMP_TYPE, ct_orig.proto.icmp.type); + diff |= _DIFF_VAL(CT_ATTR_ORIG_ICMP_CODE, ct_orig.proto.icmp.code); + diff |= _DIFF_VAL(CT_ATTR_ORIG_PACKETS, ct_orig.packets); + diff |= _DIFF_VAL(CT_ATTR_ORIG_BYTES, ct_orig.bytes); + diff |= _DIFF_ADDR(CT_ATTR_REPL_SRC, ct_repl.src); + diff |= _DIFF_ADDR(CT_ATTR_REPL_DST, ct_repl.dst); + diff |= _DIFF_VAL(CT_ATTR_REPL_SRC_PORT, ct_repl.proto.port.src); + diff |= _DIFF_VAL(CT_ATTR_REPL_DST_PORT, ct_repl.proto.port.dst); + diff |= _DIFF_VAL(CT_ATTR_REPL_ICMP_ID, ct_repl.proto.icmp.id); + diff |= _DIFF_VAL(CT_ATTR_REPL_ICMP_TYPE, ct_repl.proto.icmp.type); + diff |= _DIFF_VAL(CT_ATTR_REPL_ICMP_CODE, ct_repl.proto.icmp.code); + diff |= _DIFF_VAL(CT_ATTR_REPL_PACKETS, ct_repl.packets); + diff |= _DIFF_VAL(CT_ATTR_REPL_BYTES, ct_repl.bytes); if (flags & LOOSE_COMPARISON) - diff |= CT_DIFF(STATUS, (a->ct_status ^ b->ct_status) & - b->ct_status_mask); + diff |= _DIFF(CT_ATTR_STATUS, (a->ct_status ^ b->ct_status) & + b->ct_status_mask); else - diff |= CT_DIFF(STATUS, a->ct_status != b->ct_status); - -#undef CT_DIFF -#undef CT_DIFF_VAL -#undef CT_DIFF_ADDR + diff |= _DIFF(CT_ATTR_STATUS, a->ct_status != b->ct_status); +#undef _DIFF +#undef _DIFF_VAL +#undef _DIFF_ADDR return diff; } static const struct trans_tbl ct_attrs[] = { - __ADD(CT_ATTR_FAMILY, family) - __ADD(CT_ATTR_PROTO, proto) - __ADD(CT_ATTR_TCP_STATE, tcpstate) - __ADD(CT_ATTR_STATUS, status) - __ADD(CT_ATTR_TIMEOUT, timeout) - __ADD(CT_ATTR_MARK, mark) - __ADD(CT_ATTR_USE, use) - __ADD(CT_ATTR_ID, id) - __ADD(CT_ATTR_ORIG_SRC, origsrc) - __ADD(CT_ATTR_ORIG_DST, origdst) - __ADD(CT_ATTR_ORIG_SRC_PORT, origsrcport) - __ADD(CT_ATTR_ORIG_DST_PORT, origdstport) - __ADD(CT_ATTR_ORIG_ICMP_ID, origicmpid) - __ADD(CT_ATTR_ORIG_ICMP_TYPE, origicmptype) - __ADD(CT_ATTR_ORIG_ICMP_CODE, origicmpcode) - __ADD(CT_ATTR_ORIG_PACKETS, origpackets) - __ADD(CT_ATTR_ORIG_BYTES, origbytes) - __ADD(CT_ATTR_REPL_SRC, replysrc) - __ADD(CT_ATTR_REPL_DST, replydst) - __ADD(CT_ATTR_REPL_SRC_PORT, replysrcport) - __ADD(CT_ATTR_REPL_DST_PORT, replydstport) - __ADD(CT_ATTR_REPL_ICMP_ID, replyicmpid) - __ADD(CT_ATTR_REPL_ICMP_TYPE, replyicmptype) - __ADD(CT_ATTR_REPL_ICMP_CODE, replyicmpcode) - __ADD(CT_ATTR_REPL_PACKETS, replypackets) - __ADD(CT_ATTR_REPL_BYTES, replybytes) + __ADD(CT_ATTR_FAMILY, family), + __ADD(CT_ATTR_PROTO, proto), + __ADD(CT_ATTR_TCP_STATE, tcpstate), + __ADD(CT_ATTR_STATUS, status), + __ADD(CT_ATTR_TIMEOUT, timeout), + __ADD(CT_ATTR_MARK, mark), + __ADD(CT_ATTR_USE, use), + __ADD(CT_ATTR_ID, id), + __ADD(CT_ATTR_ORIG_SRC, origsrc), + __ADD(CT_ATTR_ORIG_DST, origdst), + __ADD(CT_ATTR_ORIG_SRC_PORT, origsrcport), + __ADD(CT_ATTR_ORIG_DST_PORT, origdstport), + __ADD(CT_ATTR_ORIG_ICMP_ID, origicmpid), + __ADD(CT_ATTR_ORIG_ICMP_TYPE, origicmptype), + __ADD(CT_ATTR_ORIG_ICMP_CODE, origicmpcode), + __ADD(CT_ATTR_ORIG_PACKETS, origpackets), + __ADD(CT_ATTR_ORIG_BYTES, origbytes), + __ADD(CT_ATTR_REPL_SRC, replysrc), + __ADD(CT_ATTR_REPL_DST, replydst), + __ADD(CT_ATTR_REPL_SRC_PORT, replysrcport), + __ADD(CT_ATTR_REPL_DST_PORT, replydstport), + __ADD(CT_ATTR_REPL_ICMP_ID, replyicmpid), + __ADD(CT_ATTR_REPL_ICMP_TYPE, replyicmptype), + __ADD(CT_ATTR_REPL_ICMP_CODE, replyicmpcode), + __ADD(CT_ATTR_REPL_PACKETS, replypackets), + __ADD(CT_ATTR_REPL_BYTES, replybytes), }; static char *ct_attrs2str(int attrs, char *buf, size_t len) @@ -442,16 +463,16 @@ uint8_t nfnl_ct_get_tcp_state(const struct nfnl_ct *ct) } static const struct trans_tbl tcp_states[] = { - __ADD(TCP_CONNTRACK_NONE,NONE) - __ADD(TCP_CONNTRACK_SYN_SENT,SYN_SENT) - __ADD(TCP_CONNTRACK_SYN_RECV,SYN_RECV) - __ADD(TCP_CONNTRACK_ESTABLISHED,ESTABLISHED) - __ADD(TCP_CONNTRACK_FIN_WAIT,FIN_WAIT) - __ADD(TCP_CONNTRACK_CLOSE_WAIT,CLOSE_WAIT) - __ADD(TCP_CONNTRACK_LAST_ACK,LAST_ACK) - __ADD(TCP_CONNTRACK_TIME_WAIT,TIME_WAIT) - __ADD(TCP_CONNTRACK_CLOSE,CLOSE) - __ADD(TCP_CONNTRACK_LISTEN,LISTEN) + __ADD(TCP_CONNTRACK_NONE,NONE), + __ADD(TCP_CONNTRACK_SYN_SENT,SYN_SENT), + __ADD(TCP_CONNTRACK_SYN_RECV,SYN_RECV), + __ADD(TCP_CONNTRACK_ESTABLISHED,ESTABLISHED), + __ADD(TCP_CONNTRACK_FIN_WAIT,FIN_WAIT), + __ADD(TCP_CONNTRACK_CLOSE_WAIT,CLOSE_WAIT), + __ADD(TCP_CONNTRACK_LAST_ACK,LAST_ACK), + __ADD(TCP_CONNTRACK_TIME_WAIT,TIME_WAIT), + __ADD(TCP_CONNTRACK_CLOSE,CLOSE), + __ADD(TCP_CONNTRACK_LISTEN,LISTEN), }; char *nfnl_ct_tcp_state2str(uint8_t state, char *buf, size_t len) @@ -461,7 +482,7 @@ char *nfnl_ct_tcp_state2str(uint8_t state, char *buf, size_t len) int nfnl_ct_str2tcp_state(const char *name) { - return __str2type(name, tcp_states, ARRAY_SIZE(tcp_states)); + return __str2type(name, tcp_states, ARRAY_SIZE(tcp_states)); } void nfnl_ct_set_status(struct nfnl_ct *ct, uint32_t status) @@ -478,23 +499,28 @@ void nfnl_ct_unset_status(struct nfnl_ct *ct, uint32_t status) ct->ce_mask |= CT_ATTR_STATUS; } +int nfnl_ct_test_status(const struct nfnl_ct *ct) +{ + return !!(ct->ce_mask & CT_ATTR_STATUS); +} + uint32_t nfnl_ct_get_status(const struct nfnl_ct *ct) { return ct->ct_status; } static const struct trans_tbl status_flags[] = { - __ADD(IPS_EXPECTED, expected) - __ADD(IPS_SEEN_REPLY, seen_reply) - __ADD(IPS_ASSURED, assured) - __ADD(IPS_CONFIRMED, confirmed) - __ADD(IPS_SRC_NAT, snat) - __ADD(IPS_DST_NAT, dnat) - __ADD(IPS_SEQ_ADJUST, seqadjust) - __ADD(IPS_SRC_NAT_DONE, snat_done) - __ADD(IPS_DST_NAT_DONE, dnat_done) - __ADD(IPS_DYING, dying) - __ADD(IPS_FIXED_TIMEOUT, fixed_timeout) + __ADD(IPS_EXPECTED, expected), + __ADD(IPS_SEEN_REPLY, seen_reply), + __ADD(IPS_ASSURED, assured), + __ADD(IPS_CONFIRMED, confirmed), + __ADD(IPS_SRC_NAT, snat), + __ADD(IPS_DST_NAT, dnat), + __ADD(IPS_SEQ_ADJUST, seqadjust), + __ADD(IPS_SRC_NAT_DONE, snat_done), + __ADD(IPS_DST_NAT_DONE, dnat_done), + __ADD(IPS_DYING, dying), + __ADD(IPS_FIXED_TIMEOUT, fixed_timeout), }; char * nfnl_ct_status2str(int flags, char *buf, size_t len) @@ -572,6 +598,22 @@ uint32_t nfnl_ct_get_id(const struct nfnl_ct *ct) return ct->ct_id; } +void nfnl_ct_set_zone(struct nfnl_ct *ct, uint16_t zone) +{ + ct->ct_zone = zone; + ct->ce_mask |= CT_ATTR_ZONE; +} + +int nfnl_ct_test_zone(const struct nfnl_ct *ct) +{ + return !!(ct->ce_mask & CT_ATTR_ZONE); +} + +uint16_t nfnl_ct_get_zone(const struct nfnl_ct *ct) +{ + return ct->ct_zone; +} + static int ct_set_addr(struct nfnl_ct *ct, struct nl_addr *addr, int attr, struct nl_addr ** ct_addr) { @@ -777,6 +819,23 @@ uint64_t nfnl_ct_get_bytes(const struct nfnl_ct *ct, int repl) return dir->bytes; } +void nfnl_ct_set_timestamp(struct nfnl_ct *ct, uint64_t start, uint64_t stop) +{ + ct->ct_tstamp.start = start; + ct->ct_tstamp.stop = stop; + ct->ce_mask |= CT_ATTR_TIMESTAMP; +} + +int nfnl_ct_test_timestamp(const struct nfnl_ct *ct) +{ + return !!(ct->ce_mask & CT_ATTR_TIMESTAMP); +} + +const struct nfnl_ct_timestamp *nfnl_ct_get_timestamp(const struct nfnl_ct *ct) +{ + return &ct->ct_tstamp; +} + /** @} */ struct nl_object_ops ct_obj_ops = { diff --git a/lib/netfilter/exp.c b/lib/netfilter/exp.c index 86ed8d1..b0832d6 100644 --- a/lib/netfilter/exp.c +++ b/lib/netfilter/exp.c @@ -1,15 +1,9 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/netfilter/exp.c Conntrack Expectation - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation - * Copyright (c= 2008 Patrick McHardy + * Copyright (c) 2008 Patrick McHardy * Copyright (c) 2012 Rich Fought */ @@ -20,15 +14,20 @@ * @{ */ -#include +#include "nl-default.h" + #include + #include -#include #include #include #include +#include "nl-netfilter.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" + static struct nl_cache_ops nfnl_exp_ops; static struct nla_policy exp_policy[CTA_EXPECT_MAX+1] = { @@ -298,14 +297,20 @@ static int exp_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, int err; if ((err = nfnlmsg_exp_parse(nlh, &exp)) < 0) - goto errout; + return err; err = pp->pp_cb((struct nl_object *) exp, pp); -errout: nfnl_exp_put(exp); return err; } +/** + * Send nfnl exp dump request + * @arg sk Netlink socket. + * + * @return 0 on success or a negative error code. Due to a bug, this function + * returns the number of bytes sent. Treat any non-negative number as success. + */ int nfnl_exp_dump_request(struct nl_sock *sk) { return nfnl_send_simple(sk, NFNL_SUBSYS_CTNETLINK_EXP, IPCTNL_MSG_EXP_GET, @@ -346,15 +351,16 @@ static int nfnl_exp_build_tuple(struct nl_msg *msg, const struct nfnl_exp *exp, struct nlattr *tuple, *ip, *proto; struct nl_addr *addr; int family; + int type; family = nfnl_exp_get_family(exp); - int type = exp_get_tuple_attr(cta); + type = exp_get_tuple_attr(cta); - if (cta == CTA_EXPECT_NAT) - tuple = nla_nest_start(msg, CTA_EXPECT_NAT_TUPLE); - else - tuple = nla_nest_start(msg, cta); + if (cta == CTA_EXPECT_NAT) + tuple = nla_nest_start(msg, CTA_EXPECT_NAT_TUPLE); + else + tuple = nla_nest_start(msg, cta); if (!tuple) goto nla_put_failure; @@ -415,7 +421,6 @@ nla_put_failure: static int nfnl_exp_build_nat(struct nl_msg *msg, const struct nfnl_exp *exp) { struct nlattr *nat; - int err; nat = nla_nest_start(msg, CTA_EXPECT_NAT); @@ -424,7 +429,7 @@ static int nfnl_exp_build_nat(struct nl_msg *msg, const struct nfnl_exp *exp) nfnl_exp_get_nat_dir(exp)); } - if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_NAT)) < 0) + if (nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_NAT) < 0) goto nla_put_failure; nla_nest_end(msg, nat); @@ -484,6 +489,8 @@ static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags return 0; nla_put_failure: + err = -NLE_NOMEM; + err_out: nlmsg_free(msg); return err; @@ -608,12 +615,12 @@ static struct nl_cache_ops nfnl_exp_ops = { .co_obj_ops = &exp_obj_ops, }; -static void __init exp_init(void) +static void _nl_init exp_init(void) { nl_cache_mngt_register(&nfnl_exp_ops); } -static void __exit exp_exit(void) +static void _nl_exit exp_exit(void) { nl_cache_mngt_unregister(&nfnl_exp_ops); } diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c index 69b4dd3..8b78898 100644 --- a/lib/netfilter/exp_obj.c +++ b/lib/netfilter/exp_obj.c @@ -1,27 +1,27 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/netfilter/exp_obj.c Conntrack Expectation Object - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation * Copyright (c) 2012 Rich Fought */ +#include "nl-default.h" + #include -#include + #include #include + #include -#include #include #include +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-netfilter.h" +#include "nl-priv-dynamic-core/nl-core.h" + // The 32-bit attribute mask in the common object header isn't // big enough to handle all attributes of an expectation. So // we'll for sure specify optional attributes + parent attributes @@ -87,7 +87,17 @@ static int exp_clone(struct nl_object *_dst, struct nl_object *_src) struct nfnl_exp *src = (struct nfnl_exp *) _src; struct nl_addr *addr; - // Expectation + dst->exp_helper_name = NULL; + dst->exp_fn = NULL; + dst->exp_expect.src = NULL; + dst->exp_expect.dst = NULL; + dst->exp_master.src = NULL; + dst->exp_master.dst = NULL; + dst->exp_mask.src = NULL; + dst->exp_mask.dst = NULL; + dst->exp_nat.src = NULL; + dst->exp_nat.dst = NULL; + if (src->exp_expect.src) { addr = nl_addr_clone(src->exp_expect.src); if (!addr) @@ -102,7 +112,6 @@ static int exp_clone(struct nl_object *_dst, struct nl_object *_src) dst->exp_expect.dst = addr; } - // Master CT if (src->exp_master.src) { addr = nl_addr_clone(src->exp_master.src); if (!addr) @@ -117,7 +126,6 @@ static int exp_clone(struct nl_object *_dst, struct nl_object *_src) dst->exp_master.dst = addr; } - // Mask if (src->exp_mask.src) { addr = nl_addr_clone(src->exp_mask.src); if (!addr) @@ -132,7 +140,6 @@ static int exp_clone(struct nl_object *_dst, struct nl_object *_src) dst->exp_mask.dst = addr; } - // NAT if (src->exp_nat.src) { addr = nl_addr_clone(src->exp_nat.src); if (!addr) @@ -200,7 +207,7 @@ static void exp_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) if (nfnl_exp_test_dst(exp, i)) tuple_dst = nfnl_exp_get_dst(exp, i); - // Don't have tests for individual ports/types/codes/ids, + // Don't have tests for individual ports/types/codes/ids, if (nfnl_exp_test_l4protonum(exp, i)) { nl_dump(p, "%s ", nl_ip_proto2str(nfnl_exp_get_l4protonum(exp, i), buf, sizeof(buf))); @@ -217,7 +224,7 @@ static void exp_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) } if (nfnl_exp_test_nat_dir(exp)) - nl_dump(p, "nat dir %s ", exp->exp_nat_dir); + nl_dump(p, "nat dir %u ", exp->exp_nat_dir); } @@ -286,116 +293,124 @@ static int exp_cmp_l4proto_ports (union nfnl_exp_protodata *a, union nfnl_exp_pr // Must return 0 for match, 1 for mismatch int d = 0; d = ( (a->port.src != b->port.src) || - (a->port.dst != b->port.dst) ); + (a->port.dst != b->port.dst) ); return d; } static int exp_cmp_l4proto_icmp (union nfnl_exp_protodata *a, union nfnl_exp_protodata *b) { - // Must return 0 for match, 1 for mismatch + // Must return 0 for match, 1 for mismatch int d = 0; d = ( (a->icmp.code != b->icmp.code) || - (a->icmp.type != b->icmp.type) || - (a->icmp.id != b->icmp.id) ); + (a->icmp.type != b->icmp.type) || + (a->icmp.id != b->icmp.id) ); return d; } -static int exp_compare(struct nl_object *_a, struct nl_object *_b, - uint32_t attrs, int flags) +static uint64_t exp_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) { struct nfnl_exp *a = (struct nfnl_exp *) _a; struct nfnl_exp *b = (struct nfnl_exp *) _b; - int diff = 0; - -#define EXP_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, EXP_ATTR_##ATTR, a, b, EXPR) -#define EXP_DIFF_VAL(ATTR, FIELD) EXP_DIFF(ATTR, a->FIELD != b->FIELD) -#define EXP_DIFF_STRING(ATTR, FIELD) EXP_DIFF(ATTR, (strcmp(a->FIELD, b->FIELD) != 0)) -#define EXP_DIFF_ADDR(ATTR, FIELD) \ - ((flags & LOOSE_COMPARISON) \ - ? EXP_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \ - : EXP_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD))) -#define EXP_DIFF_L4PROTO_PORTS(ATTR, FIELD) \ - EXP_DIFF(ATTR, exp_cmp_l4proto_ports(&(a->FIELD), &(b->FIELD))) -#define EXP_DIFF_L4PROTO_ICMP(ATTR, FIELD) \ - EXP_DIFF(ATTR, exp_cmp_l4proto_icmp(&(a->FIELD), &(b->FIELD))) - - diff |= EXP_DIFF_VAL(FAMILY, exp_family); - diff |= EXP_DIFF_VAL(TIMEOUT, exp_timeout); - diff |= EXP_DIFF_VAL(ID, exp_id); - diff |= EXP_DIFF_VAL(ZONE, exp_zone); - diff |= EXP_DIFF_VAL(CLASS, exp_class); - diff |= EXP_DIFF_VAL(FLAGS, exp_flags); - diff |= EXP_DIFF_VAL(NAT_DIR, exp_nat_dir); - - diff |= EXP_DIFF_STRING(FN, exp_fn); - diff |= EXP_DIFF_STRING(HELPER_NAME, exp_helper_name); - - diff |= EXP_DIFF_ADDR(EXPECT_IP_SRC, exp_expect.src); - diff |= EXP_DIFF_ADDR(EXPECT_IP_DST, exp_expect.dst); - diff |= EXP_DIFF_VAL(EXPECT_L4PROTO_NUM, exp_expect.proto.l4protonum); - diff |= EXP_DIFF_L4PROTO_PORTS(EXPECT_L4PROTO_PORTS, exp_expect.proto.l4protodata); - diff |= EXP_DIFF_L4PROTO_ICMP(EXPECT_L4PROTO_ICMP, exp_expect.proto.l4protodata); - - diff |= EXP_DIFF_ADDR(MASTER_IP_SRC, exp_master.src); - diff |= EXP_DIFF_ADDR(MASTER_IP_DST, exp_master.dst); - diff |= EXP_DIFF_VAL(MASTER_L4PROTO_NUM, exp_master.proto.l4protonum); - diff |= EXP_DIFF_L4PROTO_PORTS(MASTER_L4PROTO_PORTS, exp_master.proto.l4protodata); - diff |= EXP_DIFF_L4PROTO_ICMP(MASTER_L4PROTO_ICMP, exp_master.proto.l4protodata); - - diff |= EXP_DIFF_ADDR(MASK_IP_SRC, exp_mask.src); - diff |= EXP_DIFF_ADDR(MASK_IP_DST, exp_mask.dst); - diff |= EXP_DIFF_VAL(MASK_L4PROTO_NUM, exp_mask.proto.l4protonum); - diff |= EXP_DIFF_L4PROTO_PORTS(MASK_L4PROTO_PORTS, exp_mask.proto.l4protodata); - diff |= EXP_DIFF_L4PROTO_ICMP(MASK_L4PROTO_ICMP, exp_mask.proto.l4protodata); - - diff |= EXP_DIFF_ADDR(NAT_IP_SRC, exp_nat.src); - diff |= EXP_DIFF_ADDR(NAT_IP_DST, exp_nat.dst); - diff |= EXP_DIFF_VAL(NAT_L4PROTO_NUM, exp_nat.proto.l4protonum); - diff |= EXP_DIFF_L4PROTO_PORTS(NAT_L4PROTO_PORTS, exp_nat.proto.l4protodata); - diff |= EXP_DIFF_L4PROTO_ICMP(NAT_L4PROTO_ICMP, exp_nat.proto.l4protodata); - -#undef EXP_DIFF -#undef EXP_DIFF_VAL -#undef EXP_DIFF_STRING -#undef EXP_DIFF_ADDR -#undef EXP_DIFF_L4PROTO_PORTS -#undef EXP_DIFF_L4PROTO_ICMP + uint64_t diff = 0; + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) +#define _DIFF_VAL(ATTR, FIELD) _DIFF(ATTR, a->FIELD != b->FIELD) +#define _DIFF_STRING(ATTR, FIELD) _DIFF(ATTR, (strcmp(a->FIELD, b->FIELD) != 0)) +#define _DIFF_ADDR(ATTR, FIELD) \ + ((flags & LOOSE_COMPARISON) ? \ + _DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) : \ + _DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD))) +#define _DIFF_L4PROTO_PORTS(ATTR, FIELD) \ + _DIFF(ATTR, exp_cmp_l4proto_ports(&(a->FIELD), &(b->FIELD))) +#define _DIFF_L4PROTO_ICMP(ATTR, FIELD) \ + _DIFF(ATTR, exp_cmp_l4proto_icmp(&(a->FIELD), &(b->FIELD))) + diff |= _DIFF_VAL(EXP_ATTR_FAMILY, exp_family); + diff |= _DIFF_VAL(EXP_ATTR_TIMEOUT, exp_timeout); + diff |= _DIFF_VAL(EXP_ATTR_ID, exp_id); + diff |= _DIFF_VAL(EXP_ATTR_ZONE, exp_zone); + diff |= _DIFF_VAL(EXP_ATTR_CLASS, exp_class); + diff |= _DIFF_VAL(EXP_ATTR_FLAGS, exp_flags); + diff |= _DIFF_VAL(EXP_ATTR_NAT_DIR, exp_nat_dir); + + diff |= _DIFF_STRING(EXP_ATTR_FN, exp_fn); + diff |= _DIFF_STRING(EXP_ATTR_HELPER_NAME, exp_helper_name); + + diff |= _DIFF_ADDR(EXP_ATTR_EXPECT_IP_SRC, exp_expect.src); + diff |= _DIFF_ADDR(EXP_ATTR_EXPECT_IP_DST, exp_expect.dst); + diff |= _DIFF_VAL(EXP_ATTR_EXPECT_L4PROTO_NUM, + exp_expect.proto.l4protonum); + diff |= _DIFF_L4PROTO_PORTS(EXP_ATTR_EXPECT_L4PROTO_PORTS, + exp_expect.proto.l4protodata); + diff |= _DIFF_L4PROTO_ICMP(EXP_ATTR_EXPECT_L4PROTO_ICMP, + exp_expect.proto.l4protodata); + + diff |= _DIFF_ADDR(EXP_ATTR_MASTER_IP_SRC, exp_master.src); + diff |= _DIFF_ADDR(EXP_ATTR_MASTER_IP_DST, exp_master.dst); + diff |= _DIFF_VAL(EXP_ATTR_MASTER_L4PROTO_NUM, + exp_master.proto.l4protonum); + diff |= _DIFF_L4PROTO_PORTS(EXP_ATTR_MASTER_L4PROTO_PORTS, + exp_master.proto.l4protodata); + diff |= _DIFF_L4PROTO_ICMP(EXP_ATTR_MASTER_L4PROTO_ICMP, + exp_master.proto.l4protodata); + + diff |= _DIFF_ADDR(EXP_ATTR_MASK_IP_SRC, exp_mask.src); + diff |= _DIFF_ADDR(EXP_ATTR_MASK_IP_DST, exp_mask.dst); + diff |= _DIFF_VAL(EXP_ATTR_MASK_L4PROTO_NUM, exp_mask.proto.l4protonum); + diff |= _DIFF_L4PROTO_PORTS(EXP_ATTR_MASK_L4PROTO_PORTS, + exp_mask.proto.l4protodata); + diff |= _DIFF_L4PROTO_ICMP(EXP_ATTR_MASK_L4PROTO_ICMP, + exp_mask.proto.l4protodata); + + diff |= _DIFF_ADDR(EXP_ATTR_NAT_IP_SRC, exp_nat.src); + diff |= _DIFF_ADDR(EXP_ATTR_NAT_IP_DST, exp_nat.dst); + diff |= _DIFF_VAL(EXP_ATTR_NAT_L4PROTO_NUM, exp_nat.proto.l4protonum); + diff |= _DIFF_L4PROTO_PORTS(EXP_ATTR_NAT_L4PROTO_PORTS, + exp_nat.proto.l4protodata); + diff |= _DIFF_L4PROTO_ICMP(EXP_ATTR_NAT_L4PROTO_ICMP, + exp_nat.proto.l4protodata); +#undef _DIFF +#undef _DIFF_VAL +#undef _DIFF_STRING +#undef _DIFF_ADDR +#undef _DIFF_L4PROTO_PORTS +#undef _DIFF_L4PROTO_ICMP return diff; } // CLI arguments? static const struct trans_tbl exp_attrs[] = { - __ADD(EXP_ATTR_FAMILY, family) - __ADD(EXP_ATTR_TIMEOUT, timeout) - __ADD(EXP_ATTR_ID, id) - __ADD(EXP_ATTR_HELPER_NAME, helpername) - __ADD(EXP_ATTR_ZONE, zone) - __ADD(EXP_ATTR_CLASS, class) - __ADD(EXP_ATTR_FLAGS, flags) - __ADD(EXP_ATTR_FN, function) - __ADD(EXP_ATTR_EXPECT_IP_SRC, expectipsrc) - __ADD(EXP_ATTR_EXPECT_IP_DST, expectipdst) - __ADD(EXP_ATTR_EXPECT_L4PROTO_NUM, expectprotonum) - __ADD(EXP_ATTR_EXPECT_L4PROTO_PORTS, expectports) - __ADD(EXP_ATTR_EXPECT_L4PROTO_ICMP, expecticmp) - __ADD(EXP_ATTR_MASTER_IP_SRC, masteripsrc) - __ADD(EXP_ATTR_MASTER_IP_DST, masteripdst) - __ADD(EXP_ATTR_MASTER_L4PROTO_NUM, masterprotonum) - __ADD(EXP_ATTR_MASTER_L4PROTO_PORTS, masterports) - __ADD(EXP_ATTR_MASTER_L4PROTO_ICMP, mastericmp) - __ADD(EXP_ATTR_MASK_IP_SRC, maskipsrc) - __ADD(EXP_ATTR_MASK_IP_DST, maskipdst) - __ADD(EXP_ATTR_MASK_L4PROTO_NUM, maskprotonum) - __ADD(EXP_ATTR_MASK_L4PROTO_PORTS, maskports) - __ADD(EXP_ATTR_MASK_L4PROTO_ICMP, maskicmp) - __ADD(EXP_ATTR_NAT_IP_SRC, natipsrc) - __ADD(EXP_ATTR_NAT_IP_DST, natipdst) - __ADD(EXP_ATTR_NAT_L4PROTO_NUM, natprotonum) - __ADD(EXP_ATTR_NAT_L4PROTO_PORTS, natports) - __ADD(EXP_ATTR_NAT_L4PROTO_ICMP, naticmp) - __ADD(EXP_ATTR_NAT_DIR, natdir) + __ADD(EXP_ATTR_FAMILY, family), + __ADD(EXP_ATTR_TIMEOUT, timeout), + __ADD(EXP_ATTR_ID, id), + __ADD(EXP_ATTR_HELPER_NAME, helpername), + __ADD(EXP_ATTR_ZONE, zone), + __ADD(EXP_ATTR_CLASS, class), + __ADD(EXP_ATTR_FLAGS, flags), + __ADD(EXP_ATTR_FN, function), + __ADD(EXP_ATTR_EXPECT_IP_SRC, expectipsrc), + __ADD(EXP_ATTR_EXPECT_IP_DST, expectipdst), + __ADD(EXP_ATTR_EXPECT_L4PROTO_NUM, expectprotonum), + __ADD(EXP_ATTR_EXPECT_L4PROTO_PORTS, expectports), + __ADD(EXP_ATTR_EXPECT_L4PROTO_ICMP, expecticmp), + __ADD(EXP_ATTR_MASTER_IP_SRC, masteripsrc), + __ADD(EXP_ATTR_MASTER_IP_DST, masteripdst), + __ADD(EXP_ATTR_MASTER_L4PROTO_NUM, masterprotonum), + __ADD(EXP_ATTR_MASTER_L4PROTO_PORTS, masterports), + __ADD(EXP_ATTR_MASTER_L4PROTO_ICMP, mastericmp), + __ADD(EXP_ATTR_MASK_IP_SRC, maskipsrc), + __ADD(EXP_ATTR_MASK_IP_DST, maskipdst), + __ADD(EXP_ATTR_MASK_L4PROTO_NUM, maskprotonum), + __ADD(EXP_ATTR_MASK_L4PROTO_PORTS, maskports), + __ADD(EXP_ATTR_MASK_L4PROTO_ICMP, maskicmp), + __ADD(EXP_ATTR_NAT_IP_SRC, natipsrc), + __ADD(EXP_ATTR_NAT_IP_DST, natipdst), + __ADD(EXP_ATTR_NAT_L4PROTO_NUM, natprotonum), + __ADD(EXP_ATTR_NAT_L4PROTO_PORTS, natports), + __ADD(EXP_ATTR_NAT_L4PROTO_ICMP, naticmp), + __ADD(EXP_ATTR_NAT_DIR, natdir), }; static char *exp_attrs2str(int attrs, char *buf, size_t len) @@ -467,9 +482,9 @@ uint32_t nfnl_exp_get_flags(const struct nfnl_exp *exp) } static const struct trans_tbl flag_table[] = { - __ADD(IPS_EXPECTED, expected) - __ADD(IPS_SEEN_REPLY, seen_reply) - __ADD(IPS_ASSURED, assured) + __ADD(IPS_EXPECTED, expected), + __ADD(IPS_SEEN_REPLY, seen_reply), + __ADD(IPS_ASSURED, assured), }; char * nfnl_exp_flags2str(int flags, char *buf, size_t len) diff --git a/lib/netfilter/log.c b/lib/netfilter/log.c index 1bab9b6..7b0abaa 100644 --- a/lib/netfilter/log.c +++ b/lib/netfilter/log.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/netfilter/log.c Netfilter Log - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation @@ -18,14 +12,19 @@ * @{ */ +#include "nl-default.h" + #include + #include -#include #include #include #include +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" + /** * @name Log Commands * @{ @@ -150,6 +149,11 @@ static int nfnl_log_build_request(const struct nfnl_log *log, htonl(nfnl_log_get_queue_threshold(log))) < 0) goto nla_put_failure; + if (nfnl_log_get_flags(log) && + nla_put_u16(msg, NFULA_CFG_FLAGS, + htons(nfnl_log_get_flags(log))) < 0) + goto nla_put_failure; + *result = msg; return 0; @@ -238,12 +242,12 @@ static struct nl_cache_ops nfnl_log_ops = { }, }; -static void __init log_init(void) +static void _nl_init log_init(void) { nl_cache_mngt_register(&nfnl_log_ops); } -static void __exit log_exit(void) +static void _nl_exit log_exit(void) { nl_cache_mngt_unregister(&nfnl_log_ops); } diff --git a/lib/netfilter/log_msg.c b/lib/netfilter/log_msg.c index 6e09da2..2ddc06a 100644 --- a/lib/netfilter/log_msg.c +++ b/lib/netfilter/log_msg.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/netfilter/log_msg.c Netfilter Log Message - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation @@ -19,26 +13,18 @@ * @{ */ +#include "nl-default.h" + #include + #include -#include #include #include #include -#include -#if __BYTE_ORDER == __BIG_ENDIAN -static uint64_t ntohll(uint64_t x) -{ - return x; -} -#elif __BYTE_ORDER == __LITTLE_ENDIAN -static uint64_t ntohll(uint64_t x) -{ - return bswap_64(x); -} -#endif +#include "nl-netfilter.h" +#include "nl-priv-dynamic-core/cache-api.h" static struct nla_policy log_msg_policy[NFULA_MAX+1] = { [NFULA_PACKET_HDR] = { @@ -61,8 +47,41 @@ static struct nla_policy log_msg_policy[NFULA_MAX+1] = { [NFULA_GID] = { .type = NLA_U32 }, [NFULA_SEQ] = { .type = NLA_U32 }, [NFULA_SEQ_GLOBAL] = { .type = NLA_U32 }, + [NFULA_HWTYPE] = { .type = NLA_U16 }, + [NFULA_HWLEN] = { .type = NLA_U16 }, + [NFULA_VLAN] = { .type = NLA_NESTED }, + [NFULA_CT] = { .type = NLA_NESTED }, + [NFULA_CT_INFO] = { .type = NLA_U32 }, }; +static struct nla_policy log_msg_vlan_policy[NFULA_VLAN_MAX+1] = { + [NFULA_VLAN_PROTO] = { .type = NLA_U16 }, + [NFULA_VLAN_TCI] = { .type = NLA_U16 }, +}; + +static int +nfnlmsg_log_msg_parse_vlan(struct nlattr *attr_full, struct nfnl_log_msg *msg) +{ + struct nlattr *tb[NFULA_VLAN_MAX+1]; + struct nlattr *attr; + int err; + + err = nla_parse_nested(tb, NFULA_VLAN_MAX, attr_full, + log_msg_vlan_policy); + if (err < 0) + return err; + + attr = tb[NFULA_VLAN_PROTO]; + if (attr) + nfnl_log_msg_set_vlan_proto(msg, nla_get_u16(attr)); + + attr = tb[NFULA_VLAN_TCI]; + if (attr) + nfnl_log_msg_set_vlan_tag(msg, ntohs(nla_get_u16(attr))); + + return 0; +} + int nfnlmsg_log_msg_parse(struct nlmsghdr *nlh, struct nfnl_log_msg **result) { struct nfnl_log_msg *msg; @@ -159,6 +178,39 @@ int nfnlmsg_log_msg_parse(struct nlmsghdr *nlh, struct nfnl_log_msg **result) if (attr) nfnl_log_msg_set_seq_global(msg, ntohl(nla_get_u32(attr))); + attr = tb[NFULA_HWTYPE]; + if (attr) + nfnl_log_msg_set_hwtype(msg, ntohs(nla_get_u16(attr))); + + attr = tb[NFULA_HWLEN]; + if (attr) + nfnl_log_msg_set_hwlen(msg, ntohs(nla_get_u16(attr))); + + attr = tb[NFULA_HWHEADER]; + if (attr) + nfnl_log_msg_set_hwheader(msg, nla_data(attr), nla_len(attr)); + + attr = tb[NFULA_VLAN]; + if (attr) { + err = nfnlmsg_log_msg_parse_vlan(attr, msg); + if (err < 0) + goto errout; + } + + attr = tb[NFULA_CT]; + if (attr) { + struct nfnl_ct *ct = NULL; + err = nfnlmsg_ct_parse_nested(attr, &ct); + if (err < 0) + goto errout; + nfnl_log_msg_set_ct(msg, ct); + nfnl_ct_put(ct); + } + + attr = tb[NFULA_CT_INFO]; + if (attr) + nfnl_log_msg_set_ct_info(msg, ntohl(nla_get_u32(attr))); + *result = msg; return 0; @@ -174,10 +226,9 @@ static int log_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, int err; if ((err = nfnlmsg_log_msg_parse(nlh, &msg)) < 0) - goto errout; + return err; err = pp->pp_cb((struct nl_object *) msg, pp); -errout: nfnl_log_msg_put(msg); return err; } @@ -197,12 +248,12 @@ static struct nl_cache_ops nfnl_log_msg_ops = { .co_obj_ops = &log_msg_obj_ops, }; -static void __init log_msg_init(void) +static void _nl_init log_msg_init(void) { nl_cache_mngt_register(&nfnl_log_msg_ops); } -static void __exit log_msg_exit(void) +static void _nl_exit log_msg_exit(void) { nl_cache_mngt_unregister(&nfnl_log_msg_ops); } diff --git a/lib/netfilter/log_msg_obj.c b/lib/netfilter/log_msg_obj.c index 57db9d4..6b6ff07 100644 --- a/lib/netfilter/log_msg_obj.c +++ b/lib/netfilter/log_msg_obj.c @@ -1,20 +1,20 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/netfilter/log_msg_obj.c Netfilter Log Object - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation */ -#include +#include "nl-default.h" + #include #include #include +#include +#include + +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-netfilter.h" /** @cond SKIP */ #define LOG_MSG_ATTR_FAMILY (1UL << 0) @@ -33,6 +33,13 @@ #define LOG_MSG_ATTR_GID (1UL << 13) #define LOG_MSG_ATTR_SEQ (1UL << 14) #define LOG_MSG_ATTR_SEQ_GLOBAL (1UL << 15) +#define LOG_MSG_ATTR_HWTYPE (1UL << 16) +#define LOG_MSG_ATTR_HWLEN (1UL << 17) +#define LOG_MSG_ATTR_HWHEADER (1UL << 18) +#define LOG_MSG_ATTR_VLAN_PROTO (1UL << 19) +#define LOG_MSG_ATTR_VLAN_TAG (1UL << 20) +#define LOG_MSG_ATTR_CT_INFO (1UL << 21) +#define LOG_MSG_ATTR_CT (1UL << 22) /** @endcond */ static void log_msg_free_data(struct nl_object *c) @@ -44,6 +51,9 @@ static void log_msg_free_data(struct nl_object *c) free(msg->log_msg_payload); free(msg->log_msg_prefix); + free(msg->log_msg_hwheader); + if (msg->log_msg_ct) + nfnl_ct_put(msg->log_msg_ct); } static int log_msg_clone(struct nl_object *_dst, struct nl_object *_src) @@ -52,22 +62,41 @@ static int log_msg_clone(struct nl_object *_dst, struct nl_object *_src) struct nfnl_log_msg *src = (struct nfnl_log_msg *) _src; int err; + dst->log_msg_payload = NULL; + dst->log_msg_payload_len = 0; + dst->log_msg_prefix = NULL; + dst->log_msg_hwheader = NULL; + dst->log_msg_hwheader_len = 0; + dst->log_msg_ct = NULL; + if (src->log_msg_payload) { err = nfnl_log_msg_set_payload(dst, src->log_msg_payload, - src->log_msg_payload_len); + src->log_msg_payload_len); if (err < 0) - goto errout; + return err; } if (src->log_msg_prefix) { err = nfnl_log_msg_set_prefix(dst, src->log_msg_prefix); if (err < 0) - goto errout; + return err; + } + + if (src->log_msg_hwheader) { + err = nfnl_log_msg_set_hwheader(dst, src->log_msg_hwheader, + src->log_msg_hwheader_len); + if (err < 0) + return err; + } + + if (src->log_msg_ct) { + dst->log_msg_ct = (struct nfnl_ct *) nl_object_clone((struct nl_object *) src->log_msg_ct); + if (!dst->log_msg_ct) { + return -NLE_NOMEM; + } } return 0; -errout: - return err; } static void log_msg_dump(struct nl_object *a, struct nl_dump_params *p) @@ -100,7 +129,7 @@ static void log_msg_dump(struct nl_object *a, struct nl_dump_params *p) msg->log_msg_physindev, buf, sizeof(buf))); else - nl_dump(p, "IN=%d ", msg->log_msg_physindev); + nl_dump(p, "PHYSIN=%d ", msg->log_msg_physindev); } if (msg->ce_mask & LOG_MSG_ATTR_OUTDEV) { @@ -166,8 +195,35 @@ static void log_msg_dump(struct nl_object *a, struct nl_dump_params *p) if (msg->ce_mask & LOG_MSG_ATTR_SEQ_GLOBAL) nl_dump(p, "SEQGLOBAL=%d ", msg->log_msg_seq_global); + if (msg->ce_mask & LOG_MSG_ATTR_HWTYPE) + nl_dump(p, "HWTYPE=%u ", msg->log_msg_hwtype); + + if (msg->ce_mask & LOG_MSG_ATTR_HWLEN) + nl_dump(p, "HWLEN=%u ", msg->log_msg_hwlen); + + if (msg->ce_mask & LOG_MSG_ATTR_HWHEADER) { + int i; + + nl_dump(p, "HWHEADER"); + for (i = 0; i < msg->log_msg_hwheader_len; i++) + nl_dump(p, "%c%02x", i?':':'=', ((uint8_t*) msg->log_msg_hwheader) [i]); + nl_dump(p, " "); + } + + if (msg->ce_mask & LOG_MSG_ATTR_VLAN_TAG) + nl_dump(p, "VLAN=%d CFI=%d PRIO=%d", + (int) nfnl_log_msg_get_vlan_id(msg), + (int) nfnl_log_msg_get_vlan_cfi(msg), + (int) nfnl_log_msg_get_vlan_prio(msg)); + + if (msg->ce_mask & LOG_MSG_ATTR_CT_INFO) + nl_dump(p, "CTINFO=%u ", msg->log_msg_ct_info); + nl_dump(p, "\n"); + if (msg->ce_mask & LOG_MSG_ATTR_CT) + ct_obj_ops.oo_dump[NL_DUMP_LINE]((struct nl_object *)msg->log_msg_ct, p); + if (link_cache) nl_cache_put(link_cache); } @@ -341,14 +397,22 @@ const uint8_t *nfnl_log_msg_get_hwaddr(const struct nfnl_log_msg *msg, int *len) int nfnl_log_msg_set_payload(struct nfnl_log_msg *msg, uint8_t *payload, int len) { - free(msg->log_msg_payload); - msg->log_msg_payload = malloc(len); - if (!msg->log_msg_payload) + uint8_t *p = NULL; + + if (len < 0) + return -NLE_INVAL; + + p = _nl_memdup(payload, len); + if (!p && len > 0) return -NLE_NOMEM; - memcpy(msg->log_msg_payload, payload, len); + free(msg->log_msg_payload); + msg->log_msg_payload = p; msg->log_msg_payload_len = len; - msg->ce_mask |= LOG_MSG_ATTR_PAYLOAD; + if (len > 0) + msg->ce_mask |= LOG_MSG_ATTR_PAYLOAD; + else + msg->ce_mask &= ~LOG_MSG_ATTR_PAYLOAD; return 0; } @@ -365,12 +429,21 @@ const void *nfnl_log_msg_get_payload(const struct nfnl_log_msg *msg, int *len) int nfnl_log_msg_set_prefix(struct nfnl_log_msg *msg, void *prefix) { + char *p = NULL; + + if (prefix) { + p = strdup(prefix); + if (!p) + return -NLE_NOMEM; + } + free(msg->log_msg_prefix); - msg->log_msg_prefix = strdup(prefix); - if (!msg->log_msg_prefix) - return -NLE_NOMEM; + msg->log_msg_prefix = p; - msg->ce_mask |= LOG_MSG_ATTR_PREFIX; + if (p) + msg->ce_mask |= LOG_MSG_ATTR_PREFIX; + else + msg->ce_mask &= ~LOG_MSG_ATTR_PREFIX; return 0; } @@ -444,6 +517,154 @@ uint32_t nfnl_log_msg_get_seq_global(const struct nfnl_log_msg *msg) return msg->log_msg_seq_global; } +void nfnl_log_msg_set_hwtype(struct nfnl_log_msg *msg, uint16_t hwtype) +{ + msg->log_msg_hwtype = hwtype; + msg->ce_mask |= LOG_MSG_ATTR_HWTYPE; +} + +int nfnl_log_msg_test_hwtype(const struct nfnl_log_msg *msg) +{ + return !!(msg->ce_mask & LOG_MSG_ATTR_HWTYPE); +} + +uint16_t nfnl_log_msg_get_hwtype(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_hwtype; +} + +void nfnl_log_msg_set_hwlen(struct nfnl_log_msg *msg, uint16_t hwlen) +{ + msg->log_msg_hwlen = hwlen; + msg->ce_mask |= LOG_MSG_ATTR_HWLEN; +} + +int nfnl_log_msg_test_hwlen(const struct nfnl_log_msg *msg) +{ + return !!(msg->ce_mask & LOG_MSG_ATTR_HWLEN); +} + +uint16_t nfnl_log_msg_get_hwlen(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_hwlen; +} + +int nfnl_log_msg_set_hwheader(struct nfnl_log_msg *msg, void *data, int len) +{ + void *p = NULL; + + if (len < 0) + return -NLE_INVAL; + + p = _nl_memdup(data, len); + if (!p && len > 0) + return -NLE_NOMEM; + + free(msg->log_msg_hwheader); + msg->log_msg_hwheader = p; + msg->log_msg_hwheader_len = len; + if (len > 0) + msg->ce_mask |= LOG_MSG_ATTR_HWHEADER; + else + msg->ce_mask &= ~LOG_MSG_ATTR_HWHEADER; + return 0; +} + +int nfnl_log_msg_test_hwheader(const struct nfnl_log_msg *msg) +{ + return !!(msg->ce_mask & LOG_MSG_ATTR_HWHEADER); +} + +const void *nfnl_log_msg_get_hwheader(const struct nfnl_log_msg *msg, int *len) +{ + if (!(msg->ce_mask & LOG_MSG_ATTR_HWHEADER)) { + *len = 0; + return NULL; + } + + *len = msg->log_msg_hwheader_len; + return msg->log_msg_hwheader; +} + +void nfnl_log_msg_set_vlan_proto(struct nfnl_log_msg *msg, uint16_t vlan_proto) +{ + msg->log_msg_vlan_proto = vlan_proto; + msg->ce_mask |= LOG_MSG_ATTR_VLAN_PROTO; +} + +int nfnl_log_msg_test_vlan_proto(const struct nfnl_log_msg *msg) +{ + return !!(msg->ce_mask & LOG_MSG_ATTR_VLAN_PROTO); +} + +uint16_t nfnl_log_msg_get_vlan_proto(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_vlan_proto; +} + +void nfnl_log_msg_set_vlan_tag(struct nfnl_log_msg *msg, uint16_t vlan_tag) +{ + msg->log_msg_vlan_tag = vlan_tag; + msg->ce_mask |= LOG_MSG_ATTR_VLAN_TAG; +} + +int nfnl_log_msg_test_vlan_tag(const struct nfnl_log_msg *msg) +{ + return !!(msg->ce_mask & LOG_MSG_ATTR_VLAN_TAG); +} + +uint16_t nfnl_log_msg_get_vlan_tag(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_vlan_tag; +} + +uint16_t nfnl_log_msg_get_vlan_id(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_vlan_tag & 0x0fff; +} + +uint16_t nfnl_log_msg_get_vlan_cfi(const struct nfnl_log_msg *msg) +{ + return !!(msg->log_msg_vlan_tag & 0x1000); +} + +uint16_t nfnl_log_msg_get_vlan_prio(const struct nfnl_log_msg *msg) +{ + return (msg->log_msg_vlan_tag & 0xe000 ) >> 13; +} + +void nfnl_log_msg_set_ct_info(struct nfnl_log_msg *msg, uint32_t ct_info) +{ + msg->log_msg_ct_info = ct_info; + msg->ce_mask |= LOG_MSG_ATTR_CT_INFO; +} + +int nfnl_log_msg_test_ct_info(const struct nfnl_log_msg *msg) +{ + return !!(msg->ce_mask & LOG_MSG_ATTR_CT_INFO); +} + +uint32_t nfnl_log_msg_get_ct_info(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_ct_info; +} + +void nfnl_log_msg_set_ct(struct nfnl_log_msg *msg, struct nfnl_ct *ct) +{ + msg->log_msg_ct = (struct nfnl_ct *) nl_object_clone((struct nl_object *)ct); + msg->ce_mask |= LOG_MSG_ATTR_CT; +} + +int nfnl_log_msg_test_ct(const struct nfnl_log_msg *msg) +{ + return !!(msg->ce_mask & LOG_MSG_ATTR_CT); +} + +struct nfnl_ct *nfnl_log_msg_get_ct(const struct nfnl_log_msg *msg) +{ + return msg->log_msg_ct; +} + /** @} */ struct nl_object_ops log_msg_obj_ops = { diff --git a/lib/netfilter/log_obj.c b/lib/netfilter/log_obj.c index 2b11414..acfe58b 100644 --- a/lib/netfilter/log_obj.c +++ b/lib/netfilter/log_obj.c @@ -1,22 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/netfilter/log_obj.c Netfilter Log Object - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation * Copyright (c) 2008 Patrick McHardy */ -#include +#include "nl-default.h" + #include #include +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-priv-dynamic-core/cache-api.h" +#include "nl-priv-dynamic-core/nl-core.h" + /** @cond SKIP */ +struct nfnl_log { + NLHDR_COMMON + + uint16_t log_group; + uint8_t log_copy_mode; + uint32_t log_copy_range; + uint32_t log_flush_timeout; + uint32_t log_alloc_size; + uint32_t log_queue_threshold; + uint32_t log_flags; + uint32_t log_flag_mask; +}; + #define LOG_ATTR_GROUP (1UL << 0) #define LOG_ATTR_COPY_MODE (1UL << 1) #define LOG_ATTR_COPY_RANGE (1UL << 3) @@ -57,9 +69,9 @@ static void nfnl_log_dump(struct nl_object *a, struct nl_dump_params *p) } static const struct trans_tbl copy_modes[] = { - __ADD(NFNL_LOG_COPY_NONE, none) - __ADD(NFNL_LOG_COPY_META, meta) - __ADD(NFNL_LOG_COPY_PACKET, packet) + __ADD(NFNL_LOG_COPY_NONE, none), + __ADD(NFNL_LOG_COPY_META, meta), + __ADD(NFNL_LOG_COPY_PACKET, packet), }; char *nfnl_log_copy_mode2str(enum nfnl_log_copy_mode copy_mode, char *buf, @@ -69,7 +81,7 @@ char *nfnl_log_copy_mode2str(enum nfnl_log_copy_mode copy_mode, char *buf, ARRAY_SIZE(copy_modes)); } -enum nfnl_log_copy_mode nfnl_log_str2copy_mode(const char *name) +int nfnl_log_str2copy_mode(const char *name) { return __str2type(name, copy_modes, ARRAY_SIZE(copy_modes)); } @@ -214,9 +226,15 @@ void nfnl_log_unset_flags(struct nfnl_log *log, unsigned int flags) log->log_flag_mask |= flags; } +unsigned int nfnl_log_get_flags(const struct nfnl_log *log) +{ + return log->log_flags; +} + static const struct trans_tbl log_flags[] = { - __ADD(NFNL_LOG_FLAG_SEQ, seq) - __ADD(NFNL_LOG_FLAG_SEQ_GLOBAL, seq_global) + __ADD(NFNL_LOG_FLAG_SEQ, seq), + __ADD(NFNL_LOG_FLAG_SEQ_GLOBAL, seq_global), + __ADD(NFNL_LOG_FLAG_CONNTRACK, conntrack), }; char *nfnl_log_flags2str(unsigned int flags, char *buf, size_t len) @@ -229,25 +247,23 @@ unsigned int nfnl_log_str2flags(const char *name) return __str2flags(name, log_flags, ARRAY_SIZE(log_flags)); } -static int nfnl_log_compare(struct nl_object *_a, struct nl_object *_b, - uint32_t attrs, int flags) +static uint64_t nfnl_log_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) { struct nfnl_log *a = (struct nfnl_log *) _a; struct nfnl_log *b = (struct nfnl_log *) _b; - int diff = 0; + uint64_t diff = 0; #define NFNL_LOG_DIFF(ATTR, EXPR) \ - ATTR_DIFF(attrs, LOG_ATTR_##ATTR, a, b, EXPR) + ATTR_DIFF(attrs, ATTR, a, b, EXPR) #define NFNL_LOG_DIFF_VAL(ATTR, FIELD) \ NFNL_LOG_DIFF(ATTR, a->FIELD != b->FIELD) - - diff |= NFNL_LOG_DIFF_VAL(GROUP, log_group); - diff |= NFNL_LOG_DIFF_VAL(COPY_MODE, log_copy_mode); - diff |= NFNL_LOG_DIFF_VAL(COPY_RANGE, log_copy_range); - diff |= NFNL_LOG_DIFF_VAL(FLUSH_TIMEOUT, log_flush_timeout); - diff |= NFNL_LOG_DIFF_VAL(ALLOC_SIZE, log_alloc_size); - diff |= NFNL_LOG_DIFF_VAL(QUEUE_THRESHOLD, log_queue_threshold); - + diff |= NFNL_LOG_DIFF_VAL(LOG_ATTR_GROUP, log_group); + diff |= NFNL_LOG_DIFF_VAL(LOG_ATTR_COPY_MODE, log_copy_mode); + diff |= NFNL_LOG_DIFF_VAL(LOG_ATTR_COPY_RANGE, log_copy_range); + diff |= NFNL_LOG_DIFF_VAL(LOG_ATTR_FLUSH_TIMEOUT, log_flush_timeout); + diff |= NFNL_LOG_DIFF_VAL(LOG_ATTR_ALLOC_SIZE, log_alloc_size); + diff |= NFNL_LOG_DIFF_VAL(LOG_ATTR_QUEUE_THRESHOLD, log_queue_threshold); #undef NFNL_LOG_DIFF #undef NFNL_LOG_DIFF_VAL @@ -255,12 +271,12 @@ static int nfnl_log_compare(struct nl_object *_a, struct nl_object *_b, } static const struct trans_tbl nfnl_log_attrs[] = { - __ADD(LOG_ATTR_GROUP, group) - __ADD(LOG_ATTR_COPY_MODE, copy_mode) - __ADD(LOG_ATTR_COPY_RANGE, copy_range) - __ADD(LOG_ATTR_FLUSH_TIMEOUT, flush_timeout) - __ADD(LOG_ATTR_ALLOC_SIZE, alloc_size) - __ADD(LOG_ATTR_QUEUE_THRESHOLD, queue_threshold) + __ADD(LOG_ATTR_GROUP, group), + __ADD(LOG_ATTR_COPY_MODE, copy_mode), + __ADD(LOG_ATTR_COPY_RANGE, copy_range), + __ADD(LOG_ATTR_FLUSH_TIMEOUT, flush_timeout), + __ADD(LOG_ATTR_ALLOC_SIZE, alloc_size), + __ADD(LOG_ATTR_QUEUE_THRESHOLD, queue_threshold), }; static char *nfnl_log_attrs2str(int attrs, char *buf, size_t len) diff --git a/lib/netfilter/netfilter.c b/lib/netfilter/netfilter.c index 0062994..b8a5d2a 100644 --- a/lib/netfilter/netfilter.c +++ b/lib/netfilter/netfilter.c @@ -1,25 +1,23 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/netfilter/netfilter.c Netfilter Generic Functions - * - * 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 Patrick McHardy */ -#include -#include +#include "nl-default.h" + #include +#include + +#include "nl-priv-dynamic-core/nl-core.h" + static const struct trans_tbl nfnl_verdicts[] = { - __ADD(NF_DROP, NF_DROP) - __ADD(NF_ACCEPT, NF_ACCEPT) - __ADD(NF_STOLEN, NF_STOLEN) - __ADD(NF_QUEUE, NF_QUEUE) - __ADD(NF_REPEAT, NF_REPEAT) - __ADD(NF_STOP, NF_STOP) + __ADD(NF_DROP, NF_DROP), + __ADD(NF_ACCEPT, NF_ACCEPT), + __ADD(NF_STOLEN, NF_STOLEN), + __ADD(NF_QUEUE, NF_QUEUE), + __ADD(NF_REPEAT, NF_REPEAT), + __ADD(NF_STOP, NF_STOP), }; char *nfnl_verdict2str(unsigned int verdict, char *buf, size_t len) @@ -34,11 +32,11 @@ unsigned int nfnl_str2verdict(const char *name) } static const struct trans_tbl nfnl_inet_hooks[] = { - __ADD(NF_INET_PRE_ROUTING, NF_INET_PREROUTING) - __ADD(NF_INET_LOCAL_IN, NF_INET_LOCAL_IN) - __ADD(NF_INET_FORWARD, NF_INET_FORWARD) - __ADD(NF_INET_LOCAL_OUT, NF_INET_LOCAL_OUT) - __ADD(NF_INET_POST_ROUTING, NF_INET_POST_ROUTING) + __ADD(NF_INET_PRE_ROUTING, NF_INET_PREROUTING), + __ADD(NF_INET_LOCAL_IN, NF_INET_LOCAL_IN), + __ADD(NF_INET_FORWARD, NF_INET_FORWARD), + __ADD(NF_INET_LOCAL_OUT, NF_INET_LOCAL_OUT), + __ADD(NF_INET_POST_ROUTING, NF_INET_POST_ROUTING), }; char *nfnl_inet_hook2str(unsigned int hook, char *buf, size_t len) diff --git a/lib/netfilter/nfnl.c b/lib/netfilter/nfnl.c index f028a85..c70827b 100644 --- a/lib/netfilter/nfnl.c +++ b/lib/netfilter/nfnl.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/netfilter/nfnl.c Netfilter Netlink - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation @@ -61,9 +55,16 @@ * @{ */ -#include +#include "nl-default.h" + +#include + #include #include +#include +#include + +#include "nl-aux-core/nl-core.h" /** * @name Socket Creating @@ -102,7 +103,8 @@ int nfnl_connect(struct nl_sock *sk) * @arg family nfnetlink address family * @arg res_id nfnetlink resource id * - * @return Newly allocated netlink message or NULL. + * @return 0 on success or a negative error code. Due to a bug, this function + * returns the number of bytes sent. Treat any non-negative number as success. */ int nfnl_send_simple(struct nl_sock *sk, uint8_t subsys_id, uint8_t type, int flags, uint8_t family, uint16_t res_id) diff --git a/lib/netfilter/nl-netfilter.h b/lib/netfilter/nl-netfilter.h new file mode 100644 index 0000000..c8a4899 --- /dev/null +++ b/lib/netfilter/nl-netfilter.h @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2003-2013 Thomas Graf + * Copyright (c) 2013 Sassano Systems LLC + */ + +#ifndef __LIB_NETFILTER_NL_NETFILTER_H__ +#define __LIB_NETFILTER_NL_NETFILTER_H__ + +#include + +#include "nl-priv-dynamic-core/object-api.h" + +union nfnl_ct_proto { + struct { + uint16_t src; + uint16_t dst; + } port; + struct { + uint16_t id; + uint8_t type; + uint8_t code; + } icmp; +}; + +struct nfnl_ct_dir { + struct nl_addr *src; + struct nl_addr *dst; + union nfnl_ct_proto proto; + uint64_t packets; + uint64_t bytes; +}; + +union nfnl_ct_protoinfo { + struct { + uint8_t state; + } tcp; +}; + +struct nfnl_ct { + NLHDR_COMMON + + uint8_t ct_family; + uint8_t ct_proto; + union nfnl_ct_protoinfo ct_protoinfo; + + uint32_t ct_status; + uint32_t ct_status_mask; + uint32_t ct_timeout; + uint32_t ct_mark; + uint32_t ct_use; + uint32_t ct_id; + uint16_t ct_zone; + + struct nfnl_ct_dir ct_orig; + struct nfnl_ct_dir ct_repl; + + struct nfnl_ct_timestamp ct_tstamp; +}; + +union nfnl_exp_protodata { + struct { + uint16_t src; + uint16_t dst; + } port; + struct { + uint16_t id; + uint8_t type; + uint8_t code; + } icmp; +}; + +// Allow for different master/expect l4 protocols +struct nfnl_exp_proto { + uint8_t l4protonum; + union nfnl_exp_protodata l4protodata; +}; + +struct nfnl_exp_dir { + struct nl_addr *src; + struct nl_addr *dst; + struct nfnl_exp_proto proto; +}; + +struct nfnl_exp { + NLHDR_COMMON + + uint8_t exp_family; + uint32_t exp_timeout; + uint32_t exp_id; + uint16_t exp_zone; + uint32_t exp_class; + uint32_t exp_flags; + char *exp_helper_name; + char *exp_fn; + uint8_t exp_nat_dir; + + struct nfnl_exp_dir exp_expect; + struct nfnl_exp_dir exp_master; + struct nfnl_exp_dir exp_mask; + struct nfnl_exp_dir exp_nat; +}; + +struct nfnl_log_msg { + NLHDR_COMMON + + uint8_t log_msg_family; + uint8_t log_msg_hook; + uint16_t log_msg_hwproto; + uint32_t log_msg_mark; + struct timeval log_msg_timestamp; + uint32_t log_msg_indev; + uint32_t log_msg_outdev; + uint32_t log_msg_physindev; + uint32_t log_msg_physoutdev; + uint8_t log_msg_hwaddr[8]; + int log_msg_hwaddr_len; + void *log_msg_payload; + int log_msg_payload_len; + char *log_msg_prefix; + uint32_t log_msg_uid; + uint32_t log_msg_gid; + uint32_t log_msg_seq; + uint32_t log_msg_seq_global; + uint16_t log_msg_hwtype; + uint16_t log_msg_hwlen; + void *log_msg_hwheader; + int log_msg_hwheader_len; + uint16_t log_msg_vlan_tag; + uint16_t log_msg_vlan_proto; + uint32_t log_msg_ct_info; + struct nfnl_ct *log_msg_ct; +}; + +struct nfnl_queue_msg { + NLHDR_COMMON + + uint16_t queue_msg_group; + uint8_t queue_msg_family; + uint8_t queue_msg_hook; + uint16_t queue_msg_hwproto; + uint32_t queue_msg_packetid; + uint32_t queue_msg_mark; + struct timeval queue_msg_timestamp; + uint32_t queue_msg_indev; + uint32_t queue_msg_outdev; + uint32_t queue_msg_physindev; + uint32_t queue_msg_physoutdev; + uint8_t queue_msg_hwaddr[8]; + int queue_msg_hwaddr_len; + void *queue_msg_payload; + int queue_msg_payload_len; + uint32_t queue_msg_verdict; +}; + +#endif /* __LIB_NETFILTER_NL_NETFILTER_H__*/ diff --git a/lib/netfilter/queue.c b/lib/netfilter/queue.c index 5655647..b780b0f 100644 --- a/lib/netfilter/queue.c +++ b/lib/netfilter/queue.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/netfilter/queue.c Netfilter Queue - * - * 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) 2007, 2008 Patrick McHardy */ @@ -16,14 +10,19 @@ * @{ */ +#include "nl-default.h" + #include + #include -#include #include #include #include +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" + struct nl_sock *nfnl_queue_socket_alloc(void) { struct nl_sock *nlsk; @@ -238,12 +237,12 @@ static struct nl_cache_ops nfnl_queue_ops = { }, }; -static void __init nfnl_queue_init(void) +static void _nl_init nfnl_queue_init(void) { nl_cache_mngt_register(&nfnl_queue_ops); } -static void __exit nfnl_queue_exit(void) +static void _nl_exit nfnl_queue_exit(void) { nl_cache_mngt_unregister(&nfnl_queue_ops); } diff --git a/lib/netfilter/queue_msg.c b/lib/netfilter/queue_msg.c index 95d8ad3..413d180 100644 --- a/lib/netfilter/queue_msg.c +++ b/lib/netfilter/queue_msg.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/netfilter/queue_msg.c Netfilter Queue Messages - * - * 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) 2007, 2008 Patrick McHardy * Copyright (c) 2010 Karl Hiramoto */ @@ -17,28 +11,21 @@ * @{ */ +#include "nl-default.h" + #include + #include -#include #include #include #include -#include -static struct nl_cache_ops nfnl_queue_msg_ops; +#include "nl-netfilter.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" -#if __BYTE_ORDER == __BIG_ENDIAN -static uint64_t ntohll(uint64_t x) -{ - return x; -} -#elif __BYTE_ORDER == __LITTLE_ENDIAN -static uint64_t ntohll(uint64_t x) -{ - return bswap_64(x); -} -#endif +static struct nl_cache_ops nfnl_queue_msg_ops; static struct nla_policy queue_policy[NFQA_MAX+1] = { [NFQA_PACKET_HDR] = { @@ -153,22 +140,23 @@ static int queue_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, int err; if ((err = nfnlmsg_queue_msg_parse(nlh, &msg)) < 0) - goto errout; + return err; err = pp->pp_cb((struct nl_object *) msg, pp); -errout: nfnl_queue_msg_put(msg); return err; } /** @} */ -struct nl_msg *nfnl_queue_msg_build_verdict(const struct nfnl_queue_msg *msg) +static struct nl_msg * +__nfnl_queue_msg_build_verdict(const struct nfnl_queue_msg *msg, + uint8_t type) { struct nl_msg *nlmsg; struct nfqnl_msg_verdict_hdr verdict; - nlmsg = nfnlmsg_alloc_simple(NFNL_SUBSYS_QUEUE, NFQNL_MSG_VERDICT, 0, + nlmsg = nfnlmsg_alloc_simple(NFNL_SUBSYS_QUEUE, type, 0, nfnl_queue_msg_get_family(msg), nfnl_queue_msg_get_group(msg)); if (nlmsg == NULL) @@ -191,6 +179,18 @@ nla_put_failure: return NULL; } +struct nl_msg * +nfnl_queue_msg_build_verdict(const struct nfnl_queue_msg *msg) +{ + return __nfnl_queue_msg_build_verdict(msg, NFQNL_MSG_VERDICT); +} + +struct nl_msg * +nfnl_queue_msg_build_verdict_batch(const struct nfnl_queue_msg *msg) +{ + return __nfnl_queue_msg_build_verdict(msg, NFQNL_MSG_VERDICT_BATCH); +} + /** * Send a message verdict/mark * @arg nlh netlink messsage header @@ -215,6 +215,29 @@ int nfnl_queue_msg_send_verdict(struct nl_sock *nlh, } /** +* Send a message batched verdict/mark +* @arg nlh netlink messsage header +* @arg msg queue msg +* @return 0 on OK or error code +*/ +int nfnl_queue_msg_send_verdict_batch(struct nl_sock *nlh, + const struct nfnl_queue_msg *msg) +{ + struct nl_msg *nlmsg; + int err; + + nlmsg = nfnl_queue_msg_build_verdict_batch(msg); + if (nlmsg == NULL) + return -NLE_NOMEM; + + err = nl_send_auto_complete(nlh, nlmsg); + nlmsg_free(nlmsg); + if (err < 0) + return err; + return wait_for_ack(nlh); +} + +/** * Send a message verdict including the payload * @arg nlh netlink messsage header * @arg msg queue msg @@ -272,12 +295,12 @@ static struct nl_cache_ops nfnl_queue_msg_ops = { .co_obj_ops = &queue_msg_obj_ops, }; -static void __init nfnl_msg_queue_init(void) +static void _nl_init nfnl_msg_queue_init(void) { nl_cache_mngt_register(&nfnl_queue_msg_ops); } -static void __exit nfnl_queue_msg_exit(void) +static void _nl_exit nfnl_queue_msg_exit(void) { nl_cache_mngt_unregister(&nfnl_queue_msg_ops); } diff --git a/lib/netfilter/queue_msg_obj.c b/lib/netfilter/queue_msg_obj.c index 8085f1b..000669b 100644 --- a/lib/netfilter/queue_msg_obj.c +++ b/lib/netfilter/queue_msg_obj.c @@ -1,19 +1,19 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/netfilter/queue_msg_obj.c Netfilter Queue Message Object - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2007, 2008 Patrick McHardy */ -#include +#include "nl-default.h" + +#include + #include #include #include -#include +#include + +#include "nl-netfilter.h" +#include "nl-priv-dynamic-core/nl-core.h" /** @cond SKIP */ #define QUEUE_MSG_ATTR_GROUP (1UL << 0) @@ -48,16 +48,17 @@ static int nfnl_queue_msg_clone(struct nl_object *_dst, struct nl_object *_src) struct nfnl_queue_msg *src = (struct nfnl_queue_msg *) _src; int err; + dst->queue_msg_payload = NULL; + dst->queue_msg_payload_len = 0; + if (src->queue_msg_payload) { err = nfnl_queue_msg_set_payload(dst, src->queue_msg_payload, - src->queue_msg_payload_len); + src->queue_msg_payload_len); if (err < 0) - goto errout; + return err; } return 0; -errout: - return err; } static void nfnl_queue_msg_dump(struct nl_object *a, struct nl_dump_params *p) @@ -391,7 +392,7 @@ int nfnl_queue_msg_test_hwaddr(const struct nfnl_queue_msg *msg) } const uint8_t *nfnl_queue_msg_get_hwaddr(const struct nfnl_queue_msg *msg, - int *len) + int *len) { if (!(msg->ce_mask & QUEUE_MSG_ATTR_HWADDR)) { *len = 0; @@ -403,16 +404,24 @@ const uint8_t *nfnl_queue_msg_get_hwaddr(const struct nfnl_queue_msg *msg, } int nfnl_queue_msg_set_payload(struct nfnl_queue_msg *msg, uint8_t *payload, - int len) + int len) { - free(msg->queue_msg_payload); - msg->queue_msg_payload = malloc(len); - if (!msg->queue_msg_payload) + void *p = NULL; + + if (len < 0) + return -NLE_INVAL; + + p = _nl_memdup(payload, len); + if (!p && len > 0) return -NLE_NOMEM; - memcpy(msg->queue_msg_payload, payload, len); + free(msg->queue_msg_payload); + msg->queue_msg_payload = p; msg->queue_msg_payload_len = len; - msg->ce_mask |= QUEUE_MSG_ATTR_PAYLOAD; + if (len > 0) + msg->ce_mask |= QUEUE_MSG_ATTR_PAYLOAD; + else + msg->ce_mask &= ~QUEUE_MSG_ATTR_PAYLOAD; return 0; } @@ -455,20 +464,20 @@ unsigned int nfnl_queue_msg_get_verdict(const struct nfnl_queue_msg *msg) } static const struct trans_tbl nfnl_queue_msg_attrs[] = { - __ADD(QUEUE_MSG_ATTR_GROUP, group) - __ADD(QUEUE_MSG_ATTR_FAMILY, family) - __ADD(QUEUE_MSG_ATTR_PACKETID, packetid) - __ADD(QUEUE_MSG_ATTR_HWPROTO, hwproto) - __ADD(QUEUE_MSG_ATTR_HOOK, hook) - __ADD(QUEUE_MSG_ATTR_MARK, mark) - __ADD(QUEUE_MSG_ATTR_TIMESTAMP, timestamp) - __ADD(QUEUE_MSG_ATTR_INDEV, indev) - __ADD(QUEUE_MSG_ATTR_OUTDEV, outdev) - __ADD(QUEUE_MSG_ATTR_PHYSINDEV, physindev) - __ADD(QUEUE_MSG_ATTR_PHYSOUTDEV, physoutdev) - __ADD(QUEUE_MSG_ATTR_HWADDR, hwaddr) - __ADD(QUEUE_MSG_ATTR_PAYLOAD, payload) - __ADD(QUEUE_MSG_ATTR_VERDICT, verdict) + __ADD(QUEUE_MSG_ATTR_GROUP, group), + __ADD(QUEUE_MSG_ATTR_FAMILY, family), + __ADD(QUEUE_MSG_ATTR_PACKETID, packetid), + __ADD(QUEUE_MSG_ATTR_HWPROTO, hwproto), + __ADD(QUEUE_MSG_ATTR_HOOK, hook), + __ADD(QUEUE_MSG_ATTR_MARK, mark), + __ADD(QUEUE_MSG_ATTR_TIMESTAMP, timestamp), + __ADD(QUEUE_MSG_ATTR_INDEV, indev), + __ADD(QUEUE_MSG_ATTR_OUTDEV, outdev), + __ADD(QUEUE_MSG_ATTR_PHYSINDEV, physindev), + __ADD(QUEUE_MSG_ATTR_PHYSOUTDEV, physoutdev), + __ADD(QUEUE_MSG_ATTR_HWADDR, hwaddr), + __ADD(QUEUE_MSG_ATTR_PAYLOAD, payload), + __ADD(QUEUE_MSG_ATTR_VERDICT, verdict), }; static char *nfnl_queue_msg_attrs2str(int attrs, char *buf, size_t len) diff --git a/lib/netfilter/queue_obj.c b/lib/netfilter/queue_obj.c index 5edcc68..a6b08a2 100644 --- a/lib/netfilter/queue_obj.c +++ b/lib/netfilter/queue_obj.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/netfilter/queue_obj.c Netfilter Queue - * - * 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) 2007, 2008 Patrick McHardy */ @@ -16,11 +10,24 @@ * @{ */ -#include +#include "nl-default.h" + #include #include +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-priv-dynamic-core/nl-core.h" + /** @cond SKIP */ +struct nfnl_queue { + NLHDR_COMMON + + uint16_t queue_group; + uint32_t queue_maxlen; + uint32_t queue_copy_range; + uint8_t queue_copy_mode; +}; + #define QUEUE_ATTR_GROUP (1UL << 0) #define QUEUE_ATTR_MAXLEN (1UL << 1) #define QUEUE_ATTR_COPY_MODE (1UL << 2) @@ -53,9 +60,9 @@ static void nfnl_queue_dump(struct nl_object *a, struct nl_dump_params *p) } static const struct trans_tbl copy_modes[] = { - __ADD(NFNL_QUEUE_COPY_NONE, none) - __ADD(NFNL_QUEUE_COPY_META, meta) - __ADD(NFNL_QUEUE_COPY_PACKET, packet) + __ADD(NFNL_QUEUE_COPY_NONE, none), + __ADD(NFNL_QUEUE_COPY_META, meta), + __ADD(NFNL_QUEUE_COPY_PACKET, packet), }; char *nfnl_queue_copy_mode2str(enum nfnl_queue_copy_mode copy_mode, char *buf, @@ -65,7 +72,7 @@ char *nfnl_queue_copy_mode2str(enum nfnl_queue_copy_mode copy_mode, char *buf, ARRAY_SIZE(copy_modes)); } -enum nfnl_queue_copy_mode nfnl_queue_str2copy_mode(const char *name) +int nfnl_queue_str2copy_mode(const char *name) { return __str2type(name, copy_modes, ARRAY_SIZE(copy_modes)); } @@ -161,34 +168,30 @@ uint32_t nfnl_queue_get_copy_range(const struct nfnl_queue *queue) return queue->queue_copy_range; } -static int nfnl_queue_compare(struct nl_object *_a, struct nl_object *_b, - uint32_t attrs, int flags) +static uint64_t nfnl_queue_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) { struct nfnl_queue *a = (struct nfnl_queue *) _a; struct nfnl_queue *b = (struct nfnl_queue *) _b; - int diff = 0; - -#define NFNL_QUEUE_DIFF(ATTR, EXPR) \ - ATTR_DIFF(attrs, QUEUE_ATTR_##ATTR, a, b, EXPR) -#define NFNL_QUEUE_DIFF_VAL(ATTR, FIELD) \ - NFNL_QUEUE_DIFF(ATTR, a->FIELD != b->FIELD) - - diff |= NFNL_QUEUE_DIFF_VAL(GROUP, queue_group); - diff |= NFNL_QUEUE_DIFF_VAL(MAXLEN, queue_maxlen); - diff |= NFNL_QUEUE_DIFF_VAL(COPY_MODE, queue_copy_mode); - diff |= NFNL_QUEUE_DIFF_VAL(COPY_RANGE, queue_copy_range); + uint64_t diff = 0; -#undef NFNL_QUEUE_DIFF -#undef NFNL_QUEUE_DIFF_VAL +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) +#define _DIFF_VAL(ATTR, FIELD) _DIFF(ATTR, a->FIELD != b->FIELD) + diff |= _DIFF_VAL(QUEUE_ATTR_GROUP, queue_group); + diff |= _DIFF_VAL(QUEUE_ATTR_MAXLEN, queue_maxlen); + diff |= _DIFF_VAL(QUEUE_ATTR_COPY_MODE, queue_copy_mode); + diff |= _DIFF_VAL(QUEUE_ATTR_COPY_RANGE, queue_copy_range); +#undef _DIFF +#undef _DIFF_VAL return diff; } static const struct trans_tbl nfnl_queue_attrs[] = { - __ADD(QUEUE_ATTR_GROUP, group) - __ADD(QUEUE_ATTR_MAXLEN, maxlen) - __ADD(QUEUE_ATTR_COPY_MODE, copy_mode) - __ADD(QUEUE_ATTR_COPY_RANGE, copy_range) + __ADD(QUEUE_ATTR_GROUP, group), + __ADD(QUEUE_ATTR_MAXLEN, maxlen), + __ADD(QUEUE_ATTR_COPY_MODE, copy_mode), + __ADD(QUEUE_ATTR_COPY_RANGE, copy_range), }; static char *nfnl_queue_attrs2str(int attrs, char *buf, size_t len) diff --git a/lib/nl-core.h b/lib/nl-core.h new file mode 100644 index 0000000..42d7629 --- /dev/null +++ b/lib/nl-core.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2014 Thomas Graf + */ + +#ifndef __LIB_NL_CORE_H__ +#define __LIB_NL_CORE_H__ + +struct nl_cb +{ + nl_recvmsg_msg_cb_t cb_set[NL_CB_TYPE_MAX+1]; + void * cb_args[NL_CB_TYPE_MAX+1]; + + nl_recvmsg_err_cb_t cb_err; + void * cb_err_arg; + + /** May be used to replace nl_recvmsgs with your own implementation + * in all internal calls to nl_recvmsgs. */ + int (*cb_recvmsgs_ow)(struct nl_sock *, + struct nl_cb *); + + /** Overwrite internal calls to nl_recv, must return the number of + * octets read and allocate a buffer for the received data. */ + int (*cb_recv_ow)(struct nl_sock *, + struct sockaddr_nl *, + unsigned char **, + struct ucred **); + + /** Overwrites internal calls to nl_send, must send the netlink + * message. */ + int (*cb_send_ow)(struct nl_sock *, + struct nl_msg *); + + int cb_refcnt; + /** indicates the callback that is currently active */ + enum nl_cb_type cb_active; +}; + +static inline int nl_cb_call(struct nl_cb *cb, enum nl_cb_type type, struct nl_msg *msg) +{ + int ret; + + cb->cb_active = type; + ret = cb->cb_set[type](msg, cb->cb_args[type]); + cb->cb_active = __NL_CB_TYPE_MAX; + return ret; +} + +int _nl_socket_is_local_port_unspecified (struct nl_sock *sk); +uint32_t _nl_socket_set_local_port_no_release(struct nl_sock *sk, int generate_other); + +void _nl_socket_used_ports_release_all(const uint32_t *used_ports); +void _nl_socket_used_ports_set(uint32_t *used_ports, uint32_t port); + +extern int nl_cache_parse(struct nl_cache_ops *, struct sockaddr_nl *, + struct nlmsghdr *, struct nl_parser_param *); + +extern void dump_from_ops(struct nl_object *, struct nl_dump_params *); + +#endif /* __LIB_NL_CORE_H__ */ diff --git a/lib/nl.c b/lib/nl.c index 565747a..7d729a7 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/nl.c Core Netlink Interface - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -25,13 +19,21 @@ * @{ */ -#include +#include "nl-default.h" + +#include + #include #include #include #include #include +#include "nl-core.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-aux-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" + /** * @defgroup core_types Data Types * @@ -75,8 +77,23 @@ * be closed automatically if any of the `exec` family functions succeed. * This is essential for multi threaded programs. * + * @note The local port (`nl_socket_get_local_port()`) is unspecified after + * creating a new socket. It only gets determined when accessing the + * port the first time or during `nl_connect()`. When nl_connect() + * fails during `bind()` due to `ADDRINUSE`, it will retry with + * different ports if the port is unspecified. Unless you want to enforce + * the use of a specific local port, don't access the local port (or + * reset it to `unspecified` by calling `nl_socket_set_local_port(sk, 0)`). + * This capability is indicated by + * `%NL_CAPABILITY_NL_CONNECT_RETRY_GENERATE_PORT_ON_ADDRINUSE`. + * + * @note nl_connect() creates and sets the file descriptor. You can setup the file + * descriptor yourself by creating and binding it, and then calling + * nl_socket_set_fd(). The result will be the same. + * * @see nl_socket_alloc() * @see nl_close() + * @see nl_socket_set_fd() * * @return 0 on success or a negative error code. * @@ -85,60 +102,115 @@ int nl_connect(struct nl_sock *sk, int protocol) { int err, flags = 0; + int errsv; socklen_t addrlen; + struct sockaddr_nl local = { 0 }; + int try_bind = 1; #ifdef SOCK_CLOEXEC flags |= SOCK_CLOEXEC; #endif - if (sk->s_fd != -1) - return -NLE_BAD_SOCK; + if (sk->s_fd != -1) + return -NLE_BAD_SOCK; sk->s_fd = socket(AF_NETLINK, SOCK_RAW | flags, protocol); if (sk->s_fd < 0) { - err = -nl_syserr2nlerr(errno); + errsv = errno; + NL_DBG(4, "nl_connect(%p): socket() failed with %d (%s)\n", sk, errsv, + nl_strerror_l(errsv)); + err = -nl_syserr2nlerr(errsv); goto errout; } - if (!(sk->s_flags & NL_SOCK_BUFSIZE_SET)) { - err = nl_socket_set_buffer_size(sk, 0, 0); - if (err < 0) - goto errout; - } - - err = bind(sk->s_fd, (struct sockaddr*) &sk->s_local, - sizeof(sk->s_local)); - if (err < 0) { - err = -nl_syserr2nlerr(errno); + err = nl_socket_set_buffer_size(sk, 0, 0); + if (err < 0) goto errout; + + if (_nl_socket_is_local_port_unspecified (sk)) { + uint32_t port; + uint32_t used_ports[32] = { 0 }; + int ntries = 0; + + while (1) { + if (ntries++ > 5) { + /* try only a few times. We hit this only if many ports are already in + * use but allocated *outside* libnl/generate_local_port(). */ + _nl_socket_set_local_port_no_release (sk, 0); + break; + } + + port = _nl_socket_set_local_port_no_release(sk, 1); + if (port == 0) + break; + + err = bind(sk->s_fd, (struct sockaddr*) &sk->s_local, + sizeof(sk->s_local)); + if (err == 0) { + try_bind = 0; + break; + } + + errsv = errno; + if (errsv == EADDRINUSE) { + NL_DBG(4, "nl_connect(%p): local port %u already in use. Retry.\n", sk, (unsigned) port); + _nl_socket_used_ports_set(used_ports, port); + } else { + NL_DBG(4, "nl_connect(%p): bind() for port %u failed with %d (%s)\n", + sk, (unsigned) port, errsv, nl_strerror_l(errsv)); + _nl_socket_used_ports_release_all(used_ports); + err = -nl_syserr2nlerr(errsv); + goto errout; + } + } + _nl_socket_used_ports_release_all(used_ports); + } + if (try_bind) { + err = bind(sk->s_fd, (struct sockaddr*) &sk->s_local, + sizeof(sk->s_local)); + if (err != 0) { + errsv = errno; + NL_DBG(4, "nl_connect(%p): bind() failed with %d (%s)\n", + sk, errsv, nl_strerror_l(errsv)); + err = -nl_syserr2nlerr(errsv); + goto errout; + } } - addrlen = sizeof(sk->s_local); - err = getsockname(sk->s_fd, (struct sockaddr *) &sk->s_local, + addrlen = sizeof(local); + err = getsockname(sk->s_fd, (struct sockaddr *) &local, &addrlen); if (err < 0) { + NL_DBG(4, "nl_connect(%p): getsockname() failed with %d (%s)\n", + sk, errno, nl_strerror_l(errno)); err = -nl_syserr2nlerr(errno); goto errout; } - if (addrlen != sizeof(sk->s_local)) { + if (addrlen != sizeof(local)) { err = -NLE_NOADDR; goto errout; } - if (sk->s_local.nl_family != AF_NETLINK) { + if (local.nl_family != AF_NETLINK) { err = -NLE_AF_NOSUPPORT; goto errout; } + if (sk->s_local.nl_pid != local.nl_pid) { + /* The port id is different. That can happen if the port id was zero + * and kernel assigned a local port. */ + nl_socket_set_local_port (sk, local.nl_pid); + } + sk->s_local = local; sk->s_proto = protocol; return 0; errout: - if (sk->s_fd != -1) { - close(sk->s_fd); - sk->s_fd = -1; - } + if (sk->s_fd != -1) { + close(sk->s_fd); + sk->s_fd = -1; + } return err; } @@ -206,8 +278,11 @@ int nl_sendto(struct nl_sock *sk, void *buf, size_t size) ret = sendto(sk->s_fd, buf, size, 0, (struct sockaddr *) &sk->s_peer, sizeof(sk->s_peer)); - if (ret < 0) + if (ret < 0) { + NL_DBG(4, "nl_sendto(%p): sendto() failed with %d (%s)\n", + sk, errno, nl_strerror_l(errno)); return -nl_syserr2nlerr(errno); + } return ret; } @@ -264,8 +339,11 @@ int nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr) return ret; ret = sendmsg(sk->s_fd, hdr, 0); - if (ret < 0) + if (ret < 0) { + NL_DBG(4, "nl_sendmsg(%p): sendmsg() failed with %d (%s)\n", + sk, errno, nl_strerror_l(errno)); return -nl_syserr2nlerr(errno); + } NL_DBG(4, "sent %d bytes\n", ret); return ret; @@ -301,6 +379,7 @@ int nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, uns .msg_iov = iov, .msg_iovlen = iovlen, }; + char buf[CMSG_SPACE(sizeof(struct ucred))]; /* Overwrite destination if specified in the message itself, defaults * to the peer address of the socket. @@ -312,7 +391,6 @@ int nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, uns /* Add credentials if present. */ creds = nlmsg_get_creds(msg); if (creds != NULL) { - char buf[CMSG_SPACE(sizeof(struct ucred))]; struct cmsghdr *cmsg; hdr.msg_control = buf; @@ -405,7 +483,7 @@ void nl_complete_msg(struct nl_sock *sk, struct nl_msg *msg) nlh = nlmsg_hdr(msg); if (nlh->nlmsg_pid == NL_AUTO_PORT) - nlh->nlmsg_pid = sk->s_local.nl_pid; + nlh->nlmsg_pid = nl_socket_get_local_port(sk); if (nlh->nlmsg_seq == NL_AUTO_SEQ) nlh->nlmsg_seq = sk->s_seq_next++; @@ -542,7 +620,9 @@ errout: * * This function blocks until data is available to be read unless the socket * has been put into non-blocking mode using nl_socket_set_nonblocking() in - * which case this function will return immediately with a return value of 0. + * which case this function will return immediately with a return value of + * -NLA_AGAIN (versions before 3.2.22 returned instead 0, in which case you + * should check first clear errno and then check for errno EAGAIN). * * The buffer size used when reading from the netlink socket and thus limiting * the maximum size of a netlink message that can be read defaults to the size @@ -593,13 +673,14 @@ int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla, if (!buf || !nla) return -NLE_INVAL; - if (sk->s_flags & NL_MSG_PEEK) + if ( (sk->s_flags & NL_MSG_PEEK) + || (!(sk->s_flags & NL_MSG_PEEK_EXPLICIT) && sk->s_bufsize == 0)) flags |= MSG_PEEK | MSG_TRUNC; if (page_size == 0) page_size = getpagesize() * 4; - iov.iov_len = sk->s_bufsize ? : page_size; + iov.iov_len = sk->s_bufsize ? sk->s_bufsize : page_size; iov.iov_base = malloc(iov.iov_len); if (!iov.iov_base) { @@ -627,12 +708,22 @@ retry: NL_DBG(3, "recvmsg() returned EINTR, retrying\n"); goto retry; } + + NL_DBG(4, "recvmsg(%p): nl_recv() failed with %d (%s)\n", + sk, errno, nl_strerror_l(errno)); retval = -nl_syserr2nlerr(errno); goto abort; } if (msg.msg_flags & MSG_CTRUNC) { void *tmp; + + if (msg.msg_controllen == 0) { + retval = -NLE_MSG_TRUNC; + NL_DBG(4, "recvmsg(%p): Received unexpected control data", sk); + goto abort; + } + msg.msg_controllen *= 2; tmp = realloc(msg.msg_control, msg.msg_controllen); if (!tmp) { @@ -645,6 +736,13 @@ retry: if (iov.iov_len < n || (msg.msg_flags & MSG_TRUNC)) { void *tmp; + + /* respond with error to an incomplete message */ + if (flags == 0) { + retval = -NLE_MSG_TRUNC; + goto abort; + } + /* Provided buffer is not long enough, enlarge it * to size of n (which should be total length of the message) * and try again. */ @@ -659,7 +757,7 @@ retry: goto retry; } - if (flags != 0) { + if (flags != 0) { /* Buffer is big enough, do the actual reading */ flags = 0; goto retry; @@ -819,7 +917,7 @@ continue_reading: interrupted = 1; } } - + /* Other side wishes to see an ack for this message */ if (hdr->nlmsg_flags & NLM_F_ACK) { if (cb->cb_set[NL_CB_SEND_ACK]) @@ -829,7 +927,7 @@ continue_reading: } } - /* messages terminates a multpart message, this is + /* messages terminates a multipart message, this is * usually the end of a message and therefore we slip * out of the loop by default. the user may overrule * this action by skipping this packet. */ @@ -878,10 +976,13 @@ continue_reading: goto out; } } else if (e->error) { + NL_DBG(4, "recvmsgs(%p): RTNETLINK responded with %d (%s)\n", + sk, -e->error, nl_strerror_l(-e->error)); + /* Error message reported back from kernel. */ if (cb->cb_err) { err = cb->cb_err(&nla, e, - cb->cb_err_arg); + cb->cb_err_arg); if (err < 0) goto out; else if (err == NL_SKIP) @@ -907,7 +1008,7 @@ skip: err = 0; hdr = nlmsg_next(hdr, &n); } - + nlmsg_free(msg); free(buf); free(creds); @@ -1029,6 +1130,7 @@ struct pickup_param int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *, struct nlmsghdr *, struct nl_parser_param *); struct nl_object *result; + int *syserror; }; static int __store_answer(struct nl_object *obj, struct nl_parser_param *p) @@ -1055,20 +1157,45 @@ static int __pickup_answer(struct nl_msg *msg, void *arg) return pp->parser(NULL, &msg->nm_src, msg->nm_nlh, &parse_arg); } +static int __pickup_answer_syserr(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg) +{ + *(((struct pickup_param *) arg)->syserror) = nlerr->error; + + return -nl_syserr2nlerr(nlerr->error); +} + /** @endcond */ /** * Pickup netlink answer, parse is and return object - * @arg sk Netlink socket - * @arg parser Parser function to parse answer - * @arg result Result pointer to return parsed object + * @arg sk Netlink socket + * @arg parser Parser function to parse answer + * @arg result Result pointer to return parsed object * * @return 0 on success or a negative error code. */ int nl_pickup(struct nl_sock *sk, - int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *, - struct nlmsghdr *, struct nl_parser_param *), - struct nl_object **result) + int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *, + struct nlmsghdr *, struct nl_parser_param *), + struct nl_object **result) +{ + return nl_pickup_keep_syserr(sk, parser, result, NULL); +} + +/** + * Pickup netlink answer, parse is and return object with preserving system error + * @arg sk Netlink socket + * @arg parser Parser function to parse answer + * @arg result Result pointer to return parsed object + * @arg syserr Result pointer for the system error in case of failure + * + * @return 0 on success or a negative error code. + */ +int nl_pickup_keep_syserr(struct nl_sock *sk, + int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *, + struct nlmsghdr *, struct nl_parser_param *), + struct nl_object **result, + int *syserror) { struct nl_cb *cb; int err; @@ -1081,6 +1208,11 @@ int nl_pickup(struct nl_sock *sk, return -NLE_NOMEM; nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, __pickup_answer, &pp); + if (syserror) { + *syserror = 0; + pp.syserror = syserror; + nl_cb_err(cb, NL_CB_CUSTOM, __pickup_answer_syserr, &pp); + } err = nl_recvmsgs(sk, cb); if (err < 0) diff --git a/lib/object.c b/lib/object.c index b1ebe51..9b147d6 100644 --- a/lib/object.c +++ b/lib/object.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/object.c Generic Cacheable Object - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -27,12 +21,19 @@ * ~~~~ */ -#include +#include "nl-default.h" + #include #include #include #include +#include "nl-core.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-priv-dynamic-core/cache-api.h" +#include "nl-aux-core/nl-core.h" + static inline struct nl_object_ops *obj_ops(struct nl_object *obj) { if (!obj->ce_ops) @@ -110,10 +111,14 @@ struct nl_derived_object { struct nl_object *nl_object_clone(struct nl_object *obj) { struct nl_object *new; - struct nl_object_ops *ops = obj_ops(obj); + struct nl_object_ops *ops; int doff = offsetof(struct nl_derived_object, data); int size; + if (!obj) + return NULL; + + ops = obj_ops(obj); new = nl_object_alloc(ops); if (!new) return NULL; @@ -127,7 +132,12 @@ struct nl_object *nl_object_clone(struct nl_object *obj) new->ce_mask = obj->ce_mask; if (size) - memcpy((void *)new + doff, (void *)obj + doff, size); + memcpy((char *)new + doff, (char *)obj + doff, size); + + /* Note that the base implementation already initializes @new via memcpy(). + * That means, simple fields don't need to be handled via oo_clone(). + * However, this is only a shallow-copy, so oo_clone() MUST fix all + * pointer values accordingly. */ if (ops->oo_clone) { if (ops->oo_clone(new, obj) < 0) { @@ -181,9 +191,9 @@ void nl_object_free(struct nl_object *obj) if (ops->oo_free_data) ops->oo_free_data(obj); - free(obj); - NL_DBG(4, "Freed object %p\n", obj); + + free(obj); } /** @} */ @@ -291,12 +301,12 @@ void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params) void nl_object_dump_buf(struct nl_object *obj, char *buf, size_t len) { - struct nl_dump_params dp = { - .dp_buf = buf, - .dp_buflen = len, - }; + struct nl_dump_params dp = { + .dp_buf = buf, + .dp_buflen = len, + }; - return nl_object_dump(obj, &dp); + nl_object_dump(obj, &dp); } /** @@ -308,36 +318,42 @@ void nl_object_dump_buf(struct nl_object *obj, char *buf, size_t len) */ int nl_object_identical(struct nl_object *a, struct nl_object *b) { - struct nl_object_ops *ops = obj_ops(a); - uint32_t req_attrs; + struct nl_object_ops *ops; + uint64_t req_attrs_a; + uint64_t req_attrs_b; + + if (a == b) + return 1; /* Both objects must be of same type */ + ops = obj_ops(a); if (ops != obj_ops(b)) return 0; + /* Can't judge unless we can compare */ + if (ops->oo_compare == NULL) + return 0; + if (ops->oo_id_attrs_get) { - int req_attrs_a = ops->oo_id_attrs_get(a); - int req_attrs_b = ops->oo_id_attrs_get(b); - if (req_attrs_a != req_attrs_b) - return 0; - req_attrs = req_attrs_a; + req_attrs_a = ops->oo_id_attrs_get(a); + req_attrs_b = ops->oo_id_attrs_get(b); + } else if (ops->oo_id_attrs) { + req_attrs_a = ops->oo_id_attrs; + req_attrs_b = req_attrs_a; } else { - req_attrs = ops->oo_id_attrs; + req_attrs_a = UINT64_MAX; + req_attrs_b = req_attrs_a; } - if (req_attrs == 0xFFFFFFFF) - req_attrs = a->ce_mask & b->ce_mask; + + req_attrs_a &= a->ce_mask; + req_attrs_b &= b->ce_mask; /* Both objects must provide all required attributes to uniquely * identify an object */ - if ((a->ce_mask & req_attrs) != req_attrs || - (b->ce_mask & req_attrs) != req_attrs) + if (req_attrs_a != req_attrs_b) return 0; - /* Can't judge unless we can compare */ - if (ops->oo_compare == NULL) - return 0; - - return !(ops->oo_compare(a, b, req_attrs, 0)); + return !(ops->oo_compare(a, b, req_attrs_a, ID_COMPARISON)); } /** @@ -352,14 +368,39 @@ int nl_object_identical(struct nl_object *a, struct nl_object *b) * * @return Bitmask describing differences or 0 if they are completely identical. */ -uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b) +uint64_t nl_object_diff64(struct nl_object *a, struct nl_object *b) { struct nl_object_ops *ops = obj_ops(a); if (ops != obj_ops(b) || ops->oo_compare == NULL) - return UINT_MAX; + return UINT64_MAX; - return ops->oo_compare(a, b, ~0, 0); + return ops->oo_compare(a, b, UINT64_MAX, 0); +} + +/** + * Compute 32-bit bitmask representing difference in attribute values + * @arg a an object + * @arg b another object of same type + * + * The bitmask returned is specific to an object type, each bit set represents + * an attribute which mismatches in either of the two objects. Unavailability + * of an attribute in one object and presence in the other is regarded a + * mismatch as well. + * + * @return Bitmask describing differences or 0 if they are completely identical. + * 32nd bit indicates if higher bits from the 64-bit compare were + * different. + */ +uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b) +{ + uint64_t diff; + + diff = nl_object_diff64(a, b); + + return (diff & ~((uint64_t) 0xFFFFFFFF)) + ? (uint32_t) diff | (((uint32_t ) 1u) << 31) + : (uint32_t) diff; } /** @@ -377,7 +418,7 @@ int nl_object_match_filter(struct nl_object *obj, struct nl_object *filter) if (ops != obj_ops(filter) || ops->oo_compare == NULL) return 0; - + return !(ops->oo_compare(obj, filter, filter->ce_mask, LOOSE_COMPARISON)); } diff --git a/lib/route/act.c b/lib/route/act.c new file mode 100644 index 0000000..670810f --- /dev/null +++ b/lib/route/act.c @@ -0,0 +1,631 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Cong Wang + */ + +/** + * @ingroup tc + * @defgroup act Action + * @{ + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include + +#include "nl-route.h" +#include "tc-api.h" +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-priv-dynamic-core/cache-api.h" +#include "nl-aux-route/nl-route.h" + +static struct nl_object_ops act_obj_ops; +static struct nl_cache_ops rtnl_act_ops; + +struct rtnl_act * rtnl_act_next(struct rtnl_act *act) +{ + if (act == NULL) { + return NULL; + } + + return act->a_next; +} + +int rtnl_act_append(struct rtnl_act **head, struct rtnl_act *new) +{ + struct rtnl_act *p_act; + int count = 1; + + if (*head == NULL) { + *head = new; + return 0; + } + + p_act = *head; + while (p_act->a_next) { + ++count; + p_act = p_act->a_next; + } + + if (count > TCA_ACT_MAX_PRIO) + return -NLE_RANGE; + + p_act->a_next = new; + return 0; +} + +int rtnl_act_remove(struct rtnl_act **head, struct rtnl_act *act) +{ + struct rtnl_act *a, **ap; + + for (ap = head; (a = *ap) != NULL; ap = &a->a_next) + if (a == act) + break; + if (a) { + *ap = a->a_next; + a->a_next = NULL; + return 0; + } + + return -NLE_OBJ_NOTFOUND; +} + +static int rtnl_act_fill_one(struct nl_msg *msg, struct rtnl_act *act, int order) +{ + struct rtnl_tc *tc = TC_CAST(act); + struct rtnl_tc_ops *ops; + struct nlattr *nest; + int err = -NLE_NOMEM; + + nest = nla_nest_start(msg, order); + if (!nest) + goto nla_put_failure; + + if (tc->ce_mask & TCA_ATTR_KIND) + NLA_PUT_STRING(msg, TCA_ACT_KIND, tc->tc_kind); + + ops = rtnl_tc_get_ops(tc); + if (ops && (ops->to_msg_fill || ops->to_msg_fill_raw)) { + struct nlattr *opts; + void *data = rtnl_tc_data(tc); + + if (ops->to_msg_fill) { + if (!(opts = nla_nest_start(msg, TCA_ACT_OPTIONS))) + goto nla_put_failure; + + if ((err = ops->to_msg_fill(tc, data, msg)) < 0) + goto nla_put_failure; + + nla_nest_end(msg, opts); + } else if ((err = ops->to_msg_fill_raw(tc, data, msg)) < 0) + goto nla_put_failure; + } + nla_nest_end(msg, nest); + return 0; + +nla_put_failure: + return err; +} + +int rtnl_act_fill(struct nl_msg *msg, int attrtype, struct rtnl_act *act) +{ + struct rtnl_act *p_act = act; + struct nlattr *nest; + int err, order = 0; + + nest = nla_nest_start(msg, attrtype); + if (!nest) + return -NLE_MSGSIZE; + + while (p_act) { + err = rtnl_act_fill_one(msg, p_act, ++order); + if (err < 0) + return err; + p_act = p_act->a_next; + } + + nla_nest_end(msg, nest); + return 0; +} + +static int rtnl_act_msg_build(struct rtnl_act *act, int type, int flags, + struct nl_msg **result) +{ + struct nl_msg *msg; + struct tcamsg tcahdr = { + .tca_family = AF_UNSPEC, + }; + int err = -NLE_MSGSIZE; + + msg = nlmsg_alloc_simple(type, flags); + if (!msg) + return -NLE_NOMEM; + + if (nlmsg_append(msg, &tcahdr, sizeof(tcahdr), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + err = rtnl_act_fill(msg, TCA_ACT_TAB, act); + if (err < 0) + goto nla_put_failure; + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return err; +} + +static int act_build(struct rtnl_act *act, int type, int flags, + struct nl_msg **result) +{ + int err; + + err = rtnl_act_msg_build(act, type, flags, result); + if (err < 0) + return err; + return 0; +} + +/** + * @name Allocation/Freeing + * @{ + */ + +struct rtnl_act *rtnl_act_alloc(void) +{ + struct rtnl_tc *tc; + + tc = TC_CAST(nl_object_alloc(&act_obj_ops)); + if (tc) + tc->tc_type = RTNL_TC_TYPE_ACT; + + return (struct rtnl_act *) tc; +} + +void rtnl_act_get(struct rtnl_act *act) +{ + nl_object_get(OBJ_CAST(act)); +} + +void rtnl_act_put(struct rtnl_act *act) +{ + nl_object_put((struct nl_object *) act); +} + +/** @} */ + +/** + * @name Addition/Modification/Deletion + * @{ + */ + +/** + * Build a netlink message requesting the addition of an action + * @arg act Action to add + * @arg flags Additional netlink message flags + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_act_add() with + * the exception that it will not send the message but return it int the + * provided return pointer instead. + * + * @see rtnl_act_add() + * + * @return 0 on success or a negative error code. + */ +int rtnl_act_build_add_request(struct rtnl_act *act, int flags, + struct nl_msg **result) +{ + return act_build(act, RTM_NEWACTION, flags, result); +} + +/** + * Add/Update action + * @arg sk Netlink socket + * @arg act Action to add/update + * @arg flags Additional netlink message flags + * + * Builds a \c RTM_NEWACTION netlink message requesting the addition + * of a new action and sends the message to the kernel. The + * configuration of the action is derived from the attributes of + * the specified traffic class. + * + * The following flags may be specified: + * - \c NLM_F_CREATE: Create action if it does not exist, + * otherwise -NLE_OBJ_NOTFOUND is returned. + * - \c NLM_F_EXCL: Return -NLE_EXISTS if an action with + * matching handle exists already. + * + * Existing actions with matching handles will be updated, unless + * the flag \c NLM_F_EXCL is specified. If no matching action + * exists, it will be created if the flag \c NLM_F_CREATE is set, + * otherwise the error -NLE_OBJ_NOTFOUND is returned. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @return 0 on success or a negative error code. + */ +int rtnl_act_add(struct nl_sock *sk, struct rtnl_act *act, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_act_build_add_request(act, flags, &msg)) < 0) + return err; + + return nl_send_sync(sk, msg); +} + +/** + * Build a netlink message to change action attributes + * @arg act Action to change + * @arg flags additional netlink message flags + * @arg result Pointer to store resulting message. + * + * Builds a new netlink message requesting a change of a neigh + * attributes. The netlink message header isn't fully equipped with + * all relevant fields and must thus be sent out via nl_send_auto_complete() + * or supplemented as needed. + * + * @return 0 on success or a negative error code. + */ +int rtnl_act_build_change_request(struct rtnl_act *act, int flags, + struct nl_msg **result) +{ + return act_build(act, RTM_NEWACTION, NLM_F_REPLACE | flags, result); +} + +/** + * Change an action + * @arg sk Netlink socket. + * @arg act action to change + * @arg flags additional netlink message flags + * + * Builds a netlink message by calling rtnl_act_build_change_request(), + * sends the request to the kernel and waits for the next ACK to be + * received and thus blocks until the request has been processed. + * + * @return 0 on success or a negative error if an error occured. + */ +int rtnl_act_change(struct nl_sock *sk, struct rtnl_act *act, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_act_build_change_request(act, flags, &msg)) < 0) + return err; + + return nl_send_sync(sk, msg); +} + +/** + * Build netlink message requesting the deletion of an action + * @arg act Action to delete + * @arg flags Additional netlink message flags + * @arg result Pointer to store resulting netlink message + * + * The behaviour of this function is identical to rtnl_act_delete() with + * the exception that it will not send the message but return it in the + * provided return pointer instead. + * + * @see rtnl_act_delete() + * + * @return 0 on success or a negative error code. + */ +int rtnl_act_build_delete_request(struct rtnl_act *act, int flags, + struct nl_msg **result) +{ + return act_build(act, RTM_DELACTION, flags, result); +} + +/** + * Delete action + * @arg sk Netlink socket + * @arg act Action to delete + * @arg flags Additional netlink message flags + * + * Builds a \c RTM_DELACTION netlink message requesting the deletion + * of an action and sends the message to the kernel. + * + * The message is constructed out of the following attributes: + * - \c ifindex (required) + * - \c prio (required) + * - \c protocol (required) + * - \c handle (required) + * - \c parent (optional, if not specified parent equals root-qdisc) + * - \c kind (optional, must match if provided) + * + * All other action attributes including all class type specific + * attributes are ignored. + * + * After sending, the function will wait for the ACK or an eventual + * error message to be received and will therefore block until the + * operation has been completed. + * + * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause + * this function to return immediately after sending. In this case, + * it is the responsibility of the caller to handle any error + * messages returned. + * + * @return 0 on success or a negative error code. + */ +int rtnl_act_delete(struct nl_sock *sk, struct rtnl_act *act, int flags) +{ + struct nl_msg *msg; + int err; + + if ((err = rtnl_act_build_delete_request(act, flags, &msg)) < 0) + return err; + + return nl_send_sync(sk, msg); +} + +/** @} */ + +static void act_dump_line(struct rtnl_tc *tc, struct nl_dump_params *p) +{ +} + +void rtnl_act_put_all(struct rtnl_act **head) +{ + struct rtnl_act *curr, *next; + + curr = *head; + while (curr) { + next = curr->a_next; + rtnl_act_put(curr); + curr = next; + } + *head = NULL; +} + +static struct nla_policy tc_act_stats_policy[TCA_STATS_MAX+1] = { + [TCA_STATS_BASIC] = { .minlen = sizeof(struct gnet_stats_basic) }, + [TCA_STATS_QUEUE] = { .minlen = sizeof(struct gnet_stats_queue) }, + [TCA_STATS_RATE_EST] = { .minlen = sizeof(struct gnet_stats_rate_est) }, + [TCA_STATS_RATE_EST64] = { .minlen = sizeof(struct gnet_stats_rate_est64) }, +}; + +int rtnl_act_parse(struct rtnl_act **head, struct nlattr *tb) +{ + _nl_auto_rtnl_act_all struct rtnl_act *tmp_head = NULL; + struct rtnl_tc_ops *ops; + struct nlattr *tb2[TCA_ACT_MAX + 1]; + struct nlattr *nla[TCA_ACT_MAX_PRIO + 1]; + char kind[TCKINDSIZ]; + int err, i; + + err = nla_parse(nla, TCA_ACT_MAX_PRIO, nla_data(tb), + NLMSG_ALIGN(nla_len(tb)), NULL); + if (err < 0) + return err; + + for (i = 0; i < TCA_ACT_MAX_PRIO; i++) { + _nl_auto_rtnl_act struct rtnl_act *act = NULL; + struct rtnl_tc *tc; + + if (nla[i] == NULL) + continue; + + act = rtnl_act_alloc(); + if (!act) + return -NLE_NOMEM; + + tc = TC_CAST(act); + err = nla_parse(tb2, TCA_ACT_MAX, nla_data(nla[i]), + nla_len(nla[i]), NULL); + if (err < 0) + return err; + + if (tb2[TCA_ACT_KIND] == NULL) + return -NLE_MISSING_ATTR; + + nla_strlcpy(kind, tb2[TCA_ACT_KIND], sizeof(kind)); + rtnl_tc_set_kind(tc, kind); + + if (tb2[TCA_ACT_OPTIONS]) { + tc->tc_opts = nl_data_alloc_attr(tb2[TCA_ACT_OPTIONS]); + if (!tc->tc_opts) + return -NLE_NOMEM; + tc->ce_mask |= TCA_ATTR_OPTS; + } + + if (tb2[TCA_ACT_STATS]) { + struct nlattr *tb3[TCA_STATS_MAX + 1]; + + err = nla_parse_nested(tb3, TCA_STATS_MAX, tb2[TCA_ACT_STATS], + tc_act_stats_policy); + if (err < 0) + return err; + + if (tb3[TCA_STATS_BASIC]) { + struct gnet_stats_basic bs; + + memcpy(&bs, nla_data(tb3[TCA_STATS_BASIC]), + sizeof(bs)); + tc->tc_stats[RTNL_TC_BYTES] = bs.bytes; + tc->tc_stats[RTNL_TC_PACKETS] = bs.packets; + } + if (tb3[TCA_STATS_RATE_EST64]) { + struct gnet_stats_rate_est64 re; + + memcpy(&re, nla_data(tb3[TCA_STATS_RATE_EST64]), + sizeof(re)); + tc->tc_stats[RTNL_TC_RATE_BPS] = re.bps; + tc->tc_stats[RTNL_TC_RATE_PPS] = re.pps; + } else if (tb3[TCA_STATS_RATE_EST]) { + struct gnet_stats_rate_est *re; + + re = nla_data(tb3[TCA_STATS_RATE_EST]); + tc->tc_stats[RTNL_TC_RATE_BPS] = re->bps; + tc->tc_stats[RTNL_TC_RATE_PPS] = re->pps; + } + if (tb3[TCA_STATS_QUEUE]) { + struct gnet_stats_queue *q; + + q = nla_data(tb3[TCA_STATS_QUEUE]); + tc->tc_stats[RTNL_TC_DROPS] = q->drops; + tc->tc_stats[RTNL_TC_OVERLIMITS] = q->overlimits; + } + } + + ops = rtnl_tc_get_ops(tc); + if (ops && ops->to_msg_parser) { + void *data = rtnl_tc_data(tc); + + if (!data) + return -NLE_NOMEM; + + err = ops->to_msg_parser(tc, data); + if (err < 0) + return err; + } + err = _rtnl_act_append_take(&tmp_head, _nl_steal_pointer(&act)); + if (err < 0) + return err; + } + + *head = _nl_steal_pointer(&tmp_head); + return 0; +} + +static int rtnl_act_msg_parse(struct nlmsghdr *n, struct rtnl_act **act) +{ + struct rtnl_tc *tc = TC_CAST(*act); + struct nl_cache *link_cache; + struct nlattr *tb[TCAA_MAX + 1]; + struct tcamsg *tm; + int err; + + tc->ce_msgtype = n->nlmsg_type; + + err = nlmsg_parse(n, sizeof(*tm), tb, TCAA_MAX, NULL); + if (err < 0) + return err; + + tm = nlmsg_data(n); + tc->tc_family = tm->tca_family; + + if (tb[TCA_ACT_TAB] == NULL) + return -NLE_MISSING_ATTR; + + err = rtnl_act_parse(act, tb[TCA_ACT_TAB]); + if (err < 0) + return err; + + if ((link_cache = __nl_cache_mngt_require("route/link"))) { + struct rtnl_link *link; + + if ((link = rtnl_link_get(link_cache, tc->tc_ifindex))) { + rtnl_tc_set_link(tc, link); + + /* rtnl_tc_set_link incs refcnt */ + rtnl_link_put(link); + } + } + + return 0; +} +static int act_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *nlh, struct nl_parser_param *pp) +{ + struct rtnl_act *act, *p_act; + int err; + + if (!(act = rtnl_act_alloc())) + return -NLE_NOMEM; + + if ((err = rtnl_act_msg_parse(nlh, &act)) < 0) + goto errout; + + p_act = act; + while(p_act) { + err = pp->pp_cb(OBJ_CAST(act), pp); + if (err) { + if (err > 0) { + _nl_assert_not_reached(); + err = -NLE_FAILURE; + } + break; + } + p_act = p_act->a_next; + } +errout: + rtnl_act_put(act); + + return err; +} + +static int act_request_update(struct nl_cache *cache, struct nl_sock *sk) +{ + struct tcamsg tcahdr = { + .tca_family = AF_UNSPEC, + }; + + return nl_send_simple(sk, RTM_GETACTION, NLM_F_DUMP, &tcahdr, + sizeof(tcahdr)); +} + +static struct rtnl_tc_type_ops act_ops = { + .tt_type = RTNL_TC_TYPE_ACT, + .tt_dump_prefix = "act", + .tt_dump = { + [NL_DUMP_LINE] = act_dump_line, + }, +}; + +static struct nl_cache_ops rtnl_act_ops = { + .co_name = "route/act", + .co_hdrsize = sizeof(struct tcmsg), + .co_msgtypes = { + { RTM_NEWACTION, NL_ACT_NEW, "new" }, + { RTM_DELACTION, NL_ACT_DEL, "del" }, + { RTM_GETACTION, NL_ACT_GET, "get" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_ROUTE, + .co_request_update = act_request_update, + .co_msg_parser = act_msg_parser, + .co_obj_ops = &act_obj_ops, +}; + +static struct nl_object_ops act_obj_ops = { + .oo_name = "route/act", + .oo_size = sizeof(struct rtnl_act), + .oo_free_data = rtnl_tc_free_data, + .oo_clone = rtnl_tc_clone, + .oo_dump = { + [NL_DUMP_LINE] = rtnl_tc_dump_line, + [NL_DUMP_DETAILS] = rtnl_tc_dump_details, + [NL_DUMP_STATS] = rtnl_tc_dump_stats, + }, + .oo_compare = rtnl_tc_compare, + .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE), +}; + +static void _nl_init act_init(void) +{ + rtnl_tc_type_register(&act_ops); + nl_cache_mngt_register(&rtnl_act_ops); +} + +static void _nl_exit act_exit(void) +{ + nl_cache_mngt_unregister(&rtnl_act_ops); + rtnl_tc_type_unregister(&act_ops); +} + +/** @} */ diff --git a/lib/route/act/gact.c b/lib/route/act/gact.c new file mode 100644 index 0000000..2e04c5a --- /dev/null +++ b/lib/route/act/gact.c @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2016 Sushma Sitaram + */ + +/** + * @ingroup act + * @defgroup act_gact GACT Editing + * + * @{ + */ + +#include "nl-default.h" + +#include +#include +#include +#include + +#include "tc-api.h" + +struct rtnl_gact { + struct tc_gact g_parm; +}; + +static struct nla_policy gact_policy[TCA_GACT_MAX + 1] = { + [TCA_GACT_PARMS] = { .minlen = sizeof(struct tc_gact) }, +}; + +static int gact_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct rtnl_gact *u = data; + struct nlattr *tb[TCA_GACT_MAX + 1]; + int err; + + err = tca_parse(tb, TCA_GACT_MAX, tc, gact_policy); + if (err < 0) + return err; + + if (!tb[TCA_GACT_PARMS]) + return -NLE_MISSING_ATTR; + + nla_memcpy(&u->g_parm, tb[TCA_GACT_PARMS], sizeof(u->g_parm)); + + return 0; +} + +static void gact_free_data(struct rtnl_tc *tc, void *data) +{ +} + +static void gact_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_gact *u = data; + + if (!u) + return; + + switch(u->g_parm.action){ + case TC_ACT_UNSPEC: + nl_dump(p, " continue"); + break; + case TC_ACT_SHOT: + nl_dump(p, " drop"); + break; + case TC_ACT_RECLASSIFY: + nl_dump(p, " reclassify"); + break; + case TC_ACT_OK: + nl_dump(p, " pass"); + break; + } + +} + +static void gact_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ +} + +static void gact_dump_stats(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_gact *u = data; + + if (!u) + return; + /* TODO */ +} + + +static int gact_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + struct rtnl_gact *u = data; + + if (!u) + return 0; + + NLA_PUT(msg, TCA_GACT_PARMS, sizeof(u->g_parm), &u->g_parm); + + return 0; + +nla_put_failure: + return -NLE_NOMEM; +} + +/** + * @name Attribute Modifications + * @{ + */ + +int rtnl_gact_set_action(struct rtnl_act *act, int action) +{ + struct rtnl_gact *u; + + if (!(u = (struct rtnl_gact *) rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + + u->g_parm.action = action; + + return 0; +} + +int rtnl_gact_get_action(struct rtnl_act *act) +{ + struct rtnl_gact *u; + + if (!(u = (struct rtnl_gact *) rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + return u->g_parm.action; +} + + +/** @} */ + +static struct rtnl_tc_ops gact_ops = { + .to_kind = "gact", + .to_type = RTNL_TC_TYPE_ACT, + .to_size = sizeof(struct rtnl_gact), + .to_msg_parser = gact_msg_parser, + .to_free_data = gact_free_data, + .to_clone = NULL, + .to_msg_fill = gact_msg_fill, + .to_dump = { + [NL_DUMP_LINE] = gact_dump_line, + [NL_DUMP_DETAILS] = gact_dump_details, + [NL_DUMP_STATS] = gact_dump_stats, + }, +}; + +static void _nl_init gact_init(void) +{ + rtnl_tc_register(&gact_ops); +} + +static void _nl_exit gact_exit(void) +{ + rtnl_tc_unregister(&gact_ops); +} + +/** @} */ diff --git a/lib/route/act/mirred.c b/lib/route/act/mirred.c new file mode 100644 index 0000000..72ead6b --- /dev/null +++ b/lib/route/act/mirred.c @@ -0,0 +1,222 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Cong Wang + */ + +/** + * @ingroup act + * @defgroup act_mirred Mirror and Redirect + * + * @{ + */ + +#include "nl-default.h" + +#include +#include +#include +#include + +#include "tc-api.h" + +struct rtnl_mirred { + struct tc_mirred m_parm; +}; + +static struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = { + [TCA_MIRRED_PARMS] = { .minlen = sizeof(struct tc_mirred) }, +}; + +static int mirred_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct rtnl_mirred *u = data; + struct nlattr *tb[TCA_MIRRED_MAX + 1]; + int err; + + err = tca_parse(tb, TCA_MIRRED_MAX, tc, mirred_policy); + if (err < 0) + return err; + + if (!tb[TCA_MIRRED_PARMS]) + return -NLE_MISSING_ATTR; + + nla_memcpy(&u->m_parm, tb[TCA_MIRRED_PARMS], sizeof(u->m_parm)); + return 0; +} + +static void mirred_free_data(struct rtnl_tc *tc, void *data) +{ +} + +static void mirred_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_mirred *u = data; + if (!u) + return; + + nl_dump(p, " index %u", u->m_parm.ifindex); + + if (u->m_parm.eaction == TCA_EGRESS_MIRROR) + nl_dump(p, " egress mirror"); + else if (u->m_parm.eaction == TCA_EGRESS_REDIR) + nl_dump(p, " egress redirect"); + + switch(u->m_parm.action) { + case TC_ACT_UNSPEC: + nl_dump(p, " unspecified"); + break; + case TC_ACT_PIPE: + nl_dump(p, " pipe"); + break; + case TC_ACT_STOLEN: + nl_dump(p, " stolen"); + break; + case TC_ACT_SHOT: + nl_dump(p, " shot"); + break; + case TC_ACT_QUEUED: + nl_dump(p, " queued"); + break; + case TC_ACT_REPEAT: + nl_dump(p, " repeat"); + break; + } +} + +static void mirred_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ +} + +static void mirred_dump_stats(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_mirred *u = data; + + if (!u) + return; + /* TODO */ +} + + +static int mirred_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + struct rtnl_mirred *u = data; + + if (!u) + return 0; + + NLA_PUT(msg, TCA_MIRRED_PARMS, sizeof(u->m_parm), &u->m_parm); + return 0; + +nla_put_failure: + return -NLE_NOMEM; +} + +/** + * @name Attribute Modifications + * @{ + */ + +int rtnl_mirred_set_action(struct rtnl_act *act, int action) +{ + struct rtnl_mirred *u; + + if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + + if (action > TCA_INGRESS_MIRROR || action < TCA_EGRESS_REDIR) + return -NLE_INVAL; + + switch (action) { + case TCA_EGRESS_MIRROR: + case TCA_EGRESS_REDIR: + u->m_parm.eaction = action; + break; + case TCA_INGRESS_REDIR: + case TCA_INGRESS_MIRROR: + default: + return NLE_OPNOTSUPP; + } + return 0; +} + +int rtnl_mirred_get_action(struct rtnl_act *act) +{ + struct rtnl_mirred *u; + + if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + return u->m_parm.eaction; +} + +int rtnl_mirred_set_ifindex(struct rtnl_act *act, uint32_t ifindex) +{ + struct rtnl_mirred *u; + + if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + + u->m_parm.ifindex = ifindex; + return 0; +} + +uint32_t rtnl_mirred_get_ifindex(struct rtnl_act *act) +{ + struct rtnl_mirred *u; + + if ((u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act)))) + return u->m_parm.ifindex; + return 0; +} + +int rtnl_mirred_set_policy(struct rtnl_act *act, int policy) +{ + struct rtnl_mirred *u; + + if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + + u->m_parm.action = policy; + + return 0; +} + +int rtnl_mirred_get_policy(struct rtnl_act *act) +{ + struct rtnl_mirred *u; + + if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + return u->m_parm.action; +} + +/** @} */ + +static struct rtnl_tc_ops mirred_ops = { + .to_kind = "mirred", + .to_type = RTNL_TC_TYPE_ACT, + .to_size = sizeof(struct rtnl_mirred), + .to_msg_parser = mirred_msg_parser, + .to_free_data = mirred_free_data, + .to_clone = NULL, + .to_msg_fill = mirred_msg_fill, + .to_dump = { + [NL_DUMP_LINE] = mirred_dump_line, + [NL_DUMP_DETAILS] = mirred_dump_details, + [NL_DUMP_STATS] = mirred_dump_stats, + }, +}; + +static void _nl_init mirred_init(void) +{ + rtnl_tc_register(&mirred_ops); +} + +static void _nl_exit mirred_exit(void) +{ + rtnl_tc_unregister(&mirred_ops); +} + +/** @} */ diff --git a/lib/route/act/nat.c b/lib/route/act/nat.c new file mode 100644 index 0000000..ffc9d2b --- /dev/null +++ b/lib/route/act/nat.c @@ -0,0 +1,289 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2016 Magnus Öberg + */ + +/** + * @ingroup act + * @defgroup act_nat NAT + * + * @{ + */ + +#include "nl-default.h" + +#include +#include +#include +#include +#include + +#include "tc-api.h" + +static struct nla_policy nat_policy[TCA_NAT_MAX + 1] = { + [TCA_NAT_PARMS] = { .minlen = sizeof(struct tc_nat) }, +}; + +/** + * nat operations + */ + +static int nat_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct tc_nat *nat = data; + struct nlattr *tb[TCA_NAT_MAX + 1]; + int err; + + err = tca_parse(tb, TCA_NAT_MAX, tc, nat_policy); + if (err < 0) + return err; + + if (!tb[TCA_NAT_PARMS]) + return -NLE_MISSING_ATTR; + + nla_memcpy(nat, tb[TCA_NAT_PARMS], sizeof(*nat)); + + return NLE_SUCCESS; +} + +static void nat_free_data(struct rtnl_tc *tc, void *data) +{ +} + +static int nat_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + struct tc_nat *nat = data; + + if (!nat) + return -NLE_OBJ_NOTFOUND; + + NLA_PUT(msg, TCA_NAT_PARMS, sizeof(*nat), nat); + + return NLE_SUCCESS; + +nla_put_failure: + return -NLE_NOMEM; +} + +static void nat_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct tc_nat *nat = data; + char buf[32]; + uint32_t mask; + int pfx = 0; + + if (!nat) + return; + + if (nat->flags & TCA_NAT_FLAG_EGRESS) + nl_dump(p, " egress"); + else + nl_dump(p, " ingress"); + + mask = nat->mask; + while (mask > 0) { + mask = mask >> 1; + pfx++; + } + + inet_ntop(AF_INET, &nat->old_addr, buf, sizeof(buf)); + nl_dump(p, " %s", buf); + if (pfx < 32) + nl_dump(p, "/%d", pfx); + + inet_ntop(AF_INET, &nat->new_addr, buf, sizeof(buf)); + nl_dump(p, " %s", buf); + if (pfx < 32) + nl_dump(p, "/%d", pfx); +} + +/** + * @name Attribute Modifications + * @{ + */ + +/** + * Set old IPv4 address on a netlink NAT action object + * @arg act Action object + * @arg addr Binary IPv4 address in host byte order + * + * @return 0 on success or negative error code in case of an error. + */ +int rtnl_nat_set_old_addr(struct rtnl_act *act, in_addr_t addr) +{ + struct tc_nat *nat; + + if (!(nat = (struct tc_nat *)rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + + nat->old_addr = addr; + + return NLE_SUCCESS; +} + +int rtnl_nat_get_old_addr(struct rtnl_act *act, in_addr_t *addr) +{ + struct tc_nat *nat; + + if (!(nat = (struct tc_nat *)rtnl_tc_data_peek(TC_CAST(act)))) + return -NLE_NOATTR; + + *addr = nat->old_addr; + + return NLE_SUCCESS; +} + +/** + * Set new IPv4 address on a netlink NAT action object + * @arg act Action object + * @arg addr Binary IPv4 address in host byte order + * + * @return 0 on success or negative error code in case of an error. + */ +int rtnl_nat_set_new_addr(struct rtnl_act *act, in_addr_t addr) +{ + struct tc_nat *nat; + + if (!(nat = (struct tc_nat *)rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + + nat->new_addr = addr; + + return NLE_SUCCESS; +} + +int rtnl_nat_get_new_addr(struct rtnl_act *act, in_addr_t *addr) +{ + struct tc_nat *nat; + + if (!(nat = (struct tc_nat *)rtnl_tc_data_peek(TC_CAST(act)))) + return -NLE_NOATTR; + + *addr = nat->new_addr; + + return NLE_SUCCESS; +} + +/** + * Set IPv4 address mask on a netlink NAT action object + * @arg act Action object + * @arg mask IPv4 address mask + * + * @return 0 on success or negative error code in case of an error. + */ +int rtnl_nat_set_mask(struct rtnl_act *act, in_addr_t bitmask) +{ + struct tc_nat *nat; + + if (!(nat = (struct tc_nat *)rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + + nat->mask = bitmask; + + return NLE_SUCCESS; +} + +int rtnl_nat_get_mask(struct rtnl_act *act, in_addr_t *bitmask) +{ + struct tc_nat *nat; + + if (!(nat = (struct tc_nat *)rtnl_tc_data_peek(TC_CAST(act)))) + return -NLE_NOATTR; + + *bitmask = nat->mask; + + return NLE_SUCCESS; +} + +/** + * Set flags for a netlink NAT action object + * @arg act Action object + * @arg flags TCA_NAT_FLAG_* flags. + * + * Currently only TCA_NAT_FLAG_EGRESS is defined. Selects NAT on + * egress/IP src if set, ingress/IP dst otherwise. + * + * @return 0 on success or negative error code in case of an error. + */ +int rtnl_nat_set_flags(struct rtnl_act *act, uint32_t flags) +{ + struct tc_nat *nat; + + if (!(nat = (struct tc_nat *)rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + + nat->flags = flags; + + return NLE_SUCCESS; +} + +int rtnl_nat_get_flags(struct rtnl_act *act, uint32_t *flags) +{ + struct tc_nat *nat; + + if (!(nat = (struct tc_nat *)rtnl_tc_data_peek(TC_CAST(act)))) + return -NLE_NOATTR; + + *flags = nat->flags; + + return NLE_SUCCESS; +} + +int rtnl_nat_set_action(struct rtnl_act *act, int action) +{ + struct tc_nat *nat; + + if (!(nat = (struct tc_nat *)rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + + if (action < TC_ACT_UNSPEC) + return -NLE_INVAL; + + nat->action = action; + + return NLE_SUCCESS; +} + +int rtnl_nat_get_action(struct rtnl_act *act, int *action) +{ + struct tc_nat *nat; + + if (!(nat = (struct tc_nat *)rtnl_tc_data_peek(TC_CAST(act)))) + return -NLE_NOATTR; + + *action = nat->action; + + return NLE_SUCCESS; +} + +/** + * @} + */ + +static struct rtnl_tc_ops nat_ops = { + .to_kind = "nat", + .to_type = RTNL_TC_TYPE_ACT, + .to_size = sizeof(struct tc_nat), + .to_msg_parser = nat_msg_parser, + .to_free_data = nat_free_data, + .to_clone = NULL, + .to_msg_fill = nat_msg_fill, + .to_dump = { + [NL_DUMP_LINE] = nat_dump_line, + }, +}; + +static void _nl_init nat_init(void) +{ + rtnl_tc_register(&nat_ops); +} + +static void _nl_exit nat_exit(void) +{ + rtnl_tc_unregister(&nat_ops); +} + +/** + * @} + */ diff --git a/lib/route/act/skbedit.c b/lib/route/act/skbedit.c new file mode 100644 index 0000000..32a3506 --- /dev/null +++ b/lib/route/act/skbedit.c @@ -0,0 +1,284 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2015 Cong Wang + */ + +/** + * @ingroup act + * @defgroup act_skbedit SKB Editing + * + * @{ + */ + +#include "nl-default.h" + +#include +#include +#include +#include + +#include "nl-route.h" +#include "tc-api.h" + +struct rtnl_skbedit { + struct tc_skbedit s_parm; + uint32_t s_flags; + uint32_t s_mark; + uint32_t s_prio; + uint16_t s_queue_mapping; +}; + +static struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = { + [TCA_SKBEDIT_PARMS] = { .minlen = sizeof(struct tc_skbedit) }, + [TCA_SKBEDIT_PRIORITY] = { .type = NLA_U32 }, + [TCA_SKBEDIT_QUEUE_MAPPING] = { .type = NLA_U16 }, + [TCA_SKBEDIT_MARK] = { .type = NLA_U32 }, +}; + +static int skbedit_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct rtnl_skbedit *u = data; + struct nlattr *tb[TCA_SKBEDIT_MAX + 1]; + int err; + + err = tca_parse(tb, TCA_SKBEDIT_MAX, tc, skbedit_policy); + if (err < 0) + return err; + + if (!tb[TCA_SKBEDIT_PARMS]) + return -NLE_MISSING_ATTR; + + u->s_flags = 0; + if (tb[TCA_SKBEDIT_PRIORITY] != NULL) { + u->s_flags |= SKBEDIT_F_PRIORITY; + u->s_prio = nla_get_u32(tb[TCA_SKBEDIT_PRIORITY]); + } + + if (tb[TCA_SKBEDIT_QUEUE_MAPPING] != NULL) { + u->s_flags |= SKBEDIT_F_QUEUE_MAPPING; + u->s_queue_mapping = nla_get_u16(tb[TCA_SKBEDIT_QUEUE_MAPPING]); + } + + if (tb[TCA_SKBEDIT_MARK] != NULL) { + u->s_flags |= SKBEDIT_F_MARK; + u->s_mark = nla_get_u32(tb[TCA_SKBEDIT_MARK]); + } + + return 0; +} + +static void skbedit_free_data(struct rtnl_tc *tc, void *data) +{ +} + +static void skbedit_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_skbedit *u = data; + + if (!u) + return; + + if (u->s_flags & SKBEDIT_F_PRIORITY) + nl_dump(p, " priority %u", u->s_prio); + + if (u->s_flags & SKBEDIT_F_MARK) + nl_dump(p, " mark %u", u->s_mark); + + if (u->s_flags & SKBEDIT_F_QUEUE_MAPPING) + nl_dump(p, " queue_mapping %u", u->s_queue_mapping); + + switch(u->s_parm.action){ + case TC_ACT_UNSPEC: + nl_dump(p, " unspecified"); + break; + case TC_ACT_PIPE: + nl_dump(p, " pipe"); + break; + case TC_ACT_STOLEN: + nl_dump(p, " stolen"); + break; + case TC_ACT_SHOT: + nl_dump(p, " shot"); + break; + case TC_ACT_QUEUED: + nl_dump(p, " queued"); + break; + case TC_ACT_REPEAT: + nl_dump(p, " repeat"); + break; + } +} + +static void skbedit_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ +} + +static void skbedit_dump_stats(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_skbedit *u = data; + + if (!u) + return; + /* TODO */ +} + + +static int skbedit_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + struct rtnl_skbedit *u = data; + + if (!u) + return 0; + + NLA_PUT(msg, TCA_SKBEDIT_PARMS, sizeof(u->s_parm), &u->s_parm); + + if (u->s_flags & SKBEDIT_F_MARK) + NLA_PUT_U32(msg, TCA_SKBEDIT_MARK, u->s_mark); + + if (u->s_flags & SKBEDIT_F_PRIORITY) + NLA_PUT_U32(msg, TCA_SKBEDIT_PRIORITY, u->s_prio); + + if (u->s_flags & SKBEDIT_F_QUEUE_MAPPING) + NLA_PUT_U32(msg, TCA_SKBEDIT_QUEUE_MAPPING, u->s_queue_mapping); + + return 0; + +nla_put_failure: + return -NLE_NOMEM; +} + +/** + * @name Attribute Modifications + * @{ + */ + +int rtnl_skbedit_set_action(struct rtnl_act *act, int action) +{ + struct rtnl_skbedit *u; + + if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + + u->s_parm.action = action; + + return 0; +} + +int rtnl_skbedit_get_action(struct rtnl_act *act) +{ + struct rtnl_skbedit *u; + + if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + return u->s_parm.action; +} + +int rtnl_skbedit_set_queue_mapping(struct rtnl_act *act, uint16_t index) +{ + struct rtnl_skbedit *u; + + if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + + u->s_queue_mapping = index; + u->s_flags |= SKBEDIT_F_QUEUE_MAPPING; + return 0; +} + +int rtnl_skbedit_get_queue_mapping(struct rtnl_act *act, uint16_t *index) +{ + struct rtnl_skbedit *u; + + u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act)); + if (!u) + return -NLE_NOMEM; + if (!(u->s_flags & SKBEDIT_F_QUEUE_MAPPING)) + return -NLE_NOATTR; + + *index = u->s_queue_mapping; + return 0; +} + +int rtnl_skbedit_set_mark(struct rtnl_act *act, uint32_t mark) +{ + struct rtnl_skbedit *u; + + if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + + u->s_mark = mark; + u->s_flags |= SKBEDIT_F_MARK; + return 0; +} + +int rtnl_skbedit_get_mark(struct rtnl_act *act, uint32_t *mark) +{ + struct rtnl_skbedit *u; + + u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act)); + if (!u) + return -NLE_NOMEM; + if (!(u->s_flags & SKBEDIT_F_MARK)) + return -NLE_NOATTR; + + *mark = u->s_mark; + return 0; +} + +int rtnl_skbedit_set_priority(struct rtnl_act *act, uint32_t prio) +{ + struct rtnl_skbedit *u; + + if (!(u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + + u->s_prio = prio; + u->s_flags |= SKBEDIT_F_PRIORITY; + return 0; +} + +int rtnl_skbedit_get_priority(struct rtnl_act *act, uint32_t *prio) +{ + struct rtnl_skbedit *u; + + u = (struct rtnl_skbedit *) rtnl_tc_data(TC_CAST(act)); + if (!u) + return -NLE_NOMEM; + if (!(u->s_flags & SKBEDIT_F_PRIORITY)) + return -NLE_NOATTR; + + *prio = u->s_prio; + return 0; +} + +/** @} */ + +static struct rtnl_tc_ops skbedit_ops = { + .to_kind = "skbedit", + .to_type = RTNL_TC_TYPE_ACT, + .to_size = sizeof(struct rtnl_skbedit), + .to_msg_parser = skbedit_msg_parser, + .to_free_data = skbedit_free_data, + .to_clone = NULL, + .to_msg_fill = skbedit_msg_fill, + .to_dump = { + [NL_DUMP_LINE] = skbedit_dump_line, + [NL_DUMP_DETAILS] = skbedit_dump_details, + [NL_DUMP_STATS] = skbedit_dump_stats, + }, +}; + +static void _nl_init skbedit_init(void) +{ + rtnl_tc_register(&skbedit_ops); +} + +static void _nl_exit skbedit_exit(void) +{ + rtnl_tc_unregister(&skbedit_ops); +} + +/** @} */ diff --git a/lib/route/act/vlan.c b/lib/route/act/vlan.c new file mode 100644 index 0000000..71f16e5 --- /dev/null +++ b/lib/route/act/vlan.c @@ -0,0 +1,423 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2018 Volodymyr Bendiuga + */ + +/** + * @ingroup act + * @defgroup act_vlan VLAN Manipulation + * + * @{ + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include + +#include "tc-api.h" + +struct rtnl_vlan +{ + struct tc_vlan v_parm; + uint16_t v_vid; + uint16_t v_proto; + uint8_t v_prio; + uint32_t v_flags; +}; + +#define VLAN_F_VID (1 << 0) +#define VLAN_F_PROTO (1 << 1) +#define VLAN_F_PRIO (1 << 2) +#define VLAN_F_ACT (1 << 3) +#define VLAN_F_MODE (1 << 4) + +static struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = { + [TCA_VLAN_PARMS] = { .minlen = sizeof(struct tc_vlan) }, + [TCA_VLAN_PUSH_VLAN_ID] = { .type = NLA_U16 }, + [TCA_VLAN_PUSH_VLAN_PROTOCOL] = { .type = NLA_U16 }, + [TCA_VLAN_PUSH_VLAN_PRIORITY] = { .type = NLA_U8 }, +}; + +static int vlan_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct rtnl_vlan *v = data; + struct nlattr *tb[TCA_VLAN_MAX + 1]; + int err; + + err = tca_parse(tb, TCA_VLAN_MAX, tc, vlan_policy); + if (err < 0) + return err; + + v->v_flags = 0; + if (!tb[TCA_VLAN_PARMS]) + return -NLE_MISSING_ATTR; + else { + nla_memcpy(&v->v_parm, tb[TCA_VLAN_PARMS], sizeof(v->v_parm)); + v->v_flags |= VLAN_F_ACT; + v->v_flags |= VLAN_F_MODE; + } + + if (tb[TCA_VLAN_PUSH_VLAN_ID]) { + v->v_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]); + v->v_flags |= VLAN_F_VID; + } + + if (tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]) { + v->v_proto = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]); + v->v_flags |= VLAN_F_PROTO; + } + + if (tb[TCA_VLAN_PUSH_VLAN_PRIORITY]) { + v->v_prio = nla_get_u8(tb[TCA_VLAN_PUSH_VLAN_PRIORITY]); + v->v_flags |= VLAN_F_PRIO; + } + + return 0; +} + +static int vlan_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + struct rtnl_vlan *v = data; + + if (!v) + return 0; + if (!(v->v_flags & VLAN_F_MODE)) + return -NLE_MISSING_ATTR; + + NLA_PUT(msg, TCA_VLAN_PARMS, sizeof(v->v_parm), &v->v_parm); + + /* vid is required for PUSH & MODIFY modes */ + if ((v->v_parm.v_action != TCA_VLAN_ACT_POP) && !(v->v_flags & VLAN_F_VID)) + return -NLE_MISSING_ATTR; + + if (v->v_flags & VLAN_F_VID) + NLA_PUT_U16(msg, TCA_VLAN_PUSH_VLAN_ID, v->v_vid); + + if (v->v_flags & VLAN_F_PROTO) + NLA_PUT_U16(msg, TCA_VLAN_PUSH_VLAN_PROTOCOL, v->v_proto); + + if (v->v_flags & VLAN_F_PRIO) + NLA_PUT_U8(msg, TCA_VLAN_PUSH_VLAN_PRIORITY, v->v_prio); + + return 0; + +nla_put_failure: + return -NLE_NOMEM; +} + +static void vlan_free_data(struct rtnl_tc *tc, void *data) +{ +} + +static void vlan_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_vlan *v = data; + + if (!v) + return; + + if (!(v->v_flags & VLAN_F_ACT)) + return; + + if (TC_ACT_EXT_CMP(v->v_parm.action, TC_ACT_GOTO_CHAIN)) + nl_dump(p, " goto chain %u", v->v_parm.action & TC_ACT_EXT_VAL_MASK); + + if (TC_ACT_EXT_CMP(v->v_parm.action, TC_ACT_JUMP)) + nl_dump(p, " jump %u", v->v_parm.action & TC_ACT_EXT_VAL_MASK); + + switch(v->v_parm.action){ + case TC_ACT_UNSPEC: + nl_dump(p, " unspecified"); + break; + case TC_ACT_PIPE: + nl_dump(p, " pipe"); + break; + case TC_ACT_STOLEN: + nl_dump(p, " stolen"); + break; + case TC_ACT_SHOT: + nl_dump(p, " shot"); + break; + case TC_ACT_QUEUED: + nl_dump(p, " queued"); + break; + case TC_ACT_REPEAT: + nl_dump(p, " repeat"); + break; + } +} + +static void vlan_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_vlan *v = data; + + if (!v) + return; + + if (v->v_flags & VLAN_F_MODE) { + switch (v->v_parm.v_action) { + case TCA_VLAN_ACT_POP: + nl_dump(p, " mode POP"); + break; + case TCA_VLAN_ACT_PUSH: + nl_dump(p, " mode PUSH"); + break; + case TCA_VLAN_ACT_MODIFY: + nl_dump(p, " mode MODIFY"); + break; + } + } + + if (v->v_flags & VLAN_F_VID) + nl_dump(p, " vlan id %u", v->v_vid); + + if (v->v_flags & VLAN_F_PRIO) + nl_dump(p, " priority %u", v->v_prio); + + if (v->v_flags & VLAN_F_PROTO) + nl_dump(p, " protocol %u", v->v_proto); +} + +/** + * @name Attribute Modifications + * @{ + */ + +/** + * Set vlan mode + * @arg act vlan action + * @arg mode one of (TCA_VLAN_ACT_*: POP, PUSH, MODIFY) + * @return 0 on success or a negative error code. + */ +int rtnl_vlan_set_mode(struct rtnl_act *act, int mode) +{ + struct rtnl_vlan *v; + + if (!(v = (struct rtnl_vlan *) rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + + if (mode > TCA_VLAN_ACT_MODIFY) + return -NLE_RANGE; + + v->v_parm.v_action = mode; + v->v_flags |= VLAN_F_MODE; + + return 0; +} + +/** + * Get vlan mode + * @arg act vlan action + * @arg out_mode vlan mode output paramter + * @return 0 on success if the vlan mode was returned or a negative error code. +*/ +int rtnl_vlan_get_mode(struct rtnl_act *act, int *out_mode) +{ + struct rtnl_vlan *v; + + if (!(v = (struct rtnl_vlan *) rtnl_tc_data_peek(TC_CAST(act)))) + return -NLE_INVAL; + + if (!(v->v_flags & VLAN_F_MODE)) + return -NLE_MISSING_ATTR; + + *out_mode = v->v_parm.v_action; + return 0; +} + +/** + * Set general action + * @arg act vlan action + * @arg action one of (TCA_ACT_*: PIPE, SHOT, GOTO_CHAIN, etc) + * @return 0 on success or a negative error code. + */ +int rtnl_vlan_set_action(struct rtnl_act *act, int action) +{ + struct rtnl_vlan *v; + + if (!(v = (struct rtnl_vlan *) rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + + v->v_parm.action = action; + v->v_flags |= VLAN_F_ACT; + + return 0; +} + +/** + * Get general action + * @arg act vlan action + * @arg out_action output parameter + * @return general 0 if out_action was set or a negative error code. +*/ +int rtnl_vlan_get_action(struct rtnl_act *act, int *out_action) +{ + struct rtnl_vlan *v; + + if (!(v = (struct rtnl_vlan *) rtnl_tc_data_peek(TC_CAST(act)))) + return -NLE_INVAL; + + if (!(v->v_flags & VLAN_F_ACT)) + return -NLE_MISSING_ATTR; + + *out_action = v->v_parm.action; + return 0; +} + +/** + * Set protocol + * @arg act vlan action + * @arg protocol one of (ETH_P_8021Q || ETH_P_8021AD) + * @return 0 on success or a negative error code. + */ +int rtnl_vlan_set_protocol(struct rtnl_act *act, uint16_t protocol) +{ + struct rtnl_vlan *v; + + if (!(v = (struct rtnl_vlan *) rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + + v->v_proto = protocol; + v->v_flags |= VLAN_F_PROTO; + + return 0; +} + +/** + * Get protocol + * @arg act vlan action + * @arg out_protocol protocol output argument + * @return 0 if the protocol was returned or a negative error code. +*/ +int rtnl_vlan_get_protocol(struct rtnl_act *act, uint16_t *out_protocol) +{ + struct rtnl_vlan *v; + + if (!(v = (struct rtnl_vlan *) rtnl_tc_data_peek(TC_CAST(act)))) + return -NLE_INVAL; + + if (!(v->v_flags & VLAN_F_PROTO)) + return -NLE_MISSING_ATTR; + + *out_protocol = v->v_proto; + return 0; +} + +/** + * Set vlan id + * @arg act vlan action + * @arg vid vlan id + * @return 0 on success or a negative error code. + */ +int rtnl_vlan_set_vlan_id(struct rtnl_act *act, uint16_t vid) +{ + struct rtnl_vlan *v; + + if (!(v = (struct rtnl_vlan *) rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + + if (vid > 4095) + return -NLE_RANGE; + + v->v_vid = vid; + v->v_flags |= VLAN_F_VID; + + return 0; +} + +/** + * Get vlan id + * @arg act vlan action + * @arg out_vid output vlan id + * @return 0 if the vlan id was returned or a negative error code. +*/ +int rtnl_vlan_get_vlan_id(struct rtnl_act *act, uint16_t *out_vid) +{ + struct rtnl_vlan *v; + + if (!(v = (struct rtnl_vlan *) rtnl_tc_data_peek(TC_CAST(act)))) + return -NLE_INVAL; + + if (!(v->v_flags & VLAN_F_VID)) + return -NLE_MISSING_ATTR; + + *out_vid = v->v_vid; + return 0; +} + +/** + * Set vlan prio + * @arg act vlan action + * @arg prio vlan priority (0 - 7) + * @return 0 on success or a negative error code. + */ +int rtnl_vlan_set_vlan_prio(struct rtnl_act *act, uint8_t prio) +{ + struct rtnl_vlan *v; + + if (!(v = (struct rtnl_vlan *) rtnl_tc_data(TC_CAST(act)))) + return -NLE_NOMEM; + + if (prio > 7) + return -NLE_RANGE; + + v->v_prio = prio; + v->v_flags |= VLAN_F_PRIO; + + return 0; +} + +/** + * Get vlan prio + * @arg act vlan action + * @arg out_prio the output vlan prio + * @return 0 if the vlan prio was returned or a negative error code. +*/ +int rtnl_vlan_get_vlan_prio(struct rtnl_act *act, uint8_t *out_prio) +{ + struct rtnl_vlan *v; + + if (!(v = (struct rtnl_vlan *) rtnl_tc_data_peek(TC_CAST(act)))) + return -NLE_INVAL; + + if (!(v->v_flags & VLAN_F_PRIO)) + return -NLE_MISSING_ATTR; + + *out_prio = v->v_prio; + return 0; +} + +/** @} */ + +static struct rtnl_tc_ops vlan_ops = { + .to_kind = "vlan", + .to_type = RTNL_TC_TYPE_ACT, + .to_size = sizeof(struct rtnl_vlan), + .to_msg_parser = vlan_msg_parser, + .to_free_data = vlan_free_data, + .to_clone = NULL, + .to_msg_fill = vlan_msg_fill, + .to_dump = { + [NL_DUMP_LINE] = vlan_dump_line, + [NL_DUMP_DETAILS] = vlan_dump_details, + }, +}; + +static void _nl_init vlan_init(void) +{ + rtnl_tc_register(&vlan_ops); +} + +static void _nl_exit vlan_exit(void) +{ + rtnl_tc_unregister(&vlan_ops); +} + +/** @} */ diff --git a/lib/route/addr.c b/lib/route/addr.c index 71fca94..1f72c53 100644 --- a/lib/route/addr.c +++ b/lib/route/addr.c @@ -1,14 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/addr.c Addresses - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf - * Copyright (c) 2003-2006 Baruch Even , - * Mediatrix Telecom, inc. + * Copyright (c) 2003-2006 Baruch Even + * Copyright (c) 2003-2006 Mediatrix Telecom, inc. */ /** @@ -106,7 +100,8 @@ * @{ */ -#include +#include "nl-default.h" + #include #include #include @@ -114,7 +109,47 @@ #include #include +#include "nl-route.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" + /** @cond SKIP */ +struct rtnl_addr_cacheinfo { + /* Preferred lifetime in seconds, ticking from when the message gets constructed */ + uint32_t aci_prefered; + + /* Valid lifetime in seconds, ticking from when the message gets constructed */ + uint32_t aci_valid; + + /* Timestamp of creation in 1/100s since boottime, clock_gettime(CLOCK_MONOTONIC) */ + uint32_t aci_cstamp; + + /* Timestamp of last update in 1/100s since boottime, clock_gettime(CLOCK_MONOTONIC) */ + uint32_t aci_tstamp; +}; + +struct rtnl_addr { + NLHDR_COMMON + + uint8_t a_family; + uint8_t a_prefixlen; + uint8_t a_scope; + uint32_t a_flags; + uint32_t a_ifindex; + + struct nl_addr *a_peer; + struct nl_addr *a_local; + struct nl_addr *a_bcast; + struct nl_addr *a_anycast; + struct nl_addr *a_multicast; + + struct rtnl_addr_cacheinfo a_cacheinfo; + + char a_label[IFNAMSIZ]; + uint32_t a_flag_mask; + struct rtnl_link *a_link; +}; + #define ADDR_ATTR_FAMILY 0x0001 #define ADDR_ATTR_PREFIXLEN 0x0002 #define ADDR_ATTR_FLAGS 0x0004 @@ -159,6 +194,13 @@ static int addr_clone(struct nl_object *_dst, struct nl_object *_src) struct rtnl_addr *dst = nl_object_priv(_dst); struct rtnl_addr *src = nl_object_priv(_src); + dst->a_peer = NULL; + dst->a_local = NULL; + dst->a_bcast = NULL; + dst->a_anycast = NULL; + dst->a_multicast = NULL; + dst->a_link = NULL; + if (src->a_link) { nl_object_get(OBJ_CAST(src->a_link)); dst->a_link = src->a_link; @@ -167,7 +209,7 @@ static int addr_clone(struct nl_object *_dst, struct nl_object *_src) if (src->a_peer) if (!(dst->a_peer = nl_addr_clone(src->a_peer))) return -NLE_NOMEM; - + if (src->a_local) if (!(dst->a_local = nl_addr_clone(src->a_local))) return -NLE_NOMEM; @@ -216,8 +258,9 @@ static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, ifa = nlmsg_data(nlh); addr->a_family = family = ifa->ifa_family; addr->a_prefixlen = ifa->ifa_prefixlen; - addr->a_flags = ifa->ifa_flags; addr->a_scope = ifa->ifa_scope; + addr->a_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) : + ifa->ifa_flags; addr->a_ifindex = ifa->ifa_index; addr->ce_mask = (ADDR_ATTR_FAMILY | ADDR_ATTR_PREFIXLEN | @@ -240,34 +283,69 @@ static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, addr->ce_mask |= ADDR_ATTR_CACHEINFO; } - if (tb[IFA_LOCAL]) { - addr->a_local = nl_addr_alloc_attr(tb[IFA_LOCAL], family); + if (family == AF_INET) { + uint32_t null = 0; + + /* for IPv4/AF_INET, kernel always sets IFA_LOCAL and IFA_ADDRESS, unless it + * is effectively 0.0.0.0. */ + if (tb[IFA_LOCAL]) + addr->a_local = nl_addr_alloc_attr(tb[IFA_LOCAL], family); + else + addr->a_local = nl_addr_build(family, &null, sizeof (null)); if (!addr->a_local) goto errout_nomem; addr->ce_mask |= ADDR_ATTR_LOCAL; - plen_addr = addr->a_local; - } - - if (tb[IFA_ADDRESS]) { - struct nl_addr *a; - a = nl_addr_alloc_attr(tb[IFA_ADDRESS], family); - if (!a) + if (tb[IFA_ADDRESS]) + addr->a_peer = nl_addr_alloc_attr(tb[IFA_ADDRESS], family); + else + addr->a_peer = nl_addr_build(family, &null, sizeof (null)); + if (!addr->a_peer) goto errout_nomem; - /* IPv6 sends the local address as IFA_ADDRESS with - * no IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS - * with IFA_ADDRESS being the peer address if they differ */ - if (!tb[IFA_LOCAL] || !nl_addr_cmp(a, addr->a_local)) { - nl_addr_put(addr->a_local); - addr->a_local = a; - addr->ce_mask |= ADDR_ATTR_LOCAL; - } else { - addr->a_peer = a; + if (!nl_addr_cmp (addr->a_local, addr->a_peer)) { + /* having IFA_ADDRESS equal to IFA_LOCAL does not really mean + * there is no peer. It means the peer is equal to the local address, + * which is the case for "normal" addresses. + * + * Still, clear the peer and pretend it is unset for backward + * compatibility. */ + nl_addr_put(addr->a_peer); + addr->a_peer = NULL; + } else addr->ce_mask |= ADDR_ATTR_PEER; + + plen_addr = addr->a_local; + } else { + if (tb[IFA_LOCAL]) { + addr->a_local = nl_addr_alloc_attr(tb[IFA_LOCAL], family); + if (!addr->a_local) + goto errout_nomem; + addr->ce_mask |= ADDR_ATTR_LOCAL; + plen_addr = addr->a_local; } - plen_addr = a; + if (tb[IFA_ADDRESS]) { + struct nl_addr *a; + + a = nl_addr_alloc_attr(tb[IFA_ADDRESS], family); + if (!a) + goto errout_nomem; + + /* IPv6 sends the local address as IFA_ADDRESS with + * no IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS + * with IFA_ADDRESS being the peer address if they differ */ + if (!tb[IFA_LOCAL] || !nl_addr_cmp(a, addr->a_local)) { + nl_addr_put(addr->a_local); + addr->a_local = a; + addr->ce_mask |= ADDR_ATTR_LOCAL; + } else { + addr->a_peer = a; + addr->ce_mask |= ADDR_ATTR_PEER; + } + + plen_addr = a; + } } if (plen_addr) @@ -428,49 +506,84 @@ static void addr_dump_stats(struct nl_object *obj, struct nl_dump_params *p) addr_dump_details(obj, p); } -static int addr_compare(struct nl_object *_a, struct nl_object *_b, - uint32_t attrs, int flags) +static uint32_t addr_id_attrs_get(struct nl_object *obj) +{ + struct rtnl_addr *addr = (struct rtnl_addr *)obj; + uint32_t rv; + + switch (addr->a_family) { + case AF_INET: + rv = (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX | + ADDR_ATTR_LOCAL | ADDR_ATTR_PREFIXLEN); + if (addr->a_peer) + rv |= ADDR_ATTR_PEER; + return rv; + case AF_INET6: + return (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX | + ADDR_ATTR_LOCAL); + default: + return (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX | + ADDR_ATTR_LOCAL | ADDR_ATTR_PREFIXLEN); + } +} + +static uint64_t addr_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) { struct rtnl_addr *a = (struct rtnl_addr *) _a; struct rtnl_addr *b = (struct rtnl_addr *) _b; - int diff = 0; - -#define ADDR_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ADDR_ATTR_##ATTR, a, b, EXPR) - - diff |= ADDR_DIFF(IFINDEX, a->a_ifindex != b->a_ifindex); - diff |= ADDR_DIFF(FAMILY, a->a_family != b->a_family); - diff |= ADDR_DIFF(SCOPE, a->a_scope != b->a_scope); - diff |= ADDR_DIFF(LABEL, strcmp(a->a_label, b->a_label)); - diff |= ADDR_DIFF(PEER, nl_addr_cmp(a->a_peer, b->a_peer)); - diff |= ADDR_DIFF(LOCAL, nl_addr_cmp(a->a_local, b->a_local)); - diff |= ADDR_DIFF(MULTICAST, nl_addr_cmp(a->a_multicast, - b->a_multicast)); - diff |= ADDR_DIFF(BROADCAST, nl_addr_cmp(a->a_bcast, b->a_bcast)); - diff |= ADDR_DIFF(ANYCAST, nl_addr_cmp(a->a_anycast, b->a_anycast)); + uint64_t diff = 0; + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(ADDR_ATTR_IFINDEX, a->a_ifindex != b->a_ifindex); + diff |= _DIFF(ADDR_ATTR_FAMILY, a->a_family != b->a_family); + diff |= _DIFF(ADDR_ATTR_SCOPE, a->a_scope != b->a_scope); + diff |= _DIFF(ADDR_ATTR_LABEL, strcmp(a->a_label, b->a_label)); + if (attrs & ADDR_ATTR_PEER) { + if ((flags & ID_COMPARISON) && a->a_family == AF_INET && + b->a_family == AF_INET && a->a_peer && b->a_peer && + a->a_prefixlen == b->a_prefixlen) { + /* when comparing two IPv4 addresses for id-equality, the network part + * of the PEER address shall be compared. + */ + diff |= _DIFF(ADDR_ATTR_PEER, + nl_addr_cmp_prefix(a->a_peer, b->a_peer)); + } else + diff |= _DIFF(ADDR_ATTR_PEER, + nl_addr_cmp(a->a_peer, b->a_peer)); + } + diff |= _DIFF(ADDR_ATTR_LOCAL, nl_addr_cmp(a->a_local, b->a_local)); + diff |= _DIFF(ADDR_ATTR_MULTICAST, + nl_addr_cmp(a->a_multicast, b->a_multicast)); + diff |= _DIFF(ADDR_ATTR_BROADCAST, nl_addr_cmp(a->a_bcast, b->a_bcast)); + diff |= _DIFF(ADDR_ATTR_ANYCAST, + nl_addr_cmp(a->a_anycast, b->a_anycast)); + diff |= _DIFF(ADDR_ATTR_CACHEINFO, + memcmp(&a->a_cacheinfo, &b->a_cacheinfo, + sizeof(a->a_cacheinfo))); if (flags & LOOSE_COMPARISON) - diff |= ADDR_DIFF(FLAGS, - (a->a_flags ^ b->a_flags) & b->a_flag_mask); + diff |= _DIFF(ADDR_ATTR_FLAGS, + (a->a_flags ^ b->a_flags) & b->a_flag_mask); else - diff |= ADDR_DIFF(FLAGS, a->a_flags != b->a_flags); - -#undef ADDR_DIFF + diff |= _DIFF(ADDR_ATTR_FLAGS, a->a_flags != b->a_flags); +#undef _DIFF return diff; } static const struct trans_tbl addr_attrs[] = { - __ADD(ADDR_ATTR_FAMILY, family) - __ADD(ADDR_ATTR_PREFIXLEN, prefixlen) - __ADD(ADDR_ATTR_FLAGS, flags) - __ADD(ADDR_ATTR_SCOPE, scope) - __ADD(ADDR_ATTR_IFINDEX, ifindex) - __ADD(ADDR_ATTR_LABEL, label) - __ADD(ADDR_ATTR_CACHEINFO, cacheinfo) - __ADD(ADDR_ATTR_PEER, peer) - __ADD(ADDR_ATTR_LOCAL, local) - __ADD(ADDR_ATTR_BROADCAST, broadcast) - __ADD(ADDR_ATTR_MULTICAST, multicast) + __ADD(ADDR_ATTR_FAMILY, family), + __ADD(ADDR_ATTR_PREFIXLEN, prefixlen), + __ADD(ADDR_ATTR_FLAGS, flags), + __ADD(ADDR_ATTR_SCOPE, scope), + __ADD(ADDR_ATTR_IFINDEX, ifindex), + __ADD(ADDR_ATTR_LABEL, label), + __ADD(ADDR_ATTR_CACHEINFO, cacheinfo), + __ADD(ADDR_ATTR_PEER, peer), + __ADD(ADDR_ATTR_LOCAL, local), + __ADD(ADDR_ATTR_BROADCAST, broadcast), + __ADD(ADDR_ATTR_MULTICAST, multicast), }; static char *addr_attrs2str(int attrs, char *buf, size_t len) @@ -552,6 +665,7 @@ static int build_addr_msg(struct rtnl_addr *tmpl, int cmd, int flags, .ifa_family = tmpl->a_family, .ifa_index = tmpl->a_ifindex, .ifa_prefixlen = tmpl->a_prefixlen, + .ifa_flags = tmpl->a_flags, }; if (tmpl->ce_mask & ADDR_ATTR_SCOPE) @@ -596,6 +710,19 @@ static int build_addr_msg(struct rtnl_addr *tmpl, int cmd, int flags, NLA_PUT(msg, IFA_CACHEINFO, sizeof(ca), &ca); } + if (tmpl->a_flags & ~0xFF) { + /* only set the IFA_FLAGS attribute, if they actually contain additional + * flags that are not already set to am.ifa_flags. + * + * Older kernels refuse RTM_NEWADDR and RTM_NEWROUTE messages with EINVAL + * if they contain unknown netlink attributes. See net/core/rtnetlink.c, which + * was fixed by kernel commit 661d2967b3f1b34eeaa7e212e7b9bbe8ee072b59. + * + * With this workaround, libnl will function correctly with older kernels, + * unless there is a new libnl user that wants to set these flags. In this + * case it's up to the user to workaround this issue. */ + NLA_PUT_U32(msg, IFA_FLAGS, tmpl->a_flags); + } *result = msg; return 0; @@ -656,7 +783,7 @@ int rtnl_addr_build_add_request(struct rtnl_addr *addr, int flags, * * @see rtnl_addr_build_add_request() * - * @return 0 on sucess or a negative error if an error occured. + * @return 0 on success or a negative error if an error occured. */ int rtnl_addr_add(struct nl_sock *sk, struct rtnl_addr *addr, int flags) { @@ -728,7 +855,7 @@ int rtnl_addr_build_delete_request(struct rtnl_addr *addr, int flags, * * @see rtnl_addr_build_delete_request(); * - * @return 0 on sucess or a negative error if an error occured. + * @return 0 on success or a negative error if an error occured. */ int rtnl_addr_delete(struct nl_sock *sk, struct rtnl_addr *addr, int flags) { @@ -1046,13 +1173,16 @@ uint32_t rtnl_addr_get_last_update_time(struct rtnl_addr *addr) */ static const struct trans_tbl addr_flags[] = { - __ADD(IFA_F_SECONDARY, secondary) - __ADD(IFA_F_NODAD, nodad) - __ADD(IFA_F_OPTIMISTIC, optimistic) - __ADD(IFA_F_HOMEADDRESS, homeaddress) - __ADD(IFA_F_DEPRECATED, deprecated) - __ADD(IFA_F_TENTATIVE, tentative) - __ADD(IFA_F_PERMANENT, permanent) + __ADD(IFA_F_SECONDARY, secondary), + __ADD(IFA_F_NODAD, nodad), + __ADD(IFA_F_OPTIMISTIC, optimistic), + __ADD(IFA_F_DADFAILED, dadfailed), + __ADD(IFA_F_HOMEADDRESS, homeaddress), + __ADD(IFA_F_DEPRECATED, deprecated), + __ADD(IFA_F_TENTATIVE, tentative), + __ADD(IFA_F_PERMANENT, permanent), + __ADD(IFA_F_MANAGETEMPADDR, mngtmpaddr), + __ADD(IFA_F_NOPREFIXROUTE, noprefixroute), }; char *rtnl_addr_flags2str(int flags, char *buf, size_t size) @@ -1081,6 +1211,7 @@ static struct nl_object_ops addr_obj_ops = { }, .oo_compare = addr_compare, .oo_attrs2str = addr_attrs2str, + .oo_id_attrs_get = addr_id_attrs_get, .oo_id_attrs = (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX | ADDR_ATTR_LOCAL | ADDR_ATTR_PREFIXLEN), }; @@ -1107,12 +1238,12 @@ static struct nl_cache_ops rtnl_addr_ops = { .co_obj_ops = &addr_obj_ops, }; -static void __init addr_init(void) +static void _nl_init addr_init(void) { nl_cache_mngt_register(&rtnl_addr_ops); } -static void __exit addr_exit(void) +static void _nl_exit addr_exit(void) { nl_cache_mngt_unregister(&rtnl_addr_ops); } diff --git a/lib/route/class.c b/lib/route/class.c index 050f42a..29ba809 100644 --- a/lib/route/class.c +++ b/lib/route/class.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/class.c Traffic Classes - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2013 Thomas Graf */ @@ -15,15 +9,21 @@ * @{ */ -#include -#include +#include "nl-default.h" + #include -#include #include #include #include #include +#include "nl-route.h" +#include "tc-api.h" + +struct rtnl_class { + NL_TC_GENERIC(c); +}; + static struct nl_cache_ops rtnl_class_ops; static struct nl_object_ops class_obj_ops; @@ -367,6 +367,38 @@ struct rtnl_class *rtnl_class_get(struct nl_cache *cache, int ifindex, return NULL; } +/** + * Search class by interface index and parent + * @arg cache Traffic class cache + * @arg ifindex Interface index + * @arg parent Handle of parent qdisc + * + * Searches a class cache previously allocated with rtnl_class_alloc_cache() + * and searches for a class matching the interface index and parent qdisc. + * + * The reference counter is incremented before returning the class, therefore + * the reference must be given back with rtnl_class_put() after usage. + * + * @return pointer to class inside the cache or NULL if no match was found. + */ +struct rtnl_class *rtnl_class_get_by_parent(struct nl_cache *cache, int ifindex, + uint32_t parent) +{ + struct rtnl_class *class; + + if (cache->c_ops != &rtnl_class_ops) + return NULL; + + nl_list_for_each_entry(class, &cache->c_items, ce_list) { + if (class->c_parent == parent && class->c_ifindex == ifindex) { + nl_object_get((struct nl_object *) class); + return class; + } + } + + return NULL; +} + /** @} */ /** @@ -453,18 +485,19 @@ static struct nl_cache_ops rtnl_class_ops = { END_OF_MSGTYPES_LIST, }, .co_protocol = NETLINK_ROUTE, + .co_groups = tc_groups, .co_request_update = &class_request_update, .co_msg_parser = &class_msg_parser, .co_obj_ops = &class_obj_ops, }; -static void __init class_init(void) +static void _nl_init class_init(void) { rtnl_tc_type_register(&class_ops); nl_cache_mngt_register(&rtnl_class_ops); } -static void __exit class_exit(void) +static void _nl_exit class_exit(void) { nl_cache_mngt_unregister(&rtnl_class_ops); rtnl_tc_type_unregister(&class_ops); diff --git a/lib/route/classid.c b/lib/route/classid.c index f2d3a01..f5a75f0 100644 --- a/lib/route/classid.c +++ b/lib/route/classid.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/classid.c ClassID Management - * - * 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-2013 Thomas Graf */ @@ -15,12 +9,18 @@ * @{ */ -#include -#include +#include "nl-default.h" + +#include +#include + #include #include #include +#include "nl-route.h" +#include "nl-aux-core/nl-core.h" + struct classid_map { uint32_t classid; @@ -328,7 +328,7 @@ int rtnl_tc_read_classid_file(void) } } - if (!(fd = fopen(path, "r"))) { + if (!(fd = fopen(path, "re"))) { err = -nl_syserr2nlerr(errno); goto errout; } @@ -402,7 +402,7 @@ int rtnl_classid_generate(const char *name, uint32_t *result, uint32_t parent) if (build_sysconf_path(&path, "classid") < 0) return -NLE_NOMEM; - if (!(fd = fopen(path, "a"))) { + if (!(fd = fopen(path, "ae"))) { err = -nl_syserr2nlerr(errno); goto errout; } @@ -414,7 +414,7 @@ int rtnl_classid_generate(const char *name, uint32_t *result, uint32_t parent) fclose(fd); - if ((err = classid_map_add(classid, name)) < 0) { + if (classid_map_add(classid, name) < 0) { /* * Error adding classid map, re-read classid file is best * option here. It is likely to fail as well but better @@ -433,7 +433,7 @@ errout: /** @} */ -static void __init classid_init(void) +static void _nl_init classid_init(void) { int err, i; @@ -444,12 +444,13 @@ static void __init classid_init(void) NL_DBG(1, "Failed to read classid file: %s\n", nl_geterror(err)); } -static void free_map(void *map) { +static void free_map(void *map) +{ free(((struct classid_map *)map)->name); free(map); -}; +} -static void __exit classid_exit(void) +static void _nl_exit classid_exit(void) { tdestroy(id_root, free_map); } diff --git a/lib/route/cls.c b/lib/route/cls.c index 7a809bb..8f970b1 100644 --- a/lib/route/cls.c +++ b/lib/route/cls.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/classifier.c Classifier - * - * 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-2013 Thomas Graf */ @@ -15,15 +9,25 @@ * @{ */ -#include -#include +#include "nl-default.h" + +#include + #include #include -#include #include #include +#include "nl-route.h" +#include "tc-api.h" + /** @cond SKIP */ +struct rtnl_cls { + NL_TC_GENERIC(c); + uint16_t c_prio; + uint16_t c_protocol; +}; + #define CLS_ATTR_PRIO (TCA_ATTR_MAX << 1) #define CLS_ATTR_PROTOCOL (TCA_ATTR_MAX << 2) /** @endcond */ @@ -221,7 +225,7 @@ int rtnl_cls_build_change_request(struct rtnl_cls *cls, int flags, * sends the request to the kernel and waits for the next ACK to be * received and thus blocks until the request has been processed. * - * @return 0 on sucess or a negative error if an error occured. + * @return 0 on success or a negative error if an error occured. */ int rtnl_cls_change(struct nl_sock *sk, struct rtnl_cls *cls, int flags) { @@ -324,7 +328,8 @@ int rtnl_cls_delete(struct nl_sock *sk, struct rtnl_cls *cls, int flags) * * @return 0 on success or a negative error code. */ -int rtnl_cls_alloc_cache(struct nl_sock *sk, int ifindex, uint32_t parent, struct nl_cache **result) +int rtnl_cls_alloc_cache(struct nl_sock *sk, int ifindex, uint32_t parent, + struct nl_cache **result) { struct nl_cache * cache; int err; @@ -344,6 +349,96 @@ int rtnl_cls_alloc_cache(struct nl_sock *sk, int ifindex, uint32_t parent, st return 0; } +/** + * Set interface index and parent handle for classifier cache. + * @arg cache Pointer to cache + * @arg parent Parent qdisc/traffic class class + * + * Set the interface index and parent handle of a classifier cache. + * This is useful for reusing some existed classifier cache to reduce + * the overhead introduced by memory allocation. + * + * @return void. + */ +void rtnl_cls_cache_set_tc_params(struct nl_cache *cache, + int ifindex, uint32_t parent) +{ + cache->c_iarg1 = ifindex; + cache->c_iarg2 = parent; +} + +/** + * Search classifier by interface index, parent and handle + * @arg cache Classifier cache + * @arg ifindex Interface index + * @arg parent Parent + * @arg handle Handle + * + * Searches a classifier cache previously allocated with rtnl_cls_alloc_cache() + * and searches for a classifier matching the interface index, parent + * and handle. + * + * The reference counter is incremented before returning the classifier, + * therefore the reference must be given back with rtnl_cls_put() after usage. + * + * @return Classifier or NULL if no match was found. + */ +struct rtnl_cls *rtnl_cls_find_by_handle(struct nl_cache *cache, int ifindex, uint32_t parent, + uint32_t handle) +{ + struct rtnl_cls *cls; + + if (cache->c_ops != &rtnl_cls_ops) + return NULL; + + nl_list_for_each_entry(cls, &cache->c_items, ce_list) { + if ((cls->c_parent == parent) && + (cls->c_ifindex == ifindex)&& + (cls->c_handle == handle)) { + nl_object_get((struct nl_object *) cls); + return cls; + } + } + + return NULL; +} + +/** + * Search classifier by interface index, parent and priority + * @arg cache Classifier cache + * @arg ifindex Interface index + * @arg parent Parent + * @arg prio Priority + * + * Searches a classifier cache previously allocated with rtnl_cls_alloc_cache() + * and searches for a classifier matching the interface index, parent + * and prio. + * + * The reference counter is incremented before returning the classifier, + * therefore the reference must be given back with rtnl_cls_put() after usage. + * + * @return Classifier or NULL if no match was found. + */ +struct rtnl_cls *rtnl_cls_find_by_prio(struct nl_cache *cache, int ifindex, + uint32_t parent, uint16_t prio) +{ + struct rtnl_cls *cls; + + if (cache->c_ops != &rtnl_cls_ops) + return NULL; + + nl_list_for_each_entry(cls, &cache->c_items, ce_list) { + if ((cls->c_parent == parent) && + (cls->c_ifindex == ifindex) && + (cls->c_prio == prio)) { + nl_object_get((struct nl_object *) cls); + return cls; + } + } + + return NULL; +} + /** @} */ static void cls_dump_line(struct rtnl_tc *tc, struct nl_dump_params *p) @@ -368,7 +463,11 @@ static int cls_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, goto errout; cls->c_prio = TC_H_MAJ(cls->c_info) >> 16; + if (cls->c_prio) + cls->ce_mask |= CLS_ATTR_PRIO; cls->c_protocol = ntohs(TC_H_MIN(cls->c_info)); + if (cls->c_protocol) + cls->ce_mask |= CLS_ATTR_PROTOCOL; err = pp->pp_cb(OBJ_CAST(cls), pp); errout: @@ -407,6 +506,7 @@ static struct nl_cache_ops rtnl_cls_ops = { END_OF_MSGTYPES_LIST, }, .co_protocol = NETLINK_ROUTE, + .co_groups = tc_groups, .co_request_update = cls_request_update, .co_msg_parser = cls_msg_parser, .co_obj_ops = &cls_obj_ops, @@ -426,13 +526,13 @@ static struct nl_object_ops cls_obj_ops = { .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE), }; -static void __init cls_init(void) +static void _nl_init cls_init(void) { rtnl_tc_type_register(&cls_ops); nl_cache_mngt_register(&rtnl_cls_ops); } -static void __exit cls_exit(void) +static void _nl_exit cls_exit(void) { nl_cache_mngt_unregister(&rtnl_cls_ops); rtnl_tc_type_unregister(&cls_ops); diff --git a/lib/route/cls/basic.c b/lib/route/cls/basic.c index fb1c382..dc19256 100644 --- a/lib/route/cls/basic.c +++ b/lib/route/cls/basic.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/cls/basic.c Basic Classifier - * - * 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-2013 Thomas Graf */ @@ -22,24 +16,29 @@ * @{ */ -#include -#include +#include "nl-default.h" + #include -#include #include +#include #include #include +#include "tc-api.h" +#include "nl-aux-route/nl-route.h" + struct rtnl_basic { uint32_t b_target; struct rtnl_ematch_tree * b_ematch; int b_mask; + struct rtnl_act * b_act; }; /** @cond SKIP */ #define BASIC_ATTR_TARGET 0x001 #define BASIC_ATTR_EMATCH 0x002 +#define BASIC_ATTR_ACTION 0x004 /** @endcond */ static struct nla_policy basic_policy[TCA_BASIC_MAX+1] = { @@ -59,6 +58,8 @@ static void basic_free_data(struct rtnl_tc *tc, void *data) if (!b) return; + if (b->b_act) + rtnl_act_put_all(&b->b_act); rtnl_ematch_tree_free(b->b_ematch); } @@ -85,6 +86,12 @@ static int basic_msg_parser(struct rtnl_tc *tc, void *data) if (b->b_ematch) b->b_mask |= BASIC_ATTR_EMATCH; } + if (tb[TCA_BASIC_ACT]) { + b->b_mask |= BASIC_ATTR_ACTION; + err = rtnl_act_parse(&b->b_act, tb[TCA_BASIC_ACT]); + if (err < 0) + return err; + } return 0; } @@ -131,15 +138,21 @@ static int basic_msg_fill(struct rtnl_tc *tc, void *data, if (!b) return 0; - if (!(b->b_mask & BASIC_ATTR_TARGET)) - return -NLE_MISSING_ATTR; - - NLA_PUT_U32(msg, TCA_BASIC_CLASSID, b->b_target); + if (b->b_mask & BASIC_ATTR_TARGET) + NLA_PUT_U32(msg, TCA_BASIC_CLASSID, b->b_target); if (b->b_mask & BASIC_ATTR_EMATCH && rtnl_ematch_fill_attr(msg, TCA_BASIC_EMATCHES, b->b_ematch) < 0) goto nla_put_failure; - + + if (b->b_mask & BASIC_ATTR_ACTION) { + int err; + + err = rtnl_act_fill(msg, TCA_BASIC_ACT, b->b_act); + if (err) + return err; + } + return 0; nla_put_failure: @@ -200,6 +213,59 @@ struct rtnl_ematch_tree *rtnl_basic_get_ematch(struct rtnl_cls *cls) return b->b_ematch; } +int rtnl_basic_add_action(struct rtnl_cls *cls, struct rtnl_act *act) +{ + struct rtnl_basic *b; + int err; + + if (!act) + return 0; + + if (!(b = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if ((err = _rtnl_act_append_get(&b->b_act, act)) < 0) + return err; + + b->b_mask |= BASIC_ATTR_ACTION; + return 0; +} + +struct rtnl_act* rtnl_basic_get_action(struct rtnl_cls *cls) +{ + struct rtnl_basic *b; + + if (!(b = rtnl_tc_data_peek(TC_CAST(cls)))) + return NULL; + + if (!(b->b_mask & BASIC_ATTR_ACTION)) + return NULL; + + return b->b_act; +} + +int rtnl_basic_del_action(struct rtnl_cls *cls, struct rtnl_act *act) +{ + struct rtnl_basic *b; + int ret; + + if (!act) + return 0; + + if (!(b = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if (!(b->b_mask & BASIC_ATTR_ACTION)) + return -NLE_INVAL; + ret = rtnl_act_remove(&b->b_act, act); + if (ret) + return ret; + + if (!b->b_act) + b->b_mask &= ~BASIC_ATTR_ACTION; + rtnl_act_put(act); + return 0; +} /** @} */ static struct rtnl_tc_ops basic_ops = { @@ -216,12 +282,12 @@ static struct rtnl_tc_ops basic_ops = { }, }; -static void __init basic_init(void) +static void _nl_init basic_init(void) { rtnl_tc_register(&basic_ops); } -static void __exit basic_exit(void) +static void _nl_exit basic_exit(void) { rtnl_tc_unregister(&basic_ops); } diff --git a/lib/route/cls/cgroup.c b/lib/route/cls/cgroup.c index c5b7561..3534281 100644 --- a/lib/route/cls/cgroup.c +++ b/lib/route/cls/cgroup.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/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 Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2009-2013 Thomas Graf */ @@ -16,17 +10,23 @@ * @{ */ -#include -#include +#include "nl-default.h" + #include #include #include -#include #include #include #include +#include "tc-api.h" + /** @cond SKIP */ +struct rtnl_cgroup { + struct rtnl_ematch_tree *cg_ematch; + int cg_mask; +}; + #define CGROUP_ATTR_EMATCH 0x001 /** @endcond */ @@ -34,9 +34,19 @@ static struct nla_policy cgroup_policy[TCA_CGROUP_MAX+1] = { [TCA_CGROUP_EMATCHES] = { .type = NLA_NESTED }, }; -static int cgroup_clone(void *dst, void *src) +static int cgroup_clone(void *_dst, void *_src) { - return -NLE_OPNOTSUPP; + struct rtnl_cgroup *dst = _dst, *src = _src; + + dst->cg_ematch = NULL; + + if (src->cg_ematch) { + dst->cg_ematch = rtnl_ematch_tree_clone(src->cg_ematch); + if (!dst->cg_ematch) + return -NLE_NOMEM; + } + + return 0; } static void cgroup_free_data(struct rtnl_tc *tc, void *data) @@ -176,12 +186,12 @@ static struct rtnl_tc_ops cgroup_ops = { }, }; -static void __init cgroup_init(void) +static void _nl_init cgroup_init(void) { rtnl_tc_register(&cgroup_ops); } -static void __exit cgroup_exit(void) +static void _nl_exit cgroup_exit(void) { rtnl_tc_unregister(&cgroup_ops); } diff --git a/lib/route/cls/ematch.c b/lib/route/cls/ematch.c index 89b5067..5a5a210 100644 --- a/lib/route/cls/ematch.c +++ b/lib/route/cls/ematch.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/cls/ematch.c Extended Matches - * - * 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-2013 Thomas Graf */ @@ -16,13 +10,18 @@ * @{ */ -#include -#include +#include "nl-default.h" + +#include + #include #include #include #include +#include "nl-route.h" +#include "nl-aux-core/nl-core.h" + #include "ematch_syntax.h" #include "ematch_grammar.h" @@ -282,9 +281,67 @@ void rtnl_ematch_tree_free(struct rtnl_ematch_tree *tree) return; free_ematch_list(&tree->et_list); - free(tree); NL_DBG(2, "Freed ematch tree %p\n", tree); + + free(tree); +} + +static int clone_ematch_list(struct nl_list_head *dst, struct nl_list_head *src) +{ + struct rtnl_ematch *new = NULL, *pos = NULL; + + nl_list_for_each_entry(pos, src, e_list) { + new = rtnl_ematch_alloc(); + if (!new) + goto nomem; + + new->e_id = pos->e_id; + new->e_kind = pos->e_kind; + new->e_flags = pos->e_flags; + new->e_index = pos->e_index; + new->e_datalen = pos->e_datalen; + + if (pos->e_ops) { + if (rtnl_ematch_set_ops(new, pos->e_ops)) + goto nomem; + } + + if (!nl_list_empty(&pos->e_childs)) { + if (clone_ematch_list(&new->e_childs, &pos->e_childs) < 0) + goto nomem; + } + nl_list_add_tail(&new->e_list, dst); + } + + return 0; + +nomem: + if (new) + free(new); + free_ematch_list(dst); + return -NLE_NOMEM; +} + +/** + * Clone ematch tree object + * @arg src ematch tree object + * + * This function clones the ematch tree and all ematches attached to it. + */ +struct rtnl_ematch_tree *rtnl_ematch_tree_clone(struct rtnl_ematch_tree *src) +{ + struct rtnl_ematch_tree *dst = NULL; + + if (!src) + return NULL; + + if (!(dst = rtnl_ematch_tree_alloc(src->et_progid))) + return NULL; + + clone_ematch_list(&dst->et_list, &src->et_list); + + return dst; } /** @@ -406,7 +463,7 @@ int rtnl_ematch_parse_attr(struct nlattr *attr, struct rtnl_ematch_tree **result } hdr = nla_data(a); - data = nla_data(a) + NLA_ALIGN(sizeof(*hdr)); + data = (char *) nla_data(a) + NLA_ALIGN(sizeof(*hdr)); len = nla_len(a) - NLA_ALIGN(sizeof(*hdr)); NL_DBG(3, "ematch attribute matchid=%u, kind=%u, flags=%u\n", @@ -640,22 +697,20 @@ int rtnl_ematch_parse_expr(const char *expr, char **errp, if (!(tree = rtnl_ematch_tree_alloc(RTNL_EMATCH_PROGID))) return -NLE_FAILURE; - if ((err = ematch_lex_init(&scanner)) < 0) { + if (ematch_lex_init(&scanner) < 0) { err = -NLE_FAILURE; goto errout; } buf = ematch__scan_string(expr, scanner); - if ((err = ematch_parse(scanner, errp, &tree->et_list)) != 0) { + if (ematch_parse(scanner, errp, &tree->et_list) != 0) { ematch__delete_buffer(buf, scanner); err = -NLE_PARSE_ERR; goto errout; } - if (scanner) - ematch_lex_destroy(scanner); - + ematch_lex_destroy(scanner); *result = tree; return 0; @@ -693,7 +748,7 @@ static const char *operand_txt[] = { char *rtnl_ematch_opnd2txt(uint8_t opnd, char *buf, size_t len) { snprintf(buf, len, "%s", - opnd <= ARRAY_SIZE(operand_txt) ? operand_txt[opnd] : "?"); + opnd < ARRAY_SIZE(operand_txt) ? operand_txt[opnd] : "?"); return buf; } diff --git a/lib/route/cls/ematch/cmp.c b/lib/route/cls/ematch/cmp.c index 2997cdb..9feb2e5 100644 --- a/lib/route/cls/ematch/cmp.c +++ b/lib/route/cls/ematch/cmp.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/cls/ematch/cmp.c Simple packet data comparison ematch - * - * 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-2013 Thomas Graf */ @@ -16,11 +10,13 @@ * @{ */ -#include -#include +#include "nl-default.h" + +#include + #include #include -#include +#include void rtnl_ematch_cmp_set(struct rtnl_ematch *e, struct tcf_em_cmp *cfg) { @@ -85,7 +81,7 @@ static struct rtnl_ematch_ops cmp_ops = { .eo_dump = cmp_dump, }; -static void __init cmp_init(void) +static void _nl_init cmp_init(void) { rtnl_ematch_register(&cmp_ops); } diff --git a/lib/route/cls/ematch/container.c b/lib/route/cls/ematch/container.c index 813391a..ea2d166 100644 --- a/lib/route/cls/ematch/container.c +++ b/lib/route/cls/ematch/container.c @@ -1,19 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/cls/ematch/container.c Container Ematch - * - * 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-2013 Thomas Graf */ -#include -#include +#include "nl-default.h" + #include #include +#include "nl-route.h" + static int container_parse(struct rtnl_ematch *e, void *data, size_t len __attribute__((unused))) { /* @@ -41,7 +37,7 @@ static struct rtnl_ematch_ops container_ops = { .eo_fill = container_fill, }; -static void __init container_init(void) +static void _nl_init container_init(void) { rtnl_ematch_register(&container_ops); } diff --git a/lib/route/cls/ematch/meta.c b/lib/route/cls/ematch/meta.c index 44f11b9..2c884dc 100644 --- a/lib/route/cls/ematch/meta.c +++ b/lib/route/cls/ematch/meta.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/cls/ematch/meta.c Metadata Match - * - * 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-2013 Thomas Graf */ @@ -16,12 +10,16 @@ * @{ */ -#include -#include +#include "nl-default.h" + +#include + #include #include #include +#include "nl-priv-dynamic-core/nl-core.h" + struct rtnl_meta_value { uint8_t mv_type; @@ -51,7 +49,8 @@ static struct rtnl_meta_value *meta_alloc(uint8_t type, uint16_t id, value->mv_shift = shift; value->mv_len = len; - memcpy(value + 1, data, len); + if (len) + memcpy(value + 1, data, len); return value; } @@ -165,51 +164,51 @@ static int meta_parse(struct rtnl_ematch *e, void *data, size_t len) } static const struct trans_tbl meta_int[] = { - __ADD(TCF_META_ID_RANDOM, random) - __ADD(TCF_META_ID_LOADAVG_0, loadavg_0) - __ADD(TCF_META_ID_LOADAVG_1, loadavg_1) - __ADD(TCF_META_ID_LOADAVG_2, loadavg_2) - __ADD(TCF_META_ID_DEV, dev) - __ADD(TCF_META_ID_PRIORITY, prio) - __ADD(TCF_META_ID_PROTOCOL, proto) - __ADD(TCF_META_ID_PKTTYPE, pkttype) - __ADD(TCF_META_ID_PKTLEN, pktlen) - __ADD(TCF_META_ID_DATALEN, datalen) - __ADD(TCF_META_ID_MACLEN, maclen) - __ADD(TCF_META_ID_NFMARK, mark) - __ADD(TCF_META_ID_TCINDEX, tcindex) - __ADD(TCF_META_ID_RTCLASSID, rtclassid) - __ADD(TCF_META_ID_RTIIF, rtiif) - __ADD(TCF_META_ID_SK_FAMILY, sk_family) - __ADD(TCF_META_ID_SK_STATE, sk_state) - __ADD(TCF_META_ID_SK_REUSE, sk_reuse) - __ADD(TCF_META_ID_SK_REFCNT, sk_refcnt) - __ADD(TCF_META_ID_SK_RCVBUF, sk_rcvbuf) - __ADD(TCF_META_ID_SK_SNDBUF, sk_sndbuf) - __ADD(TCF_META_ID_SK_SHUTDOWN, sk_sutdown) - __ADD(TCF_META_ID_SK_PROTO, sk_proto) - __ADD(TCF_META_ID_SK_TYPE, sk_type) - __ADD(TCF_META_ID_SK_RMEM_ALLOC, sk_rmem_alloc) - __ADD(TCF_META_ID_SK_WMEM_ALLOC, sk_wmem_alloc) - __ADD(TCF_META_ID_SK_WMEM_QUEUED, sk_wmem_queued) - __ADD(TCF_META_ID_SK_RCV_QLEN, sk_rcv_qlen) - __ADD(TCF_META_ID_SK_SND_QLEN, sk_snd_qlen) - __ADD(TCF_META_ID_SK_ERR_QLEN, sk_err_qlen) - __ADD(TCF_META_ID_SK_FORWARD_ALLOCS, sk_forward_allocs) - __ADD(TCF_META_ID_SK_ALLOCS, sk_allocs) - __ADD(TCF_META_ID_SK_ROUTE_CAPS, sk_route_caps) - __ADD(TCF_META_ID_SK_HASH, sk_hash) - __ADD(TCF_META_ID_SK_LINGERTIME, sk_lingertime) - __ADD(TCF_META_ID_SK_ACK_BACKLOG, sk_ack_backlog) - __ADD(TCF_META_ID_SK_MAX_ACK_BACKLOG, sk_max_ack_backlog) - __ADD(TCF_META_ID_SK_PRIO, sk_prio) - __ADD(TCF_META_ID_SK_RCVLOWAT, sk_rcvlowat) - __ADD(TCF_META_ID_SK_RCVTIMEO, sk_rcvtimeo) - __ADD(TCF_META_ID_SK_SNDTIMEO, sk_sndtimeo) - __ADD(TCF_META_ID_SK_SENDMSG_OFF, sk_sendmsg_off) - __ADD(TCF_META_ID_SK_WRITE_PENDING, sk_write_pending) - __ADD(TCF_META_ID_VLAN_TAG, vlan) - __ADD(TCF_META_ID_RXHASH, rxhash) + __ADD(TCF_META_ID_RANDOM, random), + __ADD(TCF_META_ID_LOADAVG_0, loadavg_0), + __ADD(TCF_META_ID_LOADAVG_1, loadavg_1), + __ADD(TCF_META_ID_LOADAVG_2, loadavg_2), + __ADD(TCF_META_ID_DEV, dev), + __ADD(TCF_META_ID_PRIORITY, prio), + __ADD(TCF_META_ID_PROTOCOL, proto), + __ADD(TCF_META_ID_PKTTYPE, pkttype), + __ADD(TCF_META_ID_PKTLEN, pktlen), + __ADD(TCF_META_ID_DATALEN, datalen), + __ADD(TCF_META_ID_MACLEN, maclen), + __ADD(TCF_META_ID_NFMARK, mark), + __ADD(TCF_META_ID_TCINDEX, tcindex), + __ADD(TCF_META_ID_RTCLASSID, rtclassid), + __ADD(TCF_META_ID_RTIIF, rtiif), + __ADD(TCF_META_ID_SK_FAMILY, sk_family), + __ADD(TCF_META_ID_SK_STATE, sk_state), + __ADD(TCF_META_ID_SK_REUSE, sk_reuse), + __ADD(TCF_META_ID_SK_REFCNT, sk_refcnt), + __ADD(TCF_META_ID_SK_RCVBUF, sk_rcvbuf), + __ADD(TCF_META_ID_SK_SNDBUF, sk_sndbuf), + __ADD(TCF_META_ID_SK_SHUTDOWN, sk_sutdown), + __ADD(TCF_META_ID_SK_PROTO, sk_proto), + __ADD(TCF_META_ID_SK_TYPE, sk_type), + __ADD(TCF_META_ID_SK_RMEM_ALLOC, sk_rmem_alloc), + __ADD(TCF_META_ID_SK_WMEM_ALLOC, sk_wmem_alloc), + __ADD(TCF_META_ID_SK_WMEM_QUEUED, sk_wmem_queued), + __ADD(TCF_META_ID_SK_RCV_QLEN, sk_rcv_qlen), + __ADD(TCF_META_ID_SK_SND_QLEN, sk_snd_qlen), + __ADD(TCF_META_ID_SK_ERR_QLEN, sk_err_qlen), + __ADD(TCF_META_ID_SK_FORWARD_ALLOCS, sk_forward_allocs), + __ADD(TCF_META_ID_SK_ALLOCS, sk_allocs), + __ADD(__TCF_META_ID_SK_ROUTE_CAPS, sk_route_caps), + __ADD(TCF_META_ID_SK_HASH, sk_hash), + __ADD(TCF_META_ID_SK_LINGERTIME, sk_lingertime), + __ADD(TCF_META_ID_SK_ACK_BACKLOG, sk_ack_backlog), + __ADD(TCF_META_ID_SK_MAX_ACK_BACKLOG, sk_max_ack_backlog), + __ADD(TCF_META_ID_SK_PRIO, sk_prio), + __ADD(TCF_META_ID_SK_RCVLOWAT, sk_rcvlowat), + __ADD(TCF_META_ID_SK_RCVTIMEO, sk_rcvtimeo), + __ADD(TCF_META_ID_SK_SNDTIMEO, sk_sndtimeo), + __ADD(TCF_META_ID_SK_SENDMSG_OFF, sk_sendmsg_off), + __ADD(TCF_META_ID_SK_WRITE_PENDING, sk_write_pending), + __ADD(TCF_META_ID_VLAN_TAG, vlan), + __ADD(TCF_META_ID_RXHASH, rxhash), }; static char *int_id2str(int id, char *buf, size_t size) @@ -218,8 +217,8 @@ static char *int_id2str(int id, char *buf, size_t size) } static const struct trans_tbl meta_var[] = { - __ADD(TCF_META_ID_DEV,devname) - __ADD(TCF_META_ID_SK_BOUND_IF,sk_bound_if) + __ADD(TCF_META_ID_DEV,devname), + __ADD(TCF_META_ID_SK_BOUND_IF,sk_bound_if), }; static char *var_id2str(int id, char *buf, size_t size) @@ -244,9 +243,9 @@ static void dump_value(struct rtnl_meta_value *v, struct nl_dump_params *p) nl_dump(p, " >> %u", v->mv_shift); if (v->mv_len == 4) - nl_dump(p, " & %#x", *(uint32_t *) (v + 1)); + nl_dump(p, " & %#lx", (long unsigned) *(uint32_t *) (v + 1)); else if (v->mv_len == 8) - nl_dump(p, " & %#x", *(uint64_t *) (v + 1)); + nl_dump(p, " & %#llx", (long long unsigned) (*(uint64_t *) (v + 1))); } break; @@ -326,7 +325,7 @@ static struct rtnl_ematch_ops meta_ops = { .eo_free = meta_free, }; -static void __init meta_init(void) +static void _nl_init meta_init(void) { rtnl_ematch_register(&meta_ops); } diff --git a/lib/route/cls/ematch/nbyte.c b/lib/route/cls/ematch/nbyte.c index 8852489..d0ab84b 100644 --- a/lib/route/cls/ematch/nbyte.c +++ b/lib/route/cls/ematch/nbyte.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/cls/ematch/nbyte.c Nbyte comparison - * - * 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-2013 Thomas Graf */ @@ -16,8 +10,10 @@ * @{ */ -#include -#include +#include "nl-default.h" + +#include + #include #include #include @@ -93,7 +89,7 @@ static int nbyte_parse(struct rtnl_ematch *e, void *data, size_t len) if (!(n->pattern = calloc(1, plen))) return -NLE_NOMEM; - memcpy(n->pattern, data + hdrlen, plen); + memcpy(n->pattern, (char *) data + hdrlen, plen); } return 0; @@ -131,7 +127,7 @@ static struct rtnl_ematch_ops nbyte_ops = { .eo_free = nbyte_free, }; -static void __init nbyte_init(void) +static void _nl_init nbyte_init(void) { rtnl_ematch_register(&nbyte_ops); } diff --git a/lib/route/cls/ematch/text.c b/lib/route/cls/ematch/text.c index e8cdcae..d7a233f 100644 --- a/lib/route/cls/ematch/text.c +++ b/lib/route/cls/ematch/text.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/cls/ematch/text.c Text Search - * - * 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-2013 Thomas Graf */ @@ -16,8 +10,10 @@ * @{ */ -#include -#include +#include "nl-default.h" + +#include + #include #include #include @@ -90,7 +86,7 @@ void rtnl_ematch_text_set_algo(struct rtnl_ematch *e, const char *algo) { struct text_data *t = rtnl_ematch_data(e); - strncpy(t->cfg.algo, algo, sizeof(t->cfg.algo)); + _nl_strncpy_trunc(t->cfg.algo, algo, sizeof(t->cfg.algo)); } char *rtnl_ematch_text_get_algo(struct rtnl_ematch *e) @@ -115,7 +111,7 @@ static int text_parse(struct rtnl_ematch *e, void *data, size_t len) if (!(t->pattern = calloc(1, t->cfg.pattern_len))) return -NLE_NOMEM; - memcpy(t->pattern, data + hdrlen, t->cfg.pattern_len); + memcpy(t->pattern, (char *) data + hdrlen, t->cfg.pattern_len); } return 0; @@ -128,7 +124,7 @@ static void text_dump(struct rtnl_ematch *e, struct nl_dump_params *p) nl_dump(p, "text(%s \"%s\"", t->cfg.algo[0] ? t->cfg.algo : "no-algo", - t->pattern ? : "no-pattern"); + t->pattern ? t->pattern : "no-pattern"); if (t->cfg.from_layer || t->cfg.from_offset) { nl_dump(p, " from %s", @@ -175,7 +171,7 @@ static struct rtnl_ematch_ops text_ops = { .eo_free = text_free, }; -static void __init text_init(void) +static void _nl_init text_init(void) { rtnl_ematch_register(&text_ops); } diff --git a/lib/route/cls/ematch_grammar.l b/lib/route/cls/ematch_grammar.l index 96ef1a0..1035079 100644 --- a/lib/route/cls/ematch_grammar.l +++ b/lib/route/cls/ematch_grammar.l @@ -1,21 +1,21 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/cls/ematch_grammar.l ematch expression grammar - * - * 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-2013 Thomas Graf */ %{ - #include - #include + #include + #include #include #include + + #include "nl-route.h" + #include "ematch_syntax.h" + + int ematch_get_column(yyscan_t); + void ematch_set_column(int, yyscan_t); %} %option 8bit diff --git a/lib/route/cls/ematch_syntax.y b/lib/route/cls/ematch_syntax.y index da21039..961ee43 100644 --- a/lib/route/cls/ematch_syntax.y +++ b/lib/route/cls/ematch_syntax.y @@ -1,17 +1,13 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/cls/ematch_syntax.y ematch expression syntax - * - * 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-2013 Thomas Graf */ %{ -#include -#include +#include + +#include + #include #include #include @@ -21,12 +17,24 @@ #include #include +#include "nl-route.h" + #define META_ALLOC rtnl_meta_value_alloc_id #define META_ID(name) TCF_META_ID_##name #define META_INT TCF_META_TYPE_INT #define META_VAR TCF_META_TYPE_VAR %} +%code requires { + +struct ematch_quoted { + char * data; + size_t len; + int index; +}; + +} + %error-verbose %define api.pure %name-prefix "ematch_" @@ -50,12 +58,13 @@ %{ extern int ematch_lex(YYSTYPE *, void *); +#define ematch_error yyerror static void yyerror(void *scanner, char **errp, struct nl_list_head *root, const char *msg) { if (msg) - *errp = strdup(msg); - else - *errp = NULL; + *errp = strdup(msg); + else + *errp = NULL; } %} @@ -374,7 +383,7 @@ meta_int_id: | META_SK_ERR_QLEN { $$ = META_ID(SK_ERR_QLEN); } | META_SK_FORWARD_ALLOCS { $$ = META_ID(SK_FORWARD_ALLOCS); } | META_SK_ALLOCS { $$ = META_ID(SK_ALLOCS); } - | META_SK_ROUTE_CAPS { $$ = META_ID(SK_ROUTE_CAPS); } + | META_SK_ROUTE_CAPS { $$ = __TCF_META_ID_SK_ROUTE_CAPS; } | META_SK_HASH { $$ = META_ID(SK_HASH); } | META_SK_LINGERTIME { $$ = META_ID(SK_LINGERTIME); } | META_SK_ACK_BACKLOG { $$ = META_ID(SK_ACK_BACKLOG); } @@ -409,7 +418,7 @@ pattern: if (nl_addr_parse($1, AF_UNSPEC, &addr) == 0) { $$.len = nl_addr_get_len(addr); - $$.index = min_t(int, $$.len, nl_addr_get_prefixlen(addr)/8); + $$.index = _NL_MIN($$.len, nl_addr_get_prefixlen(addr)/8); if (!($$.data = calloc(1, $$.len))) { nl_addr_put(addr); diff --git a/lib/route/cls/flower.c b/lib/route/cls/flower.c new file mode 100644 index 0000000..56f24c3 --- /dev/null +++ b/lib/route/cls/flower.c @@ -0,0 +1,921 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2018 Volodymyr Bendiuga + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "tc-api.h" +#include "nl-aux-route/nl-route.h" + +/** @cond SKIP */ +struct rtnl_flower { + struct rtnl_act *cf_act; + int cf_mask; + uint32_t cf_flags; + uint16_t cf_proto; + uint16_t cf_vlan_id; + uint16_t cf_vlan_ethtype; + uint8_t cf_vlan_prio; + uint8_t cf_src_mac[ETH_ALEN]; + uint8_t cf_src_mac_mask[ETH_ALEN]; + uint8_t cf_dst_mac[ETH_ALEN]; + uint8_t cf_dst_mac_mask[ETH_ALEN]; + in_addr_t cf_ipv4_src; + in_addr_t cf_ipv4_src_mask; + in_addr_t cf_ipv4_dst; + in_addr_t cf_ipv4_dst_mask; + uint8_t cf_ip_dscp; + uint8_t cf_ip_dscp_mask; +}; + +#define FLOWER_ATTR_FLAGS (1 << 0) +#define FLOWER_ATTR_ACTION (1 << 1) +#define FLOWER_ATTR_VLAN_ID (1 << 2) +#define FLOWER_ATTR_VLAN_PRIO (1 << 3) +#define FLOWER_ATTR_VLAN_ETH_TYPE (1 << 4) +#define FLOWER_ATTR_DST_MAC (1 << 5) +#define FLOWER_ATTR_DST_MAC_MASK (1 << 6) +#define FLOWER_ATTR_SRC_MAC (1 << 7) +#define FLOWER_ATTR_SRC_MAC_MASK (1 << 8) +#define FLOWER_ATTR_IP_DSCP (1 << 9) +#define FLOWER_ATTR_IP_DSCP_MASK (1 << 10) +#define FLOWER_ATTR_PROTO (1 << 11) +#define FLOWER_ATTR_IPV4_SRC (1 << 12) +#define FLOWER_ATTR_IPV4_SRC_MASK (1 << 13) +#define FLOWER_ATTR_IPV4_DST (1 << 14) +#define FLOWER_ATTR_IPV4_DST_MASK (1 << 15) +/** @endcond */ + +#define FLOWER_DSCP_MAX 0xe0 +#define FLOWER_DSCP_MASK_MAX 0xe0 +#define FLOWER_VID_MAX 4095 +#define FLOWER_VLAN_PRIO_MAX 7 + +static struct nla_policy flower_policy[TCA_FLOWER_MAX + 1] = { + [TCA_FLOWER_FLAGS] = { .type = NLA_U32 }, + [TCA_FLOWER_KEY_ETH_TYPE] = { .type = NLA_U16 }, + [TCA_FLOWER_KEY_ETH_DST] = { .maxlen = ETH_ALEN }, + [TCA_FLOWER_KEY_ETH_DST_MASK] = { .maxlen = ETH_ALEN }, + [TCA_FLOWER_KEY_ETH_SRC] = { .maxlen = ETH_ALEN }, + [TCA_FLOWER_KEY_ETH_SRC_MASK] = { .maxlen = ETH_ALEN }, + [TCA_FLOWER_KEY_VLAN_ID] = { .type = NLA_U16 }, + [TCA_FLOWER_KEY_VLAN_PRIO] = { .type = NLA_U8 }, + [TCA_FLOWER_KEY_IP_TOS] = { .type = NLA_U8 }, + [TCA_FLOWER_KEY_IP_TOS_MASK] = { .type = NLA_U8 }, + [TCA_FLOWER_KEY_VLAN_ETH_TYPE] = { .type = NLA_U16 }, + [TCA_FLOWER_KEY_IPV4_SRC] = { .type = NLA_U32 }, + [TCA_FLOWER_KEY_IPV4_SRC_MASK] = { .type = NLA_U32 }, + [TCA_FLOWER_KEY_IPV4_DST] = { .type = NLA_U32 }, + [TCA_FLOWER_KEY_IPV4_DST_MASK] = { .type = NLA_U32 }, +}; + +static int flower_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct rtnl_flower *f = data; + struct nlattr *tb[TCA_FLOWER_MAX + 1]; + int err; + + err = tca_parse(tb, TCA_FLOWER_MAX, tc, flower_policy); + if (err < 0) + return err; + + if (tb[TCA_FLOWER_FLAGS]) { + f->cf_flags = nla_get_u32(tb[TCA_FLOWER_FLAGS]); + f->cf_mask |= FLOWER_ATTR_FLAGS; + } + + if (tb[TCA_FLOWER_ACT]) { + err = rtnl_act_parse(&f->cf_act, tb[TCA_FLOWER_ACT]); + if (err) + return err; + + f->cf_mask |= FLOWER_ATTR_ACTION; + } + + if (tb[TCA_FLOWER_KEY_ETH_TYPE]) { + f->cf_proto = nla_get_u16(tb[TCA_FLOWER_KEY_ETH_TYPE]); + f->cf_mask |= FLOWER_ATTR_PROTO; + } + + if (tb[TCA_FLOWER_KEY_VLAN_ID]) { + f->cf_vlan_id = nla_get_u16(tb[TCA_FLOWER_KEY_VLAN_ID]); + f->cf_mask |= FLOWER_ATTR_VLAN_ID; + } + + if (tb[TCA_FLOWER_KEY_VLAN_PRIO]) { + f->cf_vlan_prio = nla_get_u8(tb[TCA_FLOWER_KEY_VLAN_PRIO]); + f->cf_mask |= FLOWER_ATTR_VLAN_PRIO; + } + + if (tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE]) { + f->cf_vlan_ethtype = nla_get_u16(tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE]); + f->cf_mask |= FLOWER_ATTR_VLAN_ETH_TYPE; + } + + if (tb[TCA_FLOWER_KEY_ETH_DST]) { + nla_memcpy(f->cf_dst_mac, tb[TCA_FLOWER_KEY_ETH_DST], ETH_ALEN); + f->cf_mask |= FLOWER_ATTR_DST_MAC; + } + + if (tb[TCA_FLOWER_KEY_ETH_DST_MASK]) { + nla_memcpy(f->cf_dst_mac_mask, tb[TCA_FLOWER_KEY_ETH_DST_MASK], ETH_ALEN); + f->cf_mask |= FLOWER_ATTR_DST_MAC_MASK; + } + + if (tb[TCA_FLOWER_KEY_ETH_SRC]) { + nla_memcpy(f->cf_src_mac, tb[TCA_FLOWER_KEY_ETH_SRC], ETH_ALEN); + f->cf_mask |= FLOWER_ATTR_SRC_MAC; + } + + if (tb[TCA_FLOWER_KEY_ETH_SRC_MASK]) { + nla_memcpy(f->cf_src_mac_mask, tb[TCA_FLOWER_KEY_ETH_SRC_MASK], ETH_ALEN); + f->cf_mask |= FLOWER_ATTR_SRC_MAC_MASK; + } + + if (tb[TCA_FLOWER_KEY_IP_TOS]) { + f->cf_ip_dscp = nla_get_u8(tb[TCA_FLOWER_KEY_IP_TOS]); + f->cf_mask |= FLOWER_ATTR_IP_DSCP; + } + + if (tb[TCA_FLOWER_KEY_IP_TOS_MASK]) { + f->cf_ip_dscp_mask = nla_get_u8(tb[TCA_FLOWER_KEY_IP_TOS_MASK]); + f->cf_mask |= FLOWER_ATTR_IP_DSCP_MASK; + } + + if (tb[TCA_FLOWER_KEY_IPV4_SRC]) { + f->cf_ipv4_src = nla_get_u32(tb[TCA_FLOWER_KEY_IPV4_SRC]); + f->cf_mask |= FLOWER_ATTR_IPV4_SRC; + } + + if (tb[TCA_FLOWER_KEY_IPV4_SRC_MASK]) { + f->cf_ipv4_src_mask = + nla_get_u32(tb[TCA_FLOWER_KEY_IPV4_SRC_MASK]); + f->cf_mask |= FLOWER_ATTR_IPV4_SRC_MASK; + } + + if (tb[TCA_FLOWER_KEY_IPV4_DST]) { + f->cf_ipv4_dst = nla_get_u32(tb[TCA_FLOWER_KEY_IPV4_DST]); + f->cf_mask |= FLOWER_ATTR_IPV4_DST; + } + + if (tb[TCA_FLOWER_KEY_IPV4_DST_MASK]) { + f->cf_ipv4_dst_mask = + nla_get_u32(tb[TCA_FLOWER_KEY_IPV4_DST_MASK]); + f->cf_mask |= FLOWER_ATTR_IPV4_DST_MASK; + } + + return 0; +} + +static int flower_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + struct rtnl_flower *f = data; + int err; + + if (!f) + return 0; + + if (f->cf_mask & FLOWER_ATTR_FLAGS) + NLA_PUT_U32(msg, TCA_FLOWER_FLAGS, f->cf_flags); + + if (f->cf_mask & FLOWER_ATTR_ACTION) { + err = rtnl_act_fill(msg, TCA_FLOWER_ACT, f->cf_act); + if (err) + return err; + } + + if (f->cf_mask & FLOWER_ATTR_PROTO) + NLA_PUT_U16(msg, TCA_FLOWER_KEY_ETH_TYPE, f->cf_proto); + + if (f->cf_mask & FLOWER_ATTR_VLAN_ID) + NLA_PUT_U16(msg, TCA_FLOWER_KEY_VLAN_ID, f->cf_vlan_id); + + if (f->cf_mask & FLOWER_ATTR_VLAN_PRIO) + NLA_PUT_U8(msg, TCA_FLOWER_KEY_VLAN_PRIO, f->cf_vlan_prio); + + if (f->cf_mask & FLOWER_ATTR_VLAN_ETH_TYPE) + NLA_PUT_U16(msg, TCA_FLOWER_KEY_VLAN_ETH_TYPE, f->cf_vlan_ethtype); + + if (f->cf_mask & FLOWER_ATTR_DST_MAC) + NLA_PUT(msg, TCA_FLOWER_KEY_ETH_DST, ETH_ALEN, f->cf_dst_mac); + + if (f->cf_mask & FLOWER_ATTR_DST_MAC_MASK) + NLA_PUT(msg, TCA_FLOWER_KEY_ETH_DST_MASK, ETH_ALEN, f->cf_dst_mac_mask); + + if (f->cf_mask & FLOWER_ATTR_SRC_MAC) + NLA_PUT(msg, TCA_FLOWER_KEY_ETH_SRC, ETH_ALEN, f->cf_src_mac); + + if (f->cf_mask & FLOWER_ATTR_SRC_MAC_MASK) + NLA_PUT(msg, TCA_FLOWER_KEY_ETH_SRC_MASK, ETH_ALEN, f->cf_src_mac_mask); + + if (f->cf_mask & FLOWER_ATTR_IP_DSCP) + NLA_PUT_U8(msg, TCA_FLOWER_KEY_IP_TOS, f->cf_ip_dscp); + + if (f->cf_mask & FLOWER_ATTR_IP_DSCP_MASK) + NLA_PUT_U8(msg, TCA_FLOWER_KEY_IP_TOS_MASK, f->cf_ip_dscp_mask); + + if (f->cf_mask & FLOWER_ATTR_IPV4_SRC) + NLA_PUT_U32(msg, TCA_FLOWER_KEY_IPV4_SRC, f->cf_ipv4_src); + + if (f->cf_mask & FLOWER_ATTR_IPV4_SRC_MASK) + NLA_PUT_U32(msg, TCA_FLOWER_KEY_IPV4_SRC_MASK, + f->cf_ipv4_src_mask); + + if (f->cf_mask & FLOWER_ATTR_IPV4_DST) + NLA_PUT_U32(msg, TCA_FLOWER_KEY_IPV4_DST, f->cf_ipv4_dst); + + if (f->cf_mask & FLOWER_ATTR_IPV4_DST_MASK) + NLA_PUT_U32(msg, TCA_FLOWER_KEY_IPV4_DST_MASK, + f->cf_ipv4_dst_mask); + + return 0; + +nla_put_failure: + return -NLE_NOMEM; +} + +static void flower_free_data(struct rtnl_tc *tc, void *data) +{ + struct rtnl_flower *f = data; + + if (f->cf_act) + rtnl_act_put_all(&f->cf_act); +} + +static int flower_clone(void *_dst, void *_src) +{ + struct rtnl_flower *dst = _dst, *src = _src; + + if (src->cf_act) { + if (!(dst->cf_act = rtnl_act_alloc())) + return -NLE_NOMEM; + + memcpy(dst->cf_act, src->cf_act, sizeof(struct rtnl_act)); + + /* action nl list next and prev pointers must be updated */ + nl_init_list_head(&dst->cf_act->ce_list); + + if ( src->cf_act->c_opts + && !(dst->cf_act->c_opts = nl_data_clone(src->cf_act->c_opts))) + return -NLE_NOMEM; + + if ( src->cf_act->c_xstats + && !(dst->cf_act->c_xstats = nl_data_clone(src->cf_act->c_xstats))) + return -NLE_NOMEM; + + if ( src->cf_act->c_subdata + && !(dst->cf_act->c_subdata = nl_data_clone(src->cf_act->c_subdata))) + return -NLE_NOMEM; + + if (dst->cf_act->c_link) { + nl_object_get(OBJ_CAST(dst->cf_act->c_link)); + } + + dst->cf_act->a_next = NULL; /* Only clone first in chain */ + } + + return 0; +} + +static void flower_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_flower *f = data; + char addr_str[INET_ADDRSTRLEN]; + char mask_str[INET_ADDRSTRLEN]; + + if (!f) + return; + + if (f->cf_mask & FLOWER_ATTR_FLAGS) + nl_dump(p, " flags %u", f->cf_flags); + + if (f->cf_mask & FLOWER_ATTR_PROTO) + nl_dump(p, " protocol %u", f->cf_proto); + + if (f->cf_mask & FLOWER_ATTR_VLAN_ID) + nl_dump(p, " vlan_id %u", f->cf_vlan_id); + + if (f->cf_mask & FLOWER_ATTR_VLAN_PRIO) + nl_dump(p, " vlan_prio %u", f->cf_vlan_prio); + + if (f->cf_mask & FLOWER_ATTR_VLAN_ETH_TYPE) + nl_dump(p, " vlan_ethtype %u", f->cf_vlan_ethtype); + + if (f->cf_mask & FLOWER_ATTR_DST_MAC) + nl_dump(p, " dst_mac %02x:%02x:%02x:%02x:%02x:%02x", + f->cf_dst_mac[0], f->cf_dst_mac[1], + f->cf_dst_mac[2], f->cf_dst_mac[3], + f->cf_dst_mac[4], f->cf_dst_mac[5]); + + if (f->cf_mask & FLOWER_ATTR_DST_MAC_MASK) + nl_dump(p, " dst_mac_mask %02x:%02x:%02x:%02x:%02x:%02x", + f->cf_dst_mac_mask[0], f->cf_dst_mac_mask[1], + f->cf_dst_mac_mask[2], f->cf_dst_mac_mask[3], + f->cf_dst_mac_mask[4], f->cf_dst_mac_mask[5]); + + if (f->cf_mask & FLOWER_ATTR_SRC_MAC) + nl_dump(p, " src_mac %02x:%02x:%02x:%02x:%02x:%02x", + f->cf_src_mac[0], f->cf_src_mac[1], + f->cf_src_mac[2], f->cf_src_mac[3], + f->cf_src_mac[4], f->cf_src_mac[5]); + + if (f->cf_mask & FLOWER_ATTR_SRC_MAC_MASK) + nl_dump(p, " src_mac_mask %02x:%02x:%02x:%02x:%02x:%02x", + f->cf_src_mac_mask[0], f->cf_src_mac_mask[1], + f->cf_src_mac_mask[2], f->cf_src_mac_mask[3], + f->cf_src_mac_mask[4], f->cf_src_mac_mask[5]); + + if (f->cf_mask & FLOWER_ATTR_IP_DSCP) + nl_dump(p, " dscp %u", f->cf_ip_dscp); + + if (f->cf_mask & FLOWER_ATTR_IP_DSCP_MASK) + nl_dump(p, " dscp_mask %u", f->cf_ip_dscp_mask); + + if (f->cf_mask & FLOWER_ATTR_IPV4_SRC) { + inet_ntop(AF_INET, &f->cf_ipv4_src, addr_str, sizeof(addr_str)); + inet_ntop(AF_INET, &f->cf_ipv4_src_mask, mask_str, sizeof(mask_str)); + nl_dump(p, "IPv4 src %s mask %s\n", addr_str, mask_str); + } + + if (f->cf_mask & FLOWER_ATTR_IPV4_DST) { + inet_ntop(AF_INET, &f->cf_ipv4_dst, addr_str, sizeof(addr_str)); + inet_ntop(AF_INET, &f->cf_ipv4_dst_mask, mask_str, sizeof(mask_str)); + nl_dump(p, "IPv4 dst %s mask %s\n", addr_str, mask_str); + } +} + +/** + * @name Attribute Modification + * @{ + */ + +/** + * Set protocol for flower classifier + * @arg cls Flower classifier. + * @arg proto protocol (ETH_P_*) + * @return 0 on success or a negative error code. + */ +int rtnl_flower_set_proto(struct rtnl_cls *cls, uint16_t proto) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + f->cf_proto = htons(proto); + f->cf_mask |= FLOWER_ATTR_PROTO; + + return 0; +} + +/** + * Get protocol for flower classifier + * @arg cls Flower classifier. + * @arg proto protocol + * @return 0 on success or a negative error code. +*/ +int rtnl_flower_get_proto(struct rtnl_cls *cls, uint16_t *proto) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data_peek(TC_CAST(cls)))) + return -NLE_INVAL; + + if (!(f->cf_mask & FLOWER_ATTR_PROTO)) + return -NLE_MISSING_ATTR; + + *proto = ntohs(f->cf_proto); + + return 0; +} + +/** + * Set vlan id for flower classifier + * @arg cls Flower classifier. + * @arg vid vlan id + * @return 0 on success or a negative error code. + */ +int rtnl_flower_set_vlan_id(struct rtnl_cls *cls, uint16_t vid) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if (vid > FLOWER_VID_MAX) + return -NLE_RANGE; + + f->cf_vlan_id = vid; + f->cf_mask |= FLOWER_ATTR_VLAN_ID; + + return 0; +} + +/** + * Get vlan id for flower classifier + * @arg cls Flower classifier. + * @arg vid vlan id + * @return 0 on success or a negative error code. +*/ +int rtnl_flower_get_vlan_id(struct rtnl_cls *cls, uint16_t *vid) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data_peek(TC_CAST(cls)))) + return -NLE_INVAL; + + if (!(f->cf_mask & FLOWER_ATTR_VLAN_ID)) + return -NLE_MISSING_ATTR; + + *vid = f->cf_vlan_id; + + return 0; +} + +/** + * Set vlan priority for flower classifier + * @arg cls Flower classifier. + * @arg prio vlan priority + * @return 0 on success or a negative error code. + */ +int rtnl_flower_set_vlan_prio(struct rtnl_cls *cls, uint8_t prio) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if (prio > FLOWER_VLAN_PRIO_MAX) + return -NLE_RANGE; + + f->cf_vlan_prio = prio; + f->cf_mask |= FLOWER_ATTR_VLAN_PRIO; + + return 0; +} + +/** + * Get vlan prio for flower classifier + * @arg cls Flower classifier. + * @arg prio vlan priority + * @return 0 on success or a negative error code. +*/ +int rtnl_flower_get_vlan_prio(struct rtnl_cls *cls, uint8_t *prio) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data_peek(TC_CAST(cls)))) + return -NLE_INVAL; + + if (!(f->cf_mask & FLOWER_ATTR_VLAN_PRIO)) + return -NLE_MISSING_ATTR; + + *prio = f->cf_vlan_prio; + + return 0; +} + +/** + * Set vlan ethertype for flower classifier + * @arg cls Flower classifier. + * @arg ethtype vlan ethertype + * @return 0 on success or a negative error code. + */ +int rtnl_flower_set_vlan_ethtype(struct rtnl_cls *cls, uint16_t ethtype) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if (!(f->cf_mask & FLOWER_ATTR_PROTO)) + return -NLE_MISSING_ATTR; + + if (f->cf_proto != htons(ETH_P_8021Q)) + return -NLE_INVAL; + + f->cf_vlan_ethtype = htons(ethtype); + f->cf_mask |= FLOWER_ATTR_VLAN_ETH_TYPE; + + return 0; +} + +/** + * Set destination mac address for flower classifier + * @arg cls Flower classifier. + * @arg mac destination mac address + * @arg mask mask for mac address + * @return 0 on success or a negative error code. + */ +int rtnl_flower_set_dst_mac(struct rtnl_cls *cls, unsigned char *mac, + unsigned char *mask) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if (mac) { + memcpy(f->cf_dst_mac, mac, ETH_ALEN); + f->cf_mask |= FLOWER_ATTR_DST_MAC; + + if (mask) { + memcpy(f->cf_dst_mac_mask, mask, ETH_ALEN); + f->cf_mask |= FLOWER_ATTR_DST_MAC_MASK; + } + + return 0; + } + + return -NLE_FAILURE; +} + +/** + * Get destination mac address for flower classifier + * @arg cls Flower classifier. + * @arg mac destination mac address + * @arg mask mask for mac address + * @return 0 on success or a negative error code. +*/ +int rtnl_flower_get_dst_mac(struct rtnl_cls *cls, unsigned char *mac, + unsigned char *mask) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data_peek(TC_CAST(cls)))) + return -NLE_INVAL; + + if (!(f->cf_mask & FLOWER_ATTR_DST_MAC)) + return -NLE_MISSING_ATTR; + + if (mac) + memcpy(mac, f->cf_dst_mac, ETH_ALEN); + + if (mask) + memcpy(mask, f->cf_dst_mac_mask, ETH_ALEN); + + return 0; +} + +/** + * Set source mac address for flower classifier + * @arg cls Flower classifier. + * @arg mac source mac address + * @arg mask mask for mac address + * @return 0 on success or a negative error code. + */ +int rtnl_flower_set_src_mac(struct rtnl_cls *cls, unsigned char *mac, + unsigned char *mask) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if (mac) { + memcpy(f->cf_src_mac, mac, ETH_ALEN); + f->cf_mask |= FLOWER_ATTR_SRC_MAC; + + if (mask) { + memcpy(f->cf_src_mac_mask, mask, ETH_ALEN); + f->cf_mask |= FLOWER_ATTR_SRC_MAC_MASK; + } + + return 0; + } + + return -NLE_FAILURE; +} + +/** + * Get source mac address for flower classifier + * @arg cls Flower classifier. + * @arg mac source mac address + * @arg mask mask for mac address + * @return 0 on success or a negative error code. +*/ +int rtnl_flower_get_src_mac(struct rtnl_cls *cls, unsigned char *mac, + unsigned char *mask) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data_peek(TC_CAST(cls)))) + return -NLE_INVAL; + + if (!(f->cf_mask & FLOWER_ATTR_SRC_MAC)) + return -NLE_MISSING_ATTR; + + if (mac) + memcpy(mac, f->cf_src_mac, ETH_ALEN); + + if (mask) + memcpy(mask, f->cf_src_mac_mask, ETH_ALEN); + + return 0; +} + +/** + * Set dscp value for flower classifier + * @arg cls Flower classifier. + * @arg dscp dscp value + * @arg mask mask for dscp value + * @return 0 on success or a negative error code. + */ +int rtnl_flower_set_ip_dscp(struct rtnl_cls *cls, uint8_t dscp, uint8_t mask) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if (dscp > FLOWER_DSCP_MAX) + return -NLE_RANGE; + + if (mask > FLOWER_DSCP_MASK_MAX) + return -NLE_RANGE; + + f->cf_ip_dscp = dscp; + f->cf_mask |= FLOWER_ATTR_IP_DSCP; + + if (mask) { + f->cf_ip_dscp_mask = mask; + f->cf_mask |= FLOWER_ATTR_IP_DSCP_MASK; + } + + return 0; +} + +/** + * Get dscp value for flower classifier + * @arg cls Flower classifier. + * @arg dscp dscp value + * @arg mask mask for dscp value + * @return 0 on success or a negative error code. +*/ +int rtnl_flower_get_ip_dscp(struct rtnl_cls *cls, uint8_t *dscp, uint8_t *mask) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data_peek(TC_CAST(cls)))) + return -NLE_INVAL; + + if (!(f->cf_mask & FLOWER_ATTR_IP_DSCP)) + return -NLE_MISSING_ATTR; + + *dscp = f->cf_ip_dscp; + *mask = f->cf_ip_dscp_mask; + + return 0; +} + +/** + * Set IPv4 source address for flower classifier + * @arg cls Flower classifier. + * @arg addr IPv4 source address + * @arg mask mask for IPv4 source address + * @return 0 on success or a negative error code. + */ +int rtnl_flower_set_ipv4_src(struct rtnl_cls *cls, in_addr_t addr, + in_addr_t mask) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if (addr) { + f->cf_ipv4_src = addr; + f->cf_mask |= FLOWER_ATTR_IPV4_SRC; + + if (mask) { + f->cf_ipv4_src_mask = mask; + f->cf_mask |= FLOWER_ATTR_IPV4_SRC_MASK; + } + + return 0; + } + + return -NLE_FAILURE; +} + +/** + * Get IPv4 source address for flower classifier + * @arg cls Flower classifier. + * @arg addr IPv4 source address + * @arg mask mask for IPv4 source address + * @return 0 on success or a negative error code. + */ +int rtnl_flower_get_ipv4_src(struct rtnl_cls *cls, in_addr_t *out_addr, + in_addr_t *out_mask) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data_peek(TC_CAST(cls)))) + return -NLE_INVAL; + + if (!(f->cf_mask & FLOWER_ATTR_IPV4_SRC)) + return -NLE_MISSING_ATTR; + + if (out_addr) + *out_addr = f->cf_ipv4_src; + + if (out_mask) { + if (f->cf_mask & FLOWER_ATTR_IPV4_SRC_MASK) + *out_mask = f->cf_ipv4_src_mask; + else + *out_mask = 0xffffffff; + } + + return 0; +} + +/** + * Set IPv4 destination address for flower classifier + * @arg cls Flower classifier. + * @arg addr IPv4 destination address + * @arg mask mask for IPv4 destination address + * @return 0 on success or a negative error code. + */ +int rtnl_flower_set_ipv4_dst(struct rtnl_cls *cls, in_addr_t addr, + in_addr_t mask) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if (addr) { + f->cf_ipv4_dst = addr; + f->cf_mask |= FLOWER_ATTR_IPV4_DST; + + if (mask) { + f->cf_ipv4_dst_mask = mask; + f->cf_mask |= FLOWER_ATTR_IPV4_DST_MASK; + } + + return 0; + } + + return -NLE_FAILURE; +} + +/** + * Get IPv4 destination address for flower classifier + * @arg cls Flower classifier. + * @arg addr IPv4 destination address + * @arg mask mask for IPv4 destination address + * @return 0 on success or a negative error code. + */ +int rtnl_flower_get_ipv4_dst(struct rtnl_cls *cls, in_addr_t *out_addr, + in_addr_t *out_mask) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data_peek(TC_CAST(cls)))) + return -NLE_INVAL; + + if (!(f->cf_mask & FLOWER_ATTR_IPV4_DST)) + return -NLE_MISSING_ATTR; + + if (out_addr) + *out_addr = f->cf_ipv4_dst; + + if (out_mask) { + if (f->cf_mask & FLOWER_ATTR_IPV4_DST_MASK) + *out_mask = f->cf_ipv4_dst_mask; + else + *out_mask = 0xffffffff; + } + + return 0; +} + +/** + * Append action for flower classifier + * @arg cls Flower classifier. + * @arg act action to append + * @return 0 on success or a negative error code. + */ +int rtnl_flower_append_action(struct rtnl_cls *cls, struct rtnl_act *act) +{ + struct rtnl_flower *f; + int err; + + if (!act) + return 0; + + if (!(f = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if ((err = _rtnl_act_append_get(&f->cf_act, act)) < 0) + return err; + + f->cf_mask |= FLOWER_ATTR_ACTION; + return 0; +} + +/** + * Delete action from flower classifier + * @arg cls Flower classifier. + * @arg act action to delete + * @return 0 on success or a negative error code. + */ +int rtnl_flower_del_action(struct rtnl_cls *cls, struct rtnl_act *act) +{ + struct rtnl_flower *f; + int ret; + + if (!act) + return 0; + + if (!(f = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if (!(f->cf_mask & FLOWER_ATTR_ACTION)) + return -NLE_INVAL; + + ret = rtnl_act_remove(&f->cf_act, act); + if (ret) + return ret; + + if (!f->cf_act) + f->cf_mask &= ~FLOWER_ATTR_ACTION; + rtnl_act_put(act); + + return 0; +} + +/** + * Get action from flower classifier + * @arg cls Flower classifier. + * @return action on success or NULL on error. + */ +struct rtnl_act* rtnl_flower_get_action(struct rtnl_cls *cls) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data_peek(TC_CAST(cls)))) + return NULL; + + if (!(f->cf_mask & FLOWER_ATTR_ACTION)) + return NULL; + + rtnl_act_get(f->cf_act); + + return f->cf_act; +} + +/** + * Set flags for flower classifier + * @arg cls Flower classifier. + * @arg flags (TCA_CLS_FLAGS_SKIP_HW | TCA_CLS_FLAGS_SKIP_SW) + * @return 0 on success or a negative error code. + */ +int rtnl_flower_set_flags(struct rtnl_cls *cls, int flags) +{ + struct rtnl_flower *f; + + if (!(f = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + f->cf_flags = flags; + f->cf_mask |= FLOWER_ATTR_FLAGS; + + return 0; +} + +/** @} */ + +static struct rtnl_tc_ops flower_ops = { + .to_kind = "flower", + .to_type = RTNL_TC_TYPE_CLS, + .to_size = sizeof(struct rtnl_flower), + .to_msg_parser = flower_msg_parser, + .to_free_data = flower_free_data, + .to_clone = flower_clone, + .to_msg_fill = flower_msg_fill, + .to_dump = { + [NL_DUMP_DETAILS] = flower_dump_details, + }, +}; + +static void _nl_init flower_init(void) +{ + rtnl_tc_register(&flower_ops); +} + +static void _nl_exit flower_exit(void) +{ + rtnl_tc_unregister(&flower_ops); +} diff --git a/lib/route/cls/fw.c b/lib/route/cls/fw.c index b569d4f..01be33f 100644 --- a/lib/route/cls/fw.c +++ b/lib/route/cls/fw.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/cls/fw.c fw classifier - * - * 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-2013 Thomas Graf * Copyright (c) 2006 Petr Gotthard * Copyright (c) 2006 Siemens AG Oesterreich @@ -18,14 +12,24 @@ * @{ */ -#include -#include +#include "nl-default.h" + #include -#include #include #include +#include "tc-api.h" + /** @cond SKIP */ +struct rtnl_fw { + uint32_t cf_classid; + struct nl_data *cf_act; + struct nl_data *cf_police; + char cf_indev[IFNAMSIZ]; + uint32_t cf_fwmask; + int cf_mask; +}; + #define FW_ATTR_CLASSID 0x001 #define FW_ATTR_ACTION 0x002 #define FW_ATTR_POLICE 0x004 @@ -94,9 +98,12 @@ static int fw_clone(void *_dst, void *_src) { struct rtnl_fw *dst = _dst, *src = _src; + dst->cf_act = NULL; + dst->cf_police = NULL; + if (src->cf_act && !(dst->cf_act = nl_data_clone(src->cf_act))) return -NLE_NOMEM; - + if (src->cf_police && !(dst->cf_police = nl_data_clone(src->cf_police))) return -NLE_NOMEM; @@ -206,12 +213,12 @@ static struct rtnl_tc_ops fw_ops = { }, }; -static void __init fw_init(void) +static void _nl_init fw_init(void) { rtnl_tc_register(&fw_ops); } -static void __exit fw_exit(void) +static void _nl_exit fw_exit(void) { rtnl_tc_unregister(&fw_ops); } diff --git a/lib/route/cls/mall.c b/lib/route/cls/mall.c new file mode 100644 index 0000000..030eaa8 --- /dev/null +++ b/lib/route/cls/mall.c @@ -0,0 +1,307 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2017 Volodymyr Bendiuga + */ + +/** + * @ingroup cls + * @defgroup cls_mall Match-all Classifier + * + * @{ + */ + +#include "nl-default.h" + +#include +#include +#include +#include +#include +#include + +#include "tc-api.h" +#include "nl-aux-route/nl-route.h" + +struct rtnl_mall { + uint32_t m_classid; + uint32_t m_flags; + struct rtnl_act *m_act; + int m_mask; +}; + +#define MALL_ATTR_CLASSID 0x01 +#define MALL_ATTR_FLAGS 0x02 +#define MALL_ATTR_ACTION 0x03 + + +static struct nla_policy mall_policy[TCA_MATCHALL_MAX + 1] = { + [TCA_MATCHALL_CLASSID] = { .type = NLA_U32 }, + [TCA_MATCHALL_FLAGS] = { .type = NLA_U32 }, +}; + +/** + * @name Attribute Modifications + * @{ + */ + +int rtnl_mall_set_classid(struct rtnl_cls *cls, uint32_t classid) +{ + struct rtnl_mall *mall; + if (!(mall = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + mall->m_classid = classid; + mall->m_mask |= MALL_ATTR_CLASSID; + + return 0; +} + +int rtnl_mall_get_classid(struct rtnl_cls *cls, uint32_t *classid) +{ + struct rtnl_mall *mall; + + if (!(mall = rtnl_tc_data_peek(TC_CAST(cls)))) + return -NLE_INVAL; + + if (!(mall->m_mask & MALL_ATTR_CLASSID)) + return -NLE_INVAL; + + *classid = mall->m_classid; + return 0; +} + +int rtnl_mall_set_flags(struct rtnl_cls *cls, uint32_t flags) +{ + struct rtnl_mall *mall; + + if (!(mall = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + mall->m_flags = flags; + mall->m_mask |= MALL_ATTR_FLAGS; + + return 0; +} + +int rtnl_mall_get_flags(struct rtnl_cls *cls, uint32_t *flags) +{ + struct rtnl_mall *mall; + + if (!(mall = rtnl_tc_data_peek(TC_CAST(cls)))) + return -NLE_INVAL; + + if (!(mall->m_mask & MALL_ATTR_FLAGS)) + return -NLE_INVAL; + + *flags = mall->m_flags; + return 0; +} + +int rtnl_mall_append_action(struct rtnl_cls *cls, struct rtnl_act *act) +{ + struct rtnl_mall *mall; + int err; + + if (!act) + return 0; + + if (!(mall = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if ((err = _rtnl_act_append_get(&mall->m_act, act)) < 0) + return err; + + mall->m_mask |= MALL_ATTR_ACTION; + return 0; +} + +struct rtnl_act *rtnl_mall_get_first_action(struct rtnl_cls *cls) +{ + struct rtnl_mall *mall; + struct rtnl_act *act; + + if (!(mall = rtnl_tc_data(TC_CAST(cls)))) + return NULL; + + if (!(mall->m_mask & MALL_ATTR_ACTION)) + return NULL; + + act = mall->m_act; + rtnl_act_get(act); + + return act; +} + +int rtnl_mall_del_action(struct rtnl_cls *cls, struct rtnl_act *act) +{ + struct rtnl_mall *mall; + int ret; + + if (!act) + return 0; + + if (!(mall = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if (!(mall->m_mask & MALL_ATTR_ACTION)) + return -NLE_INVAL; + + ret = rtnl_act_remove(&mall->m_act, act); + if (ret < 0) + return ret; + + rtnl_act_put(act); + + return 0; +} + +/** @} */ + +static void mall_free_data(struct rtnl_tc *tc, void *data) +{ + struct rtnl_mall *mall = data; + + if (mall->m_act) + rtnl_act_put_all(&mall->m_act); +} + +static int mall_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct rtnl_mall *mall = data; + struct nlattr *tb[TCA_MATCHALL_MAX + 1]; + int err; + + err = tca_parse(tb, TCA_MATCHALL_MAX, tc, mall_policy); + if (err < 0) + return err; + + if (tb[TCA_MATCHALL_CLASSID]) { + mall->m_classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]); + mall->m_mask |= MALL_ATTR_CLASSID; + } + + if (tb[TCA_MATCHALL_FLAGS]) { + mall->m_flags = nla_get_u32(tb[TCA_MATCHALL_FLAGS]); + mall->m_mask |= MALL_ATTR_FLAGS; + } + + if (tb[TCA_MATCHALL_ACT]) { + mall->m_mask |= MALL_ATTR_ACTION; + err = rtnl_act_parse(&mall->m_act, tb[TCA_MATCHALL_ACT]); + if (err < 0) + return err; + } + + return 0; +} + +static int mall_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + struct rtnl_mall *mall = data; + + if (!mall) + return 0; + + if (mall->m_mask & MALL_ATTR_CLASSID) + NLA_PUT_U32(msg, TCA_MATCHALL_CLASSID, mall->m_classid); + + if (mall->m_mask & MALL_ATTR_FLAGS) + NLA_PUT_U32(msg, TCA_MATCHALL_FLAGS, mall->m_flags); + + if (mall->m_mask & MALL_ATTR_ACTION) { + int err; + + err = rtnl_act_fill(msg, TCA_MATCHALL_ACT, mall->m_act); + if (err < 0) + return err; + } + + return 0; + +nla_put_failure: + return -NLE_NOMEM; +} + +static int mall_clone(void *_dst, void *_src) +{ + struct rtnl_mall *dst = _dst, *src = _src; + struct rtnl_act *next, *new; + int err; + + dst->m_act = NULL; + + if (src->m_act) { + if (!(dst->m_act = rtnl_act_alloc())) + return -NLE_NOMEM; + + /* action nl list next and prev pointers must be updated */ + nl_init_list_head(&dst->m_act->ce_list); + + memcpy(dst->m_act, src->m_act, sizeof(struct rtnl_act)); + next = rtnl_act_next(src->m_act); + while (next) { + new = (struct rtnl_act *) nl_object_clone((struct nl_object *) next); + if (!new) + return -NLE_NOMEM; + + err = _rtnl_act_append_take(&dst->m_act, new); + if (err < 0) + return err; + + next = rtnl_act_next(next); + } + } + + return 0; +} + +static void mall_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_mall *mall = data; + char buf[32]; + + if (!mall) + return; + + if (mall->m_mask & MALL_ATTR_CLASSID) + nl_dump(p, " target %s", + rtnl_tc_handle2str(mall->m_classid, buf, sizeof(buf))); +} + +static void mall_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_mall *mall = data; + + if (!mall) + return; + + nl_dump(p, "no details for match-all"); +} + +static struct rtnl_tc_ops mall_ops = { + .to_kind = "matchall", + .to_type = RTNL_TC_TYPE_CLS, + .to_size = sizeof(struct rtnl_mall), + .to_msg_parser = mall_msg_parser, + .to_free_data = mall_free_data, + .to_clone = mall_clone, + .to_msg_fill = mall_msg_fill, + .to_dump = { + [NL_DUMP_LINE] = mall_dump_line, + [NL_DUMP_DETAILS] = mall_dump_details, + }, +}; + +static void _nl_init mall_init(void) +{ + rtnl_tc_register(&mall_ops); +} + +static void _nl_exit mall_exit(void) +{ + rtnl_tc_unregister(&mall_ops); +} + +/** @} */ diff --git a/lib/route/cls/police.c b/lib/route/cls/police.c index 1f5d284..e7e3926 100644 --- a/lib/route/cls/police.c +++ b/lib/route/cls/police.c @@ -1,34 +1,29 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/cls/police.c Policer - * - * 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-2013 Thomas Graf */ -#include -#include +#include "nl-default.h" + #include #include -#include #include #include +#include "nl-priv-dynamic-core/nl-core.h" + /** * @name Policer Type * @{ */ static const struct trans_tbl police_types[] = { - __ADD(TC_POLICE_UNSPEC,unspec) - __ADD(TC_POLICE_OK,ok) - __ADD(TC_POLICE_RECLASSIFY,reclassify) - __ADD(TC_POLICE_SHOT,shot) + __ADD(TC_POLICE_UNSPEC,unspec), + __ADD(TC_POLICE_OK,ok), + __ADD(TC_POLICE_RECLASSIFY,reclassify), + __ADD(TC_POLICE_SHOT,shot), #ifdef TC_POLICE_PIPE - __ADD(TC_POLICE_PIPE,pipe) + __ADD(TC_POLICE_PIPE,pipe), #endif }; diff --git a/lib/route/cls/u32.c b/lib/route/cls/u32.c index c468ba7..52f6e31 100644 --- a/lib/route/cls/u32.c +++ b/lib/route/cls/u32.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/cls/u32.c u32 classifier - * - * 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-2013 Thomas Graf * Copyright (c) 2005-2006 Petr Gotthard * Copyright (c) 2005-2006 Siemens AG Oesterreich @@ -18,16 +12,33 @@ * @{ */ -#include -#include +#include "nl-default.h" + #include #include #include -#include #include #include +#include + +#include "tc-api.h" +#include "nl-aux-route/nl-route.h" /** @cond SKIP */ +struct rtnl_u32 { + uint32_t cu_divisor; + uint32_t cu_hash; + uint32_t cu_classid; + uint32_t cu_link; + struct nl_data *cu_pcnt; + struct nl_data *cu_selector; + struct nl_data *cu_mark; + struct rtnl_act *cu_act; + struct nl_data *cu_police; + char cu_indev[IFNAMSIZ]; + int cu_mask; +}; + #define U32_ATTR_DIVISOR 0x001 #define U32_ATTR_HASH 0x002 #define U32_ATTR_CLASSID 0x004 @@ -37,6 +48,7 @@ #define U32_ATTR_ACTION 0x040 #define U32_ATTR_POLICE 0x080 #define U32_ATTR_INDEV 0x100 +#define U32_ATTR_MARK 0x200 /** @endcond */ static inline struct tc_u32_sel *u32_selector(struct rtnl_u32 *u) @@ -52,6 +64,14 @@ static inline struct tc_u32_sel *u32_selector_alloc(struct rtnl_u32 *u) return u32_selector(u); } +static inline struct tc_u32_mark *u32_mark_alloc(struct rtnl_u32 *u) +{ + if (!u->cu_mark) + u->cu_mark = nl_data_alloc(NULL, sizeof(struct tc_u32_mark)); + + return (struct tc_u32_mark *) u->cu_mark->d_data; +} + static struct nla_policy u32_policy[TCA_U32_MAX+1] = { [TCA_U32_DIVISOR] = { .type = NLA_U32 }, [TCA_U32_HASH] = { .type = NLA_U32 }, @@ -61,6 +81,7 @@ static struct nla_policy u32_policy[TCA_U32_MAX+1] = { .maxlen = IFNAMSIZ }, [TCA_U32_SEL] = { .minlen = sizeof(struct tc_u32_sel) }, [TCA_U32_PCNT] = { .minlen = sizeof(struct tc_u32_pcnt) }, + [TCA_U32_MARK] = { .minlen = sizeof(struct tc_u32_mark) } }; static int u32_msg_parser(struct rtnl_tc *tc, void *data) @@ -85,6 +106,13 @@ static int u32_msg_parser(struct rtnl_tc *tc, void *data) u->cu_mask |= U32_ATTR_SELECTOR; } + if (tb[TCA_U32_MARK]) { + u->cu_mark = nl_data_alloc_attr(tb[TCA_U32_MARK]); + if (!u->cu_mark) + goto errout_nomem; + u->cu_mask |= U32_ATTR_MARK; + } + if (tb[TCA_U32_HASH]) { u->cu_hash = nla_get_u32(tb[TCA_U32_HASH]); u->cu_mask |= U32_ATTR_HASH; @@ -101,10 +129,10 @@ static int u32_msg_parser(struct rtnl_tc *tc, void *data) } if (tb[TCA_U32_ACT]) { - u->cu_act = nl_data_alloc_attr(tb[TCA_U32_ACT]); - if (!u->cu_act) - goto errout_nomem; u->cu_mask |= U32_ATTR_ACTION; + err = rtnl_act_parse(&u->cu_act, tb[TCA_U32_ACT]); + if (err < 0) + return err; } if (tb[TCA_U32_POLICE]) { @@ -122,7 +150,7 @@ static int u32_msg_parser(struct rtnl_tc *tc, void *data) err = -NLE_MISSING_ATTR; goto errout; } - + sel = u->cu_selector->d_data; pcnt_size = sizeof(struct tc_u32_pcnt) + (sel->nkeys * sizeof(uint64_t)); @@ -154,8 +182,10 @@ static void u32_free_data(struct rtnl_tc *tc, void *data) { struct rtnl_u32 *u = data; + if (u->cu_act) + rtnl_act_put_all(&u->cu_act); + nl_data_free(u->cu_mark); nl_data_free(u->cu_selector); - nl_data_free(u->cu_act); nl_data_free(u->cu_police); nl_data_free(u->cu_pcnt); } @@ -163,19 +193,96 @@ static void u32_free_data(struct rtnl_tc *tc, void *data) static int u32_clone(void *_dst, void *_src) { struct rtnl_u32 *dst = _dst, *src = _src; + _nl_auto_nl_data struct nl_data *selector = NULL; + _nl_auto_nl_data struct nl_data *mark = NULL; + _nl_auto_nl_data struct nl_data *police = NULL; + _nl_auto_nl_data struct nl_data *pcnt = NULL; + _nl_auto_nl_data struct nl_data *opts = NULL; + _nl_auto_nl_data struct nl_data *xstats = NULL; + _nl_auto_nl_data struct nl_data *subdata = NULL; + _nl_auto_rtnl_act struct rtnl_act *act = NULL; + + dst->cu_pcnt = NULL; + dst->cu_selector = NULL; + dst->cu_mark = NULL; + dst->cu_act = NULL; + dst->cu_police = NULL; + + if (src->cu_selector) { + if (!(selector = nl_data_clone(src->cu_selector))) + return -NLE_NOMEM; + } - if (src->cu_selector && - !(dst->cu_selector = nl_data_clone(src->cu_selector))) - return -NLE_NOMEM; + if (src->cu_mark) { + if (!(mark = nl_data_clone(src->cu_mark))) + return -NLE_NOMEM; + } - if (src->cu_act && !(dst->cu_act = nl_data_clone(src->cu_act))) - return -NLE_NOMEM; + if (src->cu_act) { + if (!(act = rtnl_act_alloc())) + return -NLE_NOMEM; - if (src->cu_police && !(dst->cu_police = nl_data_clone(src->cu_police))) - return -NLE_NOMEM; + if (src->cu_act->c_opts) { + if (!(opts = nl_data_clone(src->cu_act->c_opts))) + return -NLE_NOMEM; + } - if (src->cu_pcnt && !(dst->cu_pcnt = nl_data_clone(src->cu_pcnt))) - return -NLE_NOMEM; + if (src->cu_act->c_xstats) { + if (!(xstats = nl_data_clone(src->cu_act->c_xstats))) + return -NLE_NOMEM; + } + + if (src->cu_act->c_subdata) { + if (!(subdata = nl_data_clone(src->cu_act->c_subdata))) + return -NLE_NOMEM; + } + } + + if (src->cu_police) { + if (!(police = nl_data_clone(src->cu_police))) + return -NLE_NOMEM; + } + + if (src->cu_pcnt) { + if (!(pcnt = nl_data_clone(src->cu_pcnt))) + return -NLE_NOMEM; + } + + /* we've passed the critical point and its safe to proceed */ + + if (selector) + dst->cu_selector = _nl_steal_pointer(&selector); + + if (mark) + dst->cu_mark = _nl_steal_pointer(&mark); + + if (police) + dst->cu_police = _nl_steal_pointer(&police); + + if (pcnt) + dst->cu_pcnt = _nl_steal_pointer(&pcnt); + + if (act) { + dst->cu_act = _nl_steal_pointer(&act); + + /* action nl list next and prev pointers must be updated */ + nl_init_list_head(&dst->cu_act->ce_list); + + if (opts) + dst->cu_act->c_opts = _nl_steal_pointer(&opts); + + if (xstats) + dst->cu_act->c_xstats = _nl_steal_pointer(&xstats); + + if (subdata) + dst->cu_act->c_subdata = _nl_steal_pointer(&subdata); + + if (dst->cu_act->c_link) { + nl_object_get(OBJ_CAST(dst->cu_act->c_link)); + } + + dst->cu_act->a_next = NULL; /* Only clone first in chain */ + } return 0; } @@ -185,7 +292,7 @@ static void u32_dump_line(struct rtnl_tc *tc, void *data, { struct rtnl_u32 *u = data; char buf[32]; - + if (!u) return; @@ -233,10 +340,10 @@ static void print_selector(struct nl_dump_params *p, struct tc_u32_sel *sel, nl_dump(p, ">"); } - - + + for (i = 0; i < sel->nkeys; i++) { - key = (struct tc_u32_key *) ((char *) sel + sizeof(*sel)) + i; + key = &sel->keys[i]; nl_dump(p, "\n"); nl_dump_line(p, " match key at %s%u ", @@ -250,7 +357,9 @@ static void print_selector(struct nl_dump_params *p, struct tc_u32_sel *sel, if (p->dp_type == NL_DUMP_STATS && (u->cu_mask & U32_ATTR_PCNT)) { struct tc_u32_pcnt *pcnt = u->cu_pcnt->d_data; - nl_dump(p, " successful %" PRIu64, pcnt->kcnts[i]); + + nl_dump(p, " successful %llu", + (long long unsigned)pcnt->kcnts[i]); } } } @@ -259,40 +368,40 @@ static void u32_dump_details(struct rtnl_tc *tc, void *data, struct nl_dump_params *p) { struct rtnl_u32 *u = data; - struct tc_u32_sel *s; + struct tc_u32_sel *s = NULL; + struct tc_u32_mark *m; if (!u) return; if (!(u->cu_mask & U32_ATTR_SELECTOR)) { - nl_dump(p, "no-selector\n"); - return; + nl_dump(p, "no-selector"); + } else { + s = u->cu_selector->d_data; + nl_dump(p, "nkeys %u", s->nkeys); } - - s = u->cu_selector->d_data; - nl_dump(p, "nkeys %u ", s->nkeys); + if (!(u->cu_mask & U32_ATTR_MARK)) { + nl_dump(p, " no-mark"); + } else { + m = u->cu_mark->d_data; + nl_dump(p, " mark 0x%u 0x%u", m->val, m->mask); + } if (u->cu_mask & U32_ATTR_HASH) - nl_dump(p, "ht key 0x%x hash 0x%u", + nl_dump(p, " ht key 0x%x hash 0x%u", TC_U32_USERHTID(u->cu_hash), TC_U32_HASH(u->cu_hash)); if (u->cu_mask & U32_ATTR_LINK) - nl_dump(p, "link %u ", u->cu_link); + nl_dump(p, " link %u", u->cu_link); if (u->cu_mask & U32_ATTR_INDEV) - nl_dump(p, "indev %s ", u->cu_indev); - - print_selector(p, s, u); - nl_dump(p, "\n"); + nl_dump(p, " indev %s", u->cu_indev); -#if 0 -#define U32_ATTR_ACTION 0x040 -#define U32_ATTR_POLICE 0x080 + if (u->cu_mask & U32_ATTR_SELECTOR) + print_selector(p, s, u); - struct nl_data act; - struct nl_data police; -#endif + nl_dump(p, "\n"); } static void u32_dump_stats(struct rtnl_tc *tc, void *data, @@ -305,9 +414,11 @@ static void u32_dump_stats(struct rtnl_tc *tc, void *data, if (u->cu_mask & U32_ATTR_PCNT) { struct tc_u32_pcnt *pc = u->cu_pcnt->d_data; + nl_dump(p, "\n"); - nl_dump_line(p, " hit %8" PRIu64 " count %8" PRIu64 "\n", - pc->rhit, pc->rcnt); + nl_dump_line(p, " hit %8llu count %8llu\n", + (long long unsigned)pc->rhit, + (long long unsigned)pc->rcnt); } } @@ -317,7 +428,7 @@ static int u32_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) if (!u) return 0; - + if (u->cu_mask & U32_ATTR_DIVISOR) NLA_PUT_U32(msg, TCA_U32_DIVISOR, u->cu_divisor); @@ -333,8 +444,16 @@ static int u32_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) if (u->cu_mask & U32_ATTR_SELECTOR) NLA_PUT_DATA(msg, TCA_U32_SEL, u->cu_selector); - if (u->cu_mask & U32_ATTR_ACTION) - NLA_PUT_DATA(msg, TCA_U32_ACT, u->cu_act); + if (u->cu_mask & U32_ATTR_MARK) + NLA_PUT_DATA(msg, TCA_U32_MARK, u->cu_mark); + + if (u->cu_mask & U32_ATTR_ACTION) { + int err; + + err = rtnl_act_fill(msg, TCA_U32_ACT, u->cu_act); + if (err < 0) + return err; + } if (u->cu_mask & U32_ATTR_POLICE) NLA_PUT_DATA(msg, TCA_U32_POLICE, u->cu_police); @@ -360,20 +479,34 @@ void rtnl_u32_set_handle(struct rtnl_cls *cls, int htid, int hash, rtnl_tc_set_handle((struct rtnl_tc *) cls, handle ); } - + int rtnl_u32_set_classid(struct rtnl_cls *cls, uint32_t classid) { struct rtnl_u32 *u; if (!(u = rtnl_tc_data(TC_CAST(cls)))) return -NLE_NOMEM; - + u->cu_classid = classid; u->cu_mask |= U32_ATTR_CLASSID; return 0; } +int rtnl_u32_get_classid(struct rtnl_cls *cls, uint32_t *classid) +{ + struct rtnl_u32 *u; + + if (!(u = rtnl_tc_data_peek(TC_CAST(cls)))) + return -NLE_INVAL; + + if (!(u->cu_mask & U32_ATTR_CLASSID)) + return -NLE_INVAL; + + *classid = u->cu_classid; + return 0; +} + int rtnl_u32_set_divisor(struct rtnl_cls *cls, uint32_t divisor) { struct rtnl_u32 *u; @@ -414,7 +547,6 @@ int rtnl_u32_set_hashmask(struct rtnl_cls *cls, uint32_t hashmask, uint32_t offs { struct rtnl_u32 *u; struct tc_u32_sel *sel; - int err; hashmask = htonl(hashmask); @@ -425,22 +557,17 @@ int rtnl_u32_set_hashmask(struct rtnl_cls *cls, uint32_t hashmask, uint32_t offs if (!sel) return -NLE_NOMEM; - err = nl_data_append(u->cu_selector, NULL, sizeof(struct tc_u32_key)); - if(err < 0) - return err; - - sel = u32_selector(u); - sel->hmask = hashmask; sel->hoff = offset; return 0; } -int rtnl_u32_set_cls_terminal(struct rtnl_cls *cls) +int rtnl_u32_set_selector(struct rtnl_cls *cls, int offoff, uint32_t offmask, char offshift, uint16_t off, char flags) { struct rtnl_u32 *u; struct tc_u32_sel *sel; - int err; + + offmask = ntohs(offmask); if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls)))) return -NLE_NOMEM; @@ -449,16 +576,85 @@ int rtnl_u32_set_cls_terminal(struct rtnl_cls *cls) if (!sel) return -NLE_NOMEM; - err = nl_data_append(u->cu_selector, NULL, sizeof(struct tc_u32_key)); - if(err < 0) - return err; + sel->offoff = offoff; + sel->offmask = offmask; + sel->offshift = offshift; + sel->flags |= TC_U32_VAROFFSET; + sel->off = off; + sel->flags |= flags; + return 0; +} - sel = u32_selector(u); +int rtnl_u32_set_cls_terminal(struct rtnl_cls *cls) +{ + struct rtnl_u32 *u; + struct tc_u32_sel *sel; + + if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + sel = u32_selector_alloc(u); + if (!sel) + return -NLE_NOMEM; sel->flags |= TC_U32_TERMINAL; return 0; } +int rtnl_u32_add_action(struct rtnl_cls *cls, struct rtnl_act *act) +{ + struct rtnl_u32 *u; + int err; + + if (!act) + return 0; + + if (!(u = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if ((err = _rtnl_act_append_get(&u->cu_act, act)) < 0) + return err; + + u->cu_mask |= U32_ATTR_ACTION; + return 0; +} + +struct rtnl_act* rtnl_u32_get_action(struct rtnl_cls *cls) +{ + struct rtnl_u32 *u; + + if (!(u = rtnl_tc_data_peek(TC_CAST(cls)))) + return NULL; + + if (!(u->cu_mask & U32_ATTR_ACTION)) + return NULL; + + return u->cu_act; +} + +int rtnl_u32_del_action(struct rtnl_cls *cls, struct rtnl_act *act) +{ + struct rtnl_u32 *u; + int ret; + + if (!act) + return 0; + + if (!(u = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if (!(u->cu_mask & U32_ATTR_ACTION)) + return -NLE_INVAL; + + ret = rtnl_act_remove(&u->cu_act, act); + if (ret) + return ret; + + if (!u->cu_act) + u->cu_mask &= ~U32_ATTR_ACTION; + rtnl_act_put(act); + return 0; +} /** @} */ /** @@ -512,6 +708,9 @@ int rtnl_u32_add_key(struct rtnl_cls *cls, uint32_t val, uint32_t mask, if (!sel) return -NLE_NOMEM; + if (sel->nkeys == UCHAR_MAX) + return -NLE_NOMEM; + err = nl_data_append(u->cu_selector, NULL, sizeof(struct tc_u32_key)); if (err < 0) return err; @@ -529,6 +728,81 @@ int rtnl_u32_add_key(struct rtnl_cls *cls, uint32_t val, uint32_t mask, return 0; } +int rtnl_u32_add_mark(struct rtnl_cls *cls, uint32_t val, uint32_t mask) +{ + struct tc_u32_mark *mark; + struct rtnl_u32 *u; + + if (!(u = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + mark = u32_mark_alloc(u); + if (!mark) + return -NLE_NOMEM; + + mark->mask = mask; + mark->val = val; + + u->cu_mask |= U32_ATTR_MARK; + + return 0; +} + +int rtnl_u32_del_mark(struct rtnl_cls *cls) +{ + struct rtnl_u32 *u; + + if (!(u = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if (!(u->cu_mask)) + return -NLE_INVAL; + + if (!(u->cu_mask & U32_ATTR_MARK)) + return -NLE_INVAL; + + nl_data_free(u->cu_mark); + u->cu_mark = NULL; + u->cu_mask &= ~U32_ATTR_MARK; + + return 0; +} + +/** + * Get the 32-bit key from the selector + * + * @arg cls classifier to be retrieve + * @arg index the index of the array of keys, start with 0 + * @arg val pointer to store value after masked (network byte-order) + * @arg mask pointer to store the mask (network byte-order) + * @arg off pointer to store the offset + * @arg offmask pointer to store offset mask + * +*/ +int rtnl_u32_get_key(struct rtnl_cls *cls, uint8_t index, + uint32_t *val, uint32_t *mask, int *off, int *offmask) +{ + struct tc_u32_sel *sel; + struct rtnl_u32 *u; + + if (!(u = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if (!(u->cu_mask & U32_ATTR_SELECTOR)) + return -NLE_INVAL; + + sel = u32_selector(u); + if (index >= sel->nkeys) + return -NLE_RANGE; + + *mask = sel->keys[index].mask; + *val = sel->keys[index].val; + *off = sel->keys[index].off; + *offmask = sel->keys[index].offmask; + return 0; +} + + int rtnl_u32_add_key_uint8(struct rtnl_cls *cls, uint8_t val, uint8_t mask, int off, int offmask) { @@ -576,14 +850,14 @@ int rtnl_u32_add_key_uint32(struct rtnl_cls *cls, uint32_t val, uint32_t mask, off & ~3, offmask); } -int rtnl_u32_add_key_in_addr(struct rtnl_cls *cls, struct in_addr *addr, +int rtnl_u32_add_key_in_addr(struct rtnl_cls *cls, const struct in_addr *addr, uint8_t bitmask, int off, int offmask) { uint32_t mask = 0xFFFFFFFF << (32 - bitmask); return rtnl_u32_add_key(cls, addr->s_addr, htonl(mask), off, offmask); } -int rtnl_u32_add_key_in6_addr(struct rtnl_cls *cls, struct in6_addr *addr, +int rtnl_u32_add_key_in6_addr(struct rtnl_cls *cls, const struct in6_addr *addr, uint8_t bitmask, int off, int offmask) { int i, err; @@ -623,12 +897,12 @@ static struct rtnl_tc_ops u32_ops = { }, }; -static void __init u32_init(void) +static void _nl_init u32_init(void) { rtnl_tc_register(&u32_ops); } -static void __exit u32_exit(void) +static void _nl_exit u32_exit(void) { rtnl_tc_unregister(&u32_ops); } diff --git a/lib/route/link-sriov.h b/lib/route/link-sriov.h new file mode 100644 index 0000000..6493a57 --- /dev/null +++ b/lib/route/link-sriov.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2016 Intel Corp. All rights reserved. + * Copyright (c) 2016 Jef Oliver + */ + +#ifndef NETLINK_PRIV_LINK_SRIOV_H_ +#define NETLINK_PRIV_LINK_SRIOV_H_ + +#include +#include + +extern int rtnl_link_sriov_clone(struct rtnl_link *, struct rtnl_link *); +extern void rtnl_link_sriov_dump_details(struct rtnl_link *, struct nl_dump_params *); +extern void rtnl_link_sriov_dump_stats(struct rtnl_link *, struct nl_dump_params *); +extern int rtnl_link_sriov_fill_vflist(struct nl_msg *, struct rtnl_link *); +extern void rtnl_link_sriov_free_data(struct rtnl_link *); +extern int rtnl_link_sriov_parse_vflist(struct rtnl_link *, struct nlattr **); + +#endif diff --git a/lib/route/link.c b/lib/route/link.c index 77dd7f1..ce1355b 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/link.c Links (Interfaces) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -18,15 +12,25 @@ * @{ */ -#include +#include "nl-default.h" + +#include + #include #include #include #include #include +#include #include #include -#include + +#include "nl-aux-route/nl-route.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" +#include "nl-route.h" +#include "link-sriov.h" +#include "link/link-api.h" /** @cond SKIP */ #define LINK_ATTR_MTU (1 << 0) @@ -57,22 +61,44 @@ #define LINK_ATTR_CARRIER (1 << 25) #define LINK_ATTR_PROTINFO (1 << 26) #define LINK_ATTR_AF_SPEC (1 << 27) +#define LINK_ATTR_PHYS_PORT_ID (1 << 28) +#define LINK_ATTR_NS_FD (1 << 29) +#define LINK_ATTR_NS_PID (1 << 30) +/* 31 used by 32-bit api */ +#define LINK_ATTR_LINK_NETNSID ((uint64_t) 1 << 32) +#define LINK_ATTR_VF_LIST ((uint64_t) 1 << 33) +#define LINK_ATTR_CARRIER_CHANGES ((uint64_t) 1 << 34) +#define LINK_ATTR_PHYS_PORT_NAME ((uint64_t) 1 << 35) +#define LINK_ATTR_PHYS_SWITCH_ID ((uint64_t) 1 << 36) +#define LINK_ATTR_GSO_MAX_SEGS ((uint64_t) 1 << 37) +#define LINK_ATTR_GSO_MAX_SIZE ((uint64_t) 1 << 38) +#define LINK_ATTR_LINKINFO_SLAVE_KIND ((uint64_t) 1 << 39) static struct nl_cache_ops rtnl_link_ops; static struct nl_object_ops link_obj_ops; /** @endcond */ +struct rtnl_link *link_lookup(struct nl_cache *cache, int ifindex) +{ + if (!cache) { + cache = __nl_cache_mngt_require("route/link"); + if (!cache) + return NULL; + } + + return rtnl_link_get(cache, ifindex); +} + static struct rtnl_link_af_ops *af_lookup_and_alloc(struct rtnl_link *link, int family) { struct rtnl_link_af_ops *af_ops; - void *data; af_ops = rtnl_link_af_ops_lookup(family); if (!af_ops) return NULL; - if (!(data = rtnl_link_af_alloc(link, af_ops))) { + if (!rtnl_link_af_alloc(link, af_ops)) { rtnl_link_af_ops_put(af_ops); return NULL; } @@ -91,6 +117,17 @@ static int af_free(struct rtnl_link *link, struct rtnl_link_af_ops *ops, return 0; } +static int af_request_type(int af_type, struct rtnl_link *changes) +{ + struct rtnl_link_af_ops *ops; + + ops = rtnl_link_af_ops_lookup(af_type); + if (ops && ops->ao_override_rtm && ops->ao_override_rtm(changes)) + return RTM_SETLINK; + + return RTM_NEWLINK; +} + static int af_clone(struct rtnl_link *link, struct rtnl_link_af_ops *ops, void *data, void *arg) { @@ -107,19 +144,45 @@ static int af_fill(struct rtnl_link *link, struct rtnl_link_af_ops *ops, void *data, void *arg) { struct nl_msg *msg = arg; - struct nlattr *af_attr; + struct nlattr *af_attr = NULL; int err; if (!ops->ao_fill_af) return 0; - if (!(af_attr = nla_nest_start(msg, ops->ao_family))) - return -NLE_MSGSIZE; + if (!ops->ao_fill_af_no_nest) + if (!(af_attr = nla_nest_start(msg, ops->ao_family))) + return -NLE_MSGSIZE; if ((err = ops->ao_fill_af(link, arg, data)) < 0) return err; - nla_nest_end(msg, af_attr); + if (!ops->ao_fill_af_no_nest) + nla_nest_end(msg, af_attr); + + return 0; +} + +static int af_fill_pi(struct rtnl_link *link, struct rtnl_link_af_ops *ops, + void *data, void *arg) +{ + struct nl_msg *msg = arg; + struct nlattr *pi_attr; + int err, pi_type = IFLA_PROTINFO; + + if (!ops->ao_fill_pi) + return 0; + + if (ops->ao_fill_pi_flags > 0) + pi_type |= ops->ao_fill_pi_flags; + + if (!(pi_attr = nla_nest_start(msg, pi_type))) + return -NLE_MSGSIZE; + + if ((err = ops->ao_fill_pi(link, arg, data)) < 0) + return err; + + nla_nest_end(msg, pi_attr); return 0; } @@ -159,22 +222,19 @@ static int af_dump_stats(struct rtnl_link *link, struct rtnl_link_af_ops *ops, static int do_foreach_af(struct rtnl_link *link, int (*cb)(struct rtnl_link *, - struct rtnl_link_af_ops *, void *, void *), + struct rtnl_link_af_ops *, void *, void *), void *arg) { int i, err; for (i = 0; i < AF_MAX; i++) { if (link->l_af_data[i]) { - struct rtnl_link_af_ops *ops; + _nl_auto_rtnl_link_af_ops struct rtnl_link_af_ops *ops = NULL; if (!(ops = rtnl_link_af_ops_lookup(i))) BUG(); err = cb(link, ops, link->l_af_data[i], arg); - - rtnl_link_af_ops_put(ops); - if (err < 0) return err; } @@ -190,6 +250,10 @@ static void release_link_info(struct rtnl_link *link) if (io != NULL) { if (io->io_free) io->io_free(link); + else { + /* Catch missing io_free() implementations */ + BUG_ON(link->l_info); + } rtnl_link_info_ops_put(io); link->l_info_ops = NULL; } @@ -200,10 +264,7 @@ static void link_free_data(struct nl_object *c) struct rtnl_link *link = nl_object_priv(c); if (link) { - struct rtnl_link_info_ops *io; - - if ((io = link->l_info_ops) != NULL) - release_link_info(link); + release_link_info(link); /* proto info af reference */ rtnl_link_af_ops_put(link->l_af_ops); @@ -213,8 +274,15 @@ static void link_free_data(struct nl_object *c) free(link->l_ifalias); free(link->l_info_kind); + free(link->l_info_slave_kind); do_foreach_af(link, af_free, NULL); + + nl_data_free(link->l_phys_port_id); + nl_data_free(link->l_phys_switch_id); + + if (link->ce_mask & LINK_ATTR_VF_LIST) + rtnl_link_sriov_free_data(link); } } @@ -224,6 +292,19 @@ static int link_clone(struct nl_object *_dst, struct nl_object *_src) struct rtnl_link *src = nl_object_priv(_src); int err; + dst->l_addr = NULL; + dst->l_bcast = NULL; + dst->l_info_kind = NULL; + dst->l_info_slave_kind = NULL; + dst->l_info_ops = NULL; + memset(dst->l_af_data, 0, sizeof (dst->l_af_data)); + dst->l_info = NULL; + dst->l_ifalias = NULL; + dst->l_af_ops = NULL; + dst->l_phys_port_id = NULL; + dst->l_phys_switch_id = NULL; + dst->l_vf_list = NULL; + if (src->l_addr) if (!(dst->l_addr = nl_addr_clone(src->l_addr))) return -NLE_NOMEM; @@ -240,19 +321,44 @@ static int link_clone(struct nl_object *_dst, struct nl_object *_src) if (!(dst->l_info_kind = strdup(src->l_info_kind))) return -NLE_NOMEM; - if (src->l_info_ops && src->l_info_ops->io_clone) { - err = src->l_info_ops->io_clone(dst, src); - if (err < 0) - return err; + if (src->l_info_slave_kind) + if (!(dst->l_info_slave_kind = strdup(src->l_info_slave_kind))) + return -NLE_NOMEM; + + if (src->l_info_ops) { + + rtnl_link_info_ops_get(src->l_info_ops); + dst->l_info_ops = src->l_info_ops; + + if (src->l_info_ops->io_clone) { + err = src->l_info_ops->io_clone(dst, src); + if (err < 0) + return err; + } } if ((err = do_foreach_af(src, af_clone, dst)) < 0) return err; + if (src->l_af_ops) + dst->l_af_ops = af_lookup_and_alloc(dst, src->l_af_ops->ao_family); + + if (src->l_phys_port_id) + if (!(dst->l_phys_port_id = nl_data_clone(src->l_phys_port_id))) + return -NLE_NOMEM; + + if (src->l_phys_switch_id) + if (!(dst->l_phys_switch_id = nl_data_clone(src->l_phys_switch_id))) + return -NLE_NOMEM; + + if (src->ce_mask & LINK_ATTR_VF_LIST) + if ((err = rtnl_link_sriov_clone(dst, src)) < 0) + return err; + return 0; } -static struct nla_policy link_policy[IFLA_MAX+1] = { +struct nla_policy rtln_link_policy[IFLA_MAX+1] = { [IFLA_IFNAME] = { .type = NLA_STRING, .maxlen = IFNAMSIZ }, [IFLA_MTU] = { .type = NLA_U32 }, @@ -265,17 +371,26 @@ static struct nla_policy link_policy[IFLA_MAX+1] = { [IFLA_LINKINFO] = { .type = NLA_NESTED }, [IFLA_QDISC] = { .type = NLA_STRING, .maxlen = IFQDISCSIZ }, - [IFLA_STATS] = { .minlen = sizeof(struct rtnl_link_stats) }, - [IFLA_STATS64] = { .minlen = sizeof(struct rtnl_link_stats64)}, + [IFLA_STATS] = { .minlen = _nl_offsetofend (struct rtnl_link_stats, tx_compressed) }, + [IFLA_STATS64] = { .minlen = _nl_offsetofend (struct rtnl_link_stats64, tx_compressed) }, [IFLA_MAP] = { .minlen = sizeof(struct rtnl_link_ifmap) }, [IFLA_IFALIAS] = { .type = NLA_STRING, .maxlen = IFALIASZ }, [IFLA_NUM_VF] = { .type = NLA_U32 }, + [IFLA_VFINFO_LIST] = { .type = NLA_NESTED }, [IFLA_AF_SPEC] = { .type = NLA_NESTED }, [IFLA_PROMISCUITY] = { .type = NLA_U32 }, [IFLA_NUM_TX_QUEUES] = { .type = NLA_U32 }, [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 }, + [IFLA_GSO_MAX_SEGS] = { .type = NLA_U32 }, + [IFLA_GSO_MAX_SIZE] = { .type = NLA_U32 }, [IFLA_GROUP] = { .type = NLA_U32 }, [IFLA_CARRIER] = { .type = NLA_U8 }, + [IFLA_CARRIER_CHANGES] = { .type = NLA_U32 }, + [IFLA_PHYS_PORT_ID] = { .type = NLA_UNSPEC }, + [IFLA_PHYS_PORT_NAME] = { .type = NLA_STRING, .maxlen = IFNAMSIZ }, + [IFLA_PHYS_SWITCH_ID] = { .type = NLA_UNSPEC }, + [IFLA_NET_NS_PID] = { .type = NLA_U32 }, + [IFLA_NET_NS_FD] = { .type = NLA_U32 }, }; static struct nla_policy link_info_policy[IFLA_INFO_MAX+1] = { @@ -284,60 +399,13 @@ static struct nla_policy link_info_policy[IFLA_INFO_MAX+1] = { [IFLA_INFO_XSTATS] = { .type = NLA_NESTED }, }; -static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, - struct nlmsghdr *n, struct nl_parser_param *pp) +int rtnl_link_info_parse(struct rtnl_link *link, struct nlattr **tb) { - struct rtnl_link *link; - struct ifinfomsg *ifi; - struct nlattr *tb[IFLA_MAX+1]; - struct rtnl_link_af_ops *af_ops = NULL; - int err, family; - struct nla_policy real_link_policy[IFLA_MAX+1]; - - memcpy(&real_link_policy, link_policy, sizeof(link_policy)); - - link = rtnl_link_alloc(); - if (link == NULL) { - err = -NLE_NOMEM; - goto errout; - } - - link->ce_msgtype = n->nlmsg_type; - - if (!nlmsg_valid_hdr(n, sizeof(*ifi))) - return -NLE_MSG_TOOSHORT; - - ifi = nlmsg_data(n); - link->l_family = family = ifi->ifi_family; - link->l_arptype = ifi->ifi_type; - link->l_index = ifi->ifi_index; - link->l_flags = ifi->ifi_flags; - link->l_change = ifi->ifi_change; - link->ce_mask = (LINK_ATTR_IFNAME | LINK_ATTR_FAMILY | - LINK_ATTR_ARPTYPE| LINK_ATTR_IFINDEX | - LINK_ATTR_FLAGS | LINK_ATTR_CHANGE); - - if ((af_ops = af_lookup_and_alloc(link, family))) { - if (af_ops->ao_protinfo_policy) { - memcpy(&real_link_policy[IFLA_PROTINFO], - af_ops->ao_protinfo_policy, - sizeof(struct nla_policy)); - } - - link->l_af_ops = af_ops; - } - - err = nlmsg_parse(n, sizeof(*ifi), tb, IFLA_MAX, real_link_policy); - if (err < 0) - goto errout; - - if (tb[IFLA_IFNAME] == NULL) { - err = -NLE_MISSING_ATTR; - goto errout; - } + if (tb[IFLA_IFNAME] == NULL) + return -NLE_MISSING_ATTR; nla_strlcpy(link->l_name, tb[IFLA_IFNAME], IFNAMSIZ); - + link->ce_mask |= LINK_ATTR_IFNAME; if (tb[IFLA_STATS]) { struct rtnl_link_stats *st = nla_data(tb[IFLA_STATS]); @@ -369,6 +437,14 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, link->l_stats[RTNL_LINK_RX_COMPRESSED] = st->rx_compressed; link->l_stats[RTNL_LINK_TX_COMPRESSED] = st->tx_compressed; + /* beware: @st might not be the full struct, only fields up to + * tx_compressed are present. See _nl_offsetofend() above. */ + + if (nla_len(tb[IFLA_STATS]) >= _nl_offsetofend (struct rtnl_link_stats, rx_nohandler)) + link->l_stats[RTNL_LINK_RX_NOHANDLER] = st->rx_nohandler; + else + link->l_stats[RTNL_LINK_RX_NOHANDLER] = 0; + link->ce_mask |= LINK_ATTR_STATS; } @@ -380,11 +456,10 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, * Therefore, copy the data to the stack and access it from * there, where it will be aligned to 8. */ - struct rtnl_link_stats64 st; + struct rtnl_link_stats64 st = { 0 }; + + nla_memcpy(&st, tb[IFLA_STATS64], sizeof (st)); - nla_memcpy(&st, tb[IFLA_STATS64], - sizeof(struct rtnl_link_stats64)); - link->l_stats[RTNL_LINK_RX_PACKETS] = st.rx_packets; link->l_stats[RTNL_LINK_TX_PACKETS] = st.tx_packets; link->l_stats[RTNL_LINK_RX_BYTES] = st.rx_bytes; @@ -412,6 +487,11 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, link->l_stats[RTNL_LINK_RX_COMPRESSED] = st.rx_compressed; link->l_stats[RTNL_LINK_TX_COMPRESSED] = st.tx_compressed; + /* beware: @st might not be the full struct, only fields up to + * tx_compressed are present. See _nl_offsetofend() above. */ + + link->l_stats[RTNL_LINK_RX_NOHANDLER] = st.rx_nohandler; + link->ce_mask |= LINK_ATTR_STATS; } @@ -427,10 +507,8 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, if (tb[IFLA_ADDRESS]) { link->l_addr = nl_addr_alloc_attr(tb[IFLA_ADDRESS], AF_UNSPEC); - if (link->l_addr == NULL) { - err = -NLE_NOMEM; - goto errout; - } + if (link->l_addr == NULL) + return -NLE_NOMEM; nl_addr_set_family(link->l_addr, nl_addr_guess_family(link->l_addr)); link->ce_mask |= LINK_ATTR_ADDR; @@ -439,10 +517,8 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, if (tb[IFLA_BROADCAST]) { link->l_bcast = nl_addr_alloc_attr(tb[IFLA_BROADCAST], AF_UNSPEC); - if (link->l_bcast == NULL) { - err = -NLE_NOMEM; - goto errout; - } + if (link->l_bcast == NULL) + return -NLE_NOMEM; nl_addr_set_family(link->l_bcast, nl_addr_guess_family(link->l_bcast)); link->ce_mask |= LINK_ATTR_BRD; @@ -453,6 +529,11 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, link->ce_mask |= LINK_ATTR_LINK; } + if (tb[IFLA_LINK_NETNSID]) { + link->l_link_netnsid = nla_get_s32(tb[IFLA_LINK_NETNSID]); + link->ce_mask |= LINK_ATTR_LINK_NETNSID; + } + if (tb[IFLA_WEIGHT]) { link->l_weight = nla_get_u32(tb[IFLA_WEIGHT]); link->ce_mask |= LINK_ATTR_WEIGHT; @@ -464,7 +545,7 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, } if (tb[IFLA_MAP]) { - nla_memcpy(&link->l_map, tb[IFLA_MAP], + nla_memcpy(&link->l_map, tb[IFLA_MAP], sizeof(struct rtnl_link_ifmap)); link->ce_mask |= LINK_ATTR_MAP; } @@ -479,6 +560,11 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, link->ce_mask |= LINK_ATTR_CARRIER; } + if (tb[IFLA_CARRIER_CHANGES]) { + link->l_carrier_changes = nla_get_u32(tb[IFLA_CARRIER_CHANGES]); + link->ce_mask |= LINK_ATTR_CARRIER_CHANGES; + } + if (tb[IFLA_OPERSTATE]) { link->l_operstate = nla_get_u8(tb[IFLA_OPERSTATE]); link->ce_mask |= LINK_ATTR_OPERSTATE; @@ -491,16 +577,83 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, if (tb[IFLA_IFALIAS]) { link->l_ifalias = nla_strdup(tb[IFLA_IFALIAS]); - if (link->l_ifalias == NULL) { - err = -NLE_NOMEM; - goto errout; - } + if (link->l_ifalias == NULL) + return -NLE_NOMEM; link->ce_mask |= LINK_ATTR_IFALIAS; } + if (tb[IFLA_NET_NS_FD]) { + link->l_ns_fd = nla_get_u32(tb[IFLA_NET_NS_FD]); + link->ce_mask |= LINK_ATTR_NS_FD; + } + + if (tb[IFLA_NET_NS_PID]) { + link->l_ns_pid = nla_get_u32(tb[IFLA_NET_NS_PID]); + link->ce_mask |= LINK_ATTR_NS_PID; + } + + return 0; +} + +static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *n, struct nl_parser_param *pp) +{ + _nl_auto_rtnl_link struct rtnl_link *link = NULL; + struct nla_policy real_link_policy[ARRAY_SIZE(rtln_link_policy)]; + struct nla_policy *link_policy = rtln_link_policy; + struct rtnl_link_af_ops *af_ops_family; + struct ifinfomsg *ifi; + struct nlattr *tb[IFLA_MAX+1]; + int err, family; + + link = rtnl_link_alloc(); + if (link == NULL) + return -NLE_NOMEM; + + link->ce_msgtype = n->nlmsg_type; + + if (!nlmsg_valid_hdr(n, sizeof(*ifi))) + return -NLE_MSG_TOOSHORT; + + ifi = nlmsg_data(n); + link->l_family = family = ifi->ifi_family; + link->l_arptype = ifi->ifi_type; + link->l_index = ifi->ifi_index; + link->l_flags = ifi->ifi_flags; + link->l_change = ifi->ifi_change; + link->ce_mask = (LINK_ATTR_FAMILY | + LINK_ATTR_ARPTYPE| LINK_ATTR_IFINDEX | + LINK_ATTR_FLAGS | LINK_ATTR_CHANGE); + + if ((link->l_af_ops = af_lookup_and_alloc(link, family))) { + if (link->l_af_ops->ao_protinfo_policy) { + _NL_STATIC_ASSERT (sizeof(rtln_link_policy) == sizeof(real_link_policy)); + memcpy(&real_link_policy, rtln_link_policy, sizeof(rtln_link_policy)); + memcpy(&real_link_policy[IFLA_PROTINFO], + link->l_af_ops->ao_protinfo_policy, + sizeof(struct nla_policy)); + link_policy = real_link_policy; + } + } + + af_ops_family = link->l_af_ops; + + err = nlmsg_parse(n, sizeof(*ifi), tb, IFLA_MAX, link_policy); + if (err < 0) + return err; + + err = rtnl_link_info_parse(link, tb); + if (err < 0) + return err; + if (tb[IFLA_NUM_VF]) { link->l_num_vf = nla_get_u32(tb[IFLA_NUM_VF]); link->ce_mask |= LINK_ATTR_NUM_VF; + if (link->l_num_vf && tb[IFLA_VFINFO_LIST]) { + if ((err = rtnl_link_sriov_parse_vflist(link, tb)) < 0) + return err; + link->ce_mask |= LINK_ATTR_VF_LIST; + } } if (tb[IFLA_LINKINFO]) { @@ -509,19 +662,27 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, err = nla_parse_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO], link_info_policy); if (err < 0) - goto errout; + return err; if (li[IFLA_INFO_KIND]) { struct rtnl_link_info_ops *ops; - char *kind; + const char *kind = nla_get_string(li[IFLA_INFO_KIND]); + int af; - kind = nla_strdup(li[IFLA_INFO_KIND]); - if (kind == NULL) { - err = -NLE_NOMEM; - goto errout; + err = rtnl_link_set_type(link, kind); + if (err < 0) + return err; + + if ( (af = nl_str2af(kind)) >= 0 + && !link->l_af_ops + && (link->l_af_ops = af_lookup_and_alloc(link, af))) { + link->l_family = af; + if (link->l_af_ops->ao_protinfo_policy) + tb[IFLA_PROTINFO] = (struct nlattr *)link->l_af_ops->ao_protinfo_policy; } - link->l_info_kind = kind; - link->ce_mask |= LINK_ATTR_LINKINFO; + + if (link->l_info_ops) + release_link_info(link); ops = rtnl_link_info_ops_lookup(kind); link->l_info_ops = ops; @@ -532,39 +693,69 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, err = ops->io_parse(link, li[IFLA_INFO_DATA], li[IFLA_INFO_XSTATS]); if (err < 0) - goto errout; + return err; } else { /* XXX: Warn about unparsed info? */ } } + + link->ce_mask |= LINK_ATTR_LINKINFO; + } + + if (li[IFLA_INFO_SLAVE_KIND]) { + const char *kind = nla_get_string(li[IFLA_INFO_SLAVE_KIND]); + + err = rtnl_link_set_slave_type(link, kind); + if (err < 0) + return err; + + link->ce_mask |= LINK_ATTR_LINKINFO_SLAVE_KIND; } - link->ce_mask |= LINK_ATTR_LINKINFO; } - if (tb[IFLA_PROTINFO] && af_ops && af_ops->ao_parse_protinfo) { - err = af_ops->ao_parse_protinfo(link, tb[IFLA_PROTINFO], - link->l_af_data[link->l_family]); + if ( tb[IFLA_PROTINFO] + && link->l_af_ops + && link->l_af_ops->ao_parse_protinfo) { + err = link->l_af_ops->ao_parse_protinfo(link, tb[IFLA_PROTINFO], + link->l_af_data[link->l_family]); if (err < 0) - goto errout; + return err; link->ce_mask |= LINK_ATTR_PROTINFO; } if (tb[IFLA_AF_SPEC]) { - struct nlattr *af_attr; - int remaining; + /* parsing of IFLA_AF_SPEC is dependent on the family used + * in the request message. + */ + if ( af_ops_family + && af_ops_family->ao_parse_af_full) { + err = af_ops_family->ao_parse_af_full(link, + tb[IFLA_AF_SPEC], + link->l_af_data[af_ops_family->ao_family]); + if (err < 0) + return err; + link->ce_mask |= LINK_ATTR_AF_SPEC; + } else if (family == AF_UNSPEC) { + struct nlattr *af_attr; + int remaining; - nla_for_each_nested(af_attr, tb[IFLA_AF_SPEC], remaining) { - af_ops = af_lookup_and_alloc(link, nla_type(af_attr)); - if (af_ops && af_ops->ao_parse_af) { - char *af_data = link->l_af_data[nla_type(af_attr)]; + nla_for_each_nested(af_attr, tb[IFLA_AF_SPEC], remaining) { + _nl_auto_rtnl_link_af_ops struct rtnl_link_af_ops *af_ops = NULL; - err = af_ops->ao_parse_af(link, af_attr, af_data); - if (err < 0) - goto errout; - } + af_ops = af_lookup_and_alloc(link, nla_type(af_attr)); + if (af_ops && af_ops->ao_parse_af) { + char *af_data = link->l_af_data[nla_type(af_attr)]; + err = af_ops->ao_parse_af(link, af_attr, af_data); + if (err < 0) + return err; + } + } + link->ce_mask |= LINK_ATTR_AF_SPEC; + } else { + NL_DBG(3, "IFLA_AF_SPEC parsing not implemented for family %d\n", + family); } - link->ce_mask |= LINK_ATTR_AF_SPEC; } if (tb[IFLA_PROMISCUITY]) { @@ -582,23 +773,77 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, link->ce_mask |= LINK_ATTR_NUM_RX_QUEUES; } + if (tb[IFLA_GSO_MAX_SEGS]) { + link->l_gso_max_segs = nla_get_u32(tb[IFLA_GSO_MAX_SEGS]); + link->ce_mask |= LINK_ATTR_GSO_MAX_SEGS; + } + + if (tb[IFLA_GSO_MAX_SIZE]) { + link->l_gso_max_size = nla_get_u32(tb[IFLA_GSO_MAX_SIZE]); + link->ce_mask |= LINK_ATTR_GSO_MAX_SIZE; + } + if (tb[IFLA_GROUP]) { link->l_group = nla_get_u32(tb[IFLA_GROUP]); link->ce_mask |= LINK_ATTR_GROUP; } - err = pp->pp_cb((struct nl_object *) link, pp); -errout: - rtnl_link_af_ops_put(af_ops); - rtnl_link_put(link); - return err; + if (tb[IFLA_PHYS_PORT_ID]) { + link->l_phys_port_id = nl_data_alloc_attr(tb[IFLA_PHYS_PORT_ID]); + if (link->l_phys_port_id == NULL) + return -NLE_NOMEM; + link->ce_mask |= LINK_ATTR_PHYS_PORT_ID; + } + + if (tb[IFLA_PHYS_PORT_NAME]) { + nla_strlcpy(link->l_phys_port_name, tb[IFLA_PHYS_PORT_NAME], IFNAMSIZ); + link->ce_mask |= LINK_ATTR_PHYS_PORT_NAME; + } + + if (tb[IFLA_PHYS_SWITCH_ID]) { + link->l_phys_switch_id = nl_data_alloc_attr(tb[IFLA_PHYS_SWITCH_ID]); + if (link->l_phys_switch_id == NULL) + return -NLE_NOMEM; + link->ce_mask |= LINK_ATTR_PHYS_SWITCH_ID; + } + + return pp->pp_cb((struct nl_object *) link, pp); } static int link_request_update(struct nl_cache *cache, struct nl_sock *sk) { + _nl_auto_nl_msg struct nl_msg *msg = NULL; int family = cache->c_iarg1; + struct ifinfomsg hdr = { .ifi_family = family }; + struct rtnl_link_af_ops *ops; + int err; + __u32 ext_filter_mask = RTEXT_FILTER_VF; + + msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_DUMP); + if (!msg) + return -NLE_NOMEM; + + if (nlmsg_append(msg, &hdr, sizeof(hdr), NLMSG_ALIGNTO) < 0) + return -NLE_MSGSIZE; + + ops = rtnl_link_af_ops_lookup(family); + if (ops && ops->ao_get_af) { + err = ops->ao_get_af(msg, &ext_filter_mask); + if (err < 0) + return err; + } + + if (ext_filter_mask) { + err = nla_put(msg, IFLA_EXT_MASK, sizeof(ext_filter_mask), &ext_filter_mask); + if (err < 0) + return err; + } + + err = nl_send_auto(sk, msg); + if (err < 0) + return 0; - return nl_rtgen_request(sk, RTM_GETLINK, family, NLM_F_DUMP); + return 0; } static void link_dump_line(struct nl_object *obj, struct nl_dump_params *p) @@ -606,6 +851,15 @@ static void link_dump_line(struct nl_object *obj, struct nl_dump_params *p) char buf[128]; struct nl_cache *cache = obj->ce_cache; struct rtnl_link *link = (struct rtnl_link *) obj; + int fetched_cache = 0; + + if (!cache) { + cache = nl_cache_mngt_require_safe("route/link"); + fetched_cache = 1; + } + + if (link->l_family != AF_UNSPEC) + nl_dump_line(p, "%s ", nl_af2str(link->l_family, buf, sizeof(buf))); nl_dump_line(p, "%s %s ", link->l_name, nl_llproto2str(link->l_arptype, buf, sizeof(buf))); @@ -614,10 +868,12 @@ static void link_dump_line(struct nl_object *obj, struct nl_dump_params *p) nl_dump(p, "%s ", nl_addr2str(link->l_addr, buf, sizeof(buf))); if (link->ce_mask & LINK_ATTR_MASTER) { - struct rtnl_link *master = rtnl_link_get(cache, link->l_master); - nl_dump(p, "master %s ", master ? master->l_name : "inv"); - if (master) - rtnl_link_put(master); + if (cache) { + _nl_auto_rtnl_link struct rtnl_link *master = rtnl_link_get(cache, link->l_master); + + nl_dump(p, "master %s ", master ? master->l_name : "inv"); + } else + nl_dump(p, "master %d ", link->l_master); } rtnl_link_flags2str(link->l_flags, buf, sizeof(buf)); @@ -625,11 +881,16 @@ static void link_dump_line(struct nl_object *obj, struct nl_dump_params *p) nl_dump(p, "<%s> ", buf); if (link->ce_mask & LINK_ATTR_LINK) { - struct rtnl_link *ll = rtnl_link_get(cache, link->l_link); - nl_dump(p, "slave-of %s ", ll ? ll->l_name : "NONE"); - if (ll) - rtnl_link_put(ll); + if ( cache + && !(link->ce_mask & LINK_ATTR_LINK_NETNSID)) { + _nl_auto_rtnl_link struct rtnl_link *ll = rtnl_link_get(cache, link->l_link); + + nl_dump(p, "slave-of %s ", ll ? ll->l_name : "NONE"); + } else + nl_dump(p, "slave-of %d ", link->l_link); } + if (link->ce_mask & LINK_ATTR_LINK_NETNSID) + nl_dump(p, "link-netnsid %d ", link->l_link_netnsid); if (link->ce_mask & LINK_ATTR_GROUP) nl_dump(p, "group %u ", link->l_group); @@ -640,6 +901,9 @@ static void link_dump_line(struct nl_object *obj, struct nl_dump_params *p) do_foreach_af(link, af_dump_line, p); nl_dump(p, "\n"); + + if (fetched_cache) + nl_cache_put(cache); } static void link_dump_details(struct nl_object *obj, struct nl_dump_params *p) @@ -696,12 +960,18 @@ static void link_dump_details(struct nl_object *obj, struct nl_dump_params *p) nl_dump(p, "carrier %s", rtnl_link_carrier2str(link->l_carrier, buf, sizeof(buf))); + if (link->ce_mask & LINK_ATTR_CARRIER_CHANGES) + nl_dump(p, " carrier-changes %u", link->l_carrier_changes); + nl_dump(p, "\n"); if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_DETAILS]) link->l_info_ops->io_dump[NL_DUMP_DETAILS](link, p); do_foreach_af(link, af_dump_details, p); + + if (link->ce_mask & LINK_ATTR_VF_LIST) + rtnl_link_sriov_dump_details(link, p); } static void link_dump_stats(struct nl_object *obj, struct nl_dump_params *p) @@ -709,7 +979,7 @@ static void link_dump_stats(struct nl_object *obj, struct nl_dump_params *p) struct rtnl_link *link = (struct rtnl_link *) obj; char *unit, fmt[64]; float res; - + link_dump_details(obj, p); nl_dump_line(p, " Stats: bytes packets errors " @@ -719,7 +989,7 @@ static void link_dump_stats(struct nl_object *obj, struct nl_dump_params *p) strcpy(fmt, " RX %X.2f %s %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 "\n"); fmt[9] = *unit == 'B' ? '9' : '7'; - + nl_dump_line(p, fmt, res, unit, link->l_stats[RTNL_LINK_RX_PACKETS], link->l_stats[RTNL_LINK_RX_ERRORS], @@ -731,7 +1001,7 @@ static void link_dump_stats(struct nl_object *obj, struct nl_dump_params *p) strcpy(fmt, " TX %X.2f %s %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 "\n"); fmt[9] = *unit == 'B' ? '9' : '7'; - + nl_dump_line(p, fmt, res, unit, link->l_stats[RTNL_LINK_TX_PACKETS], link->l_stats[RTNL_LINK_TX_ERRORS], @@ -754,7 +1024,7 @@ static void link_dump_stats(struct nl_object *obj, struct nl_dump_params *p) nl_dump_line(p, " aborted carrier heartbeat " " window collision\n"); - + nl_dump_line(p, " TX %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 "\n", link->l_stats[RTNL_LINK_TX_ABORT_ERR], @@ -767,6 +1037,9 @@ static void link_dump_stats(struct nl_object *obj, struct nl_dump_params *p) link->l_info_ops->io_dump[NL_DUMP_STATS](link, p); do_foreach_af(link, af_dump_stats, p); + + if (link->ce_mask & LINK_ATTR_VF_LIST) + rtnl_link_sriov_dump_stats(link, p); } #if 0 @@ -824,7 +1097,7 @@ static void link_keygen(struct nl_object *obj, uint32_t *hashkey, struct link_hash_key { uint32_t l_index; uint32_t l_family; - } __attribute__((packed)) lkey; + } _nl_packed lkey; lkey_sz = sizeof(lkey); lkey.l_index = link->l_index; @@ -838,40 +1111,44 @@ static void link_keygen(struct nl_object *obj, uint32_t *hashkey, return; } -static int link_compare(struct nl_object *_a, struct nl_object *_b, - uint32_t attrs, int flags) +static uint64_t link_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) { struct rtnl_link *a = (struct rtnl_link *) _a; struct rtnl_link *b = (struct rtnl_link *) _b; - int diff = 0; - -#define LINK_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, LINK_ATTR_##ATTR, a, b, EXPR) - - diff |= LINK_DIFF(IFINDEX, a->l_index != b->l_index); - diff |= LINK_DIFF(MTU, a->l_mtu != b->l_mtu); - diff |= LINK_DIFF(LINK, a->l_link != b->l_link); - diff |= LINK_DIFF(TXQLEN, a->l_txqlen != b->l_txqlen); - diff |= LINK_DIFF(WEIGHT, a->l_weight != b->l_weight); - diff |= LINK_DIFF(MASTER, a->l_master != b->l_master); - diff |= LINK_DIFF(FAMILY, a->l_family != b->l_family); - diff |= LINK_DIFF(OPERSTATE, a->l_operstate != b->l_operstate); - diff |= LINK_DIFF(LINKMODE, a->l_linkmode != b->l_linkmode); - diff |= LINK_DIFF(QDISC, strcmp(a->l_qdisc, b->l_qdisc)); - diff |= LINK_DIFF(IFNAME, strcmp(a->l_name, b->l_name)); - diff |= LINK_DIFF(ADDR, nl_addr_cmp(a->l_addr, b->l_addr)); - diff |= LINK_DIFF(BRD, nl_addr_cmp(a->l_bcast, b->l_bcast)); - diff |= LINK_DIFF(IFALIAS, strcmp(a->l_ifalias, b->l_ifalias)); - diff |= LINK_DIFF(NUM_VF, a->l_num_vf != b->l_num_vf); - diff |= LINK_DIFF(PROMISCUITY, a->l_promiscuity != b->l_promiscuity); - diff |= LINK_DIFF(NUM_TX_QUEUES,a->l_num_tx_queues != b->l_num_tx_queues); - diff |= LINK_DIFF(NUM_RX_QUEUES,a->l_num_rx_queues != b->l_num_rx_queues); - diff |= LINK_DIFF(GROUP, a->l_group != b->l_group); + uint64_t diff = 0; + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(LINK_ATTR_IFINDEX, a->l_index != b->l_index); + diff |= _DIFF(LINK_ATTR_MTU, a->l_mtu != b->l_mtu); + diff |= _DIFF(LINK_ATTR_LINK, a->l_link != b->l_link); + diff |= _DIFF(LINK_ATTR_LINK_NETNSID, + a->l_link_netnsid != b->l_link_netnsid); + diff |= _DIFF(LINK_ATTR_TXQLEN, a->l_txqlen != b->l_txqlen); + diff |= _DIFF(LINK_ATTR_WEIGHT, a->l_weight != b->l_weight); + diff |= _DIFF(LINK_ATTR_MASTER, a->l_master != b->l_master); + diff |= _DIFF(LINK_ATTR_FAMILY, a->l_family != b->l_family); + diff |= _DIFF(LINK_ATTR_OPERSTATE, a->l_operstate != b->l_operstate); + diff |= _DIFF(LINK_ATTR_LINKMODE, a->l_linkmode != b->l_linkmode); + diff |= _DIFF(LINK_ATTR_QDISC, strcmp(a->l_qdisc, b->l_qdisc)); + diff |= _DIFF(LINK_ATTR_IFNAME, strcmp(a->l_name, b->l_name)); + diff |= _DIFF(LINK_ATTR_ADDR, nl_addr_cmp(a->l_addr, b->l_addr)); + diff |= _DIFF(LINK_ATTR_BRD, nl_addr_cmp(a->l_bcast, b->l_bcast)); + diff |= _DIFF(LINK_ATTR_IFALIAS, strcmp(a->l_ifalias, b->l_ifalias)); + diff |= _DIFF(LINK_ATTR_NUM_VF, a->l_num_vf != b->l_num_vf); + diff |= _DIFF(LINK_ATTR_PROMISCUITY, + a->l_promiscuity != b->l_promiscuity); + diff |= _DIFF(LINK_ATTR_NUM_TX_QUEUES, + a->l_num_tx_queues != b->l_num_tx_queues); + diff |= _DIFF(LINK_ATTR_NUM_RX_QUEUES, + a->l_num_rx_queues != b->l_num_rx_queues); + diff |= _DIFF(LINK_ATTR_GROUP, a->l_group != b->l_group); if (flags & LOOSE_COMPARISON) - diff |= LINK_DIFF(FLAGS, + diff |= _DIFF(LINK_ATTR_FLAGS, (a->l_flags ^ b->l_flags) & b->l_flag_mask); else - diff |= LINK_DIFF(FLAGS, a->l_flags != b->l_flags); + diff |= _DIFF(LINK_ATTR_FLAGS, a->l_flags != b->l_flags); /* * Compare LINK_ATTR_PROTINFO af_data @@ -881,42 +1158,52 @@ static int link_compare(struct nl_object *_a, struct nl_object *_b, goto protinfo_mismatch; } + diff |= _DIFF(LINK_ATTR_LINKINFO, rtnl_link_info_data_compare(a, b, flags) != 0); out: return diff; protinfo_mismatch: - diff |= LINK_DIFF(PROTINFO, 1); + diff |= _DIFF(LINK_ATTR_PROTINFO, 1); goto out; -#undef LINK_DIFF +#undef _DIFF } static const struct trans_tbl link_attrs[] = { - __ADD(LINK_ATTR_MTU, mtu) - __ADD(LINK_ATTR_LINK, link) - __ADD(LINK_ATTR_TXQLEN, txqlen) - __ADD(LINK_ATTR_WEIGHT, weight) - __ADD(LINK_ATTR_MASTER, master) - __ADD(LINK_ATTR_QDISC, qdisc) - __ADD(LINK_ATTR_MAP, map) - __ADD(LINK_ATTR_ADDR, address) - __ADD(LINK_ATTR_BRD, broadcast) - __ADD(LINK_ATTR_FLAGS, flags) - __ADD(LINK_ATTR_IFNAME, name) - __ADD(LINK_ATTR_IFINDEX, ifindex) - __ADD(LINK_ATTR_FAMILY, family) - __ADD(LINK_ATTR_ARPTYPE, arptype) - __ADD(LINK_ATTR_STATS, stats) - __ADD(LINK_ATTR_CHANGE, change) - __ADD(LINK_ATTR_OPERSTATE, operstate) - __ADD(LINK_ATTR_LINKMODE, linkmode) - __ADD(LINK_ATTR_IFALIAS, ifalias) - __ADD(LINK_ATTR_NUM_VF, num_vf) - __ADD(LINK_ATTR_PROMISCUITY, promiscuity) - __ADD(LINK_ATTR_NUM_TX_QUEUES, num_tx_queues) - __ADD(LINK_ATTR_NUM_RX_QUEUES, num_rx_queues) - __ADD(LINK_ATTR_GROUP, group) - __ADD(LINK_ATTR_CARRIER, carrier) + __ADD(LINK_ATTR_MTU, mtu), + __ADD(LINK_ATTR_LINK, link), + __ADD(LINK_ATTR_TXQLEN, txqlen), + __ADD(LINK_ATTR_WEIGHT, weight), + __ADD(LINK_ATTR_MASTER, master), + __ADD(LINK_ATTR_QDISC, qdisc), + __ADD(LINK_ATTR_MAP, map), + __ADD(LINK_ATTR_ADDR, address), + __ADD(LINK_ATTR_BRD, broadcast), + __ADD(LINK_ATTR_FLAGS, flags), + __ADD(LINK_ATTR_IFNAME, name), + __ADD(LINK_ATTR_IFINDEX, ifindex), + __ADD(LINK_ATTR_FAMILY, family), + __ADD(LINK_ATTR_ARPTYPE, arptype), + __ADD(LINK_ATTR_STATS, stats), + __ADD(LINK_ATTR_CHANGE, change), + __ADD(LINK_ATTR_OPERSTATE, operstate), + __ADD(LINK_ATTR_LINKMODE, linkmode), + __ADD(LINK_ATTR_IFALIAS, ifalias), + __ADD(LINK_ATTR_NUM_VF, num_vf), + __ADD(LINK_ATTR_PROMISCUITY, promiscuity), + __ADD(LINK_ATTR_NUM_TX_QUEUES, num_tx_queues), + __ADD(LINK_ATTR_NUM_RX_QUEUES, num_rx_queues), + __ADD(LINK_ATTR_GSO_MAX_SEGS, gso_max_segs), + __ADD(LINK_ATTR_GSO_MAX_SIZE, gso_max_size), + __ADD(LINK_ATTR_GROUP, group), + __ADD(LINK_ATTR_CARRIER, carrier), + __ADD(LINK_ATTR_CARRIER_CHANGES, carrier_changes), + __ADD(LINK_ATTR_PHYS_PORT_ID, phys_port_id), + __ADD(LINK_ATTR_PHYS_PORT_NAME, phys_port_name), + __ADD(LINK_ATTR_PHYS_SWITCH_ID, phys_switch_id), + __ADD(LINK_ATTR_NS_FD, ns_fd), + __ADD(LINK_ATTR_NS_PID, ns_pid), + __ADD(LINK_ATTR_LINK_NETNSID, link_netnsid), }; static char *link_attrs2str(int attrs, char *buf, size_t len) @@ -936,12 +1223,14 @@ static char *link_attrs2str(int attrs, char *buf, size_t len) * @arg sk Netlink socket. * @arg family Link address family or AF_UNSPEC * @arg result Pointer to store resulting cache. + * @arg flags Flags to set in link cache before filling * - * Allocates and initializes a new link cache. A netlink message is sent to - * the kernel requesting a full dump of all configured links. The returned - * messages are parsed and filled into the cache. If the operation succeeds - * the resulting cache will a link object for each link configured in the - * kernel. + * Allocates and initializes a new link cache. If \c sk is valid, a netlink + * message is sent to the kernel requesting a full dump of all configured + * links. The returned messages are parsed and filled into the cache. If + * the operation succeeds, the resulting cache will contain a link object for + * each link configured in the kernel. If \c sk is NULL, returns 0 but the + * cache is still empty. * * If \c family is set to an address family other than \c AF_UNSPEC the * contents of the cache can be limited to a specific address family. @@ -954,17 +1243,21 @@ static char *link_attrs2str(int attrs, char *buf, size_t len) * @see rtnl_link_get_by_name() * @return 0 on success or a negative error code. */ -int rtnl_link_alloc_cache(struct nl_sock *sk, int family, struct nl_cache **result) +int rtnl_link_alloc_cache_flags(struct nl_sock *sk, int family, + struct nl_cache **result, unsigned int flags) { struct nl_cache * cache; int err; - + cache = nl_cache_alloc(&rtnl_link_ops); if (!cache) return -NLE_NOMEM; cache->c_iarg1 = family; - + + if (flags) + nl_cache_set_flags(cache, flags); + if (sk && (err = nl_cache_refill(sk, cache)) < 0) { nl_cache_free(cache); return err; @@ -975,6 +1268,36 @@ int rtnl_link_alloc_cache(struct nl_sock *sk, int family, struct nl_cache **resu } /** + * Allocate link cache and fill in all configured links. + * @arg sk Netlink socket. + * @arg family Link address family or AF_UNSPEC + * @arg result Pointer to store resulting cache. + * + * Allocates and initializes a new link cache. If \c sk is valid, a netlink + * message is sent to the kernel requesting a full dump of all configured + * links. The returned messages are parsed and filled into the cache. If + * the operation succeeds, the resulting cache will contain a link object for + * each link configured in the kernel. If \c sk is NULL, returns 0 but the + * cache is still empty. + * + * If \c family is set to an address family other than \c AF_UNSPEC the + * contents of the cache can be limited to a specific address family. + * Currently the following address families are supported: + * - AF_BRIDGE + * - AF_INET6 + * + * @route_doc{link_list, Get List of Links} + * @see rtnl_link_get() + * @see rtnl_link_get_by_name() + * @return 0 on success or a negative error code. + */ +int rtnl_link_alloc_cache(struct nl_sock *sk, int family, struct nl_cache **result) +{ + return rtnl_link_alloc_cache_flags(sk, family, result, 0); +} + + +/** * Lookup link in cache by interface index * @arg cache Link cache * @arg ifindex Interface index @@ -1056,8 +1379,9 @@ struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache, int rtnl_link_build_get_request(int ifindex, const char *name, struct nl_msg **result) { + _nl_auto_nl_msg struct nl_msg *msg = NULL; struct ifinfomsg ifi; - struct nl_msg *msg; + __u32 vf_mask = RTEXT_FILTER_VF; if (ifindex <= 0 && !name) { APPBUG("ifindex or name must be specified"); @@ -1072,18 +1396,15 @@ int rtnl_link_build_get_request(int ifindex, const char *name, if (ifindex > 0) ifi.ifi_index = ifindex; - if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) - goto nla_put_failure; + _NL_RETURN_ON_PUT_ERR(nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO)); if (name) - NLA_PUT_STRING(msg, IFLA_IFNAME, name); + _NL_RETURN_ON_PUT_ERR(nla_put_string(msg, IFLA_IFNAME, name)); - *result = msg; - return 0; + _NL_RETURN_ON_PUT_ERR(nla_put(msg, IFLA_EXT_MASK, sizeof(vf_mask), &vf_mask)); -nla_put_failure: - nlmsg_free(msg); - return -NLE_MSGSIZE; + *result = _nl_steal_pointer(&msg); + return 0; } /** @@ -1099,34 +1420,49 @@ nla_put_failure: * pointer or -NLE_OBJ_NOTFOUND is returned if no matching link was * found. * + * Older kernels do not support lookup by name. In that case, libnl + * will fail with -NLE_OPNOTSUPP. Note that previous version of libnl + * failed in this case with -NLE_INVAL. You can check libnl behavior + * using NL_CAPABILITY_ROUTE_LINK_GET_KERNEL_FAIL_OPNOTSUPP capability. + * * @route_doc{link_direct_lookup, Lookup Single Link (Direct Lookup)} * @return 0 on success or a negative error code. */ int rtnl_link_get_kernel(struct nl_sock *sk, int ifindex, const char *name, struct rtnl_link **result) { - struct nl_msg *msg = NULL; - struct nl_object *obj; + _nl_auto_rtnl_link struct rtnl_link *link = NULL; + _nl_auto_nl_msg struct nl_msg *msg = NULL; int err; + int syserr; if ((err = rtnl_link_build_get_request(ifindex, name, &msg)) < 0) return err; err = nl_send_auto(sk, msg); - nlmsg_free(msg); if (err < 0) return err; - if ((err = nl_pickup(sk, link_msg_parser, &obj)) < 0) + err = nl_pickup_keep_syserr(sk, link_msg_parser, (struct nl_object **) &link, &syserr); + if (err < 0) { + if ( syserr == -EINVAL + && ifindex <= 0 + && name + && *name) { + /* Older kernels do not support lookup by ifname. This was added + * by commit kernel a3d1289126e7b14307074b76bf1677015ea5036f . + * Detect this error case and return NLE_OPNOTSUPP instead of + * NLE_INVAL. */ + return -NLE_OPNOTSUPP; + } return err; - - /* We have used link_msg_parser(), object is definitely a link */ - *result = (struct rtnl_link *) obj; + } /* If an object has been returned, we also need to wait for the ACK */ - if (err == 0 && obj) - wait_for_ack(sk); + if (err == 0 && link) + wait_for_ack(sk); + *result = _nl_steal_pointer(&link); return 0; } @@ -1147,11 +1483,11 @@ int rtnl_link_get_kernel(struct nl_sock *sk, int ifindex, const char *name, char * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst, size_t len) { - struct rtnl_link *link = rtnl_link_get(cache, ifindex); + _nl_auto_rtnl_link struct rtnl_link *link = NULL; + link = rtnl_link_get(cache, ifindex); if (link) { - strncpy(dst, link->l_name, len - 1); - rtnl_link_put(link); + _nl_strncpy_trunc(dst, link->l_name, len); return dst; } @@ -1169,33 +1505,19 @@ char * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst, */ int rtnl_link_name2i(struct nl_cache *cache, const char *name) { - int ifindex = 0; - struct rtnl_link *link; - + _nl_auto_rtnl_link struct rtnl_link *link = NULL; + link = rtnl_link_get_by_name(cache, name); - if (link) { - ifindex = link->l_index; - rtnl_link_put(link); - } + if (link) + return link->l_index; - return ifindex; + return 0; } /** @} */ -static int build_link_msg(int cmd, struct ifinfomsg *hdr, - struct rtnl_link *link, int flags, struct nl_msg **result) +int rtnl_link_fill_info(struct nl_msg *msg, struct rtnl_link *link) { - struct nl_msg *msg; - struct nlattr *af_spec; - - msg = nlmsg_alloc_simple(cmd, flags); - if (!msg) - return -NLE_NOMEM; - - if (nlmsg_append(msg, hdr, sizeof(*hdr), NLMSG_ALIGNTO) < 0) - goto nla_put_failure; - if (link->ce_mask & LINK_ATTR_ADDR) NLA_PUT_ADDR(msg, IFLA_ADDRESS, link->l_addr); @@ -1229,6 +1551,9 @@ static int build_link_msg(int cmd, struct ifinfomsg *hdr, if (link->ce_mask & LINK_ATTR_LINK) NLA_PUT_U32(msg, IFLA_LINK, link->l_link); + if (link->ce_mask & LINK_ATTR_LINK_NETNSID) + NLA_PUT_S32(msg, IFLA_LINK_NETNSID, link->l_link_netnsid); + if (link->ce_mask & LINK_ATTR_MASTER) NLA_PUT_U32(msg, IFLA_MASTER, link->l_master); @@ -1238,26 +1563,68 @@ static int build_link_msg(int cmd, struct ifinfomsg *hdr, if (link->ce_mask & LINK_ATTR_NUM_RX_QUEUES) NLA_PUT_U32(msg, IFLA_NUM_RX_QUEUES, link->l_num_rx_queues); + if (link->ce_mask & LINK_ATTR_NS_FD) + NLA_PUT_U32(msg, IFLA_NET_NS_FD, link->l_ns_fd); + + if (link->ce_mask & LINK_ATTR_NS_PID) + NLA_PUT_U32(msg, IFLA_NET_NS_PID, link->l_ns_pid); + + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +static int build_link_msg(int cmd, struct ifinfomsg *hdr, + struct rtnl_link *link, int flags, struct nl_msg **result) +{ + _nl_auto_nl_msg struct nl_msg *msg = NULL; + struct nlattr *af_spec; + + msg = nlmsg_alloc_simple(cmd, flags); + if (!msg) + return -NLE_NOMEM; + + if (nlmsg_append(msg, hdr, sizeof(*hdr), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if (rtnl_link_fill_info(msg, link)) + goto nla_put_failure; + if (link->ce_mask & LINK_ATTR_GROUP) NLA_PUT_U32(msg, IFLA_GROUP, link->l_group); - if (link->ce_mask & LINK_ATTR_LINKINFO) { + if (link->ce_mask & (LINK_ATTR_LINKINFO|LINK_ATTR_LINKINFO_SLAVE_KIND)) { struct nlattr *info; if (!(info = nla_nest_start(msg, IFLA_LINKINFO))) goto nla_put_failure; - NLA_PUT_STRING(msg, IFLA_INFO_KIND, link->l_info_kind); + if (link->ce_mask & LINK_ATTR_LINKINFO) { + NLA_PUT_STRING(msg, IFLA_INFO_KIND, link->l_info_kind); - if (link->l_info_ops) { - if (link->l_info_ops->io_put_attrs && - link->l_info_ops->io_put_attrs(msg, link) < 0) - goto nla_put_failure; + if (link->l_info_ops) { + if (link->l_info_ops->io_put_attrs && + link->l_info_ops->io_put_attrs(msg, link) < 0) + goto nla_put_failure; + } + } + + if (link->ce_mask & LINK_ATTR_LINKINFO_SLAVE_KIND) { + NLA_PUT_STRING(msg, IFLA_INFO_SLAVE_KIND, link->l_info_slave_kind); } nla_nest_end(msg, info); } + if (link->ce_mask & LINK_ATTR_VF_LIST) { + if (rtnl_link_sriov_fill_vflist(msg, link) < 0) + goto nla_put_failure; + } + + if (do_foreach_af(link, af_fill_pi, msg) < 0) + goto nla_put_failure; + if (!(af_spec = nla_nest_start(msg, IFLA_AF_SPEC))) goto nla_put_failure; @@ -1266,11 +1633,10 @@ static int build_link_msg(int cmd, struct ifinfomsg *hdr, nla_nest_end(msg, af_spec); - *result = msg; + *result = _nl_steal_pointer(&msg); return 0; nla_put_failure: - nlmsg_free(msg); return -NLE_MSGSIZE; } @@ -1302,6 +1668,7 @@ int rtnl_link_build_add_request(struct rtnl_link *link, int flags, .ifi_family = link->l_family, .ifi_index = link->l_index, .ifi_flags = link->l_flags, + .ifi_change = link->l_flag_mask, }; return build_link_msg(RTM_NEWLINK, &ifi, link, flags, result); @@ -1328,7 +1695,7 @@ int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags) { struct nl_msg *msg; int err; - + err = rtnl_link_build_add_request(link, flags, &msg); if (err < 0) return err; @@ -1364,11 +1731,12 @@ int rtnl_link_build_change_request(struct rtnl_link *orig, .ifi_family = orig->l_family, .ifi_index = orig->l_index, }; - int err; + int err, rt; if (changes->ce_mask & LINK_ATTR_FLAGS) { ifi.ifi_flags = orig->l_flags & ~changes->l_flag_mask; ifi.ifi_flags |= changes->l_flags; + ifi.ifi_change = changes->l_flag_mask; } if (changes->l_family && changes->l_family != orig->l_family) { @@ -1383,13 +1751,12 @@ int rtnl_link_build_change_request(struct rtnl_link *orig, !strcmp(orig->l_name, changes->l_name)) changes->ce_mask &= ~LINK_ATTR_IFNAME; - if ((err = build_link_msg(RTM_NEWLINK, &ifi, changes, flags, result)) < 0) - goto errout; + rt = af_request_type(orig->l_family, changes); - return 0; + if ((err = build_link_msg(rt, &ifi, changes, flags, result)) < 0) + return err; -errout: - return err; + return 0; } /** @@ -1421,32 +1788,40 @@ errout: * @note The link name can only be changed if the link has been put * in opertional down state. (~IF_UP) * + * @note On versions up to 3.4.0, \c NLE_SEQ_MISMATCH would be returned if the + * kernel does not supports \c RTM_NEWLINK. It is advised to ignore the + * error code if you cannot upgrade the library. + * * @return 0 on success or a negative error code. */ int rtnl_link_change(struct nl_sock *sk, struct rtnl_link *orig, struct rtnl_link *changes, int flags) { - struct nl_msg *msg; + _nl_auto_nl_msg struct nl_msg *msg = NULL; int err; - + err = rtnl_link_build_change_request(orig, changes, flags, &msg); if (err < 0) return err; + BUG_ON(msg->nm_nlh->nlmsg_seq != NL_AUTO_SEQ); retry: err = nl_send_auto_complete(sk, msg); if (err < 0) - goto errout; + return err; err = wait_for_ack(sk); - if (err == -NLE_OPNOTSUPP && msg->nm_nlh->nlmsg_type == RTM_NEWLINK) { + if ( err == -NLE_OPNOTSUPP + && msg->nm_nlh->nlmsg_type == RTM_NEWLINK) { msg->nm_nlh->nlmsg_type = RTM_SETLINK; + msg->nm_nlh->nlmsg_seq = NL_AUTO_SEQ; goto retry; } -errout: - nlmsg_free(msg); - return err; + if (err < 0) + return err; + + return 0; } /** @} */ @@ -1472,7 +1847,7 @@ errout: int rtnl_link_build_delete_request(const struct rtnl_link *link, struct nl_msg **result) { - struct nl_msg *msg; + _nl_auto_nl_msg struct nl_msg *msg = NULL; struct ifinfomsg ifi = { .ifi_index = link->l_index, }; @@ -1485,18 +1860,13 @@ int rtnl_link_build_delete_request(const struct rtnl_link *link, if (!(msg = nlmsg_alloc_simple(RTM_DELLINK, 0))) return -NLE_NOMEM; - if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) - goto nla_put_failure; + _NL_RETURN_ON_PUT_ERR(nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO)); if (link->ce_mask & LINK_ATTR_IFNAME) - NLA_PUT_STRING(msg, IFLA_IFNAME, link->l_name); + _NL_RETURN_ON_PUT_ERR(nla_put_string(msg, IFLA_IFNAME, link->l_name)); - *result = msg; + *result = _nl_steal_pointer(&msg); return 0; - -nla_put_failure: - nlmsg_free(msg); - return -NLE_MSGSIZE; } /** @@ -1527,7 +1897,7 @@ int rtnl_link_delete(struct nl_sock *sk, const struct rtnl_link *link) { struct nl_msg *msg; int err; - + if ((err = rtnl_link_build_delete_request(link, &msg)) < 0) return err; @@ -1553,7 +1923,7 @@ struct rtnl_link *rtnl_link_alloc(void) } /** - * Return a link object reference + * Release a link object reference * @arg link Link object */ void rtnl_link_put(struct rtnl_link *link) @@ -1577,7 +1947,7 @@ void rtnl_link_put(struct rtnl_link *link) */ void rtnl_link_set_name(struct rtnl_link *link, const char *name) { - strncpy(link->l_name, name, sizeof(link->l_name) - 1); + _nl_strncpy_trunc(link->l_name, name, sizeof(link->l_name)); link->ce_mask |= LINK_ATTR_IFNAME; } @@ -1743,9 +2113,12 @@ void rtnl_link_set_family(struct rtnl_link *link, int family) link->l_family = family; link->ce_mask |= LINK_ATTR_FAMILY; - if (link->l_af_ops) - af_free(link, link->l_af_ops, - link->l_af_data[link->l_af_ops->ao_family], NULL); + if (link->l_af_ops) { + int ao_family = link->l_af_ops->ao_family; + + af_free(link, link->l_af_ops, link->l_af_data[ao_family], NULL); + link->l_af_data[ao_family] = NULL; + } link->l_af_ops = af_lookup_and_alloc(link, family); } @@ -1891,6 +2264,40 @@ int rtnl_link_get_link(struct rtnl_link *link) } /** + * Set the netnsid of the link + * @arg link Link object + * @link_netnsid the netnsid to set + * + * Sets the IFLA_LINK_NETNSID attribute of the link + * @returns 0 on success + */ +int rtnl_link_set_link_netnsid(struct rtnl_link *link, int32_t link_netnsid) +{ + link->l_link_netnsid = link_netnsid; + link->ce_mask |= LINK_ATTR_LINK_NETNSID; + return 0; +} + +/** + * Get the netnsid of the link + * @arg link Link object + * @out_link_netnsid the netnsid + * + * Gets the IFLA_LINK_NETNSID attribute of the link + * or returns an error if the value is unset. + * + * @returns 0 on success + */ +int rtnl_link_get_link_netnsid(const struct rtnl_link *link, int32_t *out_link_netnsid) +{ + if (!(link->ce_mask & LINK_ATTR_LINK_NETNSID)) + return -NLE_INVAL; + + *out_link_netnsid = link->l_link_netnsid; + return 0; +} + +/** * Set master link of link object * @arg link Link object * @arg ifindex Interface index of master link @@ -1941,6 +2348,24 @@ uint8_t rtnl_link_get_carrier(struct rtnl_link *link) } /** + * Return carrier on/off changes of link object + * @arg link Link object + * @arg carrier_changes Pointer to store number of carrier changes + * + * @return 0 on success, negative error number otherwise + */ +int rtnl_link_get_carrier_changes(struct rtnl_link *link, uint32_t *carrier_changes) +{ + if (!(link->ce_mask & LINK_ATTR_CARRIER_CHANGES)) + return -NLE_NOATTR; + + if (carrier_changes) + *carrier_changes = link->l_carrier_changes; + + return 0; +} + +/** * Set operational status of link object * @arg link Link object * @arg status New opertional status @@ -2022,11 +2447,13 @@ const char *rtnl_link_get_ifalias(struct rtnl_link *link) void rtnl_link_set_ifalias(struct rtnl_link *link, const char *alias) { free(link->l_ifalias); - link->ce_mask &= ~LINK_ATTR_IFALIAS; if (alias) { link->l_ifalias = strdup(alias); link->ce_mask |= LINK_ATTR_IFALIAS; + } else { + link->l_ifalias = NULL; + link->ce_mask &= ~LINK_ATTR_IFALIAS; } } @@ -2045,7 +2472,7 @@ void rtnl_link_set_ifalias(struct rtnl_link *link, const char *alias) */ void rtnl_link_set_qdisc(struct rtnl_link *link, const char *name) { - strncpy(link->l_qdisc, name, sizeof(link->l_qdisc) - 1); + _nl_strncpy_trunc(link->l_qdisc, name, sizeof(link->l_qdisc)); link->ce_mask |= LINK_ATTR_QDISC; } @@ -2126,18 +2553,17 @@ int rtnl_link_set_stat(struct rtnl_link *link, rtnl_link_stat_id_t id, * be released with all link type specific attributes lost. * * @route_doc{link_modules, Link Modules} - * @return 0 on success or a negative errror code. + * @return 0 on success or a negative error code. */ int rtnl_link_set_type(struct rtnl_link *link, const char *type) { struct rtnl_link_info_ops *io; + _nl_auto_free char *kind = NULL; int err; - char *kind; free(link->l_info_kind); link->ce_mask &= ~LINK_ATTR_LINKINFO; - if (link->l_info_ops) - release_link_info(link); + release_link_info(link); if (!type) return 0; @@ -2148,20 +2574,18 @@ int rtnl_link_set_type(struct rtnl_link *link, const char *type) io = rtnl_link_info_ops_lookup(type); if (io) { - if (io->io_alloc && (err = io->io_alloc(link)) < 0) - goto errout; + if (io->io_alloc && (err = io->io_alloc(link)) < 0) { + _nl_clear_free(&kind); + return err; + } link->l_info_ops = io; } - link->l_info_kind = kind; + link->l_info_kind = _nl_steal_pointer(&kind); link->ce_mask |= LINK_ATTR_LINKINFO; return 0; - -errout: - free(kind); - return err; } /** @@ -2177,6 +2601,49 @@ char *rtnl_link_get_type(struct rtnl_link *link) } /** + * Set type of slave link object + * @arg link Link object (slave) + * @arg type Name of link type + * + * If a slave type has been assigned already it will be released. + * + * @route_doc{link_modules, Link Modules} + * @return 0 on success or a negative error code. + */ +int rtnl_link_set_slave_type(struct rtnl_link *link, const char *type) +{ + char *kind = NULL; + + if (type) { + kind = strdup(type); + if (!kind) + return -NLE_NOMEM; + } + + free(link->l_info_slave_kind); + link->l_info_slave_kind = kind; + + if (kind) + link->ce_mask |= LINK_ATTR_LINKINFO_SLAVE_KIND; + else + link->ce_mask &= ~LINK_ATTR_LINKINFO_SLAVE_KIND; + return 0; +} + +/** + * Return type of enslaved link + * @arg link Link object + * + * @route_doc{link_modules, Link Modules} + * @return Name of enslaved link type or NULL if not specified. + */ +const char *rtnl_link_get_slave_type(const struct rtnl_link *link) +{ + return link->l_info_slave_kind; +} + + +/** * Set link promiscuity count * @arg link Link object * @arg count New promiscuity count @@ -2265,6 +2732,97 @@ uint32_t rtnl_link_get_num_rx_queues(struct rtnl_link *link) return link->l_num_rx_queues; } +/** + * Return maximum number of segments for generic segmentation offload + * @arg link Link object + * @arg gso_max_segs Pointer to store maximum number GSO segments + * + * @return 0 on success, negative error number otherwise + */ +int rtnl_link_get_gso_max_segs(struct rtnl_link *link, uint32_t *gso_max_segs) +{ + if (!(link->ce_mask & LINK_ATTR_GSO_MAX_SEGS)) + return -NLE_NOATTR; + + if (gso_max_segs) + *gso_max_segs = link->l_gso_max_segs; + + return 0; +} + +/** + * Return maximum size for generic segmentation offload + * @arg link Link object + * @arg gso_max_segs Pointer to store maximum GSO size + * + * @return 0 on success, negative error number otherwise + */ +int rtnl_link_get_gso_max_size(struct rtnl_link *link, uint32_t *gso_max_size) +{ + if (!(link->ce_mask & LINK_ATTR_GSO_MAX_SIZE)) + return -NLE_NOATTR; + + if (gso_max_size) + *gso_max_size = link->l_gso_max_size; + + return 0; +} + +/** + * Return physical port id of link object + * @arg link Link object + * + * @return Physical port id or NULL if not set. + */ +struct nl_data *rtnl_link_get_phys_port_id(struct rtnl_link *link) +{ + return link->l_phys_port_id; +} + +/** + * Return physical port name of link object + * @arg link Link object + * + * @return Physical port name or NULL if not set. + */ +char *rtnl_link_get_phys_port_name(struct rtnl_link *link) +{ + return link->l_phys_port_name; +} + +/* + * Return physical switch id of link object + * @arg link Link object + * + * @return Physical switch id or NULL if not set. + */ +struct nl_data *rtnl_link_get_phys_switch_id(struct rtnl_link *link) +{ + return link->l_phys_switch_id; +} + +void rtnl_link_set_ns_fd(struct rtnl_link *link, int fd) +{ + link->l_ns_fd = fd; + link->ce_mask |= LINK_ATTR_NS_FD; +} + +int rtnl_link_get_ns_fd(struct rtnl_link *link) +{ + return link->l_ns_fd; +} + +void rtnl_link_set_ns_pid(struct rtnl_link *link, pid_t pid) +{ + link->l_ns_pid = pid; + link->ce_mask |= LINK_ATTR_NS_PID; +} + +pid_t rtnl_link_get_ns_pid(struct rtnl_link *link) +{ + return link->l_ns_pid; +} + /** @} */ /** @@ -2287,7 +2845,7 @@ uint32_t rtnl_link_get_num_rx_queues(struct rtnl_link *link) */ int rtnl_link_enslave_ifindex(struct nl_sock *sock, int master, int slave) { - struct rtnl_link *link; + _nl_auto_rtnl_link struct rtnl_link *link = NULL; int err; if (!(link = rtnl_link_alloc())) @@ -2295,14 +2853,14 @@ int rtnl_link_enslave_ifindex(struct nl_sock *sock, int master, int slave) rtnl_link_set_ifindex(link, slave); rtnl_link_set_master(link, master); - + if ((err = rtnl_link_change(sock, link, link, 0)) < 0) - goto errout; + return err; - rtnl_link_put(link); + _nl_clear_pointer(&link, rtnl_link_put); /* - * Due to the kernel not signaling whether this opertion is + * Due to the kernel not signaling whether this operation is * supported or not, we will retrieve the attribute to see if the * request was successful. If the master assigned remains unchanged * we will return NLE_OPNOTSUPP to allow performing backwards @@ -2312,12 +2870,9 @@ int rtnl_link_enslave_ifindex(struct nl_sock *sock, int master, int slave) return err; if (rtnl_link_get_master(link) != master) - err = -NLE_OPNOTSUPP; - -errout: - rtnl_link_put(link); + return -NLE_OPNOTSUPP; - return err; + return 0; } /** @@ -2396,25 +2951,25 @@ int rtnl_link_release(struct nl_sock *sock, struct rtnl_link *slave) */ static const struct trans_tbl link_flags[] = { - __ADD(IFF_LOOPBACK, loopback) - __ADD(IFF_BROADCAST, broadcast) - __ADD(IFF_POINTOPOINT, pointopoint) - __ADD(IFF_MULTICAST, multicast) - __ADD(IFF_NOARP, noarp) - __ADD(IFF_ALLMULTI, allmulti) - __ADD(IFF_PROMISC, promisc) - __ADD(IFF_MASTER, master) - __ADD(IFF_SLAVE, slave) - __ADD(IFF_DEBUG, debug) - __ADD(IFF_DYNAMIC, dynamic) - __ADD(IFF_AUTOMEDIA, automedia) - __ADD(IFF_PORTSEL, portsel) - __ADD(IFF_NOTRAILERS, notrailers) - __ADD(IFF_UP, up) - __ADD(IFF_RUNNING, running) - __ADD(IFF_LOWER_UP, lowerup) - __ADD(IFF_DORMANT, dormant) - __ADD(IFF_ECHO, echo) + __ADD(IFF_LOOPBACK, loopback), + __ADD(IFF_BROADCAST, broadcast), + __ADD(IFF_POINTOPOINT, pointopoint), + __ADD(IFF_MULTICAST, multicast), + __ADD(IFF_NOARP, noarp), + __ADD(IFF_ALLMULTI, allmulti), + __ADD(IFF_PROMISC, promisc), + __ADD(IFF_MASTER, master), + __ADD(IFF_SLAVE, slave), + __ADD(IFF_DEBUG, debug), + __ADD(IFF_DYNAMIC, dynamic), + __ADD(IFF_AUTOMEDIA, automedia), + __ADD(IFF_PORTSEL, portsel), + __ADD(IFF_NOTRAILERS, notrailers), + __ADD(IFF_UP, up), + __ADD(IFF_RUNNING, running), + __ADD(IFF_LOWER_UP, lowerup), + __ADD(IFF_DORMANT, dormant), + __ADD(IFF_ECHO, echo), }; char *rtnl_link_flags2str(int flags, char *buf, size_t len) @@ -2429,63 +2984,71 @@ int rtnl_link_str2flags(const char *name) } static const struct trans_tbl link_stats[] = { - __ADD(RTNL_LINK_RX_PACKETS, rx_packets) - __ADD(RTNL_LINK_TX_PACKETS, tx_packets) - __ADD(RTNL_LINK_RX_BYTES, rx_bytes) - __ADD(RTNL_LINK_TX_BYTES, tx_bytes) - __ADD(RTNL_LINK_RX_ERRORS, rx_errors) - __ADD(RTNL_LINK_TX_ERRORS, tx_errors) - __ADD(RTNL_LINK_RX_DROPPED, rx_dropped) - __ADD(RTNL_LINK_TX_DROPPED, tx_dropped) - __ADD(RTNL_LINK_RX_COMPRESSED, rx_compressed) - __ADD(RTNL_LINK_TX_COMPRESSED, tx_compressed) - __ADD(RTNL_LINK_RX_FIFO_ERR, rx_fifo_err) - __ADD(RTNL_LINK_TX_FIFO_ERR, tx_fifo_err) - __ADD(RTNL_LINK_RX_LEN_ERR, rx_len_err) - __ADD(RTNL_LINK_RX_OVER_ERR, rx_over_err) - __ADD(RTNL_LINK_RX_CRC_ERR, rx_crc_err) - __ADD(RTNL_LINK_RX_FRAME_ERR, rx_frame_err) - __ADD(RTNL_LINK_RX_MISSED_ERR, rx_missed_err) - __ADD(RTNL_LINK_TX_ABORT_ERR, tx_abort_err) - __ADD(RTNL_LINK_TX_CARRIER_ERR, tx_carrier_err) - __ADD(RTNL_LINK_TX_HBEAT_ERR, tx_hbeat_err) - __ADD(RTNL_LINK_TX_WIN_ERR, tx_win_err) - __ADD(RTNL_LINK_COLLISIONS, collisions) - __ADD(RTNL_LINK_MULTICAST, multicast) - __ADD(RTNL_LINK_IP6_INPKTS, Ip6InReceives) - __ADD(RTNL_LINK_IP6_INHDRERRORS, Ip6InHdrErrors) - __ADD(RTNL_LINK_IP6_INTOOBIGERRORS, Ip6InTooBigErrors) - __ADD(RTNL_LINK_IP6_INNOROUTES, Ip6InNoRoutes) - __ADD(RTNL_LINK_IP6_INADDRERRORS, Ip6InAddrErrors) - __ADD(RTNL_LINK_IP6_INUNKNOWNPROTOS, Ip6InUnknownProtos) - __ADD(RTNL_LINK_IP6_INTRUNCATEDPKTS, Ip6InTruncatedPkts) - __ADD(RTNL_LINK_IP6_INDISCARDS, Ip6InDiscards) - __ADD(RTNL_LINK_IP6_INDELIVERS, Ip6InDelivers) - __ADD(RTNL_LINK_IP6_OUTFORWDATAGRAMS, Ip6OutForwDatagrams) - __ADD(RTNL_LINK_IP6_OUTPKTS, Ip6OutRequests) - __ADD(RTNL_LINK_IP6_OUTDISCARDS, Ip6OutDiscards) - __ADD(RTNL_LINK_IP6_OUTNOROUTES, Ip6OutNoRoutes) - __ADD(RTNL_LINK_IP6_REASMTIMEOUT, Ip6ReasmTimeout) - __ADD(RTNL_LINK_IP6_REASMREQDS, Ip6ReasmReqds) - __ADD(RTNL_LINK_IP6_REASMOKS, Ip6ReasmOKs) - __ADD(RTNL_LINK_IP6_REASMFAILS, Ip6ReasmFails) - __ADD(RTNL_LINK_IP6_FRAGOKS, Ip6FragOKs) - __ADD(RTNL_LINK_IP6_FRAGFAILS, Ip6FragFails) - __ADD(RTNL_LINK_IP6_FRAGCREATES, Ip6FragCreates) - __ADD(RTNL_LINK_IP6_INMCASTPKTS, Ip6InMcastPkts) - __ADD(RTNL_LINK_IP6_OUTMCASTPKTS, Ip6OutMcastPkts) - __ADD(RTNL_LINK_IP6_INBCASTPKTS, Ip6InBcastPkts) - __ADD(RTNL_LINK_IP6_OUTBCASTPKTS, Ip6OutBcastPkts) - __ADD(RTNL_LINK_IP6_INOCTETS, Ip6InOctets) - __ADD(RTNL_LINK_IP6_OUTOCTETS, Ip6OutOctets) - __ADD(RTNL_LINK_IP6_INMCASTOCTETS, Ip6InMcastOctets) - __ADD(RTNL_LINK_IP6_OUTMCASTOCTETS, Ip6OutMcastOctets) - __ADD(RTNL_LINK_IP6_INBCASTOCTETS, Ip6InBcastOctets) - __ADD(RTNL_LINK_IP6_OUTBCASTOCTETS, Ip6OutBcastOctets) - __ADD(RTNL_LINK_ICMP6_INMSGS, ICMP6_InMsgs) - __ADD(RTNL_LINK_ICMP6_INERRORS, ICMP6_InErrors) - __ADD(RTNL_LINK_ICMP6_OUTMSGS, ICMP6_OutMsgs) - __ADD(RTNL_LINK_ICMP6_OUTERRORS, ICMP6_OutErrors) + __ADD(RTNL_LINK_RX_PACKETS, rx_packets), + __ADD(RTNL_LINK_TX_PACKETS, tx_packets), + __ADD(RTNL_LINK_RX_BYTES, rx_bytes), + __ADD(RTNL_LINK_TX_BYTES, tx_bytes), + __ADD(RTNL_LINK_RX_ERRORS, rx_errors), + __ADD(RTNL_LINK_TX_ERRORS, tx_errors), + __ADD(RTNL_LINK_RX_DROPPED, rx_dropped), + __ADD(RTNL_LINK_TX_DROPPED, tx_dropped), + __ADD(RTNL_LINK_RX_COMPRESSED, rx_compressed), + __ADD(RTNL_LINK_TX_COMPRESSED, tx_compressed), + __ADD(RTNL_LINK_RX_FIFO_ERR, rx_fifo_err), + __ADD(RTNL_LINK_TX_FIFO_ERR, tx_fifo_err), + __ADD(RTNL_LINK_RX_LEN_ERR, rx_len_err), + __ADD(RTNL_LINK_RX_OVER_ERR, rx_over_err), + __ADD(RTNL_LINK_RX_CRC_ERR, rx_crc_err), + __ADD(RTNL_LINK_RX_FRAME_ERR, rx_frame_err), + __ADD(RTNL_LINK_RX_MISSED_ERR, rx_missed_err), + __ADD(RTNL_LINK_TX_ABORT_ERR, tx_abort_err), + __ADD(RTNL_LINK_TX_CARRIER_ERR, tx_carrier_err), + __ADD(RTNL_LINK_TX_HBEAT_ERR, tx_hbeat_err), + __ADD(RTNL_LINK_TX_WIN_ERR, tx_win_err), + __ADD(RTNL_LINK_COLLISIONS, collisions), + __ADD(RTNL_LINK_MULTICAST, multicast), + __ADD(RTNL_LINK_IP6_INPKTS, Ip6InReceives), + __ADD(RTNL_LINK_IP6_INHDRERRORS, Ip6InHdrErrors), + __ADD(RTNL_LINK_IP6_INTOOBIGERRORS, Ip6InTooBigErrors), + __ADD(RTNL_LINK_IP6_INNOROUTES, Ip6InNoRoutes), + __ADD(RTNL_LINK_IP6_INADDRERRORS, Ip6InAddrErrors), + __ADD(RTNL_LINK_IP6_INUNKNOWNPROTOS, Ip6InUnknownProtos), + __ADD(RTNL_LINK_IP6_INTRUNCATEDPKTS, Ip6InTruncatedPkts), + __ADD(RTNL_LINK_IP6_INDISCARDS, Ip6InDiscards), + __ADD(RTNL_LINK_IP6_INDELIVERS, Ip6InDelivers), + __ADD(RTNL_LINK_IP6_OUTFORWDATAGRAMS, Ip6OutForwDatagrams), + __ADD(RTNL_LINK_IP6_OUTPKTS, Ip6OutRequests), + __ADD(RTNL_LINK_IP6_OUTDISCARDS, Ip6OutDiscards), + __ADD(RTNL_LINK_IP6_OUTNOROUTES, Ip6OutNoRoutes), + __ADD(RTNL_LINK_IP6_REASMTIMEOUT, Ip6ReasmTimeout), + __ADD(RTNL_LINK_IP6_REASMREQDS, Ip6ReasmReqds), + __ADD(RTNL_LINK_IP6_REASMOKS, Ip6ReasmOKs), + __ADD(RTNL_LINK_IP6_REASMFAILS, Ip6ReasmFails), + __ADD(RTNL_LINK_IP6_FRAGOKS, Ip6FragOKs), + __ADD(RTNL_LINK_IP6_FRAGFAILS, Ip6FragFails), + __ADD(RTNL_LINK_IP6_FRAGCREATES, Ip6FragCreates), + __ADD(RTNL_LINK_IP6_INMCASTPKTS, Ip6InMcastPkts), + __ADD(RTNL_LINK_IP6_OUTMCASTPKTS, Ip6OutMcastPkts), + __ADD(RTNL_LINK_IP6_INBCASTPKTS, Ip6InBcastPkts), + __ADD(RTNL_LINK_IP6_OUTBCASTPKTS, Ip6OutBcastPkts), + __ADD(RTNL_LINK_IP6_INOCTETS, Ip6InOctets), + __ADD(RTNL_LINK_IP6_OUTOCTETS, Ip6OutOctets), + __ADD(RTNL_LINK_IP6_INMCASTOCTETS, Ip6InMcastOctets), + __ADD(RTNL_LINK_IP6_OUTMCASTOCTETS, Ip6OutMcastOctets), + __ADD(RTNL_LINK_IP6_INBCASTOCTETS, Ip6InBcastOctets), + __ADD(RTNL_LINK_IP6_OUTBCASTOCTETS, Ip6OutBcastOctets), + __ADD(RTNL_LINK_ICMP6_INMSGS, ICMP6_InMsgs), + __ADD(RTNL_LINK_ICMP6_INERRORS, ICMP6_InErrors), + __ADD(RTNL_LINK_ICMP6_OUTMSGS, ICMP6_OutMsgs), + __ADD(RTNL_LINK_ICMP6_OUTERRORS, ICMP6_OutErrors), + __ADD(RTNL_LINK_ICMP6_CSUMERRORS, ICMP6_InCsumErrors), + __ADD(RTNL_LINK_IP6_CSUMERRORS, Ip6_InCsumErrors), + __ADD(RTNL_LINK_IP6_NOECTPKTS, Ip6_InNoECTPkts), + __ADD(RTNL_LINK_IP6_ECT1PKTS, Ip6_InECT1Pkts), + __ADD(RTNL_LINK_IP6_ECT0PKTS, Ip6_InECT0Pkts), + __ADD(RTNL_LINK_IP6_CEPKTS, Ip6_InCEPkts), + __ADD(RTNL_LINK_RX_NOHANDLER, rx_nohandler), + __ADD(RTNL_LINK_REASM_OVERLAPS, ReasmOverlaps), }; char *rtnl_link_stat2str(int st, char *buf, size_t len) @@ -2499,13 +3062,13 @@ int rtnl_link_str2stat(const char *name) } static const struct trans_tbl link_operstates[] = { - __ADD(IF_OPER_UNKNOWN, unknown) - __ADD(IF_OPER_NOTPRESENT, notpresent) - __ADD(IF_OPER_DOWN, down) - __ADD(IF_OPER_LOWERLAYERDOWN, lowerlayerdown) - __ADD(IF_OPER_TESTING, testing) - __ADD(IF_OPER_DORMANT, dormant) - __ADD(IF_OPER_UP, up) + __ADD(IF_OPER_UNKNOWN, unknown), + __ADD(IF_OPER_NOTPRESENT, notpresent), + __ADD(IF_OPER_DOWN, down), + __ADD(IF_OPER_LOWERLAYERDOWN, lowerlayerdown), + __ADD(IF_OPER_TESTING, testing), + __ADD(IF_OPER_DORMANT, dormant), + __ADD(IF_OPER_UP, up), }; char *rtnl_link_operstate2str(uint8_t st, char *buf, size_t len) @@ -2521,13 +3084,13 @@ int rtnl_link_str2operstate(const char *name) } static const struct trans_tbl link_modes[] = { - __ADD(IF_LINK_MODE_DEFAULT, default) - __ADD(IF_LINK_MODE_DORMANT, dormant) + __ADD(IF_LINK_MODE_DEFAULT, default), + __ADD(IF_LINK_MODE_DORMANT, dormant), }; static const struct trans_tbl carrier_states[] = { - __ADD(IF_CARRIER_DOWN, down) - __ADD(IF_CARRIER_UP, up) + __ADD(0, down), + __ADD(1, up), }; char *rtnl_link_mode2str(uint8_t st, char *buf, size_t len) @@ -2551,6 +3114,25 @@ int rtnl_link_str2carrier(const char *name) return __str2type(name, carrier_states, ARRAY_SIZE(carrier_states)); } +int rtnl_link_has_vf_list(struct rtnl_link *link) { + if (link->ce_mask & LINK_ATTR_VF_LIST) + return 1; + else + return 0; +} + +void rtnl_link_set_vf_list(struct rtnl_link *link) +{ + if (!rtnl_link_has_vf_list(link)) + link->ce_mask |= LINK_ATTR_VF_LIST; +} + +void rtnl_link_unset_vf_list(struct rtnl_link *link) +{ + if (rtnl_link_has_vf_list(link)) + link->ce_mask &= ~LINK_ATTR_VF_LIST; +} + /** @} */ /** @@ -2611,6 +3193,7 @@ static struct nl_object_ops link_obj_ops = { static struct nl_af_group link_groups[] = { { AF_UNSPEC, RTNLGRP_LINK }, { AF_BRIDGE, RTNLGRP_LINK }, + { AF_INET6, RTNLGRP_IPV6_IFINFO }, { END_OF_GROUP_LIST }, }; @@ -2631,12 +3214,12 @@ static struct nl_cache_ops rtnl_link_ops = { .co_obj_ops = &link_obj_ops, }; -static void __init link_init(void) +static void _nl_init link_init(void) { nl_cache_mngt_register(&rtnl_link_ops); } -static void __exit link_exit(void) +static void _nl_exit link_exit(void) { nl_cache_mngt_unregister(&rtnl_link_ops); } diff --git a/lib/route/link/api.c b/lib/route/link/api.c index 6d1e12f..abc9e6a 100644 --- a/lib/route/link/api.c +++ b/lib/route/link/api.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/link/api.c Link Info API - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf */ @@ -25,12 +19,12 @@ * .io_free = vlan_free, * }; * - * static void __init vlan_init(void) + * static void _nl_init vlan_init(void) * { * rtnl_link_register_info(&vlan_info_ops); * } * - * static void __exit vlan_exit(void) + * static void _nl_exit vlan_exit(void) * { * rtnl_link_unregister_info(&vlan_info_ops); * } @@ -39,11 +33,14 @@ * @{ */ -#include +#include "nl-default.h" + #include #include #include -#include + +#include "nl-route.h" +#include "link-api.h" static NL_LIST_HEAD(info_ops); @@ -87,13 +84,32 @@ struct rtnl_link_info_ops *rtnl_link_info_ops_lookup(const char *name) } /** + * Take reference to a set of operations. + * @arg ops Link info operations. + */ +void rtnl_link_info_ops_get(struct rtnl_link_info_ops *ops) +{ + if (!ops) + return; + + nl_write_lock(&info_lock); + ops->io_refcnt++; + nl_write_unlock(&info_lock); +} + +/** * Give back reference to a set of operations. * @arg ops Link info operations. */ void rtnl_link_info_ops_put(struct rtnl_link_info_ops *ops) { - if (ops) - ops->io_refcnt--; + if (!ops) + return; + + nl_write_lock(&info_lock); + _nl_assert(ops->io_refcnt > 0); + ops->io_refcnt--; + nl_write_unlock(&info_lock); } /** @@ -152,6 +168,7 @@ int rtnl_link_unregister_info(struct rtnl_link_info_ops *ops) nl_list_for_each_entry(t, &info_ops, io_list) { if (t == ops) { + _nl_assert(t->io_refcnt >= 0); if (t->io_refcnt > 0) { err = -NLE_BUSY; goto errout; @@ -208,8 +225,11 @@ struct rtnl_link_af_ops *rtnl_link_af_ops_lookup(const unsigned int family) */ void rtnl_link_af_ops_put(struct rtnl_link_af_ops *ops) { - if (ops) + if (ops) { + nl_write_lock(&info_lock); ops->ao_refcnt--; + nl_write_unlock(&info_lock); + } } /** @@ -391,6 +411,28 @@ out: return ret; } +/** + * Compare link info data + * @arg a Link object a + * @arg b Link object b + * + * This function will compare link_info data between two links + * a and b + * + * @return 0 if link_info data matches or is not present + * or != 0 if it mismatches. + */ +int rtnl_link_info_data_compare(struct rtnl_link *a, struct rtnl_link *b, int flags) +{ + if (a->l_info_ops != b->l_info_ops) + return ~0; + + if (!a->l_info_ops || !a->l_info_ops->io_compare) + return 0; + + return a->l_info_ops->io_compare(a, b, flags); +} + /** @} */ /** @} */ diff --git a/lib/route/link/bonding.c b/lib/route/link/bonding.c index f4c520b..63fd474 100644 --- a/lib/route/link/bonding.c +++ b/lib/route/link/bonding.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/link/bonding.c Bonding Link Module - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2011-2013 Thomas Graf */ @@ -20,9 +14,186 @@ * @{ */ -#include +#include "nl-default.h" + #include -#include +#include + +#include "nl-route.h" +#include "link-api.h" + +#define BOND_HAS_MODE (1 << 0) +#define BOND_HAS_ACTIVE_SLAVE (1 << 1) +#define BOND_HAS_HASHING_TYPE (1 << 2) +#define BOND_HAS_MIIMON (1 << 3) +#define BOND_HAS_MIN_LINKS (1 << 4) + +struct bond_info { + uint8_t bn_mode; + uint8_t hashing_type; + uint32_t ifindex; + uint32_t bn_mask; + uint32_t miimon; + uint32_t min_links; +}; + +static int bond_info_alloc(struct rtnl_link *link) +{ + struct bond_info *bn; + + if (link->l_info) + memset(link->l_info, 0, sizeof(*bn)); + else { + bn = calloc(1, sizeof(*bn)); + if (!bn) + return -NLE_NOMEM; + + link->l_info = bn; + } + + return 0; +} + +static void bond_info_free(struct rtnl_link *link) +{ + _nl_clear_free(&link->l_info); +} + +static int bond_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct bond_info *bn = link->l_info; + struct nlattr *data; + + data = nla_nest_start(msg, IFLA_INFO_DATA); + if (!data) + return -NLE_MSGSIZE; + if (bn->bn_mask & BOND_HAS_MODE) + NLA_PUT_U8(msg, IFLA_BOND_MODE, bn->bn_mode); + + if (bn->bn_mask & BOND_HAS_ACTIVE_SLAVE) + NLA_PUT_U32(msg, IFLA_BOND_ACTIVE_SLAVE, bn->ifindex); + + if (bn->bn_mask & BOND_HAS_HASHING_TYPE) + NLA_PUT_U8(msg, IFLA_BOND_XMIT_HASH_POLICY, bn->hashing_type); + + if (bn->bn_mask & BOND_HAS_MIIMON) + NLA_PUT_U32(msg, IFLA_BOND_MIIMON, bn->miimon); + + if (bn->bn_mask & BOND_HAS_MIN_LINKS) + NLA_PUT_U32(msg, IFLA_BOND_MIN_LINKS, bn->min_links); + + nla_nest_end(msg, data); + return 0; + +nla_put_failure: + nla_nest_cancel(msg, data); + return -NLE_MSGSIZE; +} + +static struct rtnl_link_info_ops bonding_info_ops = { + .io_name = "bond", + .io_alloc = bond_info_alloc, + .io_put_attrs = bond_put_attrs, + .io_free = bond_info_free, +}; + +#define IS_BOND_INFO_ASSERT(link) \ + do { \ + if (link->l_info_ops != &bonding_info_ops) { \ + APPBUG("Link is not a bond link. Set type \"bond\" first."); \ + } \ + } while (0) + +/** + * Set active slave for bond + * @arg link Link object of type bond + * @arg active ifindex of active slave to set + * + * @return void + */ +void rtnl_link_bond_set_activeslave(struct rtnl_link *link, int active_slave) +{ + struct bond_info *bn = link->l_info; + + IS_BOND_INFO_ASSERT(link); + + bn->ifindex = active_slave; + + bn->bn_mask |= BOND_HAS_ACTIVE_SLAVE; +} + +/** + * Set bond mode + * @arg link Link object of type bond + * @arg mode bond mode to set + * + * @return void + */ +void rtnl_link_bond_set_mode(struct rtnl_link *link, uint8_t mode) +{ + struct bond_info *bn = link->l_info; + + IS_BOND_INFO_ASSERT(link); + + bn->bn_mode = mode; + + bn->bn_mask |= BOND_HAS_MODE; +} + +/** + * Set hashing type + * @arg link Link object of type bond + * @arg type bond hashing type to set + * + * @return void + */ +void rtnl_link_bond_set_hashing_type (struct rtnl_link *link, uint8_t type) +{ + struct bond_info *bn = link->l_info; + + IS_BOND_INFO_ASSERT(link); + + bn->hashing_type = type; + + bn->bn_mask |= BOND_HAS_HASHING_TYPE; +} + +/** + * Set MII monitoring interval + * @arg link Link object of type bond + * @arg miimon interval in milliseconds + * + * @return void + */ +void rtnl_link_bond_set_miimon (struct rtnl_link *link, uint32_t miimon) +{ + struct bond_info *bn = link->l_info; + + IS_BOND_INFO_ASSERT(link); + + bn->miimon = miimon; + + bn->bn_mask |= BOND_HAS_MIIMON; +} + +/** + * Set the minimum number of member ports that must be up before + * marking the bond device as up + * @arg link Link object of type bond + * @arg min_links Number of links + * + * @return void + */ +void rtnl_link_bond_set_min_links (struct rtnl_link *link, uint32_t min_links) +{ + struct bond_info *bn = link->l_info; + + IS_BOND_INFO_ASSERT(link); + + bn->min_links = min_links; + + bn->bn_mask |= BOND_HAS_MIN_LINKS; +} /** * Allocate link object of type bond @@ -32,12 +203,11 @@ struct rtnl_link *rtnl_link_bond_alloc(void) { struct rtnl_link *link; - int err; if (!(link = rtnl_link_alloc())) return NULL; - if ((err = rtnl_link_set_type(link, "bond")) < 0) { + if (rtnl_link_set_type(link, "bond") < 0) { rtnl_link_put(link); return NULL; } @@ -210,16 +380,12 @@ int rtnl_link_bond_release(struct nl_sock *sock, struct rtnl_link *slave) rtnl_link_get_ifindex(slave)); } -static struct rtnl_link_info_ops bonding_info_ops = { - .io_name = "bond", -}; - -static void __init bonding_init(void) +static void _nl_init bonding_init(void) { rtnl_link_register_info(&bonding_info_ops); } -static void __exit bonding_exit(void) +static void _nl_exit bonding_exit(void) { rtnl_link_unregister_info(&bonding_info_ops); } diff --git a/lib/route/link/bridge.c b/lib/route/link/bridge.c index eb02b22..5b44164 100644 --- a/lib/route/link/bridge.c +++ b/lib/route/link/bridge.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/link/bridge.c AF_BRIDGE link support - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2010-2013 Thomas Graf */ @@ -17,19 +11,29 @@ * @{ */ -#include +#include "nl-default.h" + +#include + #include #include #include #include -#include -#include + +#include "nl-route.h" +#include "link-api.h" +#include "nl-priv-dynamic-core/nl-core.h" + +#define VLAN_VID_MASK 0x0fff /* VLAN Identifier */ /** @cond SKIP */ #define BRIDGE_ATTR_PORT_STATE (1 << 0) #define BRIDGE_ATTR_PRIORITY (1 << 1) #define BRIDGE_ATTR_COST (1 << 2) #define BRIDGE_ATTR_FLAGS (1 << 3) +#define BRIDGE_ATTR_PORT_VLAN (1 << 4) +#define BRIDGE_ATTR_HWMODE (1 << 5) +#define BRIDGE_ATTR_SELF (1 << 6) #define PRIV_FLAG_NEW_ATTRS (1 << 0) @@ -37,13 +41,38 @@ struct bridge_data { uint8_t b_port_state; uint8_t b_priv_flags; /* internal flags */ + uint16_t b_hwmode; uint16_t b_priority; + uint16_t b_self; /* here for comparison reasons */ uint32_t b_cost; uint32_t b_flags; uint32_t b_flags_mask; uint32_t ce_mask; /* HACK to support attr macros */ + struct rtnl_link_bridge_vlan vlan_info; }; +static void set_bit(unsigned nr, uint32_t *addr) +{ + if (nr < RTNL_LINK_BRIDGE_VLAN_BITMAP_MAX) + addr[nr / 32] |= (((uint32_t) 1) << (nr % 32)); +} + +static int find_next_bit(int i, uint32_t x) +{ + int j; + + if (i >= 32) + return -1; + + /* find first bit */ + if (i < 0) + return __builtin_ffs(x); + + /* mask off prior finds to get next */ + j = __builtin_ffs(x >> i); + return j ? j + i : 0; +} + static struct rtnl_link_af_ops bridge_ops; #define IS_BRIDGE_LINK_ASSERT(link) \ @@ -85,6 +114,9 @@ static struct nla_policy br_attrs_policy[IFLA_BRPORT_MAX+1] = { [IFLA_BRPORT_GUARD] = { .type = NLA_U8 }, [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 }, [IFLA_BRPORT_FAST_LEAVE] = { .type = NLA_U8 }, + [IFLA_BRPORT_LEARNING] = { .type = NLA_U8 }, + [IFLA_BRPORT_LEARNING_SYNC] = { .type = NLA_U8 }, + [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 }, }; static void check_flag(struct rtnl_link *link, struct nlattr *attrs[], @@ -137,10 +169,229 @@ static int bridge_parse_protinfo(struct rtnl_link *link, struct nlattr *attr, check_flag(link, br_attrs, IFLA_BRPORT_GUARD, RTNL_BRIDGE_BPDU_GUARD); check_flag(link, br_attrs, IFLA_BRPORT_PROTECT, RTNL_BRIDGE_ROOT_BLOCK); check_flag(link, br_attrs, IFLA_BRPORT_FAST_LEAVE, RTNL_BRIDGE_FAST_LEAVE); + check_flag(link, br_attrs, IFLA_BRPORT_UNICAST_FLOOD, + RTNL_BRIDGE_UNICAST_FLOOD); + check_flag(link, br_attrs, IFLA_BRPORT_LEARNING, RTNL_BRIDGE_LEARNING); + check_flag(link, br_attrs, IFLA_BRPORT_LEARNING_SYNC, + RTNL_BRIDGE_LEARNING_SYNC); return 0; } +static int bridge_parse_af_full(struct rtnl_link *link, struct nlattr *attr_full, + void *data) +{ + struct bridge_data *bd = data; + struct bridge_vlan_info *vinfo = NULL; + uint16_t vid_range_start = 0; + uint16_t vid_range_flags = -1; + + struct nlattr *attr; + int remaining; + + nla_for_each_nested(attr, attr_full, remaining) { + + if (nla_type(attr) == IFLA_BRIDGE_MODE) { + bd->b_hwmode = nla_get_u16(attr); + bd->ce_mask |= BRIDGE_ATTR_HWMODE; + continue; + } else if (nla_type(attr) != IFLA_BRIDGE_VLAN_INFO) + continue; + + if (nla_len(attr) != sizeof(struct bridge_vlan_info)) + return -EINVAL; + + vinfo = nla_data(attr); + if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK) + return -EINVAL; + + + if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) { + vid_range_start = vinfo->vid; + vid_range_flags = (vinfo->flags ^ BRIDGE_VLAN_INFO_RANGE_BEGIN); + continue; + } + + if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END) { + /* sanity check the range flags */ + if (vid_range_flags != (vinfo->flags ^ BRIDGE_VLAN_INFO_RANGE_END)) { + NL_DBG(1, "VLAN range flags differ; can not handle it.\n"); + return -EINVAL; + } + } else { + vid_range_start = vinfo->vid; + } + + for (; vid_range_start <= vinfo->vid; vid_range_start++) { + if (vinfo->flags & BRIDGE_VLAN_INFO_PVID) + bd->vlan_info.pvid = vinfo->vid; + + if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED) + set_bit(vid_range_start, bd->vlan_info.untagged_bitmap); + + set_bit(vid_range_start, bd->vlan_info.vlan_bitmap); + bd->ce_mask |= BRIDGE_ATTR_PORT_VLAN; + } + + vid_range_flags = -1; + } + + return 0; +} + +static int bridge_fill_af(struct rtnl_link *link, struct nl_msg *msg, + void *data) +{ + struct bridge_data *bd = data; + + if ((bd->ce_mask & BRIDGE_ATTR_SELF)||(bd->ce_mask & BRIDGE_ATTR_HWMODE)) + NLA_PUT_U16(msg, IFLA_BRIDGE_FLAGS, BRIDGE_FLAGS_SELF); + + if (bd->ce_mask & BRIDGE_ATTR_HWMODE) + NLA_PUT_U16(msg, IFLA_BRIDGE_MODE, bd->b_hwmode); + + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +static int bridge_fill_pi(struct rtnl_link *link, struct nl_msg *msg, + void *data) +{ + struct bridge_data *bd = data; + + if (bd->ce_mask & BRIDGE_ATTR_FLAGS) { + if (bd->b_flags_mask & RTNL_BRIDGE_BPDU_GUARD) { + NLA_PUT_U8(msg, IFLA_BRPORT_GUARD, + bd->b_flags & RTNL_BRIDGE_BPDU_GUARD); + } + if (bd->b_flags_mask & RTNL_BRIDGE_HAIRPIN_MODE) { + NLA_PUT_U8(msg, IFLA_BRPORT_MODE, + bd->b_flags & RTNL_BRIDGE_HAIRPIN_MODE); + } + if (bd->b_flags_mask & RTNL_BRIDGE_FAST_LEAVE) { + NLA_PUT_U8(msg, IFLA_BRPORT_FAST_LEAVE, + bd->b_flags & RTNL_BRIDGE_FAST_LEAVE); + } + if (bd->b_flags_mask & RTNL_BRIDGE_ROOT_BLOCK) { + NLA_PUT_U8(msg, IFLA_BRPORT_PROTECT, + bd->b_flags & RTNL_BRIDGE_ROOT_BLOCK); + } + if (bd->b_flags_mask & RTNL_BRIDGE_UNICAST_FLOOD) { + NLA_PUT_U8(msg, IFLA_BRPORT_UNICAST_FLOOD, + bd->b_flags & RTNL_BRIDGE_UNICAST_FLOOD); + } + if (bd->b_flags_mask & RTNL_BRIDGE_LEARNING) { + NLA_PUT_U8(msg, IFLA_BRPORT_LEARNING, + bd->b_flags & RTNL_BRIDGE_LEARNING); + } + if (bd->b_flags_mask & RTNL_BRIDGE_LEARNING_SYNC) { + NLA_PUT_U8(msg, IFLA_BRPORT_LEARNING_SYNC, + bd->b_flags & RTNL_BRIDGE_LEARNING_SYNC); + } + } + + if (bd->ce_mask & BRIDGE_ATTR_COST) + NLA_PUT_U32(msg, IFLA_BRPORT_COST, bd->b_cost); + + if (bd->ce_mask & BRIDGE_ATTR_PRIORITY) + NLA_PUT_U16(msg, IFLA_BRPORT_PRIORITY, bd->b_priority); + + if (bd->ce_mask & BRIDGE_ATTR_PORT_STATE) + NLA_PUT_U8(msg, IFLA_BRPORT_STATE, bd->b_port_state); + + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +static int bridge_override_rtm(struct rtnl_link *link) { + struct bridge_data *bd; + + if (!rtnl_link_is_bridge(link)) + return 0; + + bd = bridge_data(link); + + if (bd->ce_mask & BRIDGE_ATTR_FLAGS) + return 1; + + return 0; +} + +static int bridge_get_af(struct nl_msg *msg, uint32_t *ext_filter_mask) +{ + *ext_filter_mask |= RTEXT_FILTER_BRVLAN; + return 0; +} + +static void dump_bitmap(struct nl_dump_params *p, const uint32_t *b) +{ + int i = -1, j, k; + int start = -1, prev = -1; + int done, found = 0; + + for (k = 0; k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; k++) { + int base_bit; + uint32_t a = b[k]; + + base_bit = k * 32; + i = -1; + done = 0; + while (!done) { + j = find_next_bit(i, a); + if (j > 0) { + /* first hit of any bit */ + if (start < 0 && prev < 0) { + start = prev = j - 1 + base_bit; + goto next; + } + /* this bit is a continuation of prior bits */ + if (j - 2 + base_bit == prev) { + prev++; + goto next; + } + } else + done = 1; + + if (start >= 0) { + found++; + if (done && k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN - 1) + break; + + nl_dump(p, " %d", start); + if (start != prev) + nl_dump(p, "-%d", prev); + + if (done) + break; + } + if (j > 0) + start = prev = j - 1 + base_bit; +next: + i = j; + } + } + if (!found) + nl_dump(p, " "); + + return; +} + +static void rtnl_link_bridge_dump_vlans(struct nl_dump_params *p, + struct bridge_data *bd) +{ + nl_dump(p, "pvid %u", bd->vlan_info.pvid); + + nl_dump(p, " all vlans:"); + dump_bitmap(p, bd->vlan_info.vlan_bitmap); + + nl_dump(p, " untagged vlans:"); + dump_bitmap(p, bd->vlan_info.untagged_bitmap); +} + static void bridge_dump_details(struct rtnl_link *link, struct nl_dump_params *p, void *data) { @@ -157,6 +408,24 @@ static void bridge_dump_details(struct rtnl_link *link, if (bd->ce_mask & BRIDGE_ATTR_COST) nl_dump(p, "cost %u ", bd->b_cost); + if (bd->ce_mask & BRIDGE_ATTR_HWMODE) { + char hbuf[32]; + + rtnl_link_bridge_hwmode2str(bd->b_hwmode, hbuf, sizeof(hbuf)); + nl_dump(p, "hwmode %s", hbuf); + } + + if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN) + rtnl_link_bridge_dump_vlans(p, bd); + + if (bd->ce_mask & BRIDGE_ATTR_FLAGS) { + char buf[256]; + + rtnl_link_bridge_flags2str(bd->b_flags & bd->b_flags_mask, + buf, sizeof(buf)); + nl_dump(p, "%s", buf); + } + nl_dump(p, "\n"); } @@ -167,17 +436,23 @@ static int bridge_compare(struct rtnl_link *_a, struct rtnl_link *_b, struct bridge_data *b = bridge_data(_b); int diff = 0; -#define BRIDGE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, BRIDGE_ATTR_##ATTR, a, b, EXPR) - diff |= BRIDGE_DIFF(PORT_STATE, a->b_port_state != b->b_port_state); - diff |= BRIDGE_DIFF(PRIORITY, a->b_priority != b->b_priority); - diff |= BRIDGE_DIFF(COST, a->b_cost != b->b_cost); +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(BRIDGE_ATTR_PORT_STATE, + a->b_port_state != b->b_port_state); + diff |= _DIFF(BRIDGE_ATTR_PRIORITY, a->b_priority != b->b_priority); + diff |= _DIFF(BRIDGE_ATTR_COST, a->b_cost != b->b_cost); + diff |= _DIFF(BRIDGE_ATTR_PORT_VLAN, + memcmp(&a->vlan_info, &b->vlan_info, + sizeof(struct rtnl_link_bridge_vlan))); + diff |= _DIFF(BRIDGE_ATTR_HWMODE, a->b_hwmode != b->b_hwmode); + diff |= _DIFF(BRIDGE_ATTR_SELF, a->b_self != b->b_self); if (flags & LOOSE_COMPARISON) - diff |= BRIDGE_DIFF(FLAGS, - (a->b_flags ^ b->b_flags) & b->b_flags_mask); + diff |= _DIFF(BRIDGE_ATTR_FLAGS, + (a->b_flags ^ b->b_flags) & b->b_flags_mask); else - diff |= BRIDGE_DIFF(FLAGS, a->b_flags != b->b_flags); -#undef BRIDGE_DIFF + diff |= _DIFF(BRIDGE_ATTR_FLAGS, a->b_flags != b->b_flags); +#undef _DIFF return diff; } @@ -191,12 +466,11 @@ static int bridge_compare(struct rtnl_link *_a, struct rtnl_link *_b, struct rtnl_link *rtnl_link_bridge_alloc(void) { struct rtnl_link *link; - int err; if (!(link = rtnl_link_alloc())) return NULL; - if ((err = rtnl_link_set_type(link, "bridge")) < 0) { + if (rtnl_link_set_type(link, "bridge") < 0) { rtnl_link_put(link); return NULL; } @@ -205,6 +479,34 @@ struct rtnl_link *rtnl_link_bridge_alloc(void) } /** + * Create a new kernel bridge device + * @arg sk netlink socket + * @arg name name of the bridge device or NULL + * + * Creates a new bridge device in the kernel. If no name is + * provided, the kernel will automatically pick a name of the + * form "type%d" (e.g. bridge0, vlan1, etc.) + * + * @return 0 on success or a negative error code +*/ +int rtnl_link_bridge_add(struct nl_sock *sk, const char *name) +{ + int err; + struct rtnl_link *link; + + if (!(link = rtnl_link_bridge_alloc())) + return -NLE_NOMEM; + + if(name) + rtnl_link_set_name(link, name); + + err = rtnl_link_add(sk, link, NLM_F_CREATE); + rtnl_link_put(link); + + return err; +} + +/** * Check if a link is a bridge * @arg link Link object * @@ -412,6 +714,9 @@ int rtnl_link_bridge_unset_flags(struct rtnl_link *link, unsigned int flags) * - RTNL_BRIDGE_BPDU_GUARD * - RTNL_BRIDGE_ROOT_BLOCK * - RTNL_BRIDGE_FAST_LEAVE + * - RTNL_BRIDGE_UNICAST_FLOOD + * - RTNL_BRIDGE_LEARNING + * - RTNL_BRIDGE_LEARNING_SYNC * * @see rtnl_link_bridge_unset_flags() * @see rtnl_link_bridge_get_flags() @@ -451,6 +756,213 @@ int rtnl_link_bridge_get_flags(struct rtnl_link *link) return bd->b_flags; } +/** + * Set link change type to self + * @arg link Link Object of type bridge + * + * This will set the bridge change flag to self, meaning that changes to + * be applied with this link object will be applied directly to the physical + * device in a bridge instead of the virtual device. + * + * @return 0 on success or negative error code + * @return -NLE_OPNOTSUP Link is not a bridge + */ +int rtnl_link_bridge_set_self(struct rtnl_link *link) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + bd->b_self |= 1; + bd->ce_mask |= BRIDGE_ATTR_SELF; + + return 0; +} + +/** + * Get hardware mode + * @arg link Link object of type bridge + * @arg hwmode Output argument. + * + * @see rtnl_link_bridge_set_hwmode() + * + * @return 0 if hardware mode is present and returned in hwmode + * @return -NLE_NOATTR if hardware mode is not present + * @return -NLE_OPNOTSUP Link is not a bridge + */ +int rtnl_link_bridge_get_hwmode(struct rtnl_link *link, uint16_t *hwmode) +{ + struct bridge_data *bd = bridge_data(link); + + IS_BRIDGE_LINK_ASSERT(link); + + if (!(bd->ce_mask & BRIDGE_ATTR_HWMODE)) + return -NLE_NOATTR; + + *hwmode = bd->b_hwmode; + return 0; +} + +/** + * Set hardware mode + * @arg link Link object of type bridge + * @arg hwmode Hardware mode to set on link + * + * This will set the hardware mode of a link when it supports hardware + * offloads for bridging. + * @see rtnl_link_bridge_get_hwmode() + * + * Valid modes are: + * - RTNL_BRIDGE_HWMODE_VEB + * - RTNL_BRIDGE_HWMODE_VEPA + * + * When setting hardware mode, the change type will be set to self. + * @see rtnl_link_bridge_set_self() + * + * @return 0 on success or negative error code + * @return -NLE_OPNOTSUP Link is not a bridge + * @return -NLE_INVAL when specified hwmode is unsupported. + */ +int rtnl_link_bridge_set_hwmode(struct rtnl_link *link, uint16_t hwmode) +{ + int err; + struct bridge_data *bd = bridge_data(link); + + if (hwmode > RTNL_BRIDGE_HWMODE_MAX) + return -NLE_INVAL; + + if ((err = rtnl_link_bridge_set_self(link)) < 0) + return err; + + bd->b_hwmode = hwmode; + bd->ce_mask |= BRIDGE_ATTR_HWMODE; + + return 0; +} + + +static const struct trans_tbl bridge_flags[] = { + __ADD(RTNL_BRIDGE_HAIRPIN_MODE, hairpin_mode), + __ADD(RTNL_BRIDGE_BPDU_GUARD, bpdu_guard), + __ADD(RTNL_BRIDGE_ROOT_BLOCK, root_block), + __ADD(RTNL_BRIDGE_FAST_LEAVE, fast_leave), + __ADD(RTNL_BRIDGE_UNICAST_FLOOD, flood), + __ADD(RTNL_BRIDGE_LEARNING, learning), + __ADD(RTNL_BRIDGE_LEARNING_SYNC, learning_sync), +}; + +/** + * @name Flag Translation + * @{ + */ + +char *rtnl_link_bridge_flags2str(int flags, char *buf, size_t len) +{ + return __flags2str(flags, buf, len, bridge_flags, ARRAY_SIZE(bridge_flags)); +} + +int rtnl_link_bridge_str2flags(const char *name) +{ + return __str2flags(name, bridge_flags, ARRAY_SIZE(bridge_flags)); +} + +/** @} */ + +static const struct trans_tbl port_states[] = { + __ADD(BR_STATE_DISABLED, disabled), + __ADD(BR_STATE_LISTENING, listening), + __ADD(BR_STATE_LEARNING, learning), + __ADD(BR_STATE_FORWARDING, forwarding), + __ADD(BR_STATE_BLOCKING, blocking), +}; + +/** + * @name Port State Translation + * @{ + */ + +char *rtnl_link_bridge_portstate2str(int st, char *buf, size_t len) +{ + return __type2str(st, buf, len, port_states, ARRAY_SIZE(port_states)); +} + +int rtnl_link_bridge_str2portstate(const char *name) +{ + return __str2type(name, port_states, ARRAY_SIZE(port_states)); +} + +/** @} */ + +static const struct trans_tbl hw_modes[] = { + __ADD(RTNL_BRIDGE_HWMODE_VEB, veb), + __ADD(RTNL_BRIDGE_HWMODE_VEPA, vepa), + __ADD(RTNL_BRIDGE_HWMODE_UNDEF, undef), +}; + +/** + * @name Hardware Mode Translation + * @{ + */ + +char *rtnl_link_bridge_hwmode2str(uint16_t st, char *buf, size_t len) { + return __type2str(st, buf, len, hw_modes, ARRAY_SIZE(hw_modes)); +} + +uint16_t rtnl_link_bridge_str2hwmode(const char *name) +{ + return __str2type(name, hw_modes, ARRAY_SIZE(hw_modes)); +} + +/** @} */ + +int rtnl_link_bridge_pvid(struct rtnl_link *link) +{ + struct bridge_data *bd; + + IS_BRIDGE_LINK_ASSERT(link); + + bd = link->l_af_data[AF_BRIDGE]; + if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN) + return (int) bd->vlan_info.pvid; + + return -EINVAL; +} + +int rtnl_link_bridge_has_vlan(struct rtnl_link *link) +{ + struct bridge_data *bd; + int i; + + IS_BRIDGE_LINK_ASSERT(link); + + bd = link->l_af_data[AF_BRIDGE]; + if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN) { + if (bd->vlan_info.pvid) + return 1; + + for (i = 0; i < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; ++i) { + if (bd->vlan_info.vlan_bitmap[i] || + bd->vlan_info.untagged_bitmap[i]) + return 1; + } + } + return 0; +} + +struct rtnl_link_bridge_vlan *rtnl_link_bridge_get_port_vlan(struct rtnl_link *link) +{ + struct bridge_data *data; + + if (!rtnl_link_is_bridge(link)) + return NULL; + + data = link->l_af_data[AF_BRIDGE]; + if (data && (data->ce_mask & BRIDGE_ATTR_PORT_VLAN)) + return &data->vlan_info; + + return NULL; +} + static struct rtnl_link_af_ops bridge_ops = { .ao_family = AF_BRIDGE, .ao_alloc = &bridge_alloc, @@ -459,14 +971,21 @@ static struct rtnl_link_af_ops bridge_ops = { .ao_parse_protinfo = &bridge_parse_protinfo, .ao_dump[NL_DUMP_DETAILS] = &bridge_dump_details, .ao_compare = &bridge_compare, + .ao_parse_af_full = &bridge_parse_af_full, + .ao_get_af = &bridge_get_af, + .ao_fill_af = &bridge_fill_af, + .ao_fill_pi = &bridge_fill_pi, + .ao_fill_pi_flags = NLA_F_NESTED, + .ao_override_rtm = &bridge_override_rtm, + .ao_fill_af_no_nest = 1, }; -static void __init bridge_init(void) +static void _nl_init bridge_init(void) { rtnl_link_af_register(&bridge_ops); } -static void __exit bridge_exit(void) +static void _nl_exit bridge_exit(void) { rtnl_link_af_unregister(&bridge_ops); } diff --git a/lib/route/link/bridge_info.c b/lib/route/link/bridge_info.c new file mode 100644 index 0000000..61b885f --- /dev/null +++ b/lib/route/link/bridge_info.c @@ -0,0 +1,306 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2022 MaxLinear, Inc. + */ + +/** + * @ingroup link + * @defgroup bridge Bridging + * + * @details + * @{ + */ + +#include "nl-default.h" + +#include + +#include "nl-route.h" +#include "link-api.h" + +#define BRIDGE_ATTR_VLAN_FILTERING (1 << 0) +#define BRIDGE_ATTR_VLAN_PROTOCOL (1 << 1) +#define BRIDGE_ATTR_VLAN_STATS_ENABLED (1 << 2) + +struct bridge_info { + uint32_t ce_mask; /* to support attr macros */ + uint16_t b_vlan_protocol; + uint8_t b_vlan_filtering; + uint8_t b_vlan_stats_enabled; +}; + +static const struct nla_policy bi_attrs_policy[IFLA_BR_MAX + 1] = { + [IFLA_BR_VLAN_FILTERING] = { .type = NLA_U8 }, + [IFLA_BR_VLAN_PROTOCOL] = { .type = NLA_U16 }, + [IFLA_BR_VLAN_STATS_ENABLED] = { .type = NLA_U8 }, +}; + +static inline struct bridge_info *bridge_info(struct rtnl_link *link) +{ + return link->l_info; +} + +static int bridge_info_alloc(struct rtnl_link *link) +{ + struct bridge_info *bi; + + if (link->l_info) + memset(link->l_info, 0, sizeof(*bi)); + else { + bi = calloc(1, sizeof(*bi)); + if (!bi) + return -NLE_NOMEM; + + link->l_info = bi; + } + + return 0; +} + +static int bridge_info_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_BR_MAX + 1]; + struct bridge_info *bi; + int err; + + NL_DBG(3, "Parsing Bridge link info\n"); + + if ((err = nla_parse_nested(tb, IFLA_BR_MAX, data, bi_attrs_policy)) < + 0) + return err; + + if ((err = bridge_info_alloc(link)) < 0) + return err; + + bi = link->l_info; + + if (tb[IFLA_BR_VLAN_FILTERING]) { + bi->b_vlan_filtering = nla_get_u8(tb[IFLA_BR_VLAN_FILTERING]); + bi->ce_mask |= BRIDGE_ATTR_VLAN_FILTERING; + } + + if (tb[IFLA_BR_VLAN_PROTOCOL]) { + bi->b_vlan_protocol = + ntohs(nla_get_u16(tb[IFLA_BR_VLAN_PROTOCOL])); + bi->ce_mask |= BRIDGE_ATTR_VLAN_PROTOCOL; + } + + if (tb[IFLA_BR_VLAN_STATS_ENABLED]) { + bi->b_vlan_stats_enabled = + nla_get_u8(tb[IFLA_BR_VLAN_STATS_ENABLED]); + bi->ce_mask |= BRIDGE_ATTR_VLAN_STATS_ENABLED; + } + + return 0; +} + +static int bridge_info_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct bridge_info *bi = link->l_info; + struct nlattr *data; + + data = nla_nest_start(msg, IFLA_INFO_DATA); + if (!data) + return -NLE_MSGSIZE; + + if (bi->ce_mask & BRIDGE_ATTR_VLAN_FILTERING) + NLA_PUT_U8(msg, IFLA_BR_VLAN_FILTERING, bi->b_vlan_filtering); + + if (bi->ce_mask & BRIDGE_ATTR_VLAN_PROTOCOL) + NLA_PUT_U16(msg, IFLA_BR_VLAN_PROTOCOL, + htons(bi->b_vlan_protocol)); + + if (bi->ce_mask & BRIDGE_ATTR_VLAN_STATS_ENABLED) + NLA_PUT_U8(msg, IFLA_BR_VLAN_STATS_ENABLED, + bi->b_vlan_stats_enabled); + + nla_nest_end(msg, data); + return 0; + +nla_put_failure: + nla_nest_cancel(msg, data); + return -NLE_MSGSIZE; +} + +static void bridge_info_free(struct rtnl_link *link) +{ + _nl_clear_free(&link->l_info); +} + +static struct rtnl_link_info_ops bridge_info_ops = { + .io_name = "bridge", + .io_alloc = bridge_info_alloc, + .io_parse = bridge_info_parse, + .io_put_attrs = bridge_info_put_attrs, + .io_free = bridge_info_free, +}; + +#define IS_BRIDGE_INFO_ASSERT(link) \ + do { \ + if ((link)->l_info_ops != &bridge_info_ops) { \ + APPBUG("Link is not a bridge link. Set type \"bridge\" first."); \ + } \ + } while (0) + +/** + * Set VLAN filtering flag + * @arg link Link object of type bridge + * @arg vlan_filtering VLAN_filtering boolean flag to set. + * + * @see rtnl_link_bridge_get_vlan_filtering() + * + * @return void + */ +void rtnl_link_bridge_set_vlan_filtering(struct rtnl_link *link, + uint8_t vlan_filtering) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + bi->b_vlan_filtering = vlan_filtering; + + bi->ce_mask |= BRIDGE_ATTR_VLAN_FILTERING; +} + +/** + * Get VLAN filtering flag + * @arg link Link object of type bridge + * @arg vlan_filtering Output argument. + * + * @see rtnl_link_bridge_set_vlan_filtering() + * + * @return Zero on success, otherwise a negative error code. + * @retval -NLE_NOATTR + * @retval -NLE_INVAL + */ +int rtnl_link_bridge_get_vlan_filtering(struct rtnl_link *link, + uint8_t *vlan_filtering) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_FILTERING)) + return -NLE_NOATTR; + + if (!vlan_filtering) + return -NLE_INVAL; + + *vlan_filtering = bi->b_vlan_filtering; + return 0; +} + +/** + * Set VLAN protocol + * @arg link Link object of type bridge + * @arg vlan_protocol VLAN protocol to set. The protocol + * numbers is in host byte order. + * + * @see rtnl_link_bridge_get_vlan_protocol() + * + * @return void + */ +void rtnl_link_bridge_set_vlan_protocol(struct rtnl_link *link, + uint16_t vlan_protocol) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + bi->b_vlan_protocol = vlan_protocol; + + bi->ce_mask |= BRIDGE_ATTR_VLAN_PROTOCOL; +} + +/** + * Get VLAN protocol + * @arg link Link object of type bridge + * @arg vlan_protocol Output argument. The protocol number is in host byte order. + * + * @see rtnl_link_bridge_set_vlan_protocol() + * + * @return Zero on success, otherwise a negative error code. + * @retval -NLE_NOATTR + * @retval -NLE_INVAL + */ +int rtnl_link_bridge_get_vlan_protocol(struct rtnl_link *link, + uint16_t *vlan_protocol) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_PROTOCOL)) + return -NLE_NOATTR; + + if (!vlan_protocol) + return -NLE_INVAL; + + *vlan_protocol = bi->b_vlan_protocol; + + return 0; +} + +/** + * Set VLAN stats enabled flag + * @arg link Link object of type bridge + * @arg vlan_stats_enabled VLAN stats enabled flag to set + * + * @see rtnl_link_bridge_get_vlan_stats_enabled() + * + * @return void + */ +void rtnl_link_bridge_set_vlan_stats_enabled(struct rtnl_link *link, + uint8_t vlan_stats_enabled) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + bi->b_vlan_stats_enabled = vlan_stats_enabled; + + bi->ce_mask |= BRIDGE_ATTR_VLAN_STATS_ENABLED; +} + +/** + * Get VLAN stats enabled flag + * @arg link Link object of type bridge + * @arg vlan_stats_enabled Output argument. + * + * @see rtnl_link_bridge_set_vlan_stats_enabled() + * + * @return Zero on success, otherwise a negative error code. + * @retval -NLE_NOATTR + * @retval -NLE_INVAL + */ +int rtnl_link_bridge_get_vlan_stats_enabled(struct rtnl_link *link, + uint8_t *vlan_stats_enabled) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_STATS_ENABLED)) + return -NLE_NOATTR; + + if (!vlan_stats_enabled) + return -NLE_INVAL; + + *vlan_stats_enabled = bi->b_vlan_stats_enabled; + + return 0; +} + +static void _nl_init bridge_info_init(void) +{ + rtnl_link_register_info(&bridge_info_ops); +} + +static void _nl_exit bridge_info_exit(void) +{ + rtnl_link_unregister_info(&bridge_info_ops); +} + +/** @} */ diff --git a/lib/route/link/can.c b/lib/route/link/can.c index 60da42d..da00144 100644 --- a/lib/route/link/can.c +++ b/lib/route/link/can.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/link/can.c CAN Link Info - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2012 Benedikt Spranger */ @@ -22,16 +16,19 @@ * @{ */ -#include +#include "nl-default.h" + +#include + #include #include #include #include #include -#include #include -#include +#include "nl-route.h" +#include "link-api.h" /** @cond SKIP */ #define CAN_HAS_BITTIMING (1<<0) @@ -42,6 +39,9 @@ #define CAN_HAS_RESTART_MS (1<<5) #define CAN_HAS_RESTART (1<<6) #define CAN_HAS_BERR_COUNTER (1<<7) +#define CAN_HAS_DATA_BITTIMING (1<<8) +#define CAN_HAS_DATA_BITTIMING_CONST (1<<9) +#define CAN_HAS_DEVICE_STATS (1<<10) struct can_info { uint32_t ci_state; @@ -53,6 +53,9 @@ struct can_info { struct can_clock ci_clock; struct can_berr_counter ci_berr_counter; uint32_t ci_mask; + struct can_bittiming ci_data_bittiming; + struct can_bittiming_const ci_data_bittiming_const; + struct can_device_stats ci_device_stats; }; /** @endcond */ @@ -67,17 +70,25 @@ static struct nla_policy can_policy[IFLA_CAN_MAX + 1] = { = { .minlen = sizeof(struct can_bittiming_const) }, [IFLA_CAN_CLOCK] = { .minlen = sizeof(struct can_clock) }, [IFLA_CAN_BERR_COUNTER] = { .minlen = sizeof(struct can_berr_counter) }, + [IFLA_CAN_DATA_BITTIMING] + = { .minlen = sizeof(struct can_bittiming) }, + [IFLA_CAN_DATA_BITTIMING_CONST] + = { .minlen = sizeof(struct can_bittiming_const) }, }; static int can_alloc(struct rtnl_link *link) { struct can_info *ci; - ci = calloc(1, sizeof(*ci)); - if (!ci) - return -NLE_NOMEM; + if (link->l_info) + memset(link->l_info, 0, sizeof(*ci)); + else { + ci = calloc(1, sizeof(*ci)); + if (!ci) + return -NLE_NOMEM; - link->l_info = ci; + link->l_info = ci; + } return 0; } @@ -89,7 +100,7 @@ static int can_parse(struct rtnl_link *link, struct nlattr *data, struct can_info *ci; int err; - NL_DBG(3, "Parsing CAN link info"); + NL_DBG(3, "Parsing CAN link info\n"); if ((err = nla_parse_nested(tb, IFLA_CAN_MAX, data, can_policy)) < 0) goto errout; @@ -145,6 +156,23 @@ static int can_parse(struct rtnl_link *link, struct nlattr *data, ci->ci_mask |= CAN_HAS_BERR_COUNTER; } + if (tb[IFLA_CAN_DATA_BITTIMING]) { + nla_memcpy(&ci->ci_data_bittiming, tb[IFLA_CAN_DATA_BITTIMING], + sizeof(ci->ci_data_bittiming)); + ci->ci_mask |= CAN_HAS_DATA_BITTIMING; + } + + if (tb[IFLA_CAN_DATA_BITTIMING_CONST]) { + nla_memcpy(&ci->ci_data_bittiming_const, tb[IFLA_CAN_DATA_BITTIMING_CONST], + sizeof(ci->ci_data_bittiming_const)); + ci->ci_mask |= CAN_HAS_DATA_BITTIMING_CONST; + } + + if (xstats && nla_len(xstats) >= sizeof(ci->ci_device_stats)) { + nla_memcpy(&ci->ci_device_stats, xstats, sizeof(ci->ci_device_stats)); + ci->ci_mask |= CAN_HAS_DEVICE_STATS; + } + err = 0; errout: return err; @@ -202,11 +230,8 @@ static void can_dump_line(struct rtnl_link *link, struct nl_dump_params *p) static void can_dump_details(struct rtnl_link *link, struct nl_dump_params *p) { struct can_info *ci = link->l_info; - char buf [64]; - rtnl_link_can_ctrlmode2str(ci->ci_ctrlmode.flags, buf, sizeof(buf)); - nl_dump(p, " bitrate %d %s <%s>", - ci->ci_bittiming.bitrate, print_can_state(ci->ci_state), buf); + can_dump_line(link, p); if (ci->ci_mask & CAN_HAS_RESTART) { if (ci->ci_restart) @@ -255,7 +280,7 @@ static void can_dump_details(struct rtnl_link *link, struct nl_dump_params *p) } if (ci->ci_mask & CAN_HAS_CLOCK) { - nl_dump_line(p," base freq %d Hz\n", ci->ci_clock); + nl_dump_line(p," base freq %u Hz\n", ci->ci_clock.freq); } @@ -265,8 +290,28 @@ static void can_dump_details(struct rtnl_link *link, struct nl_dump_params *p) nl_dump_line(p," bus error TX %d\n", ci->ci_berr_counter.txerr); } +} - return; +static void can_dump_stats(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct can_info *ci = link->l_info; + + can_dump_details(link, p); + + if (ci->ci_mask & CAN_HAS_DEVICE_STATS) { + nl_dump_line(p," bus errors %d\n", + ci->ci_device_stats.bus_error); + nl_dump_line(p," error warning state changes %d\n", + ci->ci_device_stats.error_warning); + nl_dump_line(p," error passive state changes %d\n", + ci->ci_device_stats.error_passive); + nl_dump_line(p," bus off state changes %d\n", + ci->ci_device_stats.bus_off); + nl_dump_line(p," arbitration lost errors %d\n", + ci->ci_device_stats.arbitration_lost); + nl_dump_line(p," restarts %d\n", + ci->ci_device_stats.restarts); + } } static int can_clone(struct rtnl_link *dst, struct rtnl_link *src) @@ -299,28 +344,36 @@ static int can_put_attrs(struct nl_msg *msg, struct rtnl_link *link) return -NLE_MSGSIZE; if (ci->ci_mask & CAN_HAS_RESTART) - NLA_PUT_U32(msg, CAN_HAS_RESTART, ci->ci_restart); + NLA_PUT_U32(msg, IFLA_CAN_RESTART, ci->ci_restart); if (ci->ci_mask & CAN_HAS_RESTART_MS) - NLA_PUT_U32(msg, CAN_HAS_RESTART_MS, ci->ci_restart_ms); + NLA_PUT_U32(msg, IFLA_CAN_RESTART_MS, ci->ci_restart_ms); if (ci->ci_mask & CAN_HAS_CTRLMODE) - NLA_PUT(msg, CAN_HAS_CTRLMODE, sizeof(ci->ci_ctrlmode), + NLA_PUT(msg, IFLA_CAN_CTRLMODE, sizeof(ci->ci_ctrlmode), &ci->ci_ctrlmode); if (ci->ci_mask & CAN_HAS_BITTIMING) - NLA_PUT(msg, CAN_HAS_BITTIMING, sizeof(ci->ci_bittiming), + NLA_PUT(msg, IFLA_CAN_BITTIMING, sizeof(ci->ci_bittiming), &ci->ci_bittiming); if (ci->ci_mask & CAN_HAS_BITTIMING_CONST) - NLA_PUT(msg, CAN_HAS_BITTIMING_CONST, + NLA_PUT(msg, IFLA_CAN_BITTIMING_CONST, sizeof(ci->ci_bittiming_const), &ci->ci_bittiming_const); if (ci->ci_mask & CAN_HAS_CLOCK) - NLA_PUT(msg, CAN_HAS_CLOCK, sizeof(ci->ci_clock), + NLA_PUT(msg, IFLA_CAN_CLOCK, sizeof(ci->ci_clock), &ci->ci_clock); + if (ci->ci_mask & CAN_HAS_DATA_BITTIMING) + NLA_PUT(msg, IFLA_CAN_DATA_BITTIMING, sizeof(ci->ci_data_bittiming), + &ci->ci_data_bittiming); + + if (ci->ci_mask & CAN_HAS_DATA_BITTIMING_CONST) + NLA_PUT(msg, IFLA_CAN_DATA_BITTIMING_CONST, sizeof(ci->ci_data_bittiming_const), + &ci->ci_data_bittiming_const); + nla_nest_end(msg, data); nla_put_failure: @@ -335,6 +388,7 @@ static struct rtnl_link_info_ops can_info_ops = { .io_dump = { [NL_DUMP_LINE] = can_dump_line, [NL_DUMP_DETAILS] = can_dump_details, + [NL_DUMP_STATS] = can_dump_stats, }, .io_clone = can_clone, .io_put_attrs = can_put_attrs, @@ -485,7 +539,7 @@ int rtnl_link_can_berr(struct rtnl_link *link, struct can_berr_counter *berr) } /** - * Get CAN harware-dependent bit-timing constant + * Get CAN hardware-dependent bit-timing constant * @arg link Link object * @arg bt_const Bit-timing constant * @@ -540,7 +594,7 @@ int rtnl_link_can_get_bittiming(struct rtnl_link *link, * @return 0 on success or a negative error code */ int rtnl_link_can_set_bittiming(struct rtnl_link *link, - struct can_bittiming *bit_timing) + const struct can_bittiming *bit_timing) { struct can_info *ci = link->l_info; @@ -743,6 +797,122 @@ int rtnl_link_can_unset_ctrlmode(struct rtnl_link *link, uint32_t ctrlmode) return 0; } +/** + * Get CAN FD hardware-dependent data bit-timing constant + * @arg link Link object + * @arg data_bt_const CAN FD data bit-timing constant + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_get_data_bittiming_const(struct rtnl_link *link, + struct can_bittiming_const *data_bt_const) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!data_bt_const) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_DATA_BITTIMING_CONST) + *data_bt_const = ci->ci_data_bittiming_const; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set CAN FD device data bit-timing-const + * @arg link Link object + * @arg data_bit_timing CAN FD data bit-timing + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_set_data_bittiming_const(struct rtnl_link *link, + const struct can_bittiming_const *data_bt_const) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!data_bt_const) + return -NLE_INVAL; + + ci->ci_data_bittiming_const = *data_bt_const; + ci->ci_mask |= CAN_HAS_DATA_BITTIMING_CONST; + + return 0; +} + +/** + * Get CAN FD device data bit-timing + * @arg link Link object + * @arg data_bit_timing CAN FD data bit-timing + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_get_data_bittiming(struct rtnl_link *link, + struct can_bittiming *data_bit_timing) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!data_bit_timing) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_DATA_BITTIMING) + *data_bit_timing = ci->ci_data_bittiming; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set CAN FD device data bit-timing + * @arg link Link object + * @arg data_bit_timing CAN FD data bit-timing + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_set_data_bittiming(struct rtnl_link *link, + const struct can_bittiming *data_bit_timing) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!data_bit_timing) + return -NLE_INVAL; + + ci->ci_data_bittiming = *data_bit_timing; + ci->ci_mask |= CAN_HAS_DATA_BITTIMING; + + return 0; +} + +/** + * Get CAN device stats + * @arg link Link object + * @arg device_stats CAN device stats + * + * @return 0 on success or a negative error code + */ +int rtnl_link_can_get_device_stats(struct rtnl_link* link, + struct can_device_stats *device_stats) +{ + struct can_info *ci = link->l_info; + + IS_CAN_LINK_ASSERT(link); + if (!device_stats) + return -NLE_INVAL; + + if (ci->ci_mask & CAN_HAS_DEVICE_STATS) + *device_stats = ci->ci_device_stats; + else + return -NLE_MISSING_ATTR; + + return 0; +} + /** @} */ /** @@ -751,11 +921,14 @@ int rtnl_link_can_unset_ctrlmode(struct rtnl_link *link, uint32_t ctrlmode) */ static const struct trans_tbl can_ctrlmode[] = { - __ADD(CAN_CTRLMODE_LOOPBACK, loopback) - __ADD(CAN_CTRLMODE_LISTENONLY, listen-only) - __ADD(CAN_CTRLMODE_3_SAMPLES, triple-sampling) - __ADD(CAN_CTRLMODE_ONE_SHOT, one-shot) - __ADD(CAN_CTRLMODE_BERR_REPORTING, berr-reporting) + __ADD(CAN_CTRLMODE_LOOPBACK, loopback), + __ADD(CAN_CTRLMODE_LISTENONLY, listen-only), + __ADD(CAN_CTRLMODE_3_SAMPLES, triple-sampling), + __ADD(CAN_CTRLMODE_ONE_SHOT, one-shot), + __ADD(CAN_CTRLMODE_BERR_REPORTING, berr-reporting), + __ADD(CAN_CTRLMODE_FD, fd), + __ADD(CAN_CTRLMODE_PRESUME_ACK, presume-ack), + __ADD(CAN_CTRLMODE_FD_NON_ISO, fd-non-iso), }; char *rtnl_link_can_ctrlmode2str(int ctrlmode, char *buf, size_t len) @@ -771,12 +944,12 @@ int rtnl_link_can_str2ctrlmode(const char *name) /** @} */ -static void __init can_init(void) +static void _nl_init can_init(void) { rtnl_link_register_info(&can_info_ops); } -static void __exit can_exit(void) +static void _nl_exit can_exit(void) { rtnl_link_unregister_info(&can_info_ops); } diff --git a/lib/route/link/dummy.c b/lib/route/link/dummy.c index 1fd9f5a..83d6ba7 100644 --- a/lib/route/link/dummy.c +++ b/lib/route/link/dummy.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/link/dummy.c Dummy Interfaces - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2011 Thomas Graf */ @@ -19,20 +13,22 @@ * @{ */ -#include +#include "nl-default.h" + #include -#include + +#include "link-api.h" static struct rtnl_link_info_ops dummy_info_ops = { .io_name = "dummy", }; -static void __init dummy_init(void) +static void _nl_init dummy_init(void) { rtnl_link_register_info(&dummy_info_ops); } -static void __exit dummy_exit(void) +static void _nl_exit dummy_exit(void) { rtnl_link_unregister_info(&dummy_info_ops); } diff --git a/lib/route/link/geneve.c b/lib/route/link/geneve.c new file mode 100644 index 0000000..61dd1f1 --- /dev/null +++ b/lib/route/link/geneve.c @@ -0,0 +1,803 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2018 Wang Jian + */ + +/** + * @ingroup link + * @defgroup geneve Geneve + * Generic Network Virtualization Encapsulation + * + * @details + * \b Link Type Name: "geneve" + * + * @route_doc{link_geneve, Geneve Documentation} + * + * @{ + */ +#include "nl-default.h" + +#include +#include +#include +#include +#include + +#include "nl-route.h" +#include "link-api.h" + +/** @cond SKIP */ +#define GENEVE_ATTR_ID (1<<0) +#define GENEVE_ATTR_REMOTE (1<<1) +#define GENEVE_ATTR_REMOTE6 (1<<2) +#define GENEVE_ATTR_TTL (1<<3) +#define GENEVE_ATTR_TOS (1<<4) +#define GENEVE_ATTR_LABEL (1<<5) +#define GENEVE_ATTR_PORT (1<<6) +#define GENEVE_ATTR_FLAGS (1<<7) +#define GENEVE_ATTR_UDP_CSUM (1<<8) +#define GENEVE_ATTR_UDP_ZERO_CSUM6_TX (1<<9) +#define GENEVE_ATTR_UDP_ZERO_CSUM6_RX (1<<10) + +struct geneve_info +{ + uint32_t id; + uint32_t remote; + struct in6_addr remote6; + uint8_t ttl; + uint8_t tos; + uint32_t label; + uint16_t port; + uint8_t flags; + uint8_t udp_csum; + uint8_t udp_zero_csum6_tx; + uint8_t udp_zero_csum6_rx; + uint32_t mask; +}; + +/** @endcond */ + +static struct nla_policy geneve_policy[IFLA_GENEVE_MAX + 1] = { + [IFLA_GENEVE_ID] = { .type = NLA_U32 }, + [IFLA_GENEVE_REMOTE] = { .minlen = sizeof(uint32_t) }, + [IFLA_GENEVE_REMOTE6] = { .minlen = sizeof(struct in6_addr) }, + [IFLA_GENEVE_TTL] = { .type = NLA_U8 }, + [IFLA_GENEVE_TOS] = { .type = NLA_U8 }, + [IFLA_GENEVE_LABEL] = { .type = NLA_U32 }, + [IFLA_GENEVE_PORT] = { .type = NLA_U16 }, + [IFLA_GENEVE_COLLECT_METADATA] = { .type = NLA_FLAG }, + [IFLA_GENEVE_UDP_CSUM] = { .type = NLA_U8 }, + [IFLA_GENEVE_UDP_ZERO_CSUM6_TX] = { .type = NLA_U8 }, + [IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = { .type = NLA_U8 }, +}; + +static int geneve_alloc(struct rtnl_link *link) +{ + struct geneve_info *geneve; + + if (link->l_info) + memset(link->l_info, 0, sizeof(*geneve)); + else { + if ((geneve = calloc(1, sizeof(*geneve))) == NULL) + return -NLE_NOMEM; + link->l_info = geneve; + } + + return 0; +} + +static int geneve_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_GENEVE_MAX + 1]; + struct geneve_info *geneve; + int err = 0; + + NL_DBG(3, "Parsing Geneve link info\n"); + + err = nla_parse_nested(tb, IFLA_GENEVE_MAX, data, geneve_policy); + if (err < 0) + return err; + + err = geneve_alloc(link); + if (err < 0) + return err; + + geneve = link->l_info; + + if (tb[IFLA_GENEVE_ID]) { + geneve->id = nla_get_u32(tb[IFLA_GENEVE_ID]); + geneve->mask |= GENEVE_ATTR_ID; + } + + if (tb[IFLA_GENEVE_REMOTE]) { + nla_memcpy(&geneve->remote, tb[IFLA_GENEVE_REMOTE], + sizeof(geneve->remote)); + geneve->mask |= GENEVE_ATTR_REMOTE; + geneve->mask &= ~GENEVE_ATTR_REMOTE6; + } + if (tb[IFLA_GENEVE_REMOTE6]) { + nla_memcpy(&geneve->remote6, tb[IFLA_GENEVE_REMOTE6], + sizeof(geneve->remote6)); + geneve->mask |= GENEVE_ATTR_REMOTE6; + geneve->mask &= ~GENEVE_ATTR_REMOTE; + } + + if (tb[IFLA_GENEVE_TTL]) { + geneve->ttl = nla_get_u8(tb[IFLA_GENEVE_TTL]); + geneve->mask |= GENEVE_ATTR_TTL; + } + + if (tb[IFLA_GENEVE_TOS]) { + geneve->tos = nla_get_u8(tb[IFLA_GENEVE_TOS]); + geneve->mask |= GENEVE_ATTR_TOS; + } + + if (tb[IFLA_GENEVE_LABEL]) { + geneve->label = nla_get_u32(tb[IFLA_GENEVE_LABEL]); + geneve->mask |= GENEVE_ATTR_LABEL; + } + + if (tb[IFLA_GENEVE_PORT]) { + geneve->port = nla_get_u16(tb[IFLA_GENEVE_PORT]); + geneve->mask |= GENEVE_ATTR_PORT; + } + + if (tb[IFLA_GENEVE_COLLECT_METADATA]) + geneve->flags |= RTNL_LINK_GENEVE_F_COLLECT_METADATA; + + if (tb[IFLA_GENEVE_UDP_CSUM]) { + geneve->udp_csum = nla_get_u8(tb[IFLA_GENEVE_UDP_CSUM]); + geneve->mask |= GENEVE_ATTR_UDP_CSUM; + } + + if (tb[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]) { + geneve->udp_zero_csum6_tx = nla_get_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]); + geneve->mask |= GENEVE_ATTR_UDP_ZERO_CSUM6_TX; + } + + if (tb[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]) { + geneve->udp_zero_csum6_rx = nla_get_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]); + geneve->mask |= GENEVE_ATTR_UDP_ZERO_CSUM6_RX; + } + + return err; +} + +static void geneve_free(struct rtnl_link *link) +{ + struct geneve_info *geneve = link->l_info; + + free(geneve); + link->l_info = NULL; +} + +static void geneve_dump_line(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct geneve_info *geneve = link->l_info; + + nl_dump(p, "geneve-id %u", geneve->id); +} + +static void geneve_dump_details(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct geneve_info *geneve = link->l_info; + char addr[INET6_ADDRSTRLEN]; + + nl_dump_line(p, " geneve-id %u\n", geneve->id); + + if (geneve->mask & GENEVE_ATTR_REMOTE) { + nl_dump(p, " remote "); + nl_dump_line(p, "%s\n", + _nl_inet_ntop(AF_INET, &geneve->remote, addr)); + } else if (geneve->mask & GENEVE_ATTR_REMOTE6) { + nl_dump(p, " remote "); + nl_dump_line(p, "%s\n", + _nl_inet_ntop(AF_INET6, &geneve->remote6, addr)); + } + + if (geneve->mask & GENEVE_ATTR_TTL) { + nl_dump(p, " ttl "); + nl_dump_line(p, "%u\n", geneve->ttl); + } + + if (geneve->mask & GENEVE_ATTR_TOS) { + nl_dump(p, " tos "); + nl_dump_line(p, "%u\n", geneve->tos); + } + + if (geneve->mask & GENEVE_ATTR_PORT) { + nl_dump(p, " port "); + nl_dump_line(p, "%u\n", ntohs(geneve->port)); + } + + if (geneve->mask & GENEVE_ATTR_LABEL) { + nl_dump(p, " label "); + nl_dump_line(p, "%u\n", ntohl(geneve->label)); + } + + if (geneve->mask & GENEVE_ATTR_UDP_CSUM) { + nl_dump(p, " UDP checksum "); + if (geneve->udp_csum) + nl_dump_line(p, "enabled (%#x)\n", geneve->udp_csum); + else + nl_dump_line(p, "disabled\n"); + } + + if (geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_TX) { + nl_dump(p, " udp-zero-csum6-tx "); + if (geneve->udp_zero_csum6_tx) + nl_dump_line(p, "enabled (%#x)\n", geneve->udp_zero_csum6_tx); + else + nl_dump_line(p, "disabled\n"); + } + + if (geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_RX) { + nl_dump(p, " udp-zero-csum6-rx "); + if (geneve->udp_zero_csum6_rx) + nl_dump_line(p, "enabled (%#x)\n", geneve->udp_zero_csum6_rx); + else + nl_dump_line(p, "disabled\n"); + } + + if (geneve->flags & RTNL_LINK_GENEVE_F_COLLECT_METADATA) + nl_dump(p, " collect-metadata\n"); +} + +static int geneve_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct geneve_info *gdst, *gsrc; + int err; + + gsrc = src->l_info; + dst->l_info = NULL; + err = rtnl_link_set_type(dst, "geneve"); + if (err < 0) + return err; + + gdst = dst->l_info; + + if (!gsrc || !gdst) + return -NLE_NOMEM; + + memcpy(gdst, gsrc, sizeof(struct geneve_info)); + + return 0; +} + +static int geneve_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct geneve_info *geneve = link->l_info; + struct nlattr *data; + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + return -NLE_MSGSIZE; + + if (geneve->mask & GENEVE_ATTR_ID) + NLA_PUT_U32(msg, IFLA_GENEVE_ID, geneve->id); + + if (geneve->mask & GENEVE_ATTR_REMOTE) + NLA_PUT(msg, IFLA_GENEVE_REMOTE, + sizeof(geneve->remote), &geneve->remote); + + if (geneve->mask & GENEVE_ATTR_REMOTE6) + NLA_PUT(msg, IFLA_GENEVE_REMOTE6, + sizeof(geneve->remote6), &geneve->remote6); + + if (geneve->mask & GENEVE_ATTR_TTL) + NLA_PUT_U8(msg, IFLA_GENEVE_TTL, geneve->ttl); + + if (geneve->mask & GENEVE_ATTR_TOS) + NLA_PUT_U8(msg, IFLA_GENEVE_TOS, geneve->tos); + + if (geneve->mask & GENEVE_ATTR_LABEL) + NLA_PUT_U32(msg, IFLA_GENEVE_LABEL, geneve->label); + + if (geneve->mask & GENEVE_ATTR_PORT) + NLA_PUT_U32(msg, IFLA_GENEVE_PORT, geneve->port); + + if (geneve->mask & GENEVE_ATTR_UDP_CSUM) + NLA_PUT_U8(msg, IFLA_GENEVE_UDP_CSUM, geneve->udp_csum); + + if (geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_TX) + NLA_PUT_U8(msg, IFLA_GENEVE_UDP_ZERO_CSUM6_TX, geneve->udp_zero_csum6_tx); + + if (geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_RX) + NLA_PUT_U8(msg, IFLA_GENEVE_UDP_ZERO_CSUM6_RX, geneve->udp_zero_csum6_rx); + + if (geneve->flags & RTNL_LINK_GENEVE_F_COLLECT_METADATA) + NLA_PUT_FLAG(msg, IFLA_GENEVE_COLLECT_METADATA); + + nla_nest_end(msg, data); + +nla_put_failure: + + return 0; +} + +static struct rtnl_link_info_ops geneve_info_ops = { + .io_name = "geneve", + .io_alloc = geneve_alloc, + .io_parse = geneve_parse, + .io_dump = { + [NL_DUMP_LINE] = geneve_dump_line, + [NL_DUMP_DETAILS] = geneve_dump_details, + }, + .io_clone = geneve_clone, + .io_put_attrs = geneve_put_attrs, + .io_free = geneve_free, +}; + + +/** @cond SKIP */ +#define IS_GENEVE_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &geneve_info_ops) { \ + APPBUG("Link is not a geneve link. set type \"geneve\" first."); \ + return -NLE_OPNOTSUPP; \ + } +/** @endcond */ + +/** + * @name Geneve Object + * @{ + */ + +/** + * Allocate link object of type Geneve + * + * @return Allocated link object or NULL. + */ +struct rtnl_link *rtnl_link_geneve_alloc(void) +{ + struct rtnl_link *link; + + if (!(link = rtnl_link_alloc())) + return NULL; + + if (rtnl_link_set_type(link, "geneve") < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if link is a Geneve link + * @arg link Link object + * + * @return True if link is a Geneve link, otherwisee false is returned. + */ +int rtnl_link_is_geneve(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "geneve"); +} + +/** + * Set Geneve Network Indentifier + * @arg link Link object + * @arg id Geneve network identifier + * + * @return 0 on success or a negative error code + */ +int rtnl_link_geneve_set_id(struct rtnl_link *link, uint32_t id) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + if (id > RTNL_GENEVE_ID_MAX) + return -NLE_INVAL; + + geneve->id = id; + geneve->mask |= GENEVE_ATTR_ID; + + return 0; +} + +/** + * Get Geneve Network Identifier + * @arg link Link object + * @arg id Pointer to store network identifier + * + * @return 0 on success or a negative error code + */ +int rtnl_link_geneve_get_id(struct rtnl_link *link, uint32_t *id) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + if (!id) + return -NLE_INVAL; + + if (geneve->mask & GENEVE_ATTR_ID) + *id = geneve->id; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set Geneve unicast destination IP address + * @arg link Link object + * @arg addr The unicast destination IP address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_geneve_set_remote(struct rtnl_link *link, struct nl_addr *addr) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + if ((nl_addr_get_family(addr) == AF_INET) && + (nl_addr_get_len(addr) == sizeof(geneve->remote))) { + memcpy(&geneve->remote, nl_addr_get_binary_addr(addr), + sizeof(geneve->remote)); + geneve->mask |= GENEVE_ATTR_REMOTE; + geneve->mask &= ~GENEVE_ATTR_REMOTE6; + } else if ((nl_addr_get_family(addr) == AF_INET6) && + (nl_addr_get_len(addr) == sizeof(geneve->remote6))) { + memcpy(&geneve->remote6, nl_addr_get_binary_addr(addr), + sizeof(geneve->remote6)); + geneve->mask |= GENEVE_ATTR_REMOTE6; + geneve->mask &= ~GENEVE_ATTR_REMOTE; + } else + return -NLE_INVAL; + + return 0; +} + +/** + * Get Geneve unicast destination IP address + * @arg link Link object + * @arg addr Pointer to store unicast destination IP addree + * + * @return 0 on success or a a negative error code + */ +int rtnl_link_geneve_get_remote(struct rtnl_link *link, struct nl_addr **addr) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + if (!addr) + return -NLE_INVAL; + + if (geneve->mask & GENEVE_ATTR_REMOTE) + *addr = nl_addr_build(AF_INET, &geneve->remote, sizeof(geneve->remote)); + else if (geneve->mask & GENEVE_ATTR_REMOTE6) + *addr = nl_addr_build(AF_INET6, &geneve->remote6, sizeof(geneve->remote6)); + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set IP TTL value to use for Geneve + * @arg link Link object + * @arg ttl TTL value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_geneve_set_ttl(struct rtnl_link *link, uint8_t ttl) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + geneve->ttl = ttl; + geneve->mask |= GENEVE_ATTR_TTL; + + return 0; +} + +/** + * Get IP TTL value to use for Geneve + * @arg link Link object + * + * @return TTL value on success or a negative error code + */ +int rtnl_link_geneve_get_ttl(struct rtnl_link *link) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + if (!(geneve->mask & GENEVE_ATTR_TTL)) + return -NLE_AGAIN; + + return geneve->ttl; +} + +/** + * Set IP ToS value to use for Geneve + * @arg link Link object + * @arg tos ToS value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_geneve_set_tos(struct rtnl_link *link, uint8_t tos) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + geneve->tos = tos; + geneve->mask |= GENEVE_ATTR_TOS; + + return 0; +} + +/** + * Get IP ToS value to use for Geneve + * @arg link Link object + * + * @return ToS value on success or a negative error code + */ +int rtnl_link_geneve_get_tos(struct rtnl_link *link) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + if (!(geneve->mask & GENEVE_ATTR_TOS)) + return -NLE_AGAIN; + + return geneve->tos; +} + +/** + * Set UDP destination port to use for Geneve + * @arg link Link object + * @arg port Destination port + * + * @return 0 on success or a negative error code + */ + +int rtnl_link_geneve_set_port(struct rtnl_link *link, uint32_t port) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + geneve->port = htons(port); + geneve->mask |= GENEVE_ATTR_PORT; + + return 0; +} + +/** + * Get UDP destination port to use for Geneve + * @arg link Link object + * @arg port Pointer to store destination port + * + * @return 0 on success or a negative error code + */ +int rtnl_link_geneve_get_port(struct rtnl_link *link, uint32_t *port) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + if (!port) + return -NLE_INVAL; + + if (!(geneve->mask & GENEVE_ATTR_PORT)) + return -NLE_NOATTR; + + *port = ntohs(geneve->port); + + return 0; +} + +/** + * Set flow label to use for Geneve + * @arg link Link object + * @arg label Destination label + * + * @return 0 on success or a negative error code + */ +int rtnl_link_geneve_set_label(struct rtnl_link *link, uint32_t label) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + geneve->label = htonl(label); + geneve->mask |= GENEVE_ATTR_LABEL; + + return 0; +} + +/** + * Get flow label to use for Geneve + * @arg link Link object + * @arg label Pointer to store destination label + * + * @return 0 on success or a negative error code + */ +int rtnl_link_geneve_get_label(struct rtnl_link *link, uint32_t *label) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + if (!label) + return -NLE_INVAL; + if (!(geneve->mask & GENEVE_ATTR_LABEL)) + return -NLE_NOATTR; + + *label = ntohl(geneve->label); + + return 0; +} + +/** + * Set UDP checksum status to use for Geneve + * @arg link Link object + * @arg csum Status value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_geneve_set_udp_csum(struct rtnl_link *link, uint8_t csum) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + geneve->udp_csum = csum; + geneve->mask |= GENEVE_ATTR_UDP_CSUM; + + return 0; +} + +/** + * Get UDP checksum status to use for Geneve + * @arg link Link object + * + * @return status value on success or a negative error code + */ +int rtnl_link_geneve_get_udp_csum(struct rtnl_link *link) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + if (!(geneve->mask & GENEVE_ATTR_UDP_CSUM)) + return -NLE_NOATTR; + + return geneve->udp_csum; +} + +/** + * Set skip UDP checksum transmitted over IPv6 status to use for Geneve + * @arg link Link object + * @arg csum Status value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_geneve_set_udp_zero_csum6_tx(struct rtnl_link *link, uint8_t csum) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + geneve->udp_zero_csum6_tx = csum; + geneve->mask |= GENEVE_ATTR_UDP_ZERO_CSUM6_TX; + + return 0; +} + +/** + * Get skip UDP checksum transmitted over IPv6 status to use for Geneve + * @arg link Link object + * + * @return Status value on success or a negative error code + */ +int rtnl_link_geneve_get_udp_zero_csum6_tx(struct rtnl_link *link) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + if (!(geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_TX)) + return -NLE_NOATTR; + + return geneve->udp_zero_csum6_tx; +} + +/** + * Set skip UDP checksum received over IPv6 status to use for Geneve + * @arg link Link object + * @arg csum Status value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_geneve_set_udp_zero_csum6_rx(struct rtnl_link *link, uint8_t csum) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + geneve->udp_zero_csum6_rx = csum; + geneve->mask |= GENEVE_ATTR_UDP_ZERO_CSUM6_RX; + + return 0; +} + +/** + * Get skip UDP checksum received over IPv6 status to use for Geneve + * @arg link Link object + * + * @return Status value on success or a negative error code + */ +int rtnl_link_geneve_get_udp_zero_csum6_rx(struct rtnl_link *link) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + if (!(geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_RX)) + return -NLE_NOATTR; + + return geneve->udp_zero_csum6_rx; +} + +/** + * Set Geneve flags + * @arg link Link object + * @arg flags Which flags to set + * @arg enable Boolean enabling or disabling flag + * + * @return 0 on success or a negative error code + */ +int rtnl_link_geneve_set_flags(struct rtnl_link *link, uint8_t flags, int enable) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + if (flags & ~RTNL_LINK_GENEVE_F_COLLECT_METADATA) + return -NLE_INVAL; + + if (enable) + geneve->flags = flags; + else + geneve->flags &= ~flags; + + return 0; +} + +/** + * Get Geneve flags + * @arg link Link object + * @arg flags Pointer to store flags + * + * @return 0 on success or a negative error code + */ +int rtnl_link_geneve_get_flags(struct rtnl_link *link, uint8_t *flags) +{ + struct geneve_info *geneve = link->l_info; + + IS_GENEVE_LINK_ASSERT(link); + + *flags = geneve->flags; + return 0; +} + +/** @} */ +static void _nl_init geneve_init(void) +{ + rtnl_link_register_info(&geneve_info_ops); +} + +static void _nl_exit geneve_exit(void) +{ + rtnl_link_unregister_info(&geneve_info_ops); +} + +/** @} */ diff --git a/lib/route/link/ifb.c b/lib/route/link/ifb.c new file mode 100644 index 0000000..d5fc685 --- /dev/null +++ b/lib/route/link/ifb.c @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2014 Cong Wang + */ + +/** + * @ingroup link + * @defgroup ifb Intermediate Functional Block + * + * @details + * \b Link Type Name: "ifb" + * + * @{ + */ + +#include "nl-default.h" + +#include + +#include "link-api.h" + +static struct rtnl_link_info_ops ifb_info_ops = { + .io_name = "ifb", +}; + +static void _nl_init ifb_init(void) +{ + rtnl_link_register_info(&ifb_info_ops); +} + +static void _nl_exit ifb_exit(void) +{ + rtnl_link_unregister_info(&ifb_info_ops); +} + +/** @} */ diff --git a/lib/route/link/inet.c b/lib/route/link/inet.c index e2c867d..7ed705e 100644 --- a/lib/route/link/inet.c +++ b/lib/route/link/inet.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/link/inet.c AF_INET link operations - * - * 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 */ @@ -57,11 +51,16 @@ */ -#include +#include "nl-default.h" + +#include + #include #include #include -#include +#include + +#include "link-api.h" /** @cond SKIP */ struct inet_data @@ -91,8 +90,8 @@ static void inet_free(struct rtnl_link *link, void *data) free(data); } -static struct nla_policy inet_policy[IFLA_INET6_MAX+1] = { - [IFLA_INET_CONF] = { .minlen = IPV4_DEVCONF_MAX * 4 }, +static struct nla_policy inet_policy[IFLA_INET_MAX+1] = { + [IFLA_INET_CONF] = { .minlen = 4 }, }; static int inet_parse_af(struct rtnl_link *link, struct nlattr *attr, void *data) @@ -104,9 +103,17 @@ static int inet_parse_af(struct rtnl_link *link, struct nlattr *attr, void *data err = nla_parse_nested(tb, IFLA_INET_MAX, attr, inet_policy); if (err < 0) return err; + if (tb[IFLA_INET_CONF] && nla_len(tb[IFLA_INET_CONF]) % 4) + return -EINVAL; + + if (tb[IFLA_INET_CONF]) { + int i; + int len = _NL_MIN(IPV4_DEVCONF_MAX, nla_len(tb[IFLA_INET_CONF]) / 4); - if (tb[IFLA_INET_CONF]) + for (i = 0; i < len; i++) + id->i_confset[i] = 1; nla_memcpy(&id->i_conf, tb[IFLA_INET_CONF], sizeof(id->i_conf)); + } return 0; } @@ -133,31 +140,34 @@ nla_put_failure: } static const struct trans_tbl inet_devconf[] = { - __ADD(IPV4_DEVCONF_FORWARDING, forwarding) - __ADD(IPV4_DEVCONF_MC_FORWARDING, mc_forwarding) - __ADD(IPV4_DEVCONF_PROXY_ARP, proxy_arp) - __ADD(IPV4_DEVCONF_ACCEPT_REDIRECTS, accept_redirects) - __ADD(IPV4_DEVCONF_SECURE_REDIRECTS, secure_redirects) - __ADD(IPV4_DEVCONF_SEND_REDIRECTS, send_redirects) - __ADD(IPV4_DEVCONF_SHARED_MEDIA, shared_media) - __ADD(IPV4_DEVCONF_RP_FILTER, rp_filter) - __ADD(IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE, accept_source_route) - __ADD(IPV4_DEVCONF_BOOTP_RELAY, bootp_relay) - __ADD(IPV4_DEVCONF_LOG_MARTIANS, log_martians) - __ADD(IPV4_DEVCONF_TAG, tag) - __ADD(IPV4_DEVCONF_ARPFILTER, arpfilter) - __ADD(IPV4_DEVCONF_MEDIUM_ID, medium_id) - __ADD(IPV4_DEVCONF_NOXFRM, noxfrm) - __ADD(IPV4_DEVCONF_NOPOLICY, nopolicy) - __ADD(IPV4_DEVCONF_FORCE_IGMP_VERSION, force_igmp_version) - __ADD(IPV4_DEVCONF_ARP_ANNOUNCE, arp_announce) - __ADD(IPV4_DEVCONF_ARP_IGNORE, arp_ignore) - __ADD(IPV4_DEVCONF_PROMOTE_SECONDARIES, promote_secondaries) - __ADD(IPV4_DEVCONF_ARP_ACCEPT, arp_accept) - __ADD(IPV4_DEVCONF_ARP_NOTIFY, arp_notify) - __ADD(IPV4_DEVCONF_ACCEPT_LOCAL, accept_local) - __ADD(IPV4_DEVCONF_SRC_VMARK, src_vmark) - __ADD(IPV4_DEVCONF_PROXY_ARP_PVLAN, proxy_arp_pvlan) + __ADD(IPV4_DEVCONF_FORWARDING, forwarding), + __ADD(IPV4_DEVCONF_MC_FORWARDING, mc_forwarding), + __ADD(IPV4_DEVCONF_PROXY_ARP, proxy_arp), + __ADD(IPV4_DEVCONF_ACCEPT_REDIRECTS, accept_redirects), + __ADD(IPV4_DEVCONF_SECURE_REDIRECTS, secure_redirects), + __ADD(IPV4_DEVCONF_SEND_REDIRECTS, send_redirects), + __ADD(IPV4_DEVCONF_SHARED_MEDIA, shared_media), + __ADD(IPV4_DEVCONF_RP_FILTER, rp_filter), + __ADD(IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE, accept_source_route), + __ADD(IPV4_DEVCONF_BOOTP_RELAY, bootp_relay), + __ADD(IPV4_DEVCONF_LOG_MARTIANS, log_martians), + __ADD(IPV4_DEVCONF_TAG, tag), + __ADD(IPV4_DEVCONF_ARPFILTER, arpfilter), + __ADD(IPV4_DEVCONF_MEDIUM_ID, medium_id), + __ADD(IPV4_DEVCONF_NOXFRM, noxfrm), + __ADD(IPV4_DEVCONF_NOPOLICY, nopolicy), + __ADD(IPV4_DEVCONF_FORCE_IGMP_VERSION, force_igmp_version), + __ADD(IPV4_DEVCONF_ARP_ANNOUNCE, arp_announce), + __ADD(IPV4_DEVCONF_ARP_IGNORE, arp_ignore), + __ADD(IPV4_DEVCONF_PROMOTE_SECONDARIES, promote_secondaries), + __ADD(IPV4_DEVCONF_ARP_ACCEPT, arp_accept), + __ADD(IPV4_DEVCONF_ARP_NOTIFY, arp_notify), + __ADD(IPV4_DEVCONF_ACCEPT_LOCAL, accept_local), + __ADD(IPV4_DEVCONF_SRC_VMARK, src_vmark), + __ADD(IPV4_DEVCONF_PROXY_ARP_PVLAN, proxy_arp_pvlan), + __ADD(IPV4_DEVCONF_ROUTE_LOCALNET, route_localnet), + __ADD(IPV4_DEVCONF_IGMPV2_UNSOLICITED_REPORT_INTERVAL, igmpv2_unsolicited_report_interval), + __ADD(IPV4_DEVCONF_IGMPV3_UNSOLICITED_REPORT_INTERVAL, igmpv3_unsolicited_report_interval), }; const char *rtnl_link_inet_devconf2str(int type, char *buf, size_t len) @@ -184,7 +194,7 @@ static void inet_dump_details(struct rtnl_link *link, for (i = 0; i < IPV4_DEVCONF_MAX; i++) { nl_dump_line(p, "%-19s %3u", rtnl_link_inet_devconf2str(i+1, buf, sizeof(buf)), - id->i_conf[i]); + id->i_confset[i] ? id->i_conf[i] : 0); if (++n == 3) { nl_dump(p, "\n"); @@ -220,6 +230,8 @@ static struct rtnl_link_af_ops inet_ops = { * @return 0 on success or a negative error code. * @return -NLE_RANGE cfgid is out of range, 1..IPV4_DEVCONF_MAX * @return -NLE_NOATTR configuration setting not available + * @return -NLE_INVAL cfgid not set. If the link was received via netlink, + * it means that the cfgid is not supported. */ int rtnl_link_inet_get_conf(struct rtnl_link *link, const unsigned int cfgid, uint32_t *res) @@ -229,9 +241,11 @@ int rtnl_link_inet_get_conf(struct rtnl_link *link, const unsigned int cfgid, if (cfgid == 0 || cfgid > IPV4_DEVCONF_MAX) return -NLE_RANGE; - if (!(id = rtnl_link_af_alloc(link, &inet_ops))) + if (!(id = rtnl_link_af_data(link, &inet_ops))) return -NLE_NOATTR; + if (!id->i_confset[cfgid - 1]) + return -NLE_INVAL; *res = id->i_conf[cfgid - 1]; return 0; @@ -267,12 +281,12 @@ int rtnl_link_inet_set_conf(struct rtnl_link *link, const unsigned int cfgid, } -static void __init inet_init(void) +static void _nl_init inet_init(void) { rtnl_link_af_register(&inet_ops); } -static void __exit inet_exit(void) +static void _nl_exit inet_exit(void) { rtnl_link_af_unregister(&inet_ops); } diff --git a/lib/route/link/inet6.c b/lib/route/link/inet6.c index 4c627bd..87b057f 100644 --- a/lib/route/link/inet6.c +++ b/lib/route/link/inet6.c @@ -1,30 +1,43 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/link/inet6.c AF_INET6 link operations - * - * 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 */ -#include +#include "nl-default.h" + +#include +#include + #include #include #include -#include +#include + +#include "nl-route.h" +#include "link-api.h" +#include "nl-priv-static-route/nl-priv-static-route.h" + +#define I6_ADDR_GEN_MODE_UNKNOWN UINT8_MAX struct inet6_data { uint32_t i6_flags; struct ifla_cacheinfo i6_cacheinfo; uint32_t i6_conf[DEVCONF_MAX]; + struct in6_addr i6_token; + uint8_t i6_conf_len; + uint8_t i6_addr_gen_mode; }; static void *inet6_alloc(struct rtnl_link *link) { - return calloc(1, sizeof(struct inet6_data)); + struct inet6_data *i6; + + i6 = calloc(1, sizeof(struct inet6_data)); + if (i6) + i6->i6_addr_gen_mode = I6_ADDR_GEN_MODE_UNKNOWN; + + return i6; } static void *inet6_clone(struct rtnl_link *link, void *data) @@ -43,13 +56,96 @@ static void inet6_free(struct rtnl_link *link, void *data) } static struct nla_policy inet6_policy[IFLA_INET6_MAX+1] = { - [IFLA_INET6_FLAGS] = { .type = NLA_U32 }, - [IFLA_INET6_CACHEINFO] = { .minlen = sizeof(struct ifla_cacheinfo) }, - [IFLA_INET6_CONF] = { .minlen = DEVCONF_MAX * 4 }, - [IFLA_INET6_STATS] = { .minlen = __IPSTATS_MIB_MAX * 8 }, - [IFLA_INET6_ICMP6STATS] = { .minlen = __ICMP6_MIB_MAX * 8 }, + [IFLA_INET6_FLAGS] = { .type = NLA_U32 }, + [IFLA_INET6_CACHEINFO] = { .minlen = sizeof(struct ifla_cacheinfo) }, + [IFLA_INET6_CONF] = { .minlen = 4 }, + [IFLA_INET6_STATS] = { .minlen = 8 }, + [IFLA_INET6_ICMP6STATS] = { .minlen = 8 }, + [IFLA_INET6_TOKEN] = { .minlen = sizeof(struct in6_addr) }, + [IFLA_INET6_ADDR_GEN_MODE] = { .type = NLA_U8 }, +}; + +static const uint8_t map_stat_id_from_IPSTATS_MIB_v1[__IPSTATS_MIB_MAX] = { + /* 14a196807482e6fc74f15fc03176d5c08880588f^:include/linux/snmp.h + * version before the API change in commit 14a196807482e6fc74f15fc03176d5c08880588f. + * This version was valid since commit edf391ff17232f097d72441c9ad467bcb3b5db18, which + * predates support for parsing IFLA_PROTINFO in libnl3. Such an even older meaning of + * the flags is not supported in libnl3. */ + [ 1] = RTNL_LINK_IP6_INPKTS, /* IPSTATS_MIB_INPKTS */ + [ 2] = RTNL_LINK_IP6_INHDRERRORS, /* IPSTATS_MIB_INHDRERRORS */ + [ 3] = RTNL_LINK_IP6_INTOOBIGERRORS, /* IPSTATS_MIB_INTOOBIGERRORS */ + [ 4] = RTNL_LINK_IP6_INNOROUTES, /* IPSTATS_MIB_INNOROUTES */ + [ 5] = RTNL_LINK_IP6_INADDRERRORS, /* IPSTATS_MIB_INADDRERRORS */ + [ 6] = RTNL_LINK_IP6_INUNKNOWNPROTOS, /* IPSTATS_MIB_INUNKNOWNPROTOS */ + [ 7] = RTNL_LINK_IP6_INTRUNCATEDPKTS, /* IPSTATS_MIB_INTRUNCATEDPKTS */ + [ 8] = RTNL_LINK_IP6_INDISCARDS, /* IPSTATS_MIB_INDISCARDS */ + [ 9] = RTNL_LINK_IP6_INDELIVERS, /* IPSTATS_MIB_INDELIVERS */ + [10] = RTNL_LINK_IP6_OUTFORWDATAGRAMS, /* IPSTATS_MIB_OUTFORWDATAGRAMS */ + [11] = RTNL_LINK_IP6_OUTPKTS, /* IPSTATS_MIB_OUTPKTS */ + [12] = RTNL_LINK_IP6_OUTDISCARDS, /* IPSTATS_MIB_OUTDISCARDS */ + [13] = RTNL_LINK_IP6_OUTNOROUTES, /* IPSTATS_MIB_OUTNOROUTES */ + [14] = RTNL_LINK_IP6_REASMTIMEOUT, /* IPSTATS_MIB_REASMTIMEOUT */ + [15] = RTNL_LINK_IP6_REASMREQDS, /* IPSTATS_MIB_REASMREQDS */ + [16] = RTNL_LINK_IP6_REASMOKS, /* IPSTATS_MIB_REASMOKS */ + [17] = RTNL_LINK_IP6_REASMFAILS, /* IPSTATS_MIB_REASMFAILS */ + [18] = RTNL_LINK_IP6_FRAGOKS, /* IPSTATS_MIB_FRAGOKS */ + [19] = RTNL_LINK_IP6_FRAGFAILS, /* IPSTATS_MIB_FRAGFAILS */ + [20] = RTNL_LINK_IP6_FRAGCREATES, /* IPSTATS_MIB_FRAGCREATES */ + [21] = RTNL_LINK_IP6_INMCASTPKTS, /* IPSTATS_MIB_INMCASTPKTS */ + [22] = RTNL_LINK_IP6_OUTMCASTPKTS, /* IPSTATS_MIB_OUTMCASTPKTS */ + [23] = RTNL_LINK_IP6_INBCASTPKTS, /* IPSTATS_MIB_INBCASTPKTS */ + [24] = RTNL_LINK_IP6_OUTBCASTPKTS, /* IPSTATS_MIB_OUTBCASTPKTS */ + [25] = RTNL_LINK_IP6_INOCTETS, /* IPSTATS_MIB_INOCTETS */ + [26] = RTNL_LINK_IP6_OUTOCTETS, /* IPSTATS_MIB_OUTOCTETS */ + [27] = RTNL_LINK_IP6_INMCASTOCTETS, /* IPSTATS_MIB_INMCASTOCTETS */ + [28] = RTNL_LINK_IP6_OUTMCASTOCTETS, /* IPSTATS_MIB_OUTMCASTOCTETS */ + [29] = RTNL_LINK_IP6_INBCASTOCTETS, /* IPSTATS_MIB_INBCASTOCTETS */ + [30] = RTNL_LINK_IP6_OUTBCASTOCTETS, /* IPSTATS_MIB_OUTBCASTOCTETS */ }; +static const uint8_t map_stat_id_from_IPSTATS_MIB_v2[__IPSTATS_MIB_MAX] = { + /* d8ec26d7f8287f5788a494f56e8814210f0e64be:include/uapi/linux/snmp.h + * version since the API change in commit 14a196807482e6fc74f15fc03176d5c08880588f */ + [ 1] = RTNL_LINK_IP6_INPKTS, /* IPSTATS_MIB_INPKTS */ + [ 2] = RTNL_LINK_IP6_INOCTETS, /* IPSTATS_MIB_INOCTETS */ + [ 3] = RTNL_LINK_IP6_INDELIVERS, /* IPSTATS_MIB_INDELIVERS */ + [ 4] = RTNL_LINK_IP6_OUTFORWDATAGRAMS, /* IPSTATS_MIB_OUTFORWDATAGRAMS */ + [ 5] = RTNL_LINK_IP6_OUTPKTS, /* IPSTATS_MIB_OUTPKTS */ + [ 6] = RTNL_LINK_IP6_OUTOCTETS, /* IPSTATS_MIB_OUTOCTETS */ + [ 7] = RTNL_LINK_IP6_INHDRERRORS, /* IPSTATS_MIB_INHDRERRORS */ + [ 8] = RTNL_LINK_IP6_INTOOBIGERRORS, /* IPSTATS_MIB_INTOOBIGERRORS */ + [ 9] = RTNL_LINK_IP6_INNOROUTES, /* IPSTATS_MIB_INNOROUTES */ + [10] = RTNL_LINK_IP6_INADDRERRORS, /* IPSTATS_MIB_INADDRERRORS */ + [11] = RTNL_LINK_IP6_INUNKNOWNPROTOS, /* IPSTATS_MIB_INUNKNOWNPROTOS */ + [12] = RTNL_LINK_IP6_INTRUNCATEDPKTS, /* IPSTATS_MIB_INTRUNCATEDPKTS */ + [13] = RTNL_LINK_IP6_INDISCARDS, /* IPSTATS_MIB_INDISCARDS */ + [14] = RTNL_LINK_IP6_OUTDISCARDS, /* IPSTATS_MIB_OUTDISCARDS */ + [15] = RTNL_LINK_IP6_OUTNOROUTES, /* IPSTATS_MIB_OUTNOROUTES */ + [16] = RTNL_LINK_IP6_REASMTIMEOUT, /* IPSTATS_MIB_REASMTIMEOUT */ + [17] = RTNL_LINK_IP6_REASMREQDS, /* IPSTATS_MIB_REASMREQDS */ + [18] = RTNL_LINK_IP6_REASMOKS, /* IPSTATS_MIB_REASMOKS */ + [19] = RTNL_LINK_IP6_REASMFAILS, /* IPSTATS_MIB_REASMFAILS */ + [20] = RTNL_LINK_IP6_FRAGOKS, /* IPSTATS_MIB_FRAGOKS */ + [21] = RTNL_LINK_IP6_FRAGFAILS, /* IPSTATS_MIB_FRAGFAILS */ + [22] = RTNL_LINK_IP6_FRAGCREATES, /* IPSTATS_MIB_FRAGCREATES */ + [23] = RTNL_LINK_IP6_INMCASTPKTS, /* IPSTATS_MIB_INMCASTPKTS */ + [24] = RTNL_LINK_IP6_OUTMCASTPKTS, /* IPSTATS_MIB_OUTMCASTPKTS */ + [25] = RTNL_LINK_IP6_INBCASTPKTS, /* IPSTATS_MIB_INBCASTPKTS */ + [26] = RTNL_LINK_IP6_OUTBCASTPKTS, /* IPSTATS_MIB_OUTBCASTPKTS */ + [27] = RTNL_LINK_IP6_INMCASTOCTETS, /* IPSTATS_MIB_INMCASTOCTETS */ + [28] = RTNL_LINK_IP6_OUTMCASTOCTETS, /* IPSTATS_MIB_OUTMCASTOCTETS */ + [29] = RTNL_LINK_IP6_INBCASTOCTETS, /* IPSTATS_MIB_INBCASTOCTETS */ + [30] = RTNL_LINK_IP6_OUTBCASTOCTETS, /* IPSTATS_MIB_OUTBCASTOCTETS */ + [31] = RTNL_LINK_IP6_CSUMERRORS, /* IPSTATS_MIB_CSUMERRORS */ + [32] = RTNL_LINK_IP6_NOECTPKTS, /* IPSTATS_MIB_NOECTPKTS */ + [33] = RTNL_LINK_IP6_ECT1PKTS, /* IPSTATS_MIB_ECT1PKTS */ + [34] = RTNL_LINK_IP6_ECT0PKTS, /* IPSTATS_MIB_ECT0PKTS */ + [35] = RTNL_LINK_IP6_CEPKTS, /* IPSTATS_MIB_CEPKTS */ + [36] = RTNL_LINK_REASM_OVERLAPS, /* IPSTATS_MIB_REASM_OVERLAPS */ +}; + +const uint8_t *const _nltst_map_stat_id_from_IPSTATS_MIB_v2 = map_stat_id_from_IPSTATS_MIB_v2; + static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr, void *data) { @@ -60,6 +156,12 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr, err = nla_parse_nested(tb, IFLA_INET6_MAX, attr, inet6_policy); if (err < 0) return err; + if (tb[IFLA_INET6_CONF] && nla_len(tb[IFLA_INET6_CONF]) % 4) + return -EINVAL; + if (tb[IFLA_INET6_STATS] && nla_len(tb[IFLA_INET6_STATS]) % 8) + return -EINVAL; + if (tb[IFLA_INET6_ICMP6STATS] && nla_len(tb[IFLA_INET6_ICMP6STATS]) % 8) + return -EINVAL; if (tb[IFLA_INET6_FLAGS]) i6->i6_flags = nla_get_u32(tb[IFLA_INET6_FLAGS]); @@ -68,10 +170,21 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr, nla_memcpy(&i6->i6_cacheinfo, tb[IFLA_INET6_CACHEINFO], sizeof(i6->i6_cacheinfo)); - if (tb[IFLA_INET6_CONF]) + if (tb[IFLA_INET6_CONF]) { + i6->i6_conf_len = _NL_MIN(ARRAY_SIZE(i6->i6_conf), + nla_len(tb[IFLA_INET6_CONF]) / + sizeof(i6->i6_conf[0])); nla_memcpy(&i6->i6_conf, tb[IFLA_INET6_CONF], - sizeof(i6->i6_conf)); - + sizeof(i6->i6_conf[0]) * i6->i6_conf_len); + } + + if (tb[IFLA_INET6_TOKEN]) + nla_memcpy(&i6->i6_token, tb[IFLA_INET6_TOKEN], + sizeof(struct in6_addr)); + + if (tb[IFLA_INET6_ADDR_GEN_MODE]) + i6->i6_addr_gen_mode = nla_get_u8 (tb[IFLA_INET6_ADDR_GEN_MODE]); + /* * Due to 32bit data alignment, these addresses must be copied to an * aligned location prior to access. @@ -80,20 +193,37 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr, unsigned char *cnt = nla_data(tb[IFLA_INET6_STATS]); uint64_t stat; int i; + int len = nla_len(tb[IFLA_INET6_STATS]) / 8; + const uint8_t *map_stat_id = map_stat_id_from_IPSTATS_MIB_v2; + + if (len < 32 || + (tb[IFLA_INET6_ICMP6STATS] && nla_len(tb[IFLA_INET6_ICMP6STATS]) < 6)) { + /* kernel commit 14a196807482e6fc74f15fc03176d5c08880588f reordered the values. + * The later commit 6a5dc9e598fe90160fee7de098fa319665f5253e added values + * IPSTATS_MIB_CSUMERRORS/ICMP6_MIB_CSUMERRORS. If the netlink is shorter + * then this, assume that the kernel uses the previous meaning of the + * enumeration. */ + map_stat_id = map_stat_id_from_IPSTATS_MIB_v1; + } - for (i = 1; i < __IPSTATS_MIB_MAX; i++) { + len = _NL_MIN(__IPSTATS_MIB_MAX, len); + for (i = 1; i < len; i++) { memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat)); - rtnl_link_set_stat(link, RTNL_LINK_IP6_INPKTS + i - 1, - stat); + rtnl_link_set_stat(link, map_stat_id[i], stat); } } if (tb[IFLA_INET6_ICMP6STATS]) { +#define _NL_ICMP6_MIB_MAX 6 unsigned char *cnt = nla_data(tb[IFLA_INET6_ICMP6STATS]); uint64_t stat; int i; + int len = _NL_MIN(_NL_ICMP6_MIB_MAX, nla_len(tb[IFLA_INET6_ICMP6STATS]) / 8); + + _NL_STATIC_ASSERT (__ICMP6_MIB_MAX >= _NL_ICMP6_MIB_MAX); + _NL_STATIC_ASSERT (RTNL_LINK_ICMP6_CSUMERRORS - RTNL_LINK_ICMP6_INMSGS + 1 == 5); - for (i = 1; i < __ICMP6_MIB_MAX; i++) { + for (i = 1; i < len; i++) { memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat)); rtnl_link_set_stat(link, RTNL_LINK_ICMP6_INMSGS + i - 1, stat); @@ -103,6 +233,19 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr, return 0; } +static int inet6_fill_af(struct rtnl_link *link, struct nl_msg *msg, void *data) +{ + struct inet6_data *id = data; + + if (id->i6_addr_gen_mode != I6_ADDR_GEN_MODE_UNKNOWN) + NLA_PUT_U8(msg, IFLA_INET6_ADDR_GEN_MODE, id->i6_addr_gen_mode); + + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + /* These live in include/net/if_inet6.h and should be moved to include/linux */ #define IF_RA_OTHERCONF 0x80 #define IF_RA_MANAGED 0x40 @@ -111,49 +254,54 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr, #define IF_READY 0x80000000 static const struct trans_tbl inet6_flags[] = { - __ADD(IF_RA_OTHERCONF, ra_otherconf) - __ADD(IF_RA_MANAGED, ra_managed) - __ADD(IF_RA_RCVD, ra_rcvd) - __ADD(IF_RS_SENT, rs_sent) - __ADD(IF_READY, ready) + __ADD(IF_RA_OTHERCONF, ra_otherconf), + __ADD(IF_RA_MANAGED, ra_managed), + __ADD(IF_RA_RCVD, ra_rcvd), + __ADD(IF_RS_SENT, rs_sent), + __ADD(IF_READY, ready), }; -static char *inet6_flags2str(int flags, char *buf, size_t len) +char *rtnl_link_inet6_flags2str(int flags, char *buf, size_t len) { return __flags2str(flags, buf, len, inet6_flags, ARRAY_SIZE(inet6_flags)); } +int rtnl_link_inet6_str2flags(const char *name) +{ + return __str2flags(name, inet6_flags, ARRAY_SIZE(inet6_flags)); +} + static const struct trans_tbl inet6_devconf[] = { - __ADD(DEVCONF_FORWARDING, forwarding) - __ADD(DEVCONF_HOPLIMIT, hoplimit) - __ADD(DEVCONF_MTU6, mtu6) - __ADD(DEVCONF_ACCEPT_RA, accept_ra) - __ADD(DEVCONF_ACCEPT_REDIRECTS, accept_redirects) - __ADD(DEVCONF_AUTOCONF, autoconf) - __ADD(DEVCONF_DAD_TRANSMITS, dad_transmits) - __ADD(DEVCONF_RTR_SOLICITS, rtr_solicits) - __ADD(DEVCONF_RTR_SOLICIT_INTERVAL, rtr_solicit_interval) - __ADD(DEVCONF_RTR_SOLICIT_DELAY, rtr_solicit_delay) - __ADD(DEVCONF_USE_TEMPADDR, use_tempaddr) - __ADD(DEVCONF_TEMP_VALID_LFT, temp_valid_lft) - __ADD(DEVCONF_TEMP_PREFERED_LFT, temp_prefered_lft) - __ADD(DEVCONF_REGEN_MAX_RETRY, regen_max_retry) - __ADD(DEVCONF_MAX_DESYNC_FACTOR, max_desync_factor) - __ADD(DEVCONF_MAX_ADDRESSES, max_addresses) - __ADD(DEVCONF_FORCE_MLD_VERSION, force_mld_version) - __ADD(DEVCONF_ACCEPT_RA_DEFRTR, accept_ra_defrtr) - __ADD(DEVCONF_ACCEPT_RA_PINFO, accept_ra_pinfo) - __ADD(DEVCONF_ACCEPT_RA_RTR_PREF, accept_ra_rtr_pref) - __ADD(DEVCONF_RTR_PROBE_INTERVAL, rtr_probe_interval) - __ADD(DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN, accept_ra_rt_info) - __ADD(DEVCONF_PROXY_NDP, proxy_ndp) - __ADD(DEVCONF_OPTIMISTIC_DAD, optimistic_dad) - __ADD(DEVCONF_ACCEPT_SOURCE_ROUTE, accept_source_route) - __ADD(DEVCONF_MC_FORWARDING, mc_forwarding) - __ADD(DEVCONF_DISABLE_IPV6, disable_ipv6) - __ADD(DEVCONF_ACCEPT_DAD, accept_dad) - __ADD(DEVCONF_FORCE_TLLAO, force_tllao) + __ADD(DEVCONF_FORWARDING, forwarding), + __ADD(DEVCONF_HOPLIMIT, hoplimit), + __ADD(DEVCONF_MTU6, mtu6), + __ADD(DEVCONF_ACCEPT_RA, accept_ra), + __ADD(DEVCONF_ACCEPT_REDIRECTS, accept_redirects), + __ADD(DEVCONF_AUTOCONF, autoconf), + __ADD(DEVCONF_DAD_TRANSMITS, dad_transmits), + __ADD(DEVCONF_RTR_SOLICITS, rtr_solicits), + __ADD(DEVCONF_RTR_SOLICIT_INTERVAL, rtr_solicit_interval), + __ADD(DEVCONF_RTR_SOLICIT_DELAY, rtr_solicit_delay), + __ADD(DEVCONF_USE_TEMPADDR, use_tempaddr), + __ADD(DEVCONF_TEMP_VALID_LFT, temp_valid_lft), + __ADD(DEVCONF_TEMP_PREFERED_LFT, temp_prefered_lft), + __ADD(DEVCONF_REGEN_MAX_RETRY, regen_max_retry), + __ADD(DEVCONF_MAX_DESYNC_FACTOR, max_desync_factor), + __ADD(DEVCONF_MAX_ADDRESSES, max_addresses), + __ADD(DEVCONF_FORCE_MLD_VERSION, force_mld_version), + __ADD(DEVCONF_ACCEPT_RA_DEFRTR, accept_ra_defrtr), + __ADD(DEVCONF_ACCEPT_RA_PINFO, accept_ra_pinfo), + __ADD(DEVCONF_ACCEPT_RA_RTR_PREF, accept_ra_rtr_pref), + __ADD(DEVCONF_RTR_PROBE_INTERVAL, rtr_probe_interval), + __ADD(DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN, accept_ra_rt_info), + __ADD(DEVCONF_PROXY_NDP, proxy_ndp), + __ADD(DEVCONF_OPTIMISTIC_DAD, optimistic_dad), + __ADD(DEVCONF_ACCEPT_SOURCE_ROUTE, accept_source_route), + __ADD(DEVCONF_MC_FORWARDING, mc_forwarding), + __ADD(DEVCONF_DISABLE_IPV6, disable_ipv6), + __ADD(DEVCONF_ACCEPT_DAD, accept_dad), + __ADD(DEVCONF_FORCE_TLLAO, force_tllao), }; static char *inet6_devconf2str(int type, char *buf, size_t len) @@ -162,32 +310,59 @@ static char *inet6_devconf2str(int type, char *buf, size_t len) ARRAY_SIZE(inet6_devconf)); } +static const struct trans_tbl inet6_addr_gen_mode[] = { + __ADD(IN6_ADDR_GEN_MODE_EUI64, eui64), + __ADD(IN6_ADDR_GEN_MODE_NONE, none), + __ADD(IN6_ADDR_GEN_MODE_STABLE_PRIVACY, stable_privacy), +}; + +const char *rtnl_link_inet6_addrgenmode2str(uint8_t mode, char *buf, size_t len) +{ + return __type2str(mode, buf, len, inet6_addr_gen_mode, + ARRAY_SIZE(inet6_addr_gen_mode)); +} + +uint8_t rtnl_link_inet6_str2addrgenmode(const char *mode) +{ + return (uint8_t) __str2type(mode, inet6_addr_gen_mode, + ARRAY_SIZE(inet6_addr_gen_mode)); +} static void inet6_dump_details(struct rtnl_link *link, struct nl_dump_params *p, void *data) { struct inet6_data *i6 = data; - char buf[64], buf2[64]; + struct nl_addr *addr; int i, n = 0; + char buf[64]; nl_dump_line(p, " ipv6 max-reasm-len %s", - nl_size2str(i6->i6_cacheinfo.max_reasm_len, buf, sizeof(buf))); + nl_size2str(i6->i6_cacheinfo.max_reasm_len, buf, sizeof(buf))); nl_dump(p, " <%s>\n", - inet6_flags2str(i6->i6_flags, buf, sizeof(buf))); - + rtnl_link_inet6_flags2str(i6->i6_flags, buf, sizeof(buf))); nl_dump_line(p, " create-stamp %.2fs reachable-time %s", - (double) i6->i6_cacheinfo.tstamp / 100., - nl_msec2str(i6->i6_cacheinfo.reachable_time, buf, sizeof(buf))); + (double) i6->i6_cacheinfo.tstamp / 100., + nl_msec2str(i6->i6_cacheinfo.reachable_time, buf, sizeof(buf))); nl_dump(p, " retrans-time %s\n", - nl_msec2str(i6->i6_cacheinfo.retrans_time, buf, sizeof(buf))); + nl_msec2str(i6->i6_cacheinfo.retrans_time, buf, sizeof(buf))); + + addr = nl_addr_build(AF_INET6, &i6->i6_token, sizeof(i6->i6_token)); + nl_dump(p, " token %s\n", + nl_addr2str(addr, buf, sizeof(buf))); + nl_addr_put(addr); + + nl_dump(p, " link-local address mode %s\n", + rtnl_link_inet6_addrgenmode2str(i6->i6_addr_gen_mode, + buf, sizeof(buf))); nl_dump_line(p, " devconf:\n"); nl_dump_line(p, " "); - for (i = 0; i < DEVCONF_MAX; i++) { + for (i = 0; i < (int) i6->i6_conf_len; i++) { + char buf2[64]; uint32_t value = i6->i6_conf[i]; int x, offset; @@ -206,7 +381,6 @@ static void inet6_dump_details(struct rtnl_link *link, default: snprintf(buf2, sizeof(buf2), "%u", value); break; - } inet6_devconf2str(i, buf, sizeof(buf)); @@ -218,7 +392,7 @@ static void inet6_dump_details(struct rtnl_link *link, for (x = strlen(buf); x < offset; x++) buf[x] = ' '; - strncpy(&buf[offset], buf2, strlen(buf2)); + _nl_strncpy_trunc(&buf[offset], buf2, sizeof(buf) - offset); nl_dump_line(p, "%s", buf); @@ -249,7 +423,7 @@ static void inet6_dump_stats(struct rtnl_link *link, if (octets) nl_dump(p, "%14.2f %3s ", octets, octetsUnit); else - nl_dump(p, "%16" PRIu64 " B ", 0); + nl_dump(p, "%16u B ", 0); nl_dump(p, "%18" PRIu64 " %18" PRIu64 "\n", link->l_stats[RTNL_LINK_IP6_INDISCARDS], @@ -265,7 +439,7 @@ static void inet6_dump_stats(struct rtnl_link *link, if (octets) nl_dump(p, "%14.2f %3s ", octets, octetsUnit); else - nl_dump(p, "%16" PRIu64 " B ", 0); + nl_dump(p, "%16u B ", 0); nl_dump(p, "%18" PRIu64 " %18" PRIu64 "\n", link->l_stats[RTNL_LINK_IP6_OUTDISCARDS], @@ -281,7 +455,7 @@ static void inet6_dump_stats(struct rtnl_link *link, if (octets) nl_dump(p, "%14.2f %3s ", octets, octetsUnit); else - nl_dump(p, "%16" PRIu64 " B ", 0); + nl_dump(p, "%16u B ", 0); nl_dump(p, "%18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_INBCASTPKTS]); octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INBCASTOCTETS], @@ -289,7 +463,7 @@ static void inet6_dump_stats(struct rtnl_link *link, if (octets) nl_dump(p, "%14.2f %3s\n", octets, octetsUnit); else - nl_dump(p, "%16" PRIu64 " B\n", 0); + nl_dump(p, "%16u B\n", 0); nl_dump(p, " OutMcastPkts OutMcastOctets " " OutBcastPkts OutBcastOctests\n"); @@ -301,7 +475,7 @@ static void inet6_dump_stats(struct rtnl_link *link, if (octets) nl_dump(p, "%14.2f %3s ", octets, octetsUnit); else - nl_dump(p, "%16" PRIu64 " B ", 0); + nl_dump(p, "%16u B ", 0); nl_dump(p, "%18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_OUTBCASTPKTS]); octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTBCASTOCTETS], @@ -309,7 +483,7 @@ static void inet6_dump_stats(struct rtnl_link *link, if (octets) nl_dump(p, "%14.2f %3s\n", octets, octetsUnit); else - nl_dump(p, "%16" PRIu64 " B\n", 0); + nl_dump(p, "%16u B\n", 0); nl_dump(p, " ReasmOKs ReasmFails " " ReasmReqds ReasmTimeout\n"); @@ -335,19 +509,29 @@ static void inet6_dump_stats(struct rtnl_link *link, link->l_stats[RTNL_LINK_IP6_INADDRERRORS]); nl_dump(p, " InUnknownProtos InTruncatedPkts " - " OutNoRoutes\n"); - nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n", + " OutNoRoutes InCsumErrors\n"); + nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n", link->l_stats[RTNL_LINK_IP6_INUNKNOWNPROTOS], link->l_stats[RTNL_LINK_IP6_INTRUNCATEDPKTS], - link->l_stats[RTNL_LINK_IP6_OUTNOROUTES]); + link->l_stats[RTNL_LINK_IP6_OUTNOROUTES], + link->l_stats[RTNL_LINK_IP6_CSUMERRORS]); - nl_dump(p, " ICMPv6: InMsgs InErrors " - " OutMsgs OutErrors\n"); + nl_dump(p, " InNoECTPkts InECT1Pkts " + " InECT0Pkts InCEPkts\n"); nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n", + link->l_stats[RTNL_LINK_IP6_NOECTPKTS], + link->l_stats[RTNL_LINK_IP6_ECT1PKTS], + link->l_stats[RTNL_LINK_IP6_ECT0PKTS], + link->l_stats[RTNL_LINK_IP6_CEPKTS]); + + nl_dump(p, " ICMPv6: InMsgs InErrors " + " OutMsgs OutErrors InCsumErrors\n"); + nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n", link->l_stats[RTNL_LINK_ICMP6_INMSGS], link->l_stats[RTNL_LINK_ICMP6_INERRORS], link->l_stats[RTNL_LINK_ICMP6_OUTMSGS], - link->l_stats[RTNL_LINK_ICMP6_OUTERRORS]); + link->l_stats[RTNL_LINK_ICMP6_OUTERRORS], + link->l_stats[RTNL_LINK_ICMP6_CSUMERRORS]); } static const struct nla_policy protinfo_policy = { @@ -361,17 +545,196 @@ static struct rtnl_link_af_ops inet6_ops = { .ao_free = &inet6_free, .ao_parse_protinfo = &inet6_parse_protinfo, .ao_parse_af = &inet6_parse_protinfo, + .ao_fill_af = &inet6_fill_af, .ao_dump[NL_DUMP_DETAILS] = &inet6_dump_details, .ao_dump[NL_DUMP_STATS] = &inet6_dump_stats, .ao_protinfo_policy = &protinfo_policy, }; -static void __init inet6_init(void) +/** + * Return IPv6 specific flags + * @arg link Link object + * @arg out_flags Flags on success + * + * Returns the link's IPv6 flags. + * + * @return 0 on success + * @return -NLE_NOATTR configuration setting not available + */ +int rtnl_link_inet6_get_flags(struct rtnl_link *link, uint32_t* out_flags) +{ + struct inet6_data *id = NULL; + + if (!(id = rtnl_link_af_data(link, &inet6_ops))) + return -NLE_NOATTR; + + *out_flags = id->i6_flags; + return 0; +} + +/** + * Set IPv6 specific flags + * @arg link Link object + * @arg flags Flags to set + * + * Sets the link's IPv6 specific flags. Overwrites currently set flags. + * + * @return 0 on success + * @return -NLE_NOMEM could not allocate inet6 data + */ +int rtnl_link_inet6_set_flags(struct rtnl_link *link, uint32_t flags) +{ + struct inet6_data *id; + + if (!(id = rtnl_link_af_alloc(link, &inet6_ops))) + return -NLE_NOMEM; + + id->i6_flags = flags; + return 0; +} + +/** + * Get IPv6 tokenized interface identifier + * @arg link Link object + * @arg token Tokenized interface identifier on success + * + * Returns the link's IPv6 tokenized interface identifier. + * + * @return 0 on success + * @return -NLE_NOMEM failure to allocate struct nl_addr result + * @return -NLE_NOATTR configuration setting not available + * @return -NLE_NOADDR tokenized interface identifier is not set + */ +int rtnl_link_inet6_get_token(struct rtnl_link *link, struct nl_addr **addr) +{ + struct inet6_data *id; + + if (!(id = rtnl_link_af_data(link, &inet6_ops))) + return -NLE_NOATTR; + + *addr = nl_addr_build(AF_INET6, &id->i6_token, sizeof(id->i6_token)); + if (!*addr) + return -NLE_NOMEM; + if (nl_addr_iszero(*addr)) { + nl_addr_put(*addr); + *addr = NULL; + return -NLE_NOADDR; + } + + return 0; +} + +/** + * Set IPv6 tokenized interface identifier + * @arg link Link object + * @arg token Tokenized interface identifier + * + * Sets the link's IPv6 tokenized interface identifier. + * + * @return 0 on success + * @return -NLE_NOMEM could not allocate inet6 data + * @return -NLE_INVAL addr is not a valid inet6 address + */ +int rtnl_link_inet6_set_token(struct rtnl_link *link, struct nl_addr *addr) +{ + struct inet6_data *id; + + if ((nl_addr_get_family(addr) != AF_INET6) || + (nl_addr_get_len(addr) != sizeof(id->i6_token))) + return -NLE_INVAL; + + if (!(id = rtnl_link_af_alloc(link, &inet6_ops))) + return -NLE_NOMEM; + + memcpy(&id->i6_token, nl_addr_get_binary_addr(addr), + sizeof(id->i6_token)); + return 0; +} + +/** + * Get IPv6 link-local address generation mode + * @arg link Link object + * @arg mode Generation mode on success + * + * Returns the link's IPv6 link-local address generation mode. + * + * @return 0 on success + * @return -NLE_NOATTR configuration setting not available + * @return -NLE_INVAL generation mode unknown. If the link was received via + * netlink, it means that address generation mode is not + * supported by the kernel. + */ +int rtnl_link_inet6_get_addr_gen_mode(struct rtnl_link *link, uint8_t *mode) +{ + struct inet6_data *id; + + if (!(id = rtnl_link_af_data(link, &inet6_ops))) + return -NLE_NOATTR; + + if (id->i6_addr_gen_mode == I6_ADDR_GEN_MODE_UNKNOWN) + return -NLE_INVAL; + + *mode = id->i6_addr_gen_mode; + return 0; +} + +/** + * Set IPv6 link-local address generation mode + * @arg link Link object + * @arg mode Generation mode + * + * Sets the link's IPv6 link-local address generation mode. + * + * @return 0 on success + * @return -NLE_NOMEM could not allocate inet6 data + */ +int rtnl_link_inet6_set_addr_gen_mode(struct rtnl_link *link, uint8_t mode) +{ + struct inet6_data *id; + + if (!(id = rtnl_link_af_alloc(link, &inet6_ops))) + return -NLE_NOMEM; + + id->i6_addr_gen_mode = mode; + return 0; +} + +/** + * Get value of a ipv6 link configuration setting + * @arg link Link object + * @arg cfgid Configuration identifier + * @arg res Result pointer + * + * Stores the value of the specified configuration setting in the provided + * result pointer. + * + * @return 0 on success or a negative error code. + * @return -NLE_RANGE cfgid is out of range or not provided by kernel. + * @return -NLE_NOATTR configuration setting not available + */ +int rtnl_link_inet6_get_conf(struct rtnl_link *link, unsigned int cfgid, + uint32_t *res) +{ + struct inet6_data *id; + + if (!(id = rtnl_link_af_data(link, &inet6_ops))) + return -NLE_NOATTR; + + if (cfgid >= id->i6_conf_len) + return -NLE_RANGE; + + *res = id->i6_conf[cfgid]; + + return 0; +} + + +static void _nl_init inet6_init(void) { rtnl_link_af_register(&inet6_ops); } -static void __exit inet6_exit(void) +static void _nl_exit inet6_exit(void) { rtnl_link_af_unregister(&inet6_ops); } diff --git a/lib/route/link/ip6gre.c b/lib/route/link/ip6gre.c new file mode 100644 index 0000000..51d4609 --- /dev/null +++ b/lib/route/link/ip6gre.c @@ -0,0 +1,890 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +/** + * @ingroup link + * @defgroup ip6gre IP6GRE + * ip6gre link module + * + * @details + * \b Link Type Name: "ip6gre" + * + * @route_doc{link_ip6gre, IP6GRE Documentation} + * + * @{ + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "nl-route.h" +#include "link-api.h" + +#define IP6GRE_ATTR_LINK (1 << 0) +#define IP6GRE_ATTR_IFLAGS (1 << 1) +#define IP6GRE_ATTR_OFLAGS (1 << 2) +#define IP6GRE_ATTR_IKEY (1 << 3) +#define IP6GRE_ATTR_OKEY (1 << 4) +#define IP6GRE_ATTR_LOCAL (1 << 5) +#define IP6GRE_ATTR_REMOTE (1 << 6) +#define IP6GRE_ATTR_TTL (1 << 7) +#define IP6GRE_ATTR_ENCAPLIMIT (1 << 8) +#define IP6GRE_ATTR_FLOWINFO (1 << 9) +#define IP6GRE_ATTR_FLAGS (1 << 10) +#define IP6GRE_ATTR_FWMARK (1 << 11) + +struct ip6gre_info +{ + uint8_t ttl; + uint8_t encaplimit; + uint16_t iflags; + uint16_t oflags; + uint32_t ikey; + uint32_t okey; + uint32_t link; + uint32_t flowinfo; + uint32_t flags; + struct in6_addr local; + struct in6_addr remote; + uint32_t fwmark; + uint32_t ip6gre_mask; +}; + +static struct nla_policy ip6gre_policy[IFLA_GRE_MAX + 1] = { + [IFLA_GRE_LINK] = { .type = NLA_U32 }, + [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, + [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, + [IFLA_GRE_IKEY] = { .type = NLA_U32 }, + [IFLA_GRE_OKEY] = { .type = NLA_U32 }, + [IFLA_GRE_LOCAL] = { .minlen = sizeof(struct in6_addr) }, + [IFLA_GRE_REMOTE] = { .minlen = sizeof(struct in6_addr) }, + [IFLA_GRE_TTL] = { .type = NLA_U8 }, + [IFLA_GRE_ENCAP_LIMIT] = { .type = NLA_U8 }, + [IFLA_GRE_FLOWINFO] = { .type = NLA_U32 }, + [IFLA_GRE_FLAGS] = { .type = NLA_U32 }, + [IFLA_GRE_FWMARK] = { .type = NLA_U32 }, +}; + +static int ip6gre_alloc(struct rtnl_link *link) +{ + struct ip6gre_info *ip6gre; + + if (link->l_info) + memset(link->l_info, 0, sizeof(*ip6gre)); + else { + ip6gre = calloc(1, sizeof(*ip6gre)); + if (!ip6gre) + return -NLE_NOMEM; + + link->l_info = ip6gre; + } + + return 0; +} + +static int ip6gre_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_GRE_MAX + 1]; + struct ip6gre_info *ip6gre; + int err; + + NL_DBG(3, "Parsing IP6GRE link info\n"); + + err = nla_parse_nested(tb, IFLA_GRE_MAX, data, ip6gre_policy); + if (err < 0) + goto errout; + + err = ip6gre_alloc(link); + if (err < 0) + goto errout; + + ip6gre = link->l_info; + + if (tb[IFLA_GRE_LINK]) { + ip6gre->link = nla_get_u32(tb[IFLA_GRE_LINK]); + ip6gre->ip6gre_mask |= IP6GRE_ATTR_LINK; + } + + if (tb[IFLA_GRE_IFLAGS]) { + ip6gre->iflags = nla_get_u16(tb[IFLA_GRE_IFLAGS]); + ip6gre->ip6gre_mask |= IP6GRE_ATTR_IFLAGS; + } + + if (tb[IFLA_GRE_OFLAGS]) { + ip6gre->oflags = nla_get_u16(tb[IFLA_GRE_OFLAGS]); + ip6gre->ip6gre_mask |= IP6GRE_ATTR_OFLAGS; + } + + if (tb[IFLA_GRE_IKEY]) { + ip6gre->ikey = nla_get_u32(tb[IFLA_GRE_IKEY]); + ip6gre->ip6gre_mask |= IP6GRE_ATTR_IKEY; + } + + if (tb[IFLA_GRE_OKEY]) { + ip6gre->okey = nla_get_u32(tb[IFLA_GRE_OKEY]); + ip6gre->ip6gre_mask |= IP6GRE_ATTR_OKEY; + } + + if (tb[IFLA_GRE_LOCAL]) { + nla_memcpy(&ip6gre->local, tb[IFLA_GRE_LOCAL], sizeof(struct in6_addr)); + ip6gre->ip6gre_mask |= IP6GRE_ATTR_LOCAL; + } + + if (tb[IFLA_GRE_REMOTE]) { + nla_memcpy(&ip6gre->remote, tb[IFLA_GRE_REMOTE], sizeof(struct in6_addr)); + ip6gre->ip6gre_mask |= IP6GRE_ATTR_REMOTE; + } + + if (tb[IFLA_GRE_TTL]) { + ip6gre->ttl = nla_get_u8(tb[IFLA_GRE_TTL]); + ip6gre->ip6gre_mask |= IP6GRE_ATTR_TTL; + } + + if (tb[IFLA_GRE_ENCAP_LIMIT]) { + ip6gre->encaplimit = nla_get_u8(tb[IFLA_GRE_ENCAP_LIMIT]); + ip6gre->ip6gre_mask |= IP6GRE_ATTR_ENCAPLIMIT; + } + + if (tb[IFLA_GRE_FLOWINFO]) { + ip6gre->flowinfo = nla_get_u32(tb[IFLA_GRE_FLOWINFO]); + ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLOWINFO; + } + + if (tb[IFLA_GRE_FLAGS]) { + ip6gre->flags = nla_get_u32(tb[IFLA_GRE_FLAGS]); + ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLAGS; + } + + if (tb[IFLA_GRE_FWMARK]) { + ip6gre->fwmark = nla_get_u32(tb[IFLA_GRE_FWMARK]); + ip6gre->ip6gre_mask |= IP6GRE_ATTR_FWMARK; + } + + err = 0; + + errout: + return err; +} + +static int ip6gre_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct ip6gre_info *ip6gre = link->l_info; + struct nlattr *data; + + data = nla_nest_start(msg, IFLA_INFO_DATA); + if (!data) + return -NLE_MSGSIZE; + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LINK) + NLA_PUT_U32(msg, IFLA_GRE_LINK, ip6gre->link); + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IFLAGS) + NLA_PUT_U16(msg, IFLA_GRE_IFLAGS, ip6gre->iflags); + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OFLAGS) + NLA_PUT_U16(msg, IFLA_GRE_OFLAGS, ip6gre->oflags); + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IKEY) + NLA_PUT_U32(msg, IFLA_GRE_IKEY, ip6gre->ikey); + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OKEY) + NLA_PUT_U32(msg, IFLA_GRE_OKEY, ip6gre->okey); + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LOCAL) + NLA_PUT(msg, IFLA_GRE_LOCAL, sizeof(struct in6_addr), &ip6gre->local); + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_REMOTE) + NLA_PUT(msg, IFLA_GRE_REMOTE, sizeof(struct in6_addr), &ip6gre->remote); + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_TTL) + NLA_PUT_U8(msg, IFLA_GRE_TTL, ip6gre->ttl); + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_ENCAPLIMIT) + NLA_PUT_U8(msg, IFLA_GRE_ENCAP_LIMIT, ip6gre->encaplimit); + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLOWINFO) + NLA_PUT_U32(msg, IFLA_GRE_FLOWINFO, ip6gre->flowinfo); + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLAGS) + NLA_PUT_U32(msg, IFLA_GRE_FLAGS, ip6gre->flags); + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FWMARK) + NLA_PUT_U32(msg, IFLA_GRE_FWMARK, ip6gre->fwmark); + + nla_nest_end(msg, data); + + nla_put_failure: + + return 0; +} + +static void ip6gre_free(struct rtnl_link *link) +{ + struct ip6gre_info *ip6gre = link->l_info; + + free(ip6gre); + link->l_info = NULL; +} + +static void ip6gre_dump_line(struct rtnl_link *link, struct nl_dump_params *p) +{ + nl_dump(p, "ip6gre : %s", link->l_name); +} + +static void ip6gre_dump_details(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct ip6gre_info *ip6gre = link->l_info; + char *name; + char addr[INET6_ADDRSTRLEN]; + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LINK) { + nl_dump(p, " link "); + name = rtnl_link_get_name(link); + if (name) + nl_dump_line(p, "%s\n", name); + else + nl_dump_line(p, "%u\n", ip6gre->link); + } + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IFLAGS) { + nl_dump(p, " iflags "); + nl_dump_line(p, "%x\n", ip6gre->iflags); + } + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OFLAGS) { + nl_dump(p, " oflags "); + nl_dump_line(p, "%x\n", ip6gre->oflags); + } + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IKEY) { + nl_dump(p, " ikey "); + nl_dump_line(p, "%x\n",ip6gre->ikey); + } + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OKEY) { + nl_dump(p, " okey "); + nl_dump_line(p, "%x\n", ip6gre->okey); + } + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LOCAL) { + nl_dump(p, " local "); + nl_dump_line(p, "%s\n", + _nl_inet_ntop(AF_INET6, &ip6gre->local, addr)); + } + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_REMOTE) { + nl_dump(p, " remote "); + nl_dump_line(p, "%s\n", + _nl_inet_ntop(AF_INET6, &ip6gre->remote, addr)); + } + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_TTL) { + nl_dump(p, " ttl "); + nl_dump_line(p, "%u\n", ip6gre->ttl); + } + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_ENCAPLIMIT) { + nl_dump(p, " encaplimit "); + nl_dump_line(p, "%u\n", ip6gre->encaplimit); + } + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLOWINFO) { + nl_dump(p, " flowinfo "); + nl_dump_line(p, "%x\n", ip6gre->flowinfo); + } + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLAGS) { + nl_dump(p, " flags "); + nl_dump_line(p, "%x\n", ip6gre->flags); + } + + if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FWMARK) { + nl_dump(p, " fwmark "); + nl_dump_line(p, "%x\n", ip6gre->fwmark); + } +} + +static int ip6gre_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct ip6gre_info *ip6gre_dst, *ip6gre_src = src->l_info; + int err; + + dst->l_info = NULL; + + err = rtnl_link_set_type(dst, "ip6gre"); + if (err < 0) + return err; + + ip6gre_dst = dst->l_info; + + if (!ip6gre_dst || !ip6gre_src) + BUG(); + + memcpy(ip6gre_dst, ip6gre_src, sizeof(struct ip6gre_info)); + + return 0; +} + +static struct rtnl_link_info_ops ip6gre_info_ops = { + .io_name = "ip6gre", + .io_alloc = ip6gre_alloc, + .io_parse = ip6gre_parse, + .io_dump = { + [NL_DUMP_LINE] = ip6gre_dump_line, + [NL_DUMP_DETAILS] = ip6gre_dump_details, + }, + .io_clone = ip6gre_clone, + .io_put_attrs = ip6gre_put_attrs, + .io_free = ip6gre_free, +}; + +#define IS_IP6GRE_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &ip6gre_info_ops) { \ + APPBUG("Link is not a ip6gre link. set type \"ip6gre\" first.");\ + return -NLE_OPNOTSUPP; \ + } + +#define HAS_IP6GRE_ATTR_ASSERT(link,attr) \ + if (!((link)->ip6gre_mask & (attr))) \ + return -NLE_NOATTR; + +struct rtnl_link *rtnl_link_ip6gre_alloc(void) +{ + struct rtnl_link *link; + int err; + + link = rtnl_link_alloc(); + if (!link) + return NULL; + + err = rtnl_link_set_type(link, "ip6gre"); + if (err < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if link is a IP6GRE link + * @arg link Link object + * + * @return True if link is a IP6GRE link, otherwise 0 is returned. + */ +int rtnl_link_is_ip6gre(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "ip6gre"); +} + +/** + * Create a new IP6GRE tunnel device + * @arg sock netlink socket + * @arg name name of the tunnel deviceL + * + * Creates a new ip6gre tunnel device in the kernel + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_add(struct nl_sock *sk, const char *name) +{ + struct rtnl_link *link; + int err; + + link = rtnl_link_ip6gre_alloc(); + if (!link) + return -NLE_NOMEM; + + if(name) + rtnl_link_set_name(link, name); + + err = rtnl_link_add(sk, link, NLM_F_CREATE); + rtnl_link_put(link); + + return err; +} + +/** + * Set IP6GRE tunnel interface index + * @arg link Link object + * @arg index interface index + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_set_link(struct rtnl_link *link, uint32_t index) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + ip6gre->link = index; + ip6gre->ip6gre_mask |= IP6GRE_ATTR_LINK; + + return 0; +} + +/** + * Get IP6GRE tunnel interface index + * @arg link Link object + * @arg index addr to fill in with the interface index + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_get_link(struct rtnl_link *link, uint32_t *index) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_LINK); + + *index = ip6gre->link; + + return 0; +} + +/** + * Set IP6GRE tunnel set iflags + * @arg link Link object + * @arg iflags ip6gre iflags + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_set_iflags(struct rtnl_link *link, uint16_t iflags) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + ip6gre->iflags = iflags; + ip6gre->ip6gre_mask |= IP6GRE_ATTR_IFLAGS; + + return 0; +} + +/** + * Get IP6GRE tunnel iflags + * @arg link Link object + * @arg iflags addr to fill in with the iflags + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_get_iflags(struct rtnl_link *link, uint16_t *iflags) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_IFLAGS); + + *iflags = ip6gre->iflags; + + return 0; +} + +/** + * Set IP6GRE tunnel set oflags + * @arg link Link object + * @arg oflags ip6gre oflags + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_set_oflags(struct rtnl_link *link, uint16_t oflags) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + ip6gre->oflags = oflags; + ip6gre->ip6gre_mask |= IP6GRE_ATTR_OFLAGS; + + return 0; +} + +/** + * Get IP6GRE tunnel oflags + * @arg link Link object + * @arg oflags addr to fill in with the oflags + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_get_oflags(struct rtnl_link *link, uint16_t *oflags) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_OFLAGS); + + *oflags = ip6gre->oflags; + + return 0; +} + +/** + * Set IP6GRE tunnel set ikey + * @arg link Link object + * @arg ikey ip6gre ikey + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_set_ikey(struct rtnl_link *link, uint32_t ikey) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + ip6gre->ikey = ikey; + ip6gre->ip6gre_mask |= IP6GRE_ATTR_IKEY; + + return 0; +} + +/** + * Get IP6GRE tunnel ikey + * @arg link Link object + * @arg ikey addr to fill in with the ikey + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_get_ikey(struct rtnl_link *link, uint32_t *ikey) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_IKEY); + + *ikey = ip6gre->ikey; + + return 0; +} + +/** + * Set IP6GRE tunnel set okey + * @arg link Link object + * @arg okey ip6gre okey + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_set_okey(struct rtnl_link *link, uint32_t okey) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + ip6gre->okey = okey; + ip6gre->ip6gre_mask |= IP6GRE_ATTR_OKEY; + + return 0; +} + +/** + * Get IP6GRE tunnel okey + * @arg link Link object + * @arg okey addr to fill in with the okey + * + * @return okey value + */ +int rtnl_link_ip6gre_get_okey(struct rtnl_link *link, uint32_t *okey) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_OKEY); + + *okey = ip6gre->okey; + + return 0; +} + +/** + * Set IP6GRE tunnel local address + * @arg link Link object + * @arg local local address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_set_local(struct rtnl_link *link, struct in6_addr *local) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + memcpy(&ip6gre->local, local, sizeof(struct in6_addr)); + ip6gre->ip6gre_mask |= IP6GRE_ATTR_LOCAL; + + return 0; +} + +/** + * Get IP6GRE tunnel local address + * @arg link Link object + * @arg local addr to fill in with local address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_get_local(struct rtnl_link *link, struct in6_addr *local) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_LOCAL); + + memcpy(local, &ip6gre->local, sizeof(struct in6_addr)); + + return 0; +} + +/** + * Set IP6GRE tunnel remote address + * @arg link Link object + * @arg remote remote address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_set_remote(struct rtnl_link *link, struct in6_addr *remote) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + memcpy(&ip6gre->remote, remote, sizeof(struct in6_addr)); + ip6gre->ip6gre_mask |= IP6GRE_ATTR_REMOTE; + + return 0; +} + +/** + * Get IP6GRE tunnel remote address + * @arg link Link object + * @arg remote addr to fill in with remote address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_get_remote(struct rtnl_link *link, struct in6_addr *remote) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_REMOTE); + + memcpy(remote, &ip6gre->remote, sizeof(struct in6_addr)); + + return 0; +} + +/** + * Set IP6GRE tunnel ttl + * @arg link Link object + * @arg ttl tunnel ttl + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_set_ttl(struct rtnl_link *link, uint8_t ttl) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + ip6gre->ttl = ttl; + ip6gre->ip6gre_mask |= IP6GRE_ATTR_TTL; + + return 0; +} + +/** + * Set IP6GRE tunnel ttl + * @arg link Link object + * @arg ttl addr to fill in with the ttl + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_get_ttl(struct rtnl_link *link, uint8_t *ttl) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_TTL); + + *ttl = ip6gre->ttl; + + return 0; +} + +/** + * Set IP6GRE tunnel encap limit + * @arg link Link object + * @arg encaplimit tunnel encap limit value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_set_encaplimit(struct rtnl_link *link, uint8_t encaplimit) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + ip6gre->encaplimit = encaplimit; + ip6gre->ip6gre_mask |= IP6GRE_ATTR_ENCAPLIMIT; + + return 0; +} + +/** + * Get IP6GRE tunnel encap limit + * @arg link Link object + * @arg encaplimit addr to fill in with the encaplimit + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_get_encaplimit(struct rtnl_link *link, uint8_t *encaplimit) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_ENCAPLIMIT); + + *encaplimit = ip6gre->encaplimit; + + return 0; +} + +/** + * Set IP6GRE tunnel flowinfo + * @arg link Link object + * @arg flowinfo flowinfo value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_set_flowinfo(struct rtnl_link *link, uint32_t flowinfo) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + ip6gre->flowinfo = flowinfo; + ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLOWINFO; + + return 0; +} + +/** + * Get IP6GRE flowinfo + * @arg link Link object + * @arg flowinfo addr to fill in with the flowinfo + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_get_flowinfo(struct rtnl_link *link, uint32_t *flowinfo) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_FLOWINFO); + + *flowinfo = ip6gre->flowinfo; + + return 0; +} + +/** + * Set IP6GRE tunnel flags + * @arg link Link object + * @arg flags tunnel flags + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_set_flags(struct rtnl_link *link, uint32_t flags) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + ip6gre->flags = flags; + ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLAGS; + + return 0; +} + +/** + * Get IP6GRE flags + * @arg link Link object + * @arg flags addr to fill in with the tunnel flags + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_get_flags(struct rtnl_link *link, uint32_t *flags) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_FLAGS); + + *flags = ip6gre->flags; + + return 0; +} + +/** + * Set IP6GRE tunnel fwmark + * @arg link Link object + * @arg fwmark fwmark + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_set_fwmark(struct rtnl_link *link, uint32_t fwmark) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + ip6gre->fwmark = fwmark; + ip6gre->ip6gre_mask |= IP6GRE_ATTR_FWMARK; + + return 0; +} + +/** + * Get IP6GRE tunnel fwmark + * @arg link Link object + * @arg fwmark addr to fill in with the fwmark + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6gre_get_fwmark(struct rtnl_link *link, uint32_t *fwmark) +{ + struct ip6gre_info *ip6gre = link->l_info; + + IS_IP6GRE_LINK_ASSERT(link); + + HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_FWMARK); + + *fwmark = ip6gre->fwmark; + + return 0; +} + +static void _nl_init ip6gre_init(void) +{ + rtnl_link_register_info(&ip6gre_info_ops); +} + +static void _nl_exit ip6gre_exit(void) +{ + rtnl_link_unregister_info(&ip6gre_info_ops); +} diff --git a/lib/route/link/ip6tnl.c b/lib/route/link/ip6tnl.c new file mode 100644 index 0000000..9b3abfd --- /dev/null +++ b/lib/route/link/ip6tnl.c @@ -0,0 +1,746 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2014 Susant Sahani + */ + +/** + * @ingroup link + * @defgroup ip6tnl IP6TNL + * ip6tnl link module + * + * @details + * \b Link Type Name: "ip6tnl" + * + * @route_doc{link_ip6tnl, IP6TNL Documentation} + * + * @{ + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "nl-route.h" +#include "link-api.h" + +#define IP6_TNL_ATTR_LINK (1 << 0) +#define IP6_TNL_ATTR_LOCAL (1 << 1) +#define IP6_TNL_ATTR_REMOTE (1 << 2) +#define IP6_TNL_ATTR_TTL (1 << 3) +#define IP6_TNL_ATTR_TOS (1 << 4) +#define IP6_TNL_ATTR_ENCAPLIMIT (1 << 5) +#define IP6_TNL_ATTR_FLAGS (1 << 6) +#define IP6_TNL_ATTR_PROTO (1 << 7) +#define IP6_TNL_ATTR_FLOWINFO (1 << 8) +#define IP6_TNL_ATTR_FWMARK (1 << 9) + +struct ip6_tnl_info +{ + uint8_t ttl; + uint8_t tos; + uint8_t encap_limit; + uint8_t proto; + uint32_t flags; + uint32_t link; + uint32_t flowinfo; + struct in6_addr local; + struct in6_addr remote; + uint32_t fwmark; + uint32_t ip6_tnl_mask; +}; + +static struct nla_policy ip6_tnl_policy[IFLA_IPTUN_MAX + 1] = { + [IFLA_IPTUN_LINK] = { .type = NLA_U32 }, + [IFLA_IPTUN_LOCAL] = { .minlen = sizeof(struct in6_addr) }, + [IFLA_IPTUN_REMOTE] = { .minlen = sizeof(struct in6_addr) }, + [IFLA_IPTUN_TTL] = { .type = NLA_U8 }, + [IFLA_IPTUN_TOS] = { .type = NLA_U8 }, + [IFLA_IPTUN_ENCAP_LIMIT] = { .type = NLA_U8 }, + [IFLA_IPTUN_FLOWINFO] = { .type = NLA_U32 }, + [IFLA_IPTUN_FLAGS] = { .type = NLA_U32 }, + [IFLA_IPTUN_PROTO] = { .type = NLA_U8 }, + [IFLA_IPTUN_FWMARK] = { .type = NLA_U32 }, +}; + +static int ip6_tnl_alloc(struct rtnl_link *link) +{ + struct ip6_tnl_info *ip6_tnl; + + if (link->l_info) + memset(link->l_info, 0, sizeof(*ip6_tnl)); + else { + ip6_tnl = calloc(1, sizeof(*ip6_tnl)); + if (!ip6_tnl) + return -NLE_NOMEM; + + link->l_info = ip6_tnl; + } + + return 0; +} + +static int ip6_tnl_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_IPTUN_MAX + 1]; + struct ip6_tnl_info *ip6_tnl; + int err; + + NL_DBG(3, "Parsing IP6_TNL link info\n"); + + err = nla_parse_nested(tb, IFLA_IPTUN_MAX, data, ip6_tnl_policy); + if (err < 0) + goto errout; + + err = ip6_tnl_alloc(link); + if (err < 0) + goto errout; + + ip6_tnl = link->l_info; + + if (tb[IFLA_IPTUN_LINK]) { + ip6_tnl->link = nla_get_u32(tb[IFLA_IPTUN_LINK]); + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_LINK; + } + + if (tb[IFLA_IPTUN_LOCAL]) { + nla_memcpy(&ip6_tnl->local, tb[IFLA_IPTUN_LOCAL], sizeof(struct in6_addr)); + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_LOCAL; + } + + if (tb[IFLA_IPTUN_REMOTE]) { + nla_memcpy(&ip6_tnl->remote, tb[IFLA_IPTUN_REMOTE], sizeof(struct in6_addr)); + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_REMOTE; + } + + if (tb[IFLA_IPTUN_TTL]) { + ip6_tnl->ttl = nla_get_u8(tb[IFLA_IPTUN_TTL]); + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_TTL; + } + + if (tb[IFLA_IPTUN_TOS]) { + ip6_tnl->tos = nla_get_u8(tb[IFLA_IPTUN_TOS]); + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_TOS; + } + + if (tb[IFLA_IPTUN_ENCAP_LIMIT]) { + ip6_tnl->encap_limit = nla_get_u8(tb[IFLA_IPTUN_ENCAP_LIMIT]); + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_ENCAPLIMIT; + } + + if (tb[IFLA_IPTUN_FLAGS]) { + ip6_tnl->flags = nla_get_u32(tb[IFLA_IPTUN_FLAGS]); + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FLAGS; + } + + if (tb[IFLA_IPTUN_FLOWINFO]) { + ip6_tnl->flowinfo = nla_get_u32(tb[IFLA_IPTUN_FLOWINFO]); + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FLOWINFO; + } + + if (tb[IFLA_IPTUN_PROTO]) { + ip6_tnl->proto = nla_get_u8(tb[IFLA_IPTUN_PROTO]); + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_PROTO; + } + + if (tb[IFLA_IPTUN_FWMARK]) { + ip6_tnl->fwmark = nla_get_u32(tb[IFLA_IPTUN_FWMARK]); + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FWMARK; + } + + err = 0; + +errout: + return err; +} + +static int ip6_tnl_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + struct nlattr *data; + + data = nla_nest_start(msg, IFLA_INFO_DATA); + if (!data) + return -NLE_MSGSIZE; + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_LINK) + NLA_PUT_U32(msg, IFLA_IPTUN_LINK, ip6_tnl->link); + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_LOCAL) + NLA_PUT(msg, IFLA_IPTUN_LOCAL, sizeof(struct in6_addr), &ip6_tnl->local); + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_REMOTE) + NLA_PUT(msg, IFLA_IPTUN_REMOTE, sizeof(struct in6_addr), &ip6_tnl->remote); + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_TTL) + NLA_PUT_U8(msg, IFLA_IPTUN_TTL, ip6_tnl->ttl); + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_TOS) + NLA_PUT_U8(msg, IFLA_IPTUN_TOS, ip6_tnl->tos); + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_ENCAPLIMIT) + NLA_PUT_U8(msg, IFLA_IPTUN_ENCAP_LIMIT, ip6_tnl->encap_limit); + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FLAGS) + NLA_PUT_U32(msg, IFLA_IPTUN_FLAGS, ip6_tnl->flags); + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FLOWINFO) + NLA_PUT_U32(msg, IFLA_IPTUN_FLOWINFO, ip6_tnl->flowinfo); + + /* kernel crashes if this attribure is missing temporary fix */ + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_PROTO) + NLA_PUT_U8(msg, IFLA_IPTUN_PROTO, ip6_tnl->proto); + else + NLA_PUT_U8(msg, IFLA_IPTUN_PROTO, 0); + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FWMARK) + NLA_PUT_U32(msg, IFLA_IPTUN_FWMARK, ip6_tnl->fwmark); + + nla_nest_end(msg, data); + +nla_put_failure: + return 0; +} + +static void ip6_tnl_free(struct rtnl_link *link) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + free(ip6_tnl); + link->l_info = NULL; +} + +static void ip6_tnl_dump_line(struct rtnl_link *link, struct nl_dump_params *p) +{ + nl_dump(p, "ip6_tnl : %s", link->l_name); +} + +static void ip6_tnl_dump_details(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + char *name, addr[INET6_ADDRSTRLEN]; + struct rtnl_link *parent; + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_LINK) { + nl_dump(p, " link "); + + name = NULL; + parent = link_lookup(link->ce_cache, ip6_tnl->link); + if (parent) + name = rtnl_link_get_name(parent); + + if (name) + nl_dump_line(p, "%s\n", name); + else + nl_dump_line(p, "%u\n", ip6_tnl->link); + } + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_LOCAL) { + nl_dump(p, " local "); + nl_dump_line(p, "%s\n", + _nl_inet_ntop(AF_INET6, &ip6_tnl->local, addr)); + } + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_REMOTE) { + nl_dump(p, " remote "); + nl_dump_line(p, "%s\n", + _nl_inet_ntop(AF_INET6, &ip6_tnl->remote, addr)); + } + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_TTL) { + nl_dump(p, " ttl "); + nl_dump_line(p, "%d\n", ip6_tnl->ttl); + } + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_TOS) { + nl_dump(p, " tos "); + nl_dump_line(p, "%d\n", ip6_tnl->tos); + } + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_ENCAPLIMIT) { + nl_dump(p, " encaplimit "); + nl_dump_line(p, "%d\n", ip6_tnl->encap_limit); + } + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FLAGS) { + nl_dump(p, " flags "); + nl_dump_line(p, " (%x)\n", ip6_tnl->flags); + } + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FLOWINFO) { + nl_dump(p, " flowinfo "); + nl_dump_line(p, " (%x)\n", ip6_tnl->flowinfo); + } + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_PROTO) { + nl_dump(p, " proto "); + nl_dump_line(p, " (%x)\n", ip6_tnl->proto); + } + + if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FWMARK) { + nl_dump(p, " fwmark "); + nl_dump_line(p, "%x\n", ip6_tnl->fwmark); + } +} + +static int ip6_tnl_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct ip6_tnl_info *ip6_tnl_dst, *ip6_tnl_src = src->l_info; + int err; + + dst->l_info = NULL; + + err = rtnl_link_set_type(dst, "ip6tnl"); + if (err < 0) + return err; + + ip6_tnl_dst = dst->l_info; + + if (!ip6_tnl_dst || !ip6_tnl_src) + BUG(); + + memcpy(ip6_tnl_dst, ip6_tnl_src, sizeof(struct ip6_tnl_info)); + + return 0; +} + +static struct rtnl_link_info_ops ip6_tnl_info_ops = { + .io_name = "ip6tnl", + .io_alloc = ip6_tnl_alloc, + .io_parse = ip6_tnl_parse, + .io_dump = { + [NL_DUMP_LINE] = ip6_tnl_dump_line, + [NL_DUMP_DETAILS] = ip6_tnl_dump_details, + }, + .io_clone = ip6_tnl_clone, + .io_put_attrs = ip6_tnl_put_attrs, + .io_free = ip6_tnl_free, +}; + +#define IS_IP6_TNL_LINK_ASSERT(link)\ + if ((link)->l_info_ops != &ip6_tnl_info_ops) {\ + APPBUG("Link is not a ip6_tnl link. set type \"ip6tnl\" first.");\ + return -NLE_OPNOTSUPP;\ + } + +struct rtnl_link *rtnl_link_ip6_tnl_alloc(void) +{ + struct rtnl_link *link; + int err; + + link = rtnl_link_alloc(); + if (!link) + return NULL; + + err = rtnl_link_set_type(link, "ip6tnl"); + if (err < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if link is a IP6_TNL link + * @arg link Link object + * + * @return True if link is a IP6_TNL link, otherwise false is returned. + */ +int rtnl_link_is_ip6_tnl(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "ip6tnl"); +} + +/** + * Create a new ip6_tnl tunnel device + * @arg sock netlink socket + * @arg name name of the tunnel device + * + * Creates a new ip6_tnl tunnel device in the kernel + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6_tnl_add(struct nl_sock *sk, const char *name) +{ + struct rtnl_link *link; + int err; + + link = rtnl_link_ip6_tnl_alloc(); + if (!link) + return -NLE_NOMEM; + + if(name) + rtnl_link_set_name(link, name); + + err = rtnl_link_add(sk, link, NLM_F_CREATE); + rtnl_link_put(link); + + return err; +} + +/** + * Set IP6_TNL tunnel interface index + * @arg link Link object + * @arg index interface index + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6_tnl_set_link(struct rtnl_link *link, uint32_t index) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + ip6_tnl->link = index; + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_LINK; + + return 0; +} + +/** + * Get IP6_TNL tunnel interface index + * @arg link Link object + * + * @return interface index value + */ +uint32_t rtnl_link_ip6_tnl_get_link(struct rtnl_link *link) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + return ip6_tnl->link; +} + +/** + * Set IP6_TNL tunnel local address + * @arg link Link object + * @arg addr local address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6_tnl_set_local(struct rtnl_link *link, struct in6_addr *addr) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + memcpy(&ip6_tnl->local, addr, sizeof(struct in6_addr)); + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_LOCAL; + + return 0; +} + +/** + * Get IP6_TNL tunnel local address + * @arg link Link object + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6_tnl_get_local(struct rtnl_link *link, struct in6_addr *addr) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + memcpy(addr, &ip6_tnl->local, sizeof(struct in6_addr)); + + return 0; +} + +/** + * Set IP6_TNL tunnel remote address + * @arg link Link object + * @arg remote remote address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6_tnl_set_remote(struct rtnl_link *link, struct in6_addr *addr) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + memcpy(&ip6_tnl->remote, addr, sizeof(struct in6_addr)); + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_REMOTE; + + return 0; +} + +/** + * Get IP6_TNL tunnel remote address + * @arg link Link object + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6_tnl_get_remote(struct rtnl_link *link, struct in6_addr *addr) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + memcpy(addr, &ip6_tnl->remote, sizeof(struct in6_addr)); + + return 0; +} + +/** + * Set IP6_TNL tunnel ttl + * @arg link Link object + * @arg ttl tunnel ttl + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6_tnl_set_ttl(struct rtnl_link *link, uint8_t ttl) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + ip6_tnl->ttl = ttl; + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_TTL; + + return 0; +} + +/** + * Get IP6_TNL tunnel ttl + * @arg link Link object + * + * @return ttl value + */ +uint8_t rtnl_link_ip6_tnl_get_ttl(struct rtnl_link *link) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + return ip6_tnl->ttl; +} + +/** + * Set IP6_TNL tunnel tos + * @arg link Link object + * @arg tos tunnel tos + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6_tnl_set_tos(struct rtnl_link *link, uint8_t tos) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + ip6_tnl->tos = tos; + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_TOS; + + return 0; +} + +/** + * Get IP6_TNL tunnel tos + * @arg link Link object + * + * @return tos value + */ +uint8_t rtnl_link_ip6_tnl_get_tos(struct rtnl_link *link) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + return ip6_tnl->tos; +} + +/** + * Set IP6_TNL tunnel encap limit + * @arg link Link object + * @arg encap_limit encaplimit value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6_tnl_set_encaplimit(struct rtnl_link *link, uint8_t encap_limit) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + ip6_tnl->encap_limit = encap_limit; + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_ENCAPLIMIT; + + return 0; +} + +/** + * Get IP6_TNL encaplimit + * @arg link Link object + * + * @return encaplimit value + */ +uint8_t rtnl_link_ip6_tnl_get_encaplimit(struct rtnl_link *link) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + return ip6_tnl->encap_limit; +} + +/** + * Set IP6_TNL tunnel flowinfo + * @arg link Link object + * @arg flowinfo flowinfo value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6_tnl_set_flowinfo(struct rtnl_link *link, uint32_t flowinfo) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + ip6_tnl->flowinfo = flowinfo; + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FLOWINFO; + + return 0; +} + +/** + * Get IP6_TNL flowinfo + * @arg link Link object + * + * @return flowinfo value + */ +uint32_t rtnl_link_ip6_tnl_get_flowinfo(struct rtnl_link *link) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + return ip6_tnl->flowinfo; +} + +/** + * Set IP6_TNL tunnel flags + * @arg link Link object + * @arg flags tunnel flags + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6_tnl_set_flags(struct rtnl_link *link, uint32_t flags) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + ip6_tnl->flags = flags; + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FLAGS; + + return 0; +} + +/** + * Get IP6_TNL path flags + * @arg link Link object + * + * @return flags value + */ +uint32_t rtnl_link_ip6_tnl_get_flags(struct rtnl_link *link) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + return ip6_tnl->flags; +} + +/** + * Set IP6_TNL tunnel proto + * @arg link Link object + * @arg proto tunnel proto + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6_tnl_set_proto(struct rtnl_link *link, uint8_t proto) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + ip6_tnl->proto = proto; + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_PROTO; + + return 0; +} + +/** + * Get IP6_TNL proto + * @arg link Link object + * + * @return proto value + */ +uint8_t rtnl_link_ip6_tnl_get_proto(struct rtnl_link *link) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + return ip6_tnl->proto; +} + +/** + * Set IP6_TNL tunnel fwmark + * @arg link Link object + * @arg fwmark fwmark + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6_tnl_set_fwmark(struct rtnl_link *link, uint32_t fwmark) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + ip6_tnl->fwmark = fwmark; + ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FWMARK; + + return 0; +} + +/** + * Get IP6_TNL tunnel fwmark + * @arg link Link object + * @arg fwmark addr to fill in with the fwmark + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6_tnl_get_fwmark(struct rtnl_link *link, uint32_t *fwmark) +{ + struct ip6_tnl_info *ip6_tnl = link->l_info; + + IS_IP6_TNL_LINK_ASSERT(link); + + if (!(ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FWMARK)) + return -NLE_NOATTR; + + *fwmark = ip6_tnl->fwmark; + + return 0; +} + +static void _nl_init ip6_tnl_init(void) +{ + rtnl_link_register_info(&ip6_tnl_info_ops); +} + +static void _nl_exit ip6_tnl_exit(void) +{ + rtnl_link_unregister_info(&ip6_tnl_info_ops); +} diff --git a/lib/route/link/ip6vti.c b/lib/route/link/ip6vti.c new file mode 100644 index 0000000..b6c7a1b --- /dev/null +++ b/lib/route/link/ip6vti.c @@ -0,0 +1,558 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +/** + * @ingroup link + * @defgroup ip6vti IP6VTI + * ip6vti link module + * + * @details + * \b Link Type Name: "vti6" + * + * @route_doc{link_ip6vti, IP6VTI Documentation} + * + * @{ + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "nl-route.h" +#include "link-api.h" + +#define IP6VTI_ATTR_LINK (1 << 0) +#define IP6VTI_ATTR_IKEY (1 << 1) +#define IP6VTI_ATTR_OKEY (1 << 2) +#define IP6VTI_ATTR_LOCAL (1 << 3) +#define IP6VTI_ATTR_REMOTE (1 << 4) +#define IP6VTI_ATTR_FWMARK (1 << 5) + +struct ip6vti_info +{ + uint32_t link; + uint32_t ikey; + uint32_t okey; + struct in6_addr local; + struct in6_addr remote; + uint32_t fwmark; + uint32_t ip6vti_mask; +}; + +static struct nla_policy ip6vti_policy[IFLA_VTI_MAX + 1] = { + [IFLA_VTI_LINK] = { .type = NLA_U32 }, + [IFLA_VTI_IKEY] = { .type = NLA_U32 }, + [IFLA_VTI_OKEY] = { .type = NLA_U32 }, + [IFLA_VTI_LOCAL] = { .minlen = sizeof(struct in6_addr) }, + [IFLA_VTI_REMOTE] = { .minlen = sizeof(struct in6_addr) }, + [IFLA_VTI_FWMARK] = { .type = NLA_U32 }, +}; + +static int ip6vti_alloc(struct rtnl_link *link) +{ + struct ip6vti_info *ip6vti; + + if (link->l_info) + memset(link->l_info, 0, sizeof(*ip6vti)); + else { + ip6vti = calloc(1, sizeof(*ip6vti)); + if (!ip6vti) + return -NLE_NOMEM; + + link->l_info = ip6vti; + } + + return 0; +} + +static int ip6vti_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_VTI_MAX + 1]; + struct ip6vti_info *ip6vti; + int err; + + NL_DBG(3, "Parsing IP6VTI link info\n"); + + err = nla_parse_nested(tb, IFLA_VTI_MAX, data, ip6vti_policy); + if (err < 0) + goto errout; + + err = ip6vti_alloc(link); + if (err < 0) + goto errout; + + ip6vti = link->l_info; + + if (tb[IFLA_VTI_LINK]) { + ip6vti->link = nla_get_u32(tb[IFLA_VTI_LINK]); + ip6vti->ip6vti_mask |= IP6VTI_ATTR_LINK; + } + + if (tb[IFLA_VTI_IKEY]) { + ip6vti->ikey = nla_get_u32(tb[IFLA_VTI_IKEY]); + ip6vti->ip6vti_mask |= IP6VTI_ATTR_IKEY; + } + + if (tb[IFLA_VTI_OKEY]) { + ip6vti->okey = nla_get_u32(tb[IFLA_VTI_OKEY]); + ip6vti->ip6vti_mask |= IP6VTI_ATTR_OKEY; + } + + if (tb[IFLA_VTI_LOCAL]) { + nla_memcpy(&ip6vti->local, tb[IFLA_VTI_LOCAL], sizeof(struct in6_addr)); + ip6vti->ip6vti_mask |= IP6VTI_ATTR_LOCAL; + } + + if (tb[IFLA_VTI_REMOTE]) { + nla_memcpy(&ip6vti->remote, tb[IFLA_VTI_REMOTE], sizeof(struct in6_addr)); + ip6vti->ip6vti_mask |= IP6VTI_ATTR_REMOTE; + } + + if (tb[IFLA_VTI_FWMARK]) { + ip6vti->fwmark = nla_get_u32(tb[IFLA_VTI_FWMARK]); + ip6vti->ip6vti_mask |= IP6VTI_ATTR_FWMARK; + } + + err = 0; + + errout: + return err; +} + +static int ip6vti_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct ip6vti_info *ip6vti = link->l_info; + struct nlattr *data; + + data = nla_nest_start(msg, IFLA_INFO_DATA); + if (!data) + return -NLE_MSGSIZE; + + if (ip6vti->ip6vti_mask & IP6VTI_ATTR_LINK) + NLA_PUT_U32(msg, IFLA_VTI_LINK, ip6vti->link); + + if (ip6vti->ip6vti_mask & IP6VTI_ATTR_IKEY) + NLA_PUT_U32(msg, IFLA_VTI_IKEY, ip6vti->ikey); + + if (ip6vti->ip6vti_mask & IP6VTI_ATTR_OKEY) + NLA_PUT_U32(msg, IFLA_VTI_OKEY, ip6vti->okey); + + if (ip6vti->ip6vti_mask & IP6VTI_ATTR_LOCAL) + NLA_PUT(msg, IFLA_VTI_LOCAL, sizeof(struct in6_addr), &ip6vti->local); + + if (ip6vti->ip6vti_mask & IP6VTI_ATTR_REMOTE) + NLA_PUT(msg, IFLA_VTI_REMOTE, sizeof(struct in6_addr), &ip6vti->remote); + + if (ip6vti->ip6vti_mask & IP6VTI_ATTR_FWMARK) + NLA_PUT_U32(msg, IFLA_VTI_FWMARK, ip6vti->fwmark); + + nla_nest_end(msg, data); + +nla_put_failure: + + return 0; +} + +static void ip6vti_free(struct rtnl_link *link) +{ + struct ip6vti_info *ip6vti = link->l_info; + + free(ip6vti); + link->l_info = NULL; +} + +static void ip6vti_dump_line(struct rtnl_link *link, struct nl_dump_params *p) +{ + nl_dump(p, "ip6vti : %s", link->l_name); +} + +static void ip6vti_dump_details(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct ip6vti_info *ip6vti = link->l_info; + char *name; + char addr[INET6_ADDRSTRLEN]; + + if (ip6vti->ip6vti_mask & IP6VTI_ATTR_LINK) { + nl_dump(p, " link "); + name = rtnl_link_get_name(link); + if (name) + nl_dump_line(p, "%s\n", name); + else + nl_dump_line(p, "%u\n", ip6vti->link); + } + + if (ip6vti->ip6vti_mask & IP6VTI_ATTR_IKEY) { + nl_dump(p, " ikey "); + nl_dump_line(p, "%x\n",ip6vti->ikey); + } + + if (ip6vti->ip6vti_mask & IP6VTI_ATTR_OKEY) { + nl_dump(p, " okey "); + nl_dump_line(p, "%x\n", ip6vti->okey); + } + + if (ip6vti->ip6vti_mask & IP6VTI_ATTR_LOCAL) { + nl_dump(p, " local "); + nl_dump_line(p, "%s\n", + _nl_inet_ntop(AF_INET6, &ip6vti->local, addr)); + } + + if (ip6vti->ip6vti_mask & IP6VTI_ATTR_REMOTE) { + nl_dump(p, " remote "); + nl_dump_line(p, "%s\n", + _nl_inet_ntop(AF_INET6, &ip6vti->remote, addr)); + } + + if (ip6vti->ip6vti_mask & IP6VTI_ATTR_FWMARK) { + nl_dump(p, " fwmark "); + nl_dump_line(p, "%x\n", ip6vti->fwmark); + } +} + +static int ip6vti_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct ip6vti_info *ip6vti_dst, *ip6vti_src = src->l_info; + int err; + + dst->l_info = NULL; + + err = rtnl_link_set_type(dst, "vti6"); + if (err < 0) + return err; + + ip6vti_dst = dst->l_info; + + if (!ip6vti_dst || !ip6vti_src) + BUG(); + + memcpy(ip6vti_dst, ip6vti_src, sizeof(struct ip6vti_info)); + + return 0; +} + +static struct rtnl_link_info_ops ip6vti_info_ops = { + .io_name = "vti6", + .io_alloc = ip6vti_alloc, + .io_parse = ip6vti_parse, + .io_dump = { + [NL_DUMP_LINE] = ip6vti_dump_line, + [NL_DUMP_DETAILS] = ip6vti_dump_details, + }, + .io_clone = ip6vti_clone, + .io_put_attrs = ip6vti_put_attrs, + .io_free = ip6vti_free, +}; + +#define IS_IP6VTI_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &ip6vti_info_ops) { \ + APPBUG("Link is not a ip6vti link. set type \"vti6\" first."); \ + return -NLE_OPNOTSUPP; \ + } + +#define HAS_IP6VTI_ATTR_ASSERT(ip6vti,attr) \ + if (!((ip6vti)->ip6vti_mask & (attr))) \ + return -NLE_NOATTR; + +struct rtnl_link *rtnl_link_ip6vti_alloc(void) +{ + struct rtnl_link *link; + int err; + + link = rtnl_link_alloc(); + if (!link) + return NULL; + + err = rtnl_link_set_type(link, "vti6"); + if (err < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if link is a IP6VTI link + * @arg link Link object + * + * @return True if link is a IP6VTI link, otherwise 0 is returned. + */ +int rtnl_link_is_ip6vti(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "vti6"); +} +/** + * Create a new vti6 tunnel device + * @arg sock netlink socket + * @arg name name of the tunnel deviceL + * + * Creates a new vti6 tunnel device in the kernel + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6vti_add(struct nl_sock *sk, const char *name) +{ + struct rtnl_link *link; + int err; + + link = rtnl_link_ip6vti_alloc(); + if (!link) + return -NLE_NOMEM; + + if(name) + rtnl_link_set_name(link, name); + + err = rtnl_link_add(sk, link, NLM_F_CREATE); + rtnl_link_put(link); + + return err; +} +/** + * Set IP6VTI tunnel interface index + * @arg link Link object + * @arg index interface index + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6vti_set_link(struct rtnl_link *link, uint32_t index) +{ + struct ip6vti_info *ip6vti = link->l_info; + + IS_IP6VTI_LINK_ASSERT(link); + + ip6vti->link = index; + ip6vti->ip6vti_mask |= IP6VTI_ATTR_LINK; + + return 0; +} + +/** + * Get IP6VTI tunnel interface index + * @arg link Link object + * @arg index addr to fill in with the interface index + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6vti_get_link(struct rtnl_link *link, uint32_t *index) +{ + struct ip6vti_info *ip6vti = link->l_info; + + IS_IP6VTI_LINK_ASSERT(link); + + HAS_IP6VTI_ATTR_ASSERT(ip6vti, IP6VTI_ATTR_LINK); + + *index = ip6vti->link; + + return 0; +} + +/** + * Set IP6VTI tunnel set ikey + * @arg link Link object + * @arg ikey gre ikey + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6vti_set_ikey(struct rtnl_link *link, uint32_t ikey) +{ + struct ip6vti_info *ip6vti = link->l_info; + + IS_IP6VTI_LINK_ASSERT(link); + + ip6vti->ikey = ikey; + ip6vti->ip6vti_mask |= IP6VTI_ATTR_IKEY; + + return 0; +} + +/** + * Get IP6VTI tunnel ikey + * @arg link Link object + * @arg ikey addr to fill in with the ikey + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6vti_get_ikey(struct rtnl_link *link, uint32_t *ikey) +{ + struct ip6vti_info *ip6vti = link->l_info; + + IS_IP6VTI_LINK_ASSERT(link); + + HAS_IP6VTI_ATTR_ASSERT(ip6vti, IP6VTI_ATTR_IKEY); + + *ikey = ip6vti->ikey; + + return 0; +} + +/** + * Set IP6VTI tunnel set okey + * @arg link Link object + * @arg okey gre okey + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6vti_set_okey(struct rtnl_link *link, uint32_t okey) +{ + struct ip6vti_info *ip6vti = link->l_info; + + IS_IP6VTI_LINK_ASSERT(link); + + ip6vti->okey = okey; + ip6vti->ip6vti_mask |= IP6VTI_ATTR_OKEY; + + return 0; +} + +/** + * Get IP6VTI tunnel okey + * @arg link Link object + * @arg okey addr to fill in with the okey + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6vti_get_okey(struct rtnl_link *link, uint32_t *okey) +{ + struct ip6vti_info *ip6vti = link->l_info; + + IS_IP6VTI_LINK_ASSERT(link); + + HAS_IP6VTI_ATTR_ASSERT(ip6vti, IP6VTI_ATTR_OKEY); + + *okey = ip6vti->okey; + + return 0; +} + +/** + * Set IP6VTI tunnel local address + * @arg link Link object + * @arg local local address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6vti_set_local(struct rtnl_link *link, struct in6_addr *local) +{ + struct ip6vti_info *ip6vti = link->l_info; + + IS_IP6VTI_LINK_ASSERT(link); + + memcpy(&ip6vti->local, local, sizeof(struct in6_addr)); + ip6vti->ip6vti_mask |= IP6VTI_ATTR_LOCAL; + + return 0; +} + +/** + * Get IP6VTI tunnel local address + * @arg link Link object + * @arg local addr to fill in with remote address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6vti_get_local(struct rtnl_link *link, struct in6_addr *local) +{ + struct ip6vti_info *ip6vti = link->l_info; + + IS_IP6VTI_LINK_ASSERT(link); + + HAS_IP6VTI_ATTR_ASSERT(ip6vti, IP6VTI_ATTR_LOCAL); + + memcpy(local, &ip6vti->local, sizeof(struct in6_addr)); + + return 0; +} + +/** + * Set IP6VTI tunnel remote address + * @arg link Link object + * @arg remote remote address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6vti_set_remote(struct rtnl_link *link, struct in6_addr *remote) +{ + struct ip6vti_info *ip6vti = link->l_info; + + IS_IP6VTI_LINK_ASSERT(link); + + memcpy(&ip6vti->remote, remote, sizeof(struct in6_addr)); + ip6vti->ip6vti_mask |= IP6VTI_ATTR_REMOTE; + + return 0; +} + +/** + * Get IP6VTI tunnel remote address + * @arg link Link object + * @arg remote addr to fill in with remote address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6vti_get_remote(struct rtnl_link *link, struct in6_addr *remote) +{ + struct ip6vti_info *ip6vti = link->l_info; + + IS_IP6VTI_LINK_ASSERT(link); + + HAS_IP6VTI_ATTR_ASSERT(ip6vti, IP6VTI_ATTR_REMOTE); + + memcpy(remote, &ip6vti->remote, sizeof(struct in6_addr)); + + return 0; +} + +/** + * Set IP6VTI tunnel fwmark + * @arg link Link object + * @arg fwmark fwmark + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6vti_set_fwmark(struct rtnl_link *link, uint32_t fwmark) +{ + struct ip6vti_info *ip6vti = link->l_info; + + IS_IP6VTI_LINK_ASSERT(link); + + ip6vti->fwmark = fwmark; + ip6vti->ip6vti_mask |= IP6VTI_ATTR_FWMARK; + + return 0; +} + +/** + * Get IP6VTI tunnel fwmark + * @arg link Link object + * @arg fwmark addr to fill in with the fwmark + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ip6vti_get_fwmark(struct rtnl_link *link, uint32_t *fwmark) +{ + struct ip6vti_info *ip6vti = link->l_info; + + IS_IP6VTI_LINK_ASSERT(link); + + HAS_IP6VTI_ATTR_ASSERT(ip6vti, IP6VTI_ATTR_FWMARK); + + *fwmark = ip6vti->fwmark; + + return 0; +} + +static void _nl_init ip6vti_init(void) +{ + rtnl_link_register_info(&ip6vti_info_ops); +} + +static void _nl_exit ip6vti_exit(void) +{ + rtnl_link_unregister_info(&ip6vti_info_ops); +} diff --git a/lib/route/link/ipgre.c b/lib/route/link/ipgre.c new file mode 100644 index 0000000..bd3cc40 --- /dev/null +++ b/lib/route/link/ipgre.c @@ -0,0 +1,896 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2014 Susant Sahani + */ + +/** + * @ingroup link + * @defgroup ipgre IPGRE + * ipgre link module + * + * @details + * \b Link Type Name: "ipgre" + * + * @route_doc{link_ipgre, IPGRE Documentation} + * + * @{ + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "nl-route.h" +#include "link-api.h" + +#define IPGRE_ATTR_LINK (1 << 0) +#define IPGRE_ATTR_IFLAGS (1 << 1) +#define IPGRE_ATTR_OFLAGS (1 << 2) +#define IPGRE_ATTR_IKEY (1 << 3) +#define IPGRE_ATTR_OKEY (1 << 4) +#define IPGRE_ATTR_LOCAL (1 << 5) +#define IPGRE_ATTR_REMOTE (1 << 6) +#define IPGRE_ATTR_TTL (1 << 7) +#define IPGRE_ATTR_TOS (1 << 8) +#define IPGRE_ATTR_PMTUDISC (1 << 9) +#define IPGRE_ATTR_FWMARK (1 << 10) + +struct ipgre_info +{ + uint8_t ttl; + uint8_t tos; + uint8_t pmtudisc; + uint16_t iflags; + uint16_t oflags; + uint32_t ikey; + uint32_t okey; + uint32_t link; + uint32_t local; + uint32_t remote; + uint32_t fwmark; + uint32_t ipgre_mask; +}; + +static struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = { + [IFLA_GRE_LINK] = { .type = NLA_U32 }, + [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, + [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, + [IFLA_GRE_IKEY] = { .type = NLA_U32 }, + [IFLA_GRE_OKEY] = { .type = NLA_U32 }, + [IFLA_GRE_LOCAL] = { .type = NLA_U32 }, + [IFLA_GRE_REMOTE] = { .type = NLA_U32 }, + [IFLA_GRE_TTL] = { .type = NLA_U8 }, + [IFLA_GRE_TOS] = { .type = NLA_U8 }, + [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, + [IFLA_GRE_FWMARK] = { .type = NLA_U32 }, +}; + +static int ipgre_alloc(struct rtnl_link *link) +{ + struct ipgre_info *ipgre; + + if (link->l_info) + memset(link->l_info, 0, sizeof(*ipgre)); + else { + ipgre = calloc(1, sizeof(*ipgre)); + if (!ipgre) + return -NLE_NOMEM; + + link->l_info = ipgre; + } + + return 0; +} + +static int ipgre_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_GRE_MAX + 1]; + struct ipgre_info *ipgre; + int err; + + NL_DBG(3, "Parsing IPGRE link info\n"); + + err = nla_parse_nested(tb, IFLA_GRE_MAX, data, ipgre_policy); + if (err < 0) + goto errout; + + err = ipgre_alloc(link); + if (err < 0) + goto errout; + + ipgre = link->l_info; + + if (tb[IFLA_GRE_LINK]) { + ipgre->link = nla_get_u32(tb[IFLA_GRE_LINK]); + ipgre->ipgre_mask |= IPGRE_ATTR_LINK; + } + + if (tb[IFLA_GRE_IFLAGS]) { + ipgre->iflags = nla_get_u16(tb[IFLA_GRE_IFLAGS]); + ipgre->ipgre_mask |= IPGRE_ATTR_IFLAGS; + } + + if (tb[IFLA_GRE_OFLAGS]) { + ipgre->oflags = nla_get_u16(tb[IFLA_GRE_OFLAGS]); + ipgre->ipgre_mask |= IPGRE_ATTR_OFLAGS; + } + + if (tb[IFLA_GRE_IKEY]) { + ipgre->ikey = nla_get_u32(tb[IFLA_GRE_IKEY]); + ipgre->ipgre_mask |= IPGRE_ATTR_IKEY; + } + + if (tb[IFLA_GRE_OKEY]) { + ipgre->okey = nla_get_u32(tb[IFLA_GRE_OKEY]); + ipgre->ipgre_mask |= IPGRE_ATTR_OKEY; + } + + if (tb[IFLA_GRE_LOCAL]) { + ipgre->local = nla_get_u32(tb[IFLA_GRE_LOCAL]); + ipgre->ipgre_mask |= IPGRE_ATTR_LOCAL; + } + + if (tb[IFLA_GRE_REMOTE]) { + ipgre->remote = nla_get_u32(tb[IFLA_GRE_REMOTE]); + ipgre->ipgre_mask |= IPGRE_ATTR_REMOTE; + } + + if (tb[IFLA_GRE_TTL]) { + ipgre->ttl = nla_get_u8(tb[IFLA_GRE_TTL]); + ipgre->ipgre_mask |= IPGRE_ATTR_TTL; + } + + if (tb[IFLA_GRE_TOS]) { + ipgre->tos = nla_get_u8(tb[IFLA_GRE_TOS]); + ipgre->ipgre_mask |= IPGRE_ATTR_TOS; + } + + if (tb[IFLA_GRE_PMTUDISC]) { + ipgre->pmtudisc = nla_get_u8(tb[IFLA_GRE_PMTUDISC]); + ipgre->ipgre_mask |= IPGRE_ATTR_PMTUDISC; + } + + if (tb[IFLA_GRE_FWMARK]) { + ipgre->fwmark = nla_get_u32(tb[IFLA_GRE_FWMARK]); + ipgre->ipgre_mask |= IPGRE_ATTR_FWMARK; + } + + err = 0; + +errout: + return err; +} + +static int ipgre_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct ipgre_info *ipgre = link->l_info; + struct nlattr *data; + + data = nla_nest_start(msg, IFLA_INFO_DATA); + if (!data) + return -NLE_MSGSIZE; + + if (ipgre->ipgre_mask & IPGRE_ATTR_LINK) + NLA_PUT_U32(msg, IFLA_GRE_LINK, ipgre->link); + + if (ipgre->ipgre_mask & IFLA_GRE_IFLAGS) + NLA_PUT_U16(msg, IFLA_GRE_IFLAGS, ipgre->iflags); + + if (ipgre->ipgre_mask & IFLA_GRE_OFLAGS) + NLA_PUT_U16(msg, IFLA_GRE_OFLAGS, ipgre->oflags); + + if (ipgre->ipgre_mask & IPGRE_ATTR_IKEY) + NLA_PUT_U32(msg, IFLA_GRE_IKEY, ipgre->ikey); + + if (ipgre->ipgre_mask & IPGRE_ATTR_OKEY) + NLA_PUT_U32(msg, IFLA_GRE_OKEY, ipgre->okey); + + if (ipgre->ipgre_mask & IPGRE_ATTR_LOCAL) + NLA_PUT_U32(msg, IFLA_GRE_LOCAL, ipgre->local); + + if (ipgre->ipgre_mask & IPGRE_ATTR_REMOTE) + NLA_PUT_U32(msg, IFLA_GRE_REMOTE, ipgre->remote); + + if (ipgre->ipgre_mask & IPGRE_ATTR_TTL) + NLA_PUT_U8(msg, IFLA_GRE_TTL, ipgre->ttl); + + if (ipgre->ipgre_mask & IPGRE_ATTR_TOS) + NLA_PUT_U8(msg, IFLA_GRE_TOS, ipgre->tos); + + if (ipgre->ipgre_mask & IPGRE_ATTR_PMTUDISC) + NLA_PUT_U8(msg, IFLA_GRE_PMTUDISC, ipgre->pmtudisc); + + if (ipgre->ipgre_mask & IPGRE_ATTR_FWMARK) + NLA_PUT_U32(msg, IFLA_GRE_FWMARK, ipgre->fwmark); + + nla_nest_end(msg, data); + +nla_put_failure: + + return 0; +} + +static void ipgre_free(struct rtnl_link *link) +{ + struct ipgre_info *ipgre = link->l_info; + + free(ipgre); + link->l_info = NULL; +} + +static void ipgre_dump_line(struct rtnl_link *link, struct nl_dump_params *p) +{ + nl_dump(p, "ipgre : %s", link->l_name); +} + +static void ipgre_dump_details(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct ipgre_info *ipgre = link->l_info; + char *name, addr[INET_ADDRSTRLEN]; + struct rtnl_link *parent; + + if (ipgre->ipgre_mask & IPGRE_ATTR_LINK) { + nl_dump(p, " link "); + + name = NULL; + parent = link_lookup(link->ce_cache, ipgre->link); + if (parent) + name = rtnl_link_get_name(parent); + + if (name) + nl_dump_line(p, "%s\n", name); + else + nl_dump_line(p, "%u\n", ipgre->link); + } + + if (ipgre->ipgre_mask & IPGRE_ATTR_IFLAGS) { + nl_dump(p, " iflags "); + nl_dump_line(p, "%x\n", ipgre->iflags); + } + + if (ipgre->ipgre_mask & IPGRE_ATTR_OFLAGS) { + nl_dump(p, " oflags "); + nl_dump_line(p, "%x\n", ipgre->oflags); + } + + if (ipgre->ipgre_mask & IPGRE_ATTR_IKEY) { + nl_dump(p, " ikey "); + nl_dump_line(p, "%x\n",ipgre->ikey); + } + + if (ipgre->ipgre_mask & IPGRE_ATTR_OKEY) { + nl_dump(p, " okey "); + nl_dump_line(p, "%x\n", ipgre->okey); + } + + if (ipgre->ipgre_mask & IPGRE_ATTR_LOCAL) { + nl_dump(p, " local "); + if(inet_ntop(AF_INET, &ipgre->local, addr, sizeof(addr))) + nl_dump_line(p, "%s\n", addr); + else + nl_dump_line(p, "%#x\n", ntohs(ipgre->local)); + } + + if (ipgre->ipgre_mask & IPGRE_ATTR_REMOTE) { + nl_dump(p, " remote "); + if(inet_ntop(AF_INET, &ipgre->remote, addr, sizeof(addr))) + nl_dump_line(p, "%s\n", addr); + else + nl_dump_line(p, "%#x\n", ntohs(ipgre->remote)); + } + + if (ipgre->ipgre_mask & IPGRE_ATTR_TTL) { + nl_dump(p, " ttl "); + nl_dump_line(p, "%u\n", ipgre->ttl); + } + + if (ipgre->ipgre_mask & IPGRE_ATTR_TOS) { + nl_dump(p, " tos "); + nl_dump_line(p, "%u\n", ipgre->tos); + } + + if (ipgre->ipgre_mask & IPGRE_ATTR_PMTUDISC) { + nl_dump(p, " pmtudisc "); + nl_dump_line(p, "enabled (%#x)\n", ipgre->pmtudisc); + } + + if (ipgre->ipgre_mask & IPGRE_ATTR_FWMARK) { + nl_dump(p, " fwmark "); + nl_dump_line(p, "%x\n", ipgre->fwmark); + } +} + +static int ipgre_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct ipgre_info *ipgre_dst, *ipgre_src = src->l_info; + int err; + + dst->l_info = NULL; + + err = rtnl_link_set_type(dst, "gre"); + if (err < 0) + return err; + + ipgre_dst = dst->l_info; + + if (!ipgre_dst || !ipgre_src) + BUG(); + + memcpy(ipgre_dst, ipgre_src, sizeof(struct ipgre_info)); + + return 0; +} + +static int ipgretap_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct ipgre_info *ipgre_dst, *ipgre_src = src->l_info; + int err; + + dst->l_info = NULL; + + err = rtnl_link_set_type(dst, "gretap"); + if (err < 0) + return err; + + ipgre_dst = dst->l_info; + + if (!ipgre_dst || !ipgre_src) + BUG(); + + memcpy(ipgre_dst, ipgre_src, sizeof(struct ipgre_info)); + + return 0; +} + +static struct rtnl_link_info_ops ipgre_info_ops = { + .io_name = "gre", + .io_alloc = ipgre_alloc, + .io_parse = ipgre_parse, + .io_dump = { + [NL_DUMP_LINE] = ipgre_dump_line, + [NL_DUMP_DETAILS] = ipgre_dump_details, + }, + .io_clone = ipgre_clone, + .io_put_attrs = ipgre_put_attrs, + .io_free = ipgre_free, +}; + +static struct rtnl_link_info_ops ipgretap_info_ops = { + .io_name = "gretap", + .io_alloc = ipgre_alloc, + .io_parse = ipgre_parse, + .io_dump = { + [NL_DUMP_LINE] = ipgre_dump_line, + [NL_DUMP_DETAILS] = ipgre_dump_details, + }, + .io_clone = ipgretap_clone, + .io_put_attrs = ipgre_put_attrs, + .io_free = ipgre_free, +}; + +#define IS_IPGRE_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &ipgre_info_ops && \ + (link)->l_info_ops != &ipgretap_info_ops) { \ + APPBUG("Link is not a ipgre link. set type \"gre/gretap\" first.");\ + return -NLE_OPNOTSUPP; \ + } + +struct rtnl_link *rtnl_link_ipgre_alloc(void) +{ + struct rtnl_link *link; + int err; + + link = rtnl_link_alloc(); + if (!link) + return NULL; + + err = rtnl_link_set_type(link, "gre"); + if (err < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if link is a IPGRE link + * @arg link Link object + * + * @return True if link is a IPGRE link, otherwise 0 is returned. + */ +int rtnl_link_is_ipgre(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "gre"); +} + +/** + * Create a new IPGRE tunnel device + * @arg sock netlink socket + * @arg name name of the tunnel deviceL + * + * Creates a new ipip tunnel device in the kernel + * @return 0 on success or a negative error code + */ +int rtnl_link_ipgre_add(struct nl_sock *sk, const char *name) +{ + struct rtnl_link *link; + int err; + + link = rtnl_link_ipgre_alloc(); + if (!link) + return -NLE_NOMEM; + + if(name) + rtnl_link_set_name(link, name); + + err = rtnl_link_add(sk, link, NLM_F_CREATE); + rtnl_link_put(link); + + return err; +} + +struct rtnl_link *rtnl_link_ipgretap_alloc(void) +{ + struct rtnl_link *link; + int err; + + link = rtnl_link_alloc(); + if (!link) + return NULL; + + err = rtnl_link_set_type(link, "gretap"); + if (err < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if link is a IPGRETAP link + * @arg link Link object + * + * @return True if link is a IPGRETAP link, otherwise 0 is returned. + */ +int rtnl_link_is_ipgretap(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "gretap"); +} +/** + * Create a new IPGRETAP tunnel device + * @arg sock netlink socket + * @arg name name of the tunnel deviceL + * + * Creates a new IPGRETAP tunnel device in the kernel + * @return 0 on success or a negative error code + */ +int rtnl_link_ipgretap_add(struct nl_sock *sk, const char *name) +{ + struct rtnl_link *link; + int err; + + link = rtnl_link_ipgretap_alloc(); + if (!link) + return -NLE_NOMEM; + + if(name) + rtnl_link_set_name(link, name); + + err = rtnl_link_add(sk, link, NLM_F_CREATE); + rtnl_link_put(link); + + return err; +} + +/** + * Set IPGRE tunnel interface index + * @arg link Link object + * @arg index interface index + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipgre_set_link(struct rtnl_link *link, uint32_t index) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + ipgre->link = index; + ipgre->ipgre_mask |= IPGRE_ATTR_LINK; + + return 0; +} + +/** + * Get IPGRE tunnel interface index + * @arg link Link object + * + * @return interface index + */ +uint32_t rtnl_link_ipgre_get_link(struct rtnl_link *link) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + return ipgre->link; +} + +/** + * Set IPGRE tunnel set iflags + * @arg link Link object + * @arg iflags gre iflags + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipgre_set_iflags(struct rtnl_link *link, uint16_t iflags) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + ipgre->iflags = iflags; + ipgre->ipgre_mask |= IPGRE_ATTR_IFLAGS; + + return 0; +} + +/** + * Get IPGRE tunnel iflags + * @arg link Link object + * + * @return iflags + */ +uint16_t rtnl_link_ipgre_get_iflags(struct rtnl_link *link) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + return ipgre->iflags; +} + +/** + * Set IPGRE tunnel set oflags + * @arg link Link object + * @arg iflags gre oflags + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipgre_set_oflags(struct rtnl_link *link, uint16_t oflags) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + ipgre->oflags = oflags; + ipgre->ipgre_mask |= IPGRE_ATTR_OFLAGS; + + return 0; +} + +/** + * Get IPGRE tunnel oflags + * @arg link Link object + * + * @return oflags + */ +uint16_t rtnl_link_ipgre_get_oflags(struct rtnl_link *link) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + return ipgre->oflags; +} + +/** + * Set IPGRE tunnel set ikey + * @arg link Link object + * @arg ikey gre ikey + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipgre_set_ikey(struct rtnl_link *link, uint32_t ikey) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + ipgre->ikey = ikey; + ipgre->ipgre_mask |= IPGRE_ATTR_IKEY; + + return 0; +} + +/** + * Get IPGRE tunnel ikey + * @arg link Link object + * + * @return ikey + */ +uint32_t rtnl_link_ipgre_get_ikey(struct rtnl_link *link) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + return ipgre->ikey; +} + +/** + * Set IPGRE tunnel set okey + * @arg link Link object + * @arg okey gre okey + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipgre_set_okey(struct rtnl_link *link, uint32_t okey) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + ipgre->okey = okey; + ipgre->ipgre_mask |= IPGRE_ATTR_OKEY; + + return 0; +} + +/** + * Get IPGRE tunnel okey + * @arg link Link object + * + * @return okey value + */ +uint32_t rtnl_link_ipgre_get_okey(struct rtnl_link *link) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + return ipgre->okey; +} + +/** + * Set IPGRE tunnel local address + * @arg link Link object + * @arg addr local address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipgre_set_local(struct rtnl_link *link, uint32_t addr) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + ipgre->local = addr; + ipgre->ipgre_mask |= IPGRE_ATTR_LOCAL; + + return 0; +} + +/** + * Get IPGRE tunnel local address + * @arg link Link object + * + * @return local address + */ +uint32_t rtnl_link_ipgre_get_local(struct rtnl_link *link) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + return ipgre->local; +} + +/** + * Set IPGRE tunnel remote address + * @arg link Link object + * @arg remote remote address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipgre_set_remote(struct rtnl_link *link, uint32_t remote) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + ipgre->remote = remote; + ipgre->ipgre_mask |= IPGRE_ATTR_REMOTE; + + return 0; +} + +/** + * Get IPGRE tunnel remote address + * @arg link Link object + * + * @return remote address on success or a negative error code + */ +uint32_t rtnl_link_ipgre_get_remote(struct rtnl_link *link) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + return ipgre->remote; +} + +/** + * Set IPGRE tunnel ttl + * @arg link Link object + * @arg ttl tunnel ttl + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipgre_set_ttl(struct rtnl_link *link, uint8_t ttl) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + ipgre->ttl = ttl; + ipgre->ipgre_mask |= IPGRE_ATTR_TTL; + + return 0; +} + +/** + * Set IPGRE tunnel ttl + * @arg link Link object + * + * @return ttl value + */ +uint8_t rtnl_link_ipgre_get_ttl(struct rtnl_link *link) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + return ipgre->ttl; +} + +/** + * Set IPGRE tunnel tos + * @arg link Link object + * @arg tos tunnel tos + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipgre_set_tos(struct rtnl_link *link, uint8_t tos) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + ipgre->tos = tos; + ipgre->ipgre_mask |= IPGRE_ATTR_TOS; + + return 0; +} + +/** + * Get IPGRE tunnel tos + * @arg link Link object + * + * @return tos value + */ +uint8_t rtnl_link_ipgre_get_tos(struct rtnl_link *link) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + return ipgre->tos; +} + +/** + * Set IPGRE tunnel path MTU discovery + * @arg link Link object + * @arg pmtudisc path MTU discovery + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipgre_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + ipgre->pmtudisc = pmtudisc; + ipgre->ipgre_mask |= IPGRE_ATTR_PMTUDISC; + + return 0; +} + +/** + * Get IPGRE path MTU discovery + * @arg link Link object + * + * @return pmtudisc value + */ +uint8_t rtnl_link_ipgre_get_pmtudisc(struct rtnl_link *link) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + return ipgre->pmtudisc; +} + +/* Function prototype for ABI-preserving wrapper (not in public header) to avoid + * GCC warning about missing prototype. */ +uint8_t rtnl_link_get_pmtudisc(struct rtnl_link *link); + +uint8_t rtnl_link_get_pmtudisc(struct rtnl_link *link) +{ + /* rtnl_link_ipgre_get_pmtudisc() was wrongly named. Keep this + * to preserve ABI. */ + return rtnl_link_ipgre_get_pmtudisc (link); +} + +/** + * Set IPGRE tunnel fwmark + * @arg link Link object + * @arg fwmark fwmark + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipgre_set_fwmark(struct rtnl_link *link, uint32_t fwmark) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + ipgre->fwmark = fwmark; + ipgre->ipgre_mask |= IPGRE_ATTR_FWMARK; + + return 0; +} + +/** + * Get IPGRE tunnel fwmark + * @arg link Link object + * @arg fwmark addr to fill in with the fwmark + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipgre_get_fwmark(struct rtnl_link *link, uint32_t *fwmark) +{ + struct ipgre_info *ipgre = link->l_info; + + IS_IPGRE_LINK_ASSERT(link); + + if (!(ipgre->ipgre_mask & IPGRE_ATTR_FWMARK)) + return -NLE_NOATTR; + + *fwmark = ipgre->fwmark; + + return 0; +} + +static void _nl_init ipgre_init(void) +{ + rtnl_link_register_info(&ipgre_info_ops); + rtnl_link_register_info(&ipgretap_info_ops); +} + +static void _nl_exit ipgre_exit(void) +{ + rtnl_link_unregister_info(&ipgre_info_ops); + rtnl_link_unregister_info(&ipgretap_info_ops); +} diff --git a/lib/route/link/ipip.c b/lib/route/link/ipip.c new file mode 100644 index 0000000..74db890 --- /dev/null +++ b/lib/route/link/ipip.c @@ -0,0 +1,593 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2014 Susant Sahani + */ + +/** + * @ingroup link + * @defgroup ipip IPIP + * ipip link module + * + * @details + * \b Link Type Name: "ipip" + * + * @route_doc{link_ipip, IPIP Documentation} + * + * @{ + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "nl-route.h" +#include "link-api.h" + +#define IPIP_ATTR_LINK (1 << 0) +#define IPIP_ATTR_LOCAL (1 << 1) +#define IPIP_ATTR_REMOTE (1 << 2) +#define IPIP_ATTR_TTL (1 << 3) +#define IPIP_ATTR_TOS (1 << 4) +#define IPIP_ATTR_PMTUDISC (1 << 5) +#define IPIP_ATTR_FWMARK (1 << 6) + +struct ipip_info +{ + uint8_t ttl; + uint8_t tos; + uint8_t pmtudisc; + uint32_t link; + uint32_t local; + uint32_t remote; + uint32_t fwmark; + uint32_t ipip_mask; +}; + +static struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = { + [IFLA_IPTUN_LINK] = { .type = NLA_U32 }, + [IFLA_IPTUN_LOCAL] = { .type = NLA_U32 }, + [IFLA_IPTUN_REMOTE] = { .type = NLA_U32 }, + [IFLA_IPTUN_TTL] = { .type = NLA_U8 }, + [IFLA_IPTUN_TOS] = { .type = NLA_U8 }, + [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 }, + [IFLA_IPTUN_FWMARK] = { .type = NLA_U32 }, +}; + +static int ipip_alloc(struct rtnl_link *link) +{ + struct ipip_info *ipip; + + if (link->l_info) + memset(link->l_info, 0, sizeof(*ipip)); + else { + ipip = calloc(1, sizeof(*ipip)); + if (!ipip) + return -NLE_NOMEM; + + link->l_info = ipip; + } + + return 0; +} + +static int ipip_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_IPTUN_MAX + 1]; + struct ipip_info *ipip; + int err; + + NL_DBG(3, "Parsing IPIP link info\n"); + + err = nla_parse_nested(tb, IFLA_IPTUN_MAX, data, ipip_policy); + if (err < 0) + goto errout; + + err = ipip_alloc(link); + if (err < 0) + goto errout; + + ipip = link->l_info; + + if (tb[IFLA_IPTUN_LINK]) { + ipip->link = nla_get_u32(tb[IFLA_IPTUN_LINK]); + ipip->ipip_mask |= IPIP_ATTR_LINK; + } + + if (tb[IFLA_IPTUN_LOCAL]) { + ipip->local = nla_get_u32(tb[IFLA_IPTUN_LOCAL]); + ipip->ipip_mask |= IPIP_ATTR_LOCAL; + } + + if (tb[IFLA_IPTUN_REMOTE]) { + ipip->remote = nla_get_u32(tb[IFLA_IPTUN_REMOTE]); + ipip->ipip_mask |= IPIP_ATTR_REMOTE; + } + + if (tb[IFLA_IPTUN_TTL]) { + ipip->ttl = nla_get_u8(tb[IFLA_IPTUN_TTL]); + ipip->ipip_mask |= IPIP_ATTR_TTL; + } + + if (tb[IFLA_IPTUN_TOS]) { + ipip->tos = nla_get_u8(tb[IFLA_IPTUN_TOS]); + ipip->ipip_mask |= IPIP_ATTR_TOS; + } + + if (tb[IFLA_IPTUN_PMTUDISC]) { + ipip->pmtudisc = nla_get_u8(tb[IFLA_IPTUN_PMTUDISC]); + ipip->ipip_mask |= IPIP_ATTR_PMTUDISC; + } + + if (tb[IFLA_IPTUN_FWMARK]) { + ipip->fwmark = nla_get_u32(tb[IFLA_IPTUN_FWMARK]); + ipip->ipip_mask |= IPIP_ATTR_FWMARK; + } + + err = 0; + +errout: + return err; +} + +static int ipip_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct ipip_info *ipip = link->l_info; + struct nlattr *data; + + data = nla_nest_start(msg, IFLA_INFO_DATA); + if (!data) + return -NLE_MSGSIZE; + + if (ipip->ipip_mask & IPIP_ATTR_LINK) + NLA_PUT_U32(msg, IFLA_IPTUN_LINK, ipip->link); + + if (ipip->ipip_mask & IPIP_ATTR_LOCAL) + NLA_PUT_U32(msg, IFLA_IPTUN_LOCAL, ipip->local); + + if (ipip->ipip_mask & IPIP_ATTR_REMOTE) + NLA_PUT_U32(msg, IFLA_IPTUN_REMOTE, ipip->remote); + + if (ipip->ipip_mask & IPIP_ATTR_TTL) + NLA_PUT_U8(msg, IFLA_IPTUN_TTL, ipip->ttl); + + if (ipip->ipip_mask & IPIP_ATTR_TOS) + NLA_PUT_U8(msg, IFLA_IPTUN_TOS, ipip->tos); + + if (ipip->ipip_mask & IPIP_ATTR_PMTUDISC) + NLA_PUT_U8(msg, IFLA_IPTUN_PMTUDISC, ipip->pmtudisc); + + if (ipip->ipip_mask & IPIP_ATTR_FWMARK) + NLA_PUT_U32(msg, IFLA_IPTUN_FWMARK, ipip->fwmark); + + nla_nest_end(msg, data); + +nla_put_failure: + return 0; +} + +static void ipip_free(struct rtnl_link *link) +{ + struct ipip_info *ipip = link->l_info; + + free(ipip); + link->l_info = NULL; +} + +static void ipip_dump_line(struct rtnl_link *link, struct nl_dump_params *p) +{ + nl_dump(p, "ipip : %s", link->l_name); +} + +static void ipip_dump_details(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct ipip_info *ipip = link->l_info; + char *name, addr[INET_ADDRSTRLEN]; + struct rtnl_link *parent; + + if (ipip->ipip_mask & IPIP_ATTR_LINK) { + nl_dump(p, " link "); + + name = NULL; + parent = link_lookup(link->ce_cache, ipip->link); + if (parent) + name = rtnl_link_get_name(parent); + + if (name) + nl_dump_line(p, "%s\n", name); + else + nl_dump_line(p, "%u\n", ipip->link); + } + + if (ipip->ipip_mask & IPIP_ATTR_LOCAL) { + nl_dump(p, " local "); + if(inet_ntop(AF_INET, &ipip->local, addr, sizeof(addr))) + nl_dump_line(p, "%s\n", addr); + else + nl_dump_line(p, "%#x\n", ntohs(ipip->local)); + } + + if (ipip->ipip_mask & IPIP_ATTR_REMOTE) { + nl_dump(p, " remote "); + if(inet_ntop(AF_INET, &ipip->remote, addr, sizeof(addr))) + nl_dump_line(p, "%s\n", addr); + else + nl_dump_line(p, "%#x\n", ntohs(ipip->remote)); + } + + if (ipip->ipip_mask & IPIP_ATTR_TTL) { + nl_dump(p, " ttl "); + nl_dump_line(p, "%u\n", ipip->ttl); + } + + if (ipip->ipip_mask & IPIP_ATTR_TOS) { + nl_dump(p, " tos "); + nl_dump_line(p, "%u\n", ipip->tos); + } + + if (ipip->ipip_mask & IPIP_ATTR_PMTUDISC) { + nl_dump(p, " pmtudisc "); + nl_dump_line(p, "enabled (%#x)\n", ipip->pmtudisc); + } + + if (ipip->ipip_mask & IPIP_ATTR_FWMARK) { + nl_dump(p, " fwmark "); + nl_dump_line(p, "%x\n", ipip->fwmark); + } +} + +static int ipip_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct ipip_info *ipip_dst, *ipip_src = src->l_info; + int err; + + dst->l_info = NULL; + + err = rtnl_link_set_type(dst, "ipip"); + if (err < 0) + return err; + + ipip_dst = dst->l_info; + + if (!ipip_dst || !ipip_src) + BUG(); + + memcpy(ipip_dst, ipip_src, sizeof(struct ipip_info)); + + return 0; +} + +static struct rtnl_link_info_ops ipip_info_ops = { + .io_name = "ipip", + .io_alloc = ipip_alloc, + .io_parse = ipip_parse, + .io_dump = { + [NL_DUMP_LINE] = ipip_dump_line, + [NL_DUMP_DETAILS] = ipip_dump_details, + }, + .io_clone = ipip_clone, + .io_put_attrs = ipip_put_attrs, + .io_free = ipip_free, +}; + +#define IS_IPIP_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &ipip_info_ops) { \ + APPBUG("Link is not a ipip link. set type \"ipip\" first."); \ + return -NLE_OPNOTSUPP; \ + } + +struct rtnl_link *rtnl_link_ipip_alloc(void) +{ + struct rtnl_link *link; + int err; + + link = rtnl_link_alloc(); + if (!link) + return NULL; + + err = rtnl_link_set_type(link, "ipip"); + if (err < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if link is a IPIP link + * @arg link Link object + * + * @return True if link is a IPIP link, otherwise false is returned. + */ +int rtnl_link_is_ipip(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "ipip"); +} + +/** + * Create a new ipip tunnel device + * @arg sock netlink socket + * @arg name name of the tunnel deviceL + * + * Creates a new ipip tunnel device in the kernel + * @return 0 on success or a negative error code + */ +int rtnl_link_ipip_add(struct nl_sock *sk, const char *name) +{ + struct rtnl_link *link; + int err; + + link = rtnl_link_ipip_alloc(); + if (!link) + return -NLE_NOMEM; + + if(name) + rtnl_link_set_name(link, name); + + err = rtnl_link_add(sk, link, NLM_F_CREATE); + rtnl_link_put(link); + + return err; +} + +/** + * Set IPIP tunnel interface index + * @arg link Link object + * @arg index interface index + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipip_set_link(struct rtnl_link *link, uint32_t index) +{ + struct ipip_info *ipip = link->l_info; + + IS_IPIP_LINK_ASSERT(link); + + ipip->link = index; + ipip->ipip_mask |= IPIP_ATTR_LINK; + + return 0; +} + +/** + * Get IPIP tunnel interface index + * @arg link Link object + * + * @return interface index value + */ +uint32_t rtnl_link_ipip_get_link(struct rtnl_link *link) +{ + struct ipip_info *ipip = link->l_info; + + IS_IPIP_LINK_ASSERT(link); + + return ipip->link; +} + +/** + * Set IPIP tunnel local address + * @arg link Link object + * @arg addr local address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipip_set_local(struct rtnl_link *link, uint32_t addr) +{ + struct ipip_info *ipip = link->l_info; + + IS_IPIP_LINK_ASSERT(link); + + ipip->local = addr; + ipip->ipip_mask |= IPIP_ATTR_LOCAL; + + return 0; +} + +/** + * Get IPIP tunnel local address + * @arg link Link object + * + * @return local address value + */ +uint32_t rtnl_link_ipip_get_local(struct rtnl_link *link) +{ + struct ipip_info *ipip = link->l_info; + + IS_IPIP_LINK_ASSERT(link); + + return ipip->local; +} + +/** + * Set IPIP tunnel remote address + * @arg link Link object + * @arg remote remote address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipip_set_remote(struct rtnl_link *link, uint32_t addr) +{ + struct ipip_info *ipip = link->l_info; + + IS_IPIP_LINK_ASSERT(link); + + ipip->remote = addr; + ipip->ipip_mask |= IPIP_ATTR_REMOTE; + + return 0; +} + +/** + * Get IPIP tunnel remote address + * @arg link Link object + * + * @return remote address + */ +uint32_t rtnl_link_ipip_get_remote(struct rtnl_link *link) +{ + struct ipip_info *ipip = link->l_info; + + IS_IPIP_LINK_ASSERT(link); + + return ipip->remote; +} + +/** + * Set IPIP tunnel ttl + * @arg link Link object + * @arg ttl tunnel ttl + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipip_set_ttl(struct rtnl_link *link, uint8_t ttl) +{ + struct ipip_info *ipip = link->l_info; + + IS_IPIP_LINK_ASSERT(link); + + ipip->ttl = ttl; + ipip->ipip_mask |= IPIP_ATTR_TTL; + + return 0; +} + +/** + * Get IPIP tunnel ttl + * @arg link Link object + * + * @return ttl value + */ +uint8_t rtnl_link_ipip_get_ttl(struct rtnl_link *link) +{ + struct ipip_info *ipip = link->l_info; + + IS_IPIP_LINK_ASSERT(link); + + return ipip->ttl; +} + +/** + * Set IPIP tunnel tos + * @arg link Link object + * @arg tos tunnel tos + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipip_set_tos(struct rtnl_link *link, uint8_t tos) +{ + struct ipip_info *ipip = link->l_info; + + IS_IPIP_LINK_ASSERT(link); + + ipip->tos = tos; + ipip->ipip_mask |= IPIP_ATTR_TOS; + + return 0; +} + +/** + * Get IPIP tunnel tos + * @arg link Link object + * + * @return tos value + */ +uint8_t rtnl_link_ipip_get_tos(struct rtnl_link *link) +{ + struct ipip_info *ipip = link->l_info; + + IS_IPIP_LINK_ASSERT(link); + + return ipip->tos; +} + +/** + * Set IPIP tunnel path MTU discovery + * @arg link Link object + * @arg pmtudisc path MTU discovery + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipip_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc) +{ + struct ipip_info *ipip = link->l_info; + + IS_IPIP_LINK_ASSERT(link); + + ipip->pmtudisc = pmtudisc; + ipip->ipip_mask |= IPIP_ATTR_PMTUDISC; + + return 0; +} + +/** + * Get IPIP path MTU discovery + * @arg link Link object + * + * @return pmtudisc value + */ +uint8_t rtnl_link_ipip_get_pmtudisc(struct rtnl_link *link) +{ + struct ipip_info *ipip = link->l_info; + + IS_IPIP_LINK_ASSERT(link); + + return ipip->pmtudisc; +} + +/** + * Set IPIP tunnel fwmark + * @arg link Link object + * @arg fwmark fwmark + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipip_set_fwmark(struct rtnl_link *link, uint32_t fwmark) +{ + struct ipip_info *ipip = link->l_info; + + IS_IPIP_LINK_ASSERT(link); + + ipip->fwmark = fwmark; + ipip->ipip_mask |= IPIP_ATTR_FWMARK; + + return 0; +} + +/** + * Get IPIP tunnel fwmark + * @arg link Link object + * @arg fwmark addr to fill in with the fwmark + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipip_get_fwmark(struct rtnl_link *link, uint32_t *fwmark) +{ + struct ipip_info *ipip = link->l_info; + + IS_IPIP_LINK_ASSERT(link); + + if (!(ipip->ipip_mask & IPIP_ATTR_FWMARK)) + return -NLE_NOATTR; + + *fwmark = ipip->fwmark; + + return 0; +} + +static void _nl_init ipip_init(void) +{ + rtnl_link_register_info(&ipip_info_ops); +} + +static void _nl_exit ipip_exit(void) +{ + rtnl_link_unregister_info(&ipip_info_ops); +} diff --git a/lib/route/link/ipvlan.c b/lib/route/link/ipvlan.c new file mode 100644 index 0000000..807942b --- /dev/null +++ b/lib/route/link/ipvlan.c @@ -0,0 +1,273 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2015 Cong Wang + */ + +/** + * @ingroup link + * @defgroup ipvlan IPVLAN + * IP-based Virtual LAN link module + * + * @details + * \b Link Type Name: "ipvlan" + * + * @route_doc{link_ipvlan, IPVLAN Documentation} + * + * @{ + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "nl-route.h" +#include "link-api.h" + +/** @cond SKIP */ +#define IPVLAN_HAS_MODE (1<<0) + +struct ipvlan_info +{ + uint16_t ipi_mode; + uint32_t ipi_mask; +}; + +/** @endcond */ + +static struct nla_policy ipvlan_policy[IFLA_IPVLAN_MAX+1] = { + [IFLA_IPVLAN_MODE] = { .type = NLA_U16 }, +}; + +static int ipvlan_alloc(struct rtnl_link *link) +{ + struct ipvlan_info *ipi; + + if (link->l_info) + memset(link->l_info, 0, sizeof(*ipi)); + else { + if ((ipi = calloc(1, sizeof(*ipi))) == NULL) + return -NLE_NOMEM; + + link->l_info = ipi; + } + + return 0; +} + +static int ipvlan_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_IPVLAN_MAX+1]; + struct ipvlan_info *ipi; + int err; + + NL_DBG(3, "Parsing IPVLAN link info\n"); + + if ((err = nla_parse_nested(tb, IFLA_IPVLAN_MAX, data, ipvlan_policy)) < 0) + goto errout; + + if ((err = ipvlan_alloc(link)) < 0) + goto errout; + + ipi = link->l_info; + + if (tb[IFLA_IPVLAN_MODE]) { + ipi->ipi_mode = nla_get_u16(tb[IFLA_IPVLAN_MODE]); + ipi->ipi_mask |= IPVLAN_HAS_MODE; + } + + err = 0; +errout: + return err; +} + +static void ipvlan_free(struct rtnl_link *link) +{ + free(link->l_info); + link->l_info = NULL; +} + +static void ipvlan_dump(struct rtnl_link *link, struct nl_dump_params *p) +{ + char buf[64]; + struct ipvlan_info *ipi = link->l_info; + + if (ipi->ipi_mask & IPVLAN_HAS_MODE) { + rtnl_link_ipvlan_mode2str(ipi->ipi_mode, buf, sizeof(buf)); + nl_dump(p, "ipvlan-mode %s", buf); + } +} + +static int ipvlan_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct ipvlan_info *vdst, *vsrc = src->l_info; + int err; + + dst->l_info = NULL; + if ((err = rtnl_link_set_type(dst, "ipvlan")) < 0) + return err; + vdst = dst->l_info; + + if (!vdst || !vsrc) + return -NLE_NOMEM; + + memcpy(vdst, vsrc, sizeof(struct ipvlan_info)); + + return 0; +} + +static int ipvlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct ipvlan_info *ipi = link->l_info; + struct nlattr *data; + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + return -NLE_MSGSIZE; + + if (ipi->ipi_mask & IPVLAN_HAS_MODE) + NLA_PUT_U16(msg, IFLA_IPVLAN_MODE, ipi->ipi_mode); + + nla_nest_end(msg, data); + +nla_put_failure: + + return 0; +} + +static struct rtnl_link_info_ops ipvlan_info_ops = { + .io_name = "ipvlan", + .io_alloc = ipvlan_alloc, + .io_parse = ipvlan_parse, + .io_dump = { + [NL_DUMP_LINE] = ipvlan_dump, + [NL_DUMP_DETAILS] = ipvlan_dump, + }, + .io_clone = ipvlan_clone, + .io_put_attrs = ipvlan_put_attrs, + .io_free = ipvlan_free, +}; + +/** @cond SKIP */ +#define IS_IPVLAN_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &ipvlan_info_ops) { \ + APPBUG("Link is not a ipvlan link. set type \"ipvlan\" first."); \ + return -NLE_OPNOTSUPP; \ + } +/** @endcond */ + +/** + * @name IPVLAN Object + * @{ + */ + +/** + * Allocate link object of type IPVLAN + * + * @return Allocated link object or NULL. + */ +struct rtnl_link *rtnl_link_ipvlan_alloc(void) +{ + struct rtnl_link *link; + + if (!(link = rtnl_link_alloc())) + return NULL; + + if (rtnl_link_set_type(link, "ipvlan") < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if link is a IPVLAN link + * @arg link Link object + * + * @return True if link is a IPVLAN link, otherwise false is returned. + */ +int rtnl_link_is_ipvlan(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "ipvlan"); +} + +/** + * Set IPVLAN MODE + * @arg link Link object + * @arg mode IPVLAN mode + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipvlan_set_mode(struct rtnl_link *link, uint16_t mode) +{ + struct ipvlan_info *ipi = link->l_info; + + IS_IPVLAN_LINK_ASSERT(link); + + ipi->ipi_mode = mode; + ipi->ipi_mask |= IPVLAN_HAS_MODE; + + return 0; +} + +/** + * Get IPVLAN Mode + * @arg link Link object + * @arg out_mode on success, return the mode + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_ipvlan_get_mode(struct rtnl_link *link, uint16_t *out_mode) +{ + struct ipvlan_info *ipi = link->l_info; + + IS_IPVLAN_LINK_ASSERT(link); + + if (!(ipi->ipi_mask & IPVLAN_HAS_MODE)) + return -NLE_INVAL; + *out_mode = ipi->ipi_mode; + return 0; +} + +/** @} */ + +static const struct trans_tbl ipvlan_modes[] = { + __ADD(IPVLAN_MODE_L2, l2), + __ADD(IPVLAN_MODE_L3, l3), +}; + +/** + * @name Mode Translation + * @{ + */ + +char *rtnl_link_ipvlan_mode2str(int mode, char *buf, size_t len) +{ + return __type2str(mode, buf, len, ipvlan_modes, ARRAY_SIZE(ipvlan_modes)); +} + +int rtnl_link_ipvlan_str2mode(const char *name) +{ + return __str2type(name, ipvlan_modes, ARRAY_SIZE(ipvlan_modes)); +} + +/** @} */ + +static void _nl_init ipvlan_init(void) +{ + rtnl_link_register_info(&ipvlan_info_ops); +} + +static void _nl_exit ipvlan_exit(void) +{ + rtnl_link_unregister_info(&ipvlan_info_ops); +} + +/** @} */ diff --git a/lib/route/link/ipvti.c b/lib/route/link/ipvti.c new file mode 100644 index 0000000..fd57895 --- /dev/null +++ b/lib/route/link/ipvti.c @@ -0,0 +1,542 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2014 Susant Sahani + */ + +/** + * @ingroup link + * @defgroup ipvti IPVTI + * ipvti link module + * + * @details + * \b Link Type Name: "ipvti" + * + * @route_doc{link_ipvti, IPVTI Documentation} + * + * @{ + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "nl-route.h" +#include "link-api.h" + +#define IPVTI_ATTR_LINK (1 << 0) +#define IPVTI_ATTR_IKEY (1 << 1) +#define IPVTI_ATTR_OKEY (1 << 2) +#define IPVTI_ATTR_LOCAL (1 << 3) +#define IPVTI_ATTR_REMOTE (1 << 4) +#define IPVTI_ATTR_FWMARK (1 << 5) + +struct ipvti_info +{ + uint32_t link; + uint32_t ikey; + uint32_t okey; + uint32_t local; + uint32_t remote; + uint32_t fwmark; + uint32_t ipvti_mask; +}; + +static struct nla_policy ipvti_policy[IFLA_VTI_MAX + 1] = { + [IFLA_VTI_LINK] = { .type = NLA_U32 }, + [IFLA_VTI_IKEY] = { .type = NLA_U32 }, + [IFLA_VTI_OKEY] = { .type = NLA_U32 }, + [IFLA_VTI_LOCAL] = { .type = NLA_U32 }, + [IFLA_VTI_REMOTE] = { .type = NLA_U32 }, + [IFLA_VTI_FWMARK] = { .type = NLA_U32 }, +}; + +static int ipvti_alloc(struct rtnl_link *link) +{ + struct ipvti_info *ipvti; + + if (link->l_info) + memset(link->l_info, 0, sizeof(*ipvti)); + else { + ipvti = calloc(1, sizeof(*ipvti)); + if (!ipvti) + return -NLE_NOMEM; + + link->l_info = ipvti; + } + + return 0; +} + +static int ipvti_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_VTI_MAX + 1]; + struct ipvti_info *ipvti; + int err; + + NL_DBG(3, "Parsing IPVTI link info\n"); + + err = nla_parse_nested(tb, IFLA_VTI_MAX, data, ipvti_policy); + if (err < 0) + goto errout; + + err = ipvti_alloc(link); + if (err < 0) + goto errout; + + ipvti = link->l_info; + + if (tb[IFLA_VTI_LINK]) { + ipvti->link = nla_get_u32(tb[IFLA_VTI_LINK]); + ipvti->ipvti_mask |= IPVTI_ATTR_LINK; + } + + if (tb[IFLA_VTI_IKEY]) { + ipvti->ikey = nla_get_u32(tb[IFLA_VTI_IKEY]); + ipvti->ipvti_mask |= IPVTI_ATTR_IKEY; + } + + if (tb[IFLA_VTI_OKEY]) { + ipvti->okey = nla_get_u32(tb[IFLA_VTI_OKEY]); + ipvti->ipvti_mask |= IPVTI_ATTR_OKEY; + } + + if (tb[IFLA_VTI_LOCAL]) { + ipvti->local = nla_get_u32(tb[IFLA_VTI_LOCAL]); + ipvti->ipvti_mask |= IPVTI_ATTR_LOCAL; + } + + if (tb[IFLA_VTI_REMOTE]) { + ipvti->remote = nla_get_u32(tb[IFLA_VTI_REMOTE]); + ipvti->ipvti_mask |= IPVTI_ATTR_REMOTE; + } + + if (tb[IFLA_VTI_FWMARK]) { + ipvti->fwmark = nla_get_u32(tb[IFLA_VTI_FWMARK]); + ipvti->ipvti_mask |= IPVTI_ATTR_FWMARK; + } + + err = 0; + +errout: + return err; +} + +static int ipvti_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct ipvti_info *ipvti = link->l_info; + struct nlattr *data; + + data = nla_nest_start(msg, IFLA_INFO_DATA); + if (!data) + return -NLE_MSGSIZE; + + if (ipvti->ipvti_mask & IPVTI_ATTR_LINK) + NLA_PUT_U32(msg, IFLA_VTI_LINK, ipvti->link); + + if (ipvti->ipvti_mask & IPVTI_ATTR_IKEY) + NLA_PUT_U32(msg, IFLA_VTI_IKEY, ipvti->ikey); + + if (ipvti->ipvti_mask & IFLA_VTI_IKEY) + NLA_PUT_U32(msg, IFLA_VTI_OKEY, ipvti->okey); + + if (ipvti->ipvti_mask & IPVTI_ATTR_LOCAL) + NLA_PUT_U32(msg, IFLA_VTI_LOCAL, ipvti->local); + + if (ipvti->ipvti_mask & IPVTI_ATTR_REMOTE) + NLA_PUT_U32(msg, IFLA_VTI_REMOTE, ipvti->remote); + + if (ipvti->ipvti_mask & IPVTI_ATTR_FWMARK) + NLA_PUT_U32(msg, IFLA_VTI_FWMARK, ipvti->fwmark); + + nla_nest_end(msg, data); + +nla_put_failure: + + return 0; +} + +static void ipvti_free(struct rtnl_link *link) +{ + struct ipvti_info *ipvti = link->l_info; + + free(ipvti); + link->l_info = NULL; +} + +static void ipvti_dump_line(struct rtnl_link *link, struct nl_dump_params *p) +{ + nl_dump(p, "ipvti : %s", link->l_name); +} + +static void ipvti_dump_details(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct ipvti_info *ipvti = link->l_info; + char *name, addr[INET_ADDRSTRLEN]; + struct rtnl_link *parent; + + if (ipvti->ipvti_mask & IPVTI_ATTR_LINK) { + nl_dump(p, " link "); + + name = NULL; + parent = link_lookup(link->ce_cache, ipvti->link); + if (parent) + name = rtnl_link_get_name(parent); + + if (name) + nl_dump_line(p, "%s\n", name); + else + nl_dump_line(p, "%u\n", ipvti->link); + } + + if (ipvti->ipvti_mask & IPVTI_ATTR_IKEY) { + nl_dump(p, " ikey "); + nl_dump_line(p, "%x\n",ipvti->ikey); + } + + if (ipvti->ipvti_mask & IPVTI_ATTR_OKEY) { + nl_dump(p, " okey "); + nl_dump_line(p, "%x\n", ipvti->okey); + } + + if (ipvti->ipvti_mask & IPVTI_ATTR_LOCAL) { + nl_dump(p, " local "); + if(inet_ntop(AF_INET, &ipvti->local, addr, sizeof(addr))) + nl_dump_line(p, "%s\n", addr); + else + nl_dump_line(p, "%#x\n", ntohs(ipvti->local)); + } + + if (ipvti->ipvti_mask & IPVTI_ATTR_REMOTE) { + nl_dump(p, " remote "); + if(inet_ntop(AF_INET, &ipvti->remote, addr, sizeof(addr))) + nl_dump_line(p, "%s\n", addr); + else + nl_dump_line(p, "%#x\n", ntohs(ipvti->remote)); + } + + if (ipvti->ipvti_mask & IPVTI_ATTR_FWMARK) { + nl_dump(p, " fwmark "); + nl_dump_line(p, "%x\n", ipvti->fwmark); + } +} + +static int ipvti_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct ipvti_info *ipvti_dst, *ipvti_src = src->l_info; + int err; + + dst->l_info = NULL; + + err = rtnl_link_set_type(dst, "vti"); + if (err < 0) + return err; + + ipvti_dst = dst->l_info; + + if (!ipvti_dst || !ipvti_src) + BUG(); + + memcpy(ipvti_dst, ipvti_src, sizeof(struct ipvti_info)); + + return 0; +} + +static struct rtnl_link_info_ops ipvti_info_ops = { + .io_name = "vti", + .io_alloc = ipvti_alloc, + .io_parse = ipvti_parse, + .io_dump = { + [NL_DUMP_LINE] = ipvti_dump_line, + [NL_DUMP_DETAILS] = ipvti_dump_details, + }, + .io_clone = ipvti_clone, + .io_put_attrs = ipvti_put_attrs, + .io_free = ipvti_free, +}; + +#define IS_IPVTI_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &ipvti_info_ops) { \ + APPBUG("Link is not a ipvti link. set type \vti\" first."); \ + return -NLE_OPNOTSUPP; \ + } + +struct rtnl_link *rtnl_link_ipvti_alloc(void) +{ + struct rtnl_link *link; + int err; + + link = rtnl_link_alloc(); + if (!link) + return NULL; + + err = rtnl_link_set_type(link, "vti"); + if (err < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if link is a IPVTI link + * @arg link Link object + * + * @return True if link is a IPVTI link, otherwise 0 is returned. + */ +int rtnl_link_is_ipvti(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "vti"); +} +/** + * Create a new ipvti tunnel device + * @arg sock netlink socket + * @arg name name of the tunnel deviceL + * + * Creates a new ipvti tunnel device in the kernel + * @return 0 on success or a negative error code + */ +int rtnl_link_ipvti_add(struct nl_sock *sk, const char *name) +{ + struct rtnl_link *link; + int err; + + link = rtnl_link_ipvti_alloc(); + if (!link) + return -NLE_NOMEM; + + if(name) + rtnl_link_set_name(link, name); + + err = rtnl_link_add(sk, link, NLM_F_CREATE); + rtnl_link_put(link); + + return err; +} +/** + * Set IPVTI tunnel interface index + * @arg link Link object + * @arg index interface index + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipvti_set_link(struct rtnl_link *link, uint32_t index) +{ + struct ipvti_info *ipvti = link->l_info; + + IS_IPVTI_LINK_ASSERT(link); + + ipvti->link = index; + ipvti->ipvti_mask |= IPVTI_ATTR_LINK; + + return 0; +} + +/** + * Get IPVTI tunnel interface index + * @arg link Link object + * + * @return interface index + */ +uint32_t rtnl_link_ipvti_get_link(struct rtnl_link *link) +{ + struct ipvti_info *ipvti = link->l_info; + + IS_IPVTI_LINK_ASSERT(link); + + return ipvti->link; +} + +/** + * Set IPVTI tunnel set ikey + * @arg link Link object + * @arg ikey gre ikey + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipvti_set_ikey(struct rtnl_link *link, uint32_t ikey) +{ + struct ipvti_info *ipvti = link->l_info; + + IS_IPVTI_LINK_ASSERT(link); + + ipvti->ikey = ikey; + ipvti->ipvti_mask |= IPVTI_ATTR_IKEY; + + return 0; +} + +/** + * Get IPVTI tunnel ikey + * @arg link Link object + * + * @return ikey + */ +uint32_t rtnl_link_ipvti_get_ikey(struct rtnl_link *link) +{ + struct ipvti_info *ipvti = link->l_info; + + IS_IPVTI_LINK_ASSERT(link); + + return ipvti->ikey; +} + +/** + * Set IPVTI tunnel set okey + * @arg link Link object + * @arg okey gre okey + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipvti_set_okey(struct rtnl_link *link, uint32_t okey) +{ + struct ipvti_info *ipvti = link->l_info; + + IS_IPVTI_LINK_ASSERT(link); + + ipvti->okey = okey; + ipvti->ipvti_mask |= IPVTI_ATTR_OKEY; + + return 0; +} + +/** + * Get IPVTI tunnel okey + * @arg link Link object + * + * @return okey value + */ +uint32_t rtnl_link_ipvti_get_okey(struct rtnl_link *link) +{ + struct ipvti_info *ipvti = link->l_info; + + IS_IPVTI_LINK_ASSERT(link); + + return ipvti->okey; +} + +/** + * Set IPVTI tunnel local address + * @arg link Link object + * @arg addr local address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipvti_set_local(struct rtnl_link *link, uint32_t addr) +{ + struct ipvti_info *ipvti = link->l_info; + + IS_IPVTI_LINK_ASSERT(link); + + ipvti->local = addr; + ipvti->ipvti_mask |= IPVTI_ATTR_LOCAL; + + return 0; +} + +/** + * Get IPVTI tunnel local address + * @arg link Link object + * + * @return local address + */ +uint32_t rtnl_link_ipvti_get_local(struct rtnl_link *link) +{ + struct ipvti_info *ipvti = link->l_info; + + IS_IPVTI_LINK_ASSERT(link); + + return ipvti->local; +} + +/** + * Set IPVTI tunnel remote address + * @arg link Link object + * @arg remote remote address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipvti_set_remote(struct rtnl_link *link, uint32_t remote) +{ + struct ipvti_info *ipvti = link->l_info; + + IS_IPVTI_LINK_ASSERT(link); + + ipvti->remote = remote; + ipvti->ipvti_mask |= IPVTI_ATTR_REMOTE; + + return 0; +} + +/** + * Get IPVTI tunnel remote address + * @arg link Link object + * + * @return remote address on success or a negative error code + */ +uint32_t rtnl_link_ipvti_get_remote(struct rtnl_link *link) +{ + struct ipvti_info *ipvti = link->l_info; + + IS_IPVTI_LINK_ASSERT(link); + + return ipvti->remote; +} + +/** + * Set IPVTI tunnel fwmark + * @arg link Link object + * @arg fwmark fwmark + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipvti_set_fwmark(struct rtnl_link *link, uint32_t fwmark) +{ + struct ipvti_info *ipvti = link->l_info; + + IS_IPVTI_LINK_ASSERT(link); + + ipvti->fwmark = fwmark; + ipvti->ipvti_mask |= IPVTI_ATTR_FWMARK; + + return 0; +} + +/** + * Get IPVTI tunnel fwmark + * @arg link Link object + * @arg fwmark addr to fill in with the fwmark + * + * @return 0 on success or a negative error code + */ +int rtnl_link_ipvti_get_fwmark(struct rtnl_link *link, uint32_t *fwmark) +{ + struct ipvti_info *ipvti = link->l_info; + + IS_IPVTI_LINK_ASSERT(link); + + if (!(ipvti->ipvti_mask & IPVTI_ATTR_FWMARK)) + return -NLE_NOATTR; + + *fwmark = ipvti->fwmark; + + return 0; +} + +static void _nl_init ipvti_init(void) +{ + rtnl_link_register_info(&ipvti_info_ops); +} + +static void _nl_exit ipvti_exit(void) +{ + rtnl_link_unregister_info(&ipvti_info_ops); +} diff --git a/include/netlink-private/route/link/api.h b/lib/route/link/link-api.h similarity index 70% rename from include/netlink-private/route/link/api.h rename to lib/route/link/link-api.h index bb98ccc..0e54057 100644 --- a/include/netlink-private/route/link/api.h +++ b/lib/route/link/link-api.h @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * netlink-private/route/link/api.h Link Modules API - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2013 Thomas Graf */ @@ -13,10 +7,9 @@ #define NETLINK_LINK_API_H_ #include +#include -#ifdef __cplusplus -extern "C" { -#endif +#include "nl-priv-dynamic-core/nl-core.h" /** * @ingroup link_api @@ -60,10 +53,15 @@ struct rtnl_link_info_ops * in either io_alloc() or io_parse(). */ void (*io_free)(struct rtnl_link *); + /** Called to compare link info parameters between two links. */ + int (*io_compare)(struct rtnl_link *, struct rtnl_link *, + int flags); + struct nl_list_head io_list; }; extern struct rtnl_link_info_ops *rtnl_link_info_ops_lookup(const char *); +extern void rtnl_link_info_ops_get(struct rtnl_link_info_ops *); extern void rtnl_link_info_ops_put(struct rtnl_link_info_ops *); extern int rtnl_link_register_info(struct rtnl_link_info_ops *); extern int rtnl_link_unregister_info(struct rtnl_link_info_ops *); @@ -115,6 +113,16 @@ struct rtnl_link_af_ops int (*ao_fill_af)(struct rtnl_link *, struct nl_msg *msg, void *); + /** Called if the full IFLA_AF_SPEC data needs to be parsed. Typically + * stores the parsed data in the address family specific buffer. */ + int (*ao_parse_af_full)(struct rtnl_link *, + struct nlattr *, void *); + + /** Called for GETLINK message to the kernel. Used to append + * link address family specific attributes to the request message. */ + int (*ao_get_af)(struct nl_msg *msg, + uint32_t *ext_filter_mask); + /** Dump address family specific link attributes */ void (*ao_dump[NL_DUMP_MAX+1])(struct rtnl_link *, struct nl_dump_params *, @@ -132,6 +140,35 @@ struct rtnl_link_af_ops */ int (*ao_compare)(struct rtnl_link *, struct rtnl_link *, int, uint32_t, int); + + /* RTM_NEWLINK override + * + * Called if a change link request is set to the kernel. If this returns + * anything other than zero, RTM_NEWLINK will be overriden with + * RTM_SETLINK when rtnl_link_build_change_request() is called. + */ + int (*ao_override_rtm)(struct rtnl_link *); + + /** Called if a link message is sent to the kernel. Must append the + * link protocol specific attributes to the message. (IFLA_PROTINFO) */ + int (*ao_fill_pi)(struct rtnl_link *, + struct nl_msg *msg, void *); + + /** PROTINFO type + * + * Called if a link message is sent to the kernel. If this is set, + * the default IFLA_PROTINFO is bitmasked with what is specified + * here. (eg. NLA_F_NESTED) + */ + const int ao_fill_pi_flags; + + /** IFLA_AF_SPEC nesting override + * + * Called if a link message is sent to the kernel. If this is set, + * the AF specific nest is not created. Instead, AF specific attributes + * are nested directly in the IFLA_AF_SPEC attribute. + */ + const int ao_fill_af_no_nest; }; extern struct rtnl_link_af_ops *rtnl_link_af_ops_lookup(unsigned int); @@ -145,9 +182,10 @@ extern int rtnl_link_af_unregister(struct rtnl_link_af_ops *); extern int rtnl_link_af_data_compare(struct rtnl_link *a, struct rtnl_link *b, int family); +extern int rtnl_link_info_data_compare(struct rtnl_link *a, + struct rtnl_link *b, + int flags); -#ifdef __cplusplus -} -#endif +extern struct rtnl_link *link_lookup(struct nl_cache *cache, int ifindex); #endif diff --git a/lib/route/link/macsec.c b/lib/route/link/macsec.c new file mode 100644 index 0000000..a989eed --- /dev/null +++ b/lib/route/link/macsec.c @@ -0,0 +1,894 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2016 Sabrina Dubroca + */ + +/** + * @ingroup link + * @defgroup macsec MACsec + * MACsec link module + * + * @details + * \b Link Type Name: "macsec" + * + * @route_doc{link_macsec, MACsec Documentation} + * + * @{ + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "nl-route.h" +#include "link-api.h" +#include "nl-priv-dynamic-core/nl-core.h" + +/** @cond SKIP */ +#define MACSEC_ATTR_SCI (1 << 0) +#define MACSEC_ATTR_ICV_LEN (1 << 1) +#define MACSEC_ATTR_CIPHER_SUITE (1 << 2) +#define MACSEC_ATTR_WINDOW (1 << 3) +#define MACSEC_ATTR_ENCODING_SA (1 << 4) +#define MACSEC_ATTR_ENCRYPT (1 << 5) +#define MACSEC_ATTR_PROTECT (1 << 6) +#define MACSEC_ATTR_INC_SCI (1 << 7) +#define MACSEC_ATTR_ES (1 << 8) +#define MACSEC_ATTR_SCB (1 << 9) +#define MACSEC_ATTR_REPLAY_PROTECT (1 << 10) +#define MACSEC_ATTR_VALIDATION (1 << 11) +#define MACSEC_ATTR_PORT (1 << 12) +#define MACSEC_ATTR_OFFLOAD (1 << 13) + +struct macsec_info { + int ifindex; + uint64_t sci; + uint16_t port; + uint64_t cipher_suite; + uint16_t icv_len; + uint32_t window; + enum macsec_validation_type validate; + uint8_t encoding_sa; + + uint8_t send_sci, end_station, scb, replay_protect, protect, encrypt, offload; + + uint32_t ce_mask; +}; + +#define DEFAULT_ICV_LEN 16 + +/** @endcond */ + +static struct nla_policy macsec_policy[IFLA_MACSEC_MAX+1] = { + [IFLA_MACSEC_SCI] = { .type = NLA_U64 }, + [IFLA_MACSEC_ICV_LEN] = { .type = NLA_U8 }, + [IFLA_MACSEC_CIPHER_SUITE] = { .type = NLA_U64 }, + [IFLA_MACSEC_WINDOW] = { .type = NLA_U32 }, + [IFLA_MACSEC_ENCODING_SA] = { .type = NLA_U8 }, + [IFLA_MACSEC_ENCRYPT] = { .type = NLA_U8 }, + [IFLA_MACSEC_PROTECT] = { .type = NLA_U8 }, + [IFLA_MACSEC_INC_SCI] = { .type = NLA_U8 }, + [IFLA_MACSEC_ES] = { .type = NLA_U8 }, + [IFLA_MACSEC_SCB] = { .type = NLA_U8 }, + [IFLA_MACSEC_REPLAY_PROTECT] = { .type = NLA_U8 }, + [IFLA_MACSEC_VALIDATION] = { .type = NLA_U8 }, + [IFLA_MACSEC_OFFLOAD] = { .type = NLA_U8 }, +}; + +/** + * @name MACsec Object + * @{ + */ + +/** + * Allocate link object of type MACsec + * + * @return Allocated link object or NULL. + */ +static int macsec_alloc(struct rtnl_link *link) +{ + struct macsec_info *info; + + if (!link->l_info) { + link->l_info = malloc(sizeof(struct macsec_info)); + if (!link->l_info) + return -NLE_NOMEM; + } + + memset(link->l_info, 0, sizeof(struct macsec_info)); + info = link->l_info; + + info->cipher_suite = MACSEC_DEFAULT_CIPHER_ID; + info->icv_len = DEFAULT_ICV_LEN; + info->ce_mask = MACSEC_ATTR_CIPHER_SUITE | MACSEC_ATTR_ICV_LEN; + + return 0; +} + +static int macsec_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_MACSEC_MAX+1]; + struct macsec_info *info; + int err; + + NL_DBG(3, "Parsing MACsec link info\n"); + + if ((err = nla_parse_nested(tb, IFLA_MACSEC_MAX, data, macsec_policy)) < 0) + goto errout; + + if ((err = macsec_alloc(link)) < 0) + goto errout; + + info = link->l_info; + + if (tb[IFLA_MACSEC_SCI]) { + info->sci = nla_get_u64(tb[IFLA_MACSEC_SCI]); + info->ce_mask |= MACSEC_ATTR_SCI; + } + + if (tb[IFLA_MACSEC_PROTECT]) { + info->protect = nla_get_u8(tb[IFLA_MACSEC_PROTECT]); + info->ce_mask |= MACSEC_ATTR_PROTECT; + } + + if (tb[IFLA_MACSEC_CIPHER_SUITE]) { + info->cipher_suite = nla_get_u64(tb[IFLA_MACSEC_CIPHER_SUITE]); + info->ce_mask |= MACSEC_ATTR_CIPHER_SUITE; + } + + if (tb[IFLA_MACSEC_ICV_LEN]) { + info->icv_len = nla_get_u8(tb[IFLA_MACSEC_ICV_LEN]); + info->ce_mask |= MACSEC_ATTR_ICV_LEN; + } + + if (tb[IFLA_MACSEC_ENCODING_SA]) { + info->encoding_sa = nla_get_u8(tb[IFLA_MACSEC_ENCODING_SA]); + info->ce_mask |= MACSEC_ATTR_ENCODING_SA; + } + + if (tb[IFLA_MACSEC_VALIDATION]) { + info->validate = nla_get_u8(tb[IFLA_MACSEC_VALIDATION]); + info->ce_mask |= MACSEC_ATTR_VALIDATION; + } + + if (tb[IFLA_MACSEC_ENCRYPT]) { + info->encrypt = nla_get_u8(tb[IFLA_MACSEC_ENCRYPT]); + info->ce_mask |= MACSEC_ATTR_ENCRYPT; + } + + if (tb[IFLA_MACSEC_OFFLOAD]) { + info->offload = nla_get_u8(tb[IFLA_MACSEC_OFFLOAD]); + info->ce_mask |= MACSEC_ATTR_OFFLOAD; + } + + if (tb[IFLA_MACSEC_INC_SCI]) { + info->send_sci = nla_get_u8(tb[IFLA_MACSEC_INC_SCI]); + info->ce_mask |= MACSEC_ATTR_INC_SCI; + } + + if (tb[IFLA_MACSEC_ES]) { + info->end_station = nla_get_u8(tb[IFLA_MACSEC_ES]); + info->ce_mask |= MACSEC_ATTR_ES; + } + + if (tb[IFLA_MACSEC_SCB]) { + info->scb = nla_get_u8(tb[IFLA_MACSEC_SCB]); + info->ce_mask |= MACSEC_ATTR_SCB; + } + + if (tb[IFLA_MACSEC_REPLAY_PROTECT]) { + info->replay_protect = nla_get_u8(tb[IFLA_MACSEC_REPLAY_PROTECT]); + info->ce_mask |= MACSEC_ATTR_REPLAY_PROTECT; + } + + if (tb[IFLA_MACSEC_WINDOW]) { + info->window = nla_get_u32(tb[IFLA_MACSEC_WINDOW]); + info->ce_mask |= MACSEC_ATTR_WINDOW; + } + + err = 0; +errout: + return err; +} + +static void macsec_free(struct rtnl_link *link) +{ + free(link->l_info); + link->l_info = NULL; +} + +static const char *values_on_off[] = { "off", "on" }; + +static const char *VALIDATE_STR[] = { + [MACSEC_VALIDATE_DISABLED] = "disabled", + [MACSEC_VALIDATE_CHECK] = "check", + [MACSEC_VALIDATE_STRICT] = "strict", +}; + +static char *replay_protect_str(char *buf, uint8_t replay_protect, uint8_t window) +{ + if (replay_protect == 1) { + sprintf(buf, "replay_protect on window %d", window); + } else if (replay_protect == 0) { + sprintf(buf, "replay_protect off"); + } else { + buf[0] = '\0'; + } + + return buf; +} + +/** @cond SKIP */ +#define PRINT_FLAG(buf, i, field, c) ({ if (i->field == 1) *buf++ = c; }) +/** @endcond */ +static char *flags_str(char *buf, unsigned char len, struct macsec_info *info) +{ + char *tmp = buf; + memset(tmp, 0, len); + + PRINT_FLAG(tmp, info, protect, 'P'); + PRINT_FLAG(tmp, info, encrypt, 'E'); + PRINT_FLAG(tmp, info, send_sci, 'S'); + PRINT_FLAG(tmp, info, end_station, 'e'); + PRINT_FLAG(tmp, info, scb, 's'); + PRINT_FLAG(tmp, info, replay_protect, 'R'); + + *tmp++ = ' '; + *tmp++ = 'v'; + switch (info->validate) { + case MACSEC_VALIDATE_DISABLED: + *tmp++ = 'd'; + break; + case MACSEC_VALIDATE_CHECK: + *tmp++ = 'c'; + break; + case MACSEC_VALIDATE_STRICT: + *tmp++ = 's'; + break; + default: + break; + } + + sprintf(tmp, " %d", info->encoding_sa); + + return buf; +} + +static void macsec_dump_line(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct macsec_info *info = link->l_info; + char tmp[128]; + + nl_dump(p, "sci %016llx <%s>", (long long unsigned)ntohll(info->sci), + flags_str(tmp, sizeof(tmp), info)); +} + +static void macsec_dump_details(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct macsec_info *info = link->l_info; + char tmp[128]; + + nl_dump(p, + " sci %016llx protect %s encoding_sa %d encrypt %s send_sci %s validate %s %s\n", + (long long unsigned)ntohll(info->sci), + values_on_off[info->protect], info->encoding_sa, + values_on_off[info->encrypt], values_on_off[info->send_sci], + VALIDATE_STR[info->validate], + replay_protect_str(tmp, info->replay_protect, info->window)); + nl_dump(p, " cipher suite: %016llx, icv_len %d\n", + (long long unsigned)info->cipher_suite, info->icv_len); +} + +static int macsec_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct macsec_info *copy, *info = src->l_info; + int err; + + dst->l_info = NULL; + if ((err = rtnl_link_set_type(dst, "macsec")) < 0) + return err; + copy = dst->l_info; + + if (!info || !copy) + return -NLE_NOMEM; + + memcpy(copy, info, sizeof(struct macsec_info)); + + return 0; +} + +static int macsec_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct macsec_info *info = link->l_info; + struct nlattr *data; + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + return -NLE_MSGSIZE; + + if (info->ce_mask & MACSEC_ATTR_SCI) + NLA_PUT_U64(msg, IFLA_MACSEC_SCI, info->sci); + else if (info->ce_mask & MACSEC_ATTR_PORT) + NLA_PUT_U16(msg, IFLA_MACSEC_PORT, htons(info->port)); + + if ((info->ce_mask & MACSEC_ATTR_ENCRYPT)) + NLA_PUT_U8(msg, IFLA_MACSEC_ENCRYPT, info->encrypt); + + if ((info->ce_mask & MACSEC_ATTR_OFFLOAD)) + NLA_PUT_U8(msg, IFLA_MACSEC_OFFLOAD, info->offload); + + if (info->cipher_suite != MACSEC_DEFAULT_CIPHER_ID || info->icv_len != DEFAULT_ICV_LEN) { + NLA_PUT_U64(msg, IFLA_MACSEC_CIPHER_SUITE, info->cipher_suite); + NLA_PUT_U8(msg, IFLA_MACSEC_ICV_LEN, info->icv_len); + } + + if ((info->ce_mask & MACSEC_ATTR_INC_SCI)) + NLA_PUT_U8(msg, IFLA_MACSEC_INC_SCI, info->send_sci); + + if ((info->ce_mask & MACSEC_ATTR_ES)) + NLA_PUT_U8(msg, IFLA_MACSEC_ES, info->end_station); + + if ((info->ce_mask & MACSEC_ATTR_SCB)) + NLA_PUT_U8(msg, IFLA_MACSEC_SCB, info->scb); + + if ((info->ce_mask & MACSEC_ATTR_PROTECT)) + NLA_PUT_U8(msg, IFLA_MACSEC_PROTECT, info->protect); + + if ((info->ce_mask & MACSEC_ATTR_REPLAY_PROTECT)) { + if (info->replay_protect && !(info->ce_mask & MACSEC_ATTR_WINDOW)) + return -NLE_INVAL; + + NLA_PUT_U8(msg, IFLA_MACSEC_REPLAY_PROTECT, info->replay_protect); + NLA_PUT_U32(msg, IFLA_MACSEC_WINDOW, info->window); + } + + if ((info->ce_mask & MACSEC_ATTR_VALIDATION)) + NLA_PUT_U8(msg, IFLA_MACSEC_VALIDATION, info->validate); + + if ((info->ce_mask & MACSEC_ATTR_ENCODING_SA)) + NLA_PUT_U8(msg, IFLA_MACSEC_ENCODING_SA, info->encoding_sa); + + nla_nest_end(msg, data); + + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +static int macsec_compare(struct rtnl_link *link_a, struct rtnl_link *link_b, + int flags) +{ + struct macsec_info *a = link_a->l_info; + struct macsec_info *b = link_b->l_info; + int diff = 0; + uint32_t attrs = flags & LOOSE_COMPARISON ? b->ce_mask : ~0; + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + if (a->ce_mask & MACSEC_ATTR_SCI && b->ce_mask & MACSEC_ATTR_SCI) + diff |= _DIFF(MACSEC_ATTR_SCI, a->sci != b->sci); + else if (a->ce_mask & MACSEC_ATTR_PORT && b->ce_mask & MACSEC_ATTR_PORT) + diff |= _DIFF(MACSEC_ATTR_PORT, a->port != b->port); + + if (a->ce_mask & MACSEC_ATTR_CIPHER_SUITE && + b->ce_mask & MACSEC_ATTR_CIPHER_SUITE) { + diff |= _DIFF(MACSEC_ATTR_ICV_LEN, a->icv_len != b->icv_len); + diff |= _DIFF(MACSEC_ATTR_CIPHER_SUITE, + a->cipher_suite != b->cipher_suite); + } + + if (a->ce_mask & MACSEC_ATTR_REPLAY_PROTECT && + b->ce_mask & MACSEC_ATTR_REPLAY_PROTECT) { + int d = _DIFF(MACSEC_ATTR_REPLAY_PROTECT, + a->replay_protect != b->replay_protect); + if (a->replay_protect && b->replay_protect) { + d |= _DIFF(MACSEC_ATTR_WINDOW, a->window != b->window); + } + diff |= d; + } + + diff |= _DIFF(MACSEC_ATTR_ENCODING_SA, + a->encoding_sa != b->encoding_sa); + diff |= _DIFF(MACSEC_ATTR_ENCRYPT, a->encrypt != b->encrypt); + diff |= _DIFF(MACSEC_ATTR_PROTECT, a->protect != b->protect); + diff |= _DIFF(MACSEC_ATTR_INC_SCI, a->send_sci != b->send_sci); + diff |= _DIFF(MACSEC_ATTR_ES, a->end_station != b->end_station); + diff |= _DIFF(MACSEC_ATTR_SCB, a->scb != b->scb); + diff |= _DIFF(MACSEC_ATTR_VALIDATION, a->validate != b->validate); +#undef _DIFF + + return diff; +} + + +static struct rtnl_link_info_ops macsec_info_ops = { + .io_name = "macsec", + .io_alloc = macsec_alloc, + .io_parse = macsec_parse, + .io_dump = { + [NL_DUMP_LINE] = macsec_dump_line, + [NL_DUMP_DETAILS] = macsec_dump_details, + }, + .io_clone = macsec_clone, + .io_put_attrs = macsec_put_attrs, + .io_free = macsec_free, + .io_compare = macsec_compare, +}; + +static void _nl_init macsec_init(void) +{ + rtnl_link_register_info(&macsec_info_ops); +} + +static void _nl_exit macsec_exit(void) +{ + rtnl_link_unregister_info(&macsec_info_ops); +} + +/** @cond SKIP */ +#define IS_MACSEC_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &macsec_info_ops) { \ + APPBUG("Link is not a MACsec link. set type \"macsec\" first."); \ + return -NLE_OPNOTSUPP; \ + } +/** @endcond */ + +struct rtnl_link *rtnl_link_macsec_alloc(void) +{ + struct rtnl_link *link = rtnl_link_alloc(); + + if (!link) + return NULL; + + if (rtnl_link_set_type(link, "macsec") < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Set SCI + * @arg link Link object + * @arg sci Secure Channel Identifier in network byte order + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_macsec_set_sci(struct rtnl_link *link, uint64_t sci) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + info->sci = sci; + info->ce_mask |= MACSEC_ATTR_SCI; + + return 0; +} + +/** + * Get SCI + * @arg link Link object + * @arg sci On return points to the Secure Channel Identifier + * in network byte order + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_macsec_get_sci(struct rtnl_link *link, uint64_t *sci) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (!(info->ce_mask & MACSEC_ATTR_SCI)) + return -NLE_NOATTR; + + if (sci) + *sci = info->sci; + + return 0; +} + +/** + * Set port identifier + * @arg link Link object + * @arg port Port identifier in host byte order + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_macsec_set_port(struct rtnl_link *link, uint16_t port) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + info->port = port; + info->ce_mask |= MACSEC_ATTR_PORT; + + return 0; +} + +/** + * Get port identifier + * @arg link Link object + * @arg port On return points to the port identifier in host byte order + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_macsec_get_port(struct rtnl_link *link, uint16_t *port) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (!(info->ce_mask & MACSEC_ATTR_PORT)) + return -NLE_NOATTR; + + if (port) + *port = info->port; + + return 0; +} + +int rtnl_link_macsec_set_cipher_suite(struct rtnl_link *link, uint64_t cipher_suite) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + info->cipher_suite = cipher_suite; + info->ce_mask |= MACSEC_ATTR_CIPHER_SUITE; + + return 0; +} + +int rtnl_link_macsec_get_cipher_suite(struct rtnl_link *link, uint64_t *cs) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (!(info->ce_mask & MACSEC_ATTR_CIPHER_SUITE)) + return -NLE_NOATTR; + + if (cs) + *cs = info->cipher_suite; + + return 0; +} + +int rtnl_link_macsec_set_icv_len(struct rtnl_link *link, uint16_t icv_len) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (icv_len > MACSEC_STD_ICV_LEN) + return -NLE_INVAL; + + info->icv_len = icv_len; + info->ce_mask |= MACSEC_ATTR_ICV_LEN; + + return 0; +} + +int rtnl_link_macsec_get_icv_len(struct rtnl_link *link, uint16_t *icv_len) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (!(info->ce_mask & MACSEC_ATTR_ICV_LEN)) + return -NLE_NOATTR; + + if (icv_len) + *icv_len = info->icv_len; + + return 0; +} + +int rtnl_link_macsec_set_protect(struct rtnl_link *link, uint8_t protect) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (protect > 1) + return -NLE_INVAL; + + info->protect = protect; + info->ce_mask |= MACSEC_ATTR_PROTECT; + + return 0; +} + +int rtnl_link_macsec_get_protect(struct rtnl_link *link, uint8_t *protect) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (!(info->ce_mask & MACSEC_ATTR_PROTECT)) + return -NLE_NOATTR; + + if (protect) + *protect = info->protect; + + return 0; +} + +int rtnl_link_macsec_set_encrypt(struct rtnl_link *link, uint8_t encrypt) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (encrypt > 1) + return -NLE_INVAL; + + info->encrypt = encrypt; + info->ce_mask |= MACSEC_ATTR_ENCRYPT; + + return 0; +} + +int rtnl_link_macsec_get_encrypt(struct rtnl_link *link, uint8_t *encrypt) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (!(info->ce_mask & MACSEC_ATTR_ENCRYPT)) + return -NLE_NOATTR; + + if (encrypt) + *encrypt = info->encrypt; + + return 0; +} + +int rtnl_link_macsec_set_offload(struct rtnl_link *link, uint8_t offload) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + info->offload = offload; + info->ce_mask |= MACSEC_ATTR_OFFLOAD; + + return 0; +} + +int rtnl_link_macsec_get_offload(struct rtnl_link *link, uint8_t *offload) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (!(info->ce_mask & MACSEC_ATTR_OFFLOAD)) + return -NLE_NOATTR; + + if (offload) + *offload = info->offload; + + return 0; +} + +int rtnl_link_macsec_set_encoding_sa(struct rtnl_link *link, uint8_t encoding_sa) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (encoding_sa > 3) + return -NLE_INVAL; + + info->encoding_sa = encoding_sa; + info->ce_mask |= MACSEC_ATTR_ENCODING_SA; + + return 0; +} + +int rtnl_link_macsec_get_encoding_sa(struct rtnl_link *link, uint8_t *encoding_sa) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (!(info->ce_mask & MACSEC_ATTR_ENCODING_SA)) + return -NLE_NOATTR; + + if (encoding_sa) + *encoding_sa = info->encoding_sa; + + return 0; +} + +int rtnl_link_macsec_set_validation_type(struct rtnl_link *link, enum macsec_validation_type validate) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (validate > MACSEC_VALIDATE_MAX) + return -NLE_INVAL; + + info->validate = validate; + info->ce_mask |= MACSEC_ATTR_VALIDATION; + + return 0; +} + +int rtnl_link_macsec_get_validation_type(struct rtnl_link *link, enum macsec_validation_type *validate) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (!(info->ce_mask & MACSEC_ATTR_VALIDATION)) + return -NLE_NOATTR; + + if (validate) + *validate = info->validate; + + return 0; +} + +int rtnl_link_macsec_set_replay_protect(struct rtnl_link *link, uint8_t replay_protect) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (replay_protect > 1) + return -NLE_INVAL; + + info->replay_protect = replay_protect; + info->ce_mask |= MACSEC_ATTR_REPLAY_PROTECT; + + return 0; +} + +int rtnl_link_macsec_get_replay_protect(struct rtnl_link *link, uint8_t *replay_protect) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (!(info->ce_mask & MACSEC_ATTR_REPLAY_PROTECT)) + return -NLE_NOATTR; + + if (replay_protect) + *replay_protect = info->replay_protect; + + return 0; +} + +int rtnl_link_macsec_set_window(struct rtnl_link *link, uint32_t window) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + info->window = window; + info->ce_mask |= MACSEC_ATTR_WINDOW; + + return 0; +} + +int rtnl_link_macsec_get_window(struct rtnl_link *link, uint32_t *window) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (!(info->ce_mask & MACSEC_ATTR_WINDOW)) + return -NLE_NOATTR; + + if (window) + *window = info->window; + + return 0; +} + +int rtnl_link_macsec_set_send_sci(struct rtnl_link *link, uint8_t send_sci) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (send_sci > 1) + return -NLE_INVAL; + + info->send_sci = send_sci; + info->ce_mask |= MACSEC_ATTR_INC_SCI; + + return 0; +} + +int rtnl_link_macsec_get_send_sci(struct rtnl_link *link, uint8_t *send_sci) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (!(info->ce_mask & MACSEC_ATTR_INC_SCI)) + return -NLE_NOATTR; + + if (send_sci) + *send_sci = info->send_sci; + + return 0; +} + +int rtnl_link_macsec_set_end_station(struct rtnl_link *link, uint8_t end_station) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (end_station > 1) + return -NLE_INVAL; + + info->end_station = end_station; + info->ce_mask |= MACSEC_ATTR_ES; + + return 0; +} + +int rtnl_link_macsec_get_end_station(struct rtnl_link *link, uint8_t *es) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (!(info->ce_mask & MACSEC_ATTR_ES)) + return -NLE_NOATTR; + + if (es) + *es = info->end_station; + + return 0; +} + +int rtnl_link_macsec_set_scb(struct rtnl_link *link, uint8_t scb) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (scb > 1) + return -NLE_INVAL; + + info->scb = scb; + info->ce_mask |= MACSEC_ATTR_SCB; + + return 0; +} + +int rtnl_link_macsec_get_scb(struct rtnl_link *link, uint8_t *scb) +{ + struct macsec_info *info = link->l_info; + + IS_MACSEC_LINK_ASSERT(link); + + if (!(info->ce_mask & MACSEC_ATTR_SCB)) + return -NLE_NOATTR; + + if (scb) + *scb = info->scb; + + return 0; +} + +/** @} */ + +/** @} */ diff --git a/lib/route/link/macvlan.c b/lib/route/link/macvlan.c new file mode 100644 index 0000000..5452d9e --- /dev/null +++ b/lib/route/link/macvlan.c @@ -0,0 +1,875 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Michael Braun + */ + +/** + * @ingroup link + * @defgroup macvlan MACVLAN/MACVTAP + * MAC-based Virtual LAN link module + * + * @details + * \b Link Type Name: "macvlan" + * + * @route_doc{link_macvlan, MACVLAN Documentation} + * @route_doc{link_macvtap, MACVTAP Documentation} + * + * @{ + */ + +#include "nl-default.h" + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "nl-route.h" +#include "link-api.h" + +/** @cond SKIP */ +#define MACVLAN_HAS_MODE (1<<0) +#define MACVLAN_HAS_FLAGS (1<<1) +#define MACVLAN_HAS_MACADDR (1<<2) + +struct macvlan_info +{ + uint32_t mvi_mode; + uint16_t mvi_flags; // there currently is only one flag and kernel has no flags_mask yet + uint32_t mvi_mask; + uint32_t mvi_maccount; + uint32_t mvi_macmode; + struct nl_addr **mvi_macaddr; +}; + +/** @endcond */ + +static struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX+1] = { + [IFLA_MACVLAN_MODE] = { .type = NLA_U32 }, + [IFLA_MACVLAN_FLAGS] = { .type = NLA_U16 }, + [IFLA_MACVLAN_MACADDR_MODE] = { .type = NLA_U32 }, + [IFLA_MACVLAN_MACADDR] = { .type = NLA_UNSPEC }, + [IFLA_MACVLAN_MACADDR_DATA] = { .type = NLA_NESTED }, + [IFLA_MACVLAN_MACADDR_COUNT] = { .type = NLA_U32 }, +}; + +static int macvlan_alloc(struct rtnl_link *link) +{ + struct macvlan_info *mvi; + uint32_t i; + + if (link->l_info) { + mvi = link->l_info; + for (i = 0; i < mvi->mvi_maccount; i++) + nl_addr_put(mvi->mvi_macaddr[i]); + free(mvi->mvi_macaddr); + memset(mvi, 0, sizeof(*mvi)); + } else { + if ((mvi = calloc(1, sizeof(*mvi))) == NULL) + return -NLE_NOMEM; + + link->l_info = mvi; + } + mvi->mvi_macmode = MACVLAN_MACADDR_SET; + + return 0; +} + +static int macvlan_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_MACVLAN_MAX+1]; + struct macvlan_info *mvi; + struct nlattr *nla; + int len; + int err; + + NL_DBG(3, "Parsing %s link info", link->l_info_ops->io_name); + + if ((err = nla_parse_nested(tb, IFLA_MACVLAN_MAX, data, macvlan_policy)) < 0) + goto errout; + + if ((err = macvlan_alloc(link)) < 0) + goto errout; + + mvi = link->l_info; + + if (tb[IFLA_MACVLAN_MODE]) { + mvi->mvi_mode = nla_get_u32(tb[IFLA_MACVLAN_MODE]); + mvi->mvi_mask |= MACVLAN_HAS_MODE; + } + + if (tb[IFLA_MACVLAN_FLAGS]) { + mvi->mvi_flags = nla_get_u16(tb[IFLA_MACVLAN_FLAGS]); + mvi->mvi_mask |= MACVLAN_HAS_FLAGS; + } + + if ( tb[IFLA_MACVLAN_MACADDR_COUNT] + && tb[IFLA_MACVLAN_MACADDR_DATA]) { + mvi->mvi_maccount = nla_get_u32(tb[IFLA_MACVLAN_MACADDR_COUNT]); + if (mvi->mvi_maccount > 0) { + uint32_t i; + + nla = nla_data(tb[IFLA_MACVLAN_MACADDR_DATA]); + len = nla_len(tb[IFLA_MACVLAN_MACADDR_DATA]); + + mvi->mvi_macaddr = calloc(mvi->mvi_maccount, + sizeof(*(mvi->mvi_macaddr))); + if (mvi->mvi_macaddr == NULL) { + err = -NLE_NOMEM; + goto errout; + } + + i = 0; + for (; nla_ok(nla, len); nla = nla_next(nla, &len)) { + if (i >= mvi->mvi_maccount) + break; + if (nla_type(nla) != IFLA_MACVLAN_MACADDR || + nla_len(nla) < ETH_ALEN) + continue; + mvi->mvi_macaddr[i] = nl_addr_alloc_attr(nla, AF_LLC); + i++; + } + } + mvi->mvi_mask |= MACVLAN_HAS_MACADDR; + } + + err = 0; +errout: + return err; +} + +static void macvlan_free(struct rtnl_link *link) +{ + struct macvlan_info *mvi; + uint32_t i; + + mvi = link->l_info; + if (!mvi) + return; + + for (i = 0; i < mvi->mvi_maccount; i++) + nl_addr_put(mvi->mvi_macaddr[i]); + free(mvi->mvi_macaddr); + free(mvi); + + link->l_info = NULL; +} + +static void macvlan_dump_details(struct rtnl_link *link, struct nl_dump_params *p) +{ + char buf[64]; + uint32_t i; + struct macvlan_info *mvi = link->l_info; + + if (mvi->mvi_mask & MACVLAN_HAS_MODE) { + rtnl_link_macvlan_mode2str(mvi->mvi_mode, buf, sizeof(buf)); + nl_dump(p, " %s-mode %s", link->l_info_ops->io_name, buf); + } + + if (mvi->mvi_mask & MACVLAN_HAS_FLAGS) { + rtnl_link_macvlan_flags2str(mvi->mvi_flags, buf, sizeof(buf)); + nl_dump(p, " %s-flags %s", link->l_info_ops->io_name, buf); + } + + if (mvi->mvi_mask & MACVLAN_HAS_MACADDR) { + nl_dump(p, " macvlan-count %u", (unsigned) mvi->mvi_maccount); + + if (mvi->mvi_maccount) + nl_dump(p, " macvlan-sourcemac"); + + for (i = 0; i < mvi->mvi_maccount; i++) { + nl_dump(p, " %s", nl_addr2str(mvi->mvi_macaddr[i], buf, + sizeof(buf))); + } + } + nl_dump(p, "\n"); +} + +static int macvlan_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct macvlan_info *vdst, *vsrc = src->l_info; + int err; + uint32_t i; + + dst->l_info = NULL; + if ((err = rtnl_link_set_type(dst, "macvlan")) < 0) + return err; + vdst = dst->l_info; + + if (!vdst || !vsrc) + return -NLE_NOMEM; + + memcpy(vdst, vsrc, sizeof(struct macvlan_info)); + + if ( vsrc->mvi_mask & MACVLAN_HAS_MACADDR + && vsrc->mvi_maccount > 0) { + vdst->mvi_macaddr = calloc(vdst->mvi_maccount, + sizeof(*(vdst->mvi_macaddr))); + for (i = 0; i < vdst->mvi_maccount; i++) + vdst->mvi_macaddr[i] = nl_addr_clone(vsrc->mvi_macaddr[i]); + } else + vdst->mvi_macaddr = NULL; + + return 0; +} + +static int macvlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct macvlan_info *mvi = link->l_info; + struct nlattr *data, *datamac = NULL; + int i, ret; + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + return -NLE_MSGSIZE; + + ret = -NLE_NOMEM; + + if (mvi->mvi_mask & MACVLAN_HAS_MODE) + NLA_PUT_U32(msg, IFLA_MACVLAN_MODE, mvi->mvi_mode); + + if (mvi->mvi_mask & MACVLAN_HAS_FLAGS) + NLA_PUT_U16(msg, IFLA_MACVLAN_FLAGS, mvi->mvi_flags); + + if (mvi->mvi_mask & MACVLAN_HAS_MACADDR) { + NLA_PUT_U32(msg, IFLA_MACVLAN_MACADDR_MODE, mvi->mvi_macmode); + datamac = nla_nest_start(msg, IFLA_MACVLAN_MACADDR_DATA); + if (!datamac) + goto nla_put_failure; + + for (i = 0; i < mvi->mvi_maccount; i++) { + NLA_PUT_ADDR(msg, IFLA_MACVLAN_MACADDR, + mvi->mvi_macaddr[i]); + } + } + + ret = 0; + +nla_put_failure: + if (datamac) + nla_nest_end(msg, datamac); + + nla_nest_end(msg, data); + + return ret; +} + +static struct rtnl_link_info_ops macvlan_info_ops = { + .io_name = "macvlan", + .io_alloc = macvlan_alloc, + .io_parse = macvlan_parse, + .io_dump = { + [NL_DUMP_DETAILS] = macvlan_dump_details, + }, + .io_clone = macvlan_clone, + .io_put_attrs = macvlan_put_attrs, + .io_free = macvlan_free, +}; + +static struct rtnl_link_info_ops macvtap_info_ops = { + .io_name = "macvtap", + .io_alloc = macvlan_alloc, + .io_parse = macvlan_parse, + .io_dump = { + [NL_DUMP_DETAILS] = macvlan_dump_details, + }, + .io_clone = macvlan_clone, + .io_put_attrs = macvlan_put_attrs, + .io_free = macvlan_free, +}; + +/** @cond SKIP */ +#define IS_MACVLAN_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &macvlan_info_ops) { \ + APPBUG("Link is not a macvlan link. set type \"macvlan\" first."); \ + return -NLE_OPNOTSUPP; \ + } + +#define IS_MACVTAP_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &macvtap_info_ops) { \ + APPBUG("Link is not a macvtap link. set type \"macvtap\" first."); \ + return -NLE_OPNOTSUPP; \ + } +/** @endcond */ + +/** + * @name MACVLAN Object + * @{ + */ + +/** + * Allocate link object of type MACVLAN + * + * @return Allocated link object or NULL. + */ +struct rtnl_link *rtnl_link_macvlan_alloc(void) +{ + struct rtnl_link *link; + + if (!(link = rtnl_link_alloc())) + return NULL; + + if (rtnl_link_set_type(link, "macvlan") < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if link is a MACVLAN link + * @arg link Link object + * + * @return True if link is a MACVLAN link, otherwise false is returned. + */ +int rtnl_link_is_macvlan(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "macvlan"); +} + +/** + * Set MACVLAN MODE + * @arg link Link object + * @arg mode MACVLAN mode + * + * @return 0 on success or a negative error code + */ +int rtnl_link_macvlan_set_mode(struct rtnl_link *link, uint32_t mode) +{ + struct macvlan_info *mvi = link->l_info; + int i; + + IS_MACVLAN_LINK_ASSERT(link); + + mvi->mvi_mode = mode; + mvi->mvi_mask |= MACVLAN_HAS_MODE; + + if (mode != MACVLAN_MODE_SOURCE) { + for (i = 0; i < mvi->mvi_maccount; i++) + nl_addr_put(mvi->mvi_macaddr[i]); + free(mvi->mvi_macaddr); + mvi->mvi_maccount = 0; + mvi->mvi_macaddr = NULL; + mvi->mvi_macmode = MACVLAN_MACADDR_SET; + mvi->mvi_mask &= ~MACVLAN_HAS_MACADDR; + } + + return 0; +} + +/** + * Get MACVLAN Mode + * @arg link Link object + * + * @return MACVLAN mode, 0 if not set or a negative error code. + */ +uint32_t rtnl_link_macvlan_get_mode(struct rtnl_link *link) +{ + struct macvlan_info *mvi = link->l_info; + + IS_MACVLAN_LINK_ASSERT(link); + + if (mvi->mvi_mask & MACVLAN_HAS_MODE) + return mvi->mvi_mode; + else + return 0; +} + +/** + * Set MACVLAN MACMODE + * @arg link Link object + * @arg mode MACVLAN mac list modification mode + * + * Only for macvlan SOURCE mode. + * + * @return 0 on success or a negative error code + */ +int rtnl_link_macvlan_set_macmode(struct rtnl_link *link, uint32_t macmode) +{ + struct macvlan_info *mvi = link->l_info; + + IS_MACVLAN_LINK_ASSERT(link); + + if (!(mvi->mvi_mask & MACVLAN_HAS_MODE) || + (mvi->mvi_mode != MACVLAN_MODE_SOURCE)) + return -NLE_INVAL; + + mvi->mvi_macmode = macmode; + mvi->mvi_mask |= MACVLAN_HAS_MACADDR; + + return 0; +} + +/** + * Get MACVLAN MACMODE + * @arg link Link object + * @arg out_macmode mac list modification mode + * + * Only for SOURCE mode. + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_macvlan_get_macmode(struct rtnl_link *link, uint32_t *out_macmode) +{ + struct macvlan_info *mvi = link->l_info; + + IS_MACVLAN_LINK_ASSERT(link); + + if (!(mvi->mvi_mask & MACVLAN_HAS_MODE) || + (mvi->mvi_mode != MACVLAN_MODE_SOURCE)) + return -NLE_INVAL; + + if (!(mvi->mvi_mask & MACVLAN_HAS_MACADDR)) + return -NLE_INVAL; + + *out_macmode = mvi->mvi_macmode; + + return 0; +} + +/** + * Set MACVLAN flags + * @arg link Link object + * @arg flags MACVLAN flags + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_macvlan_set_flags(struct rtnl_link *link, uint16_t flags) +{ + struct macvlan_info *mvi = link->l_info; + + IS_MACVLAN_LINK_ASSERT(link); + + mvi->mvi_flags |= flags; + mvi->mvi_mask |= MACVLAN_HAS_FLAGS; + + return 0; +} + +/** + * Unset MACVLAN flags + * @arg link Link object + * @arg flags MACVLAN flags + * + * Note: kernel currently only has a single flag and lacks flags_mask to + * indicate which flags shall be changed (it always all). + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_macvlan_unset_flags(struct rtnl_link *link, uint16_t flags) +{ + struct macvlan_info *mvi = link->l_info; + + IS_MACVLAN_LINK_ASSERT(link); + + mvi->mvi_flags &= ~flags; + mvi->mvi_mask |= MACVLAN_HAS_FLAGS; + + return 0; +} + +/** + * Get MACVLAN flags + * @arg link Link object + * + * @return MACVLAN flags, 0 if none set, or a negative error code. + */ +uint16_t rtnl_link_macvlan_get_flags(struct rtnl_link *link) +{ + struct macvlan_info *mvi = link->l_info; + + IS_MACVLAN_LINK_ASSERT(link); + + return mvi->mvi_flags; +} + +/** + * Get number of MAC-Addr for MACVLAN device in source mode + * @arg link Link object + * @arg out_count number of mac addresses + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_macvlan_count_macaddr(struct rtnl_link *link, uint32_t *out_count) +{ + struct macvlan_info *mvi = link->l_info; + + IS_MACVLAN_LINK_ASSERT(link); + + if (!(mvi->mvi_mask & MACVLAN_HAS_MODE) || + (mvi->mvi_mode != MACVLAN_MODE_SOURCE)) + return -NLE_INVAL; + + if (!(mvi->mvi_mask & MACVLAN_HAS_MACADDR)) + return -NLE_INVAL; + + *out_count = mvi->mvi_maccount; + + return 0; +} + +/** + * Get configured remote MAC-Addr from MACVLAN device in source mode + * @arg link Link object + * @arg out_addr address object + * + * The returned nl_addr struct needs NOT to be released using nl_addr_put. + * It is only valid until the address is not removed from this link object + * or its mode is changed to non-source. + * + * @return 0 on success or negative error code + */ +int rtnl_link_macvlan_get_macaddr(struct rtnl_link *link, uint32_t idx, + const struct nl_addr **out_addr) +{ + struct macvlan_info *mvi = link->l_info; + + IS_MACVLAN_LINK_ASSERT(link); + + if (!(mvi->mvi_mask & MACVLAN_HAS_MODE) || + (mvi->mvi_mode != MACVLAN_MODE_SOURCE)) + return -NLE_INVAL; + + if (!(mvi->mvi_mask & MACVLAN_HAS_MACADDR)) + return -NLE_INVAL; + + if (idx >= mvi->mvi_maccount) + return -NLE_INVAL; + + *out_addr = mvi->mvi_macaddr[idx]; + return 0; +} + +/** + * Add MAC-Addr to MACVLAN device in source mode + * @arg link Link object + * @arg addr MAC-Addr + * + * addr is not release but cloned by this method. + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_macvlan_add_macaddr(struct rtnl_link *link, struct nl_addr *addr) +{ + struct macvlan_info *mvi = link->l_info; + struct nl_addr **mvi_macaddr; + size_t newsize; + + IS_MACVLAN_LINK_ASSERT(link); + + if (nl_addr_get_family(addr) != AF_LLC) + return -NLE_INVAL; + + if (!(mvi->mvi_mask & MACVLAN_HAS_MODE) || + (mvi->mvi_mode != MACVLAN_MODE_SOURCE)) + return -NLE_INVAL; + + if (!(mvi->mvi_mask & MACVLAN_HAS_MACADDR)) + return -NLE_INVAL; + + if (mvi->mvi_maccount >= UINT32_MAX) + return -NLE_INVAL; + + newsize = (mvi->mvi_maccount + 1) * sizeof(*(mvi->mvi_macaddr)); + mvi_macaddr = realloc(mvi->mvi_macaddr, newsize); + if (!mvi_macaddr) + return -NLE_NOMEM; + + mvi->mvi_macaddr = mvi_macaddr; + mvi->mvi_macaddr[mvi->mvi_maccount] = nl_addr_clone(addr); + mvi->mvi_maccount++; + + mvi->mvi_mask |= MACVLAN_HAS_MACADDR; + + return 0; +} + +/** + * Remove MAC-Addr from MACVLAN device in source mode + * @arg link Link object + * @arg addr MAC-Addr + * + * addr is not release by this method. + * + * @return a negative error code on failure, or the number + * of deleted addresses on success. + */ +int rtnl_link_macvlan_del_macaddr(struct rtnl_link *link, struct nl_addr *addr) +{ + struct macvlan_info *mvi = link->l_info; + uint32_t found, i; + + IS_MACVLAN_LINK_ASSERT(link); + + if (nl_addr_get_family(addr) != AF_LLC) + return -NLE_INVAL; + + if (!(mvi->mvi_mask & MACVLAN_HAS_MODE) || + (mvi->mvi_mode != MACVLAN_MODE_SOURCE)) + return -NLE_INVAL; + + if (!(mvi->mvi_mask & MACVLAN_HAS_MACADDR)) + return -NLE_INVAL; + + nl_addr_get(addr); + + found = 0; i = 0; + while (i + found < mvi->mvi_maccount) { + mvi->mvi_macaddr[i] = mvi->mvi_macaddr[i + found]; + if (found > 0) + mvi->mvi_macaddr[i + found] = NULL; + if (nl_addr_cmp(addr, mvi->mvi_macaddr[i]) == 0) { + nl_addr_put(mvi->mvi_macaddr[i]); + mvi->mvi_macaddr[i] = NULL; + found++; + } else + i++; + } + + nl_addr_put(addr); + + mvi->mvi_maccount -= found; + + return found > INT_MAX ? INT_MAX : (int) found; +} + +/** @} */ + + +/** + * @name MACVTAP Object + * @{ + */ + +/** + * Allocate link object of type MACVTAP + * + * @return Allocated link object or NULL. + */ +struct rtnl_link *rtnl_link_macvtap_alloc(void) +{ + struct rtnl_link *link; + + if (!(link = rtnl_link_alloc())) + return NULL; + + if (rtnl_link_set_type(link, "macvtap") < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if link is a MACVTAP link + * @arg link Link object + * + * @return True if link is a MACVTAP link, otherwise false is returned. + */ +int rtnl_link_is_macvtap(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "macvtap"); +} + +/** + * Set MACVTAP MODE + * @arg link Link object + * @arg mode MACVTAP mode + * + * @return 0 on success or a negative error code + */ +int rtnl_link_macvtap_set_mode(struct rtnl_link *link, uint32_t mode) +{ + struct macvlan_info *mvi = link->l_info; + + IS_MACVTAP_LINK_ASSERT(link); + + mvi->mvi_mode = mode; + mvi->mvi_mask |= MACVLAN_HAS_MODE; + + return 0; +} + +/** + * Get MACVTAP Mode + * @arg link Link object + * + * @return MACVTAP mode, 0 if not set or a negative error code. + */ +uint32_t rtnl_link_macvtap_get_mode(struct rtnl_link *link) +{ + struct macvlan_info *mvi = link->l_info; + + IS_MACVTAP_LINK_ASSERT(link); + + if (mvi->mvi_mask & MACVLAN_HAS_MODE) + return mvi->mvi_mode; + else + return 0; +} + +/** + * Set MACVTAP flags + * @arg link Link object + * @arg flags MACVTAP flags + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_macvtap_set_flags(struct rtnl_link *link, uint16_t flags) +{ + struct macvlan_info *mvi = link->l_info; + + IS_MACVTAP_LINK_ASSERT(link); + + mvi->mvi_flags |= flags; + mvi->mvi_mask |= MACVLAN_HAS_FLAGS; + + return 0; +} + +/** + * Unset MACVTAP flags + * @arg link Link object + * @arg flags MACVTAP flags + * + * Note: kernel currently only has a single flag and lacks flags_mask to + * indicate which flags shall be changed (it always all). + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_macvtap_unset_flags(struct rtnl_link *link, uint16_t flags) +{ + struct macvlan_info *mvi = link->l_info; + + IS_MACVTAP_LINK_ASSERT(link); + + mvi->mvi_flags &= ~flags; + mvi->mvi_mask |= MACVLAN_HAS_FLAGS; + + return 0; +} + +/** + * Get MACVTAP flags + * @arg link Link object + * + * @return MACVTAP flags, 0 if none set, or a negative error code. + */ +uint16_t rtnl_link_macvtap_get_flags(struct rtnl_link *link) +{ + struct macvlan_info *mvi = link->l_info; + + IS_MACVTAP_LINK_ASSERT(link); + + return mvi->mvi_flags; +} + +/** @} */ + + +static const struct trans_tbl macvlan_flags[] = { + __ADD(MACVLAN_FLAG_NOPROMISC, nopromisc), +}; + +static const struct trans_tbl macvlan_modes[] = { + __ADD(MACVLAN_MODE_PRIVATE, private), + __ADD(MACVLAN_MODE_VEPA, vepa), + __ADD(MACVLAN_MODE_BRIDGE, bridge), + __ADD(MACVLAN_MODE_PASSTHRU, passthru), + __ADD(MACVLAN_MODE_SOURCE, source), +}; + +static const struct trans_tbl macvlan_macmodes[] = { + __ADD(MACVLAN_MACADDR_ADD, "add"), + __ADD(MACVLAN_MACADDR_DEL, "del"), + __ADD(MACVLAN_MACADDR_SET, "set"), + __ADD(MACVLAN_MACADDR_FLUSH, "flush"), +}; + +/** + * @name Flag Translation + * @{ + */ + +char *rtnl_link_macvlan_flags2str(int flags, char *buf, size_t len) +{ + return __flags2str(flags, buf, len, macvlan_flags, ARRAY_SIZE(macvlan_flags)); +} + +int rtnl_link_macvlan_str2flags(const char *name) +{ + return __str2flags(name, macvlan_flags, ARRAY_SIZE(macvlan_flags)); +} + +char *rtnl_link_macvtap_flags2str(int flags, char *buf, size_t len) +{ + return __flags2str(flags, buf, len, macvlan_flags, ARRAY_SIZE(macvlan_flags)); +} + +int rtnl_link_macvtap_str2flags(const char *name) +{ + return __str2flags(name, macvlan_flags, ARRAY_SIZE(macvlan_flags)); +} + +/** @} */ + +/** + * @name Mode Translation + * @{ + */ + +char *rtnl_link_macvlan_mode2str(int mode, char *buf, size_t len) +{ + return __type2str(mode, buf, len, macvlan_modes, ARRAY_SIZE(macvlan_modes)); +} + +int rtnl_link_macvlan_str2mode(const char *name) +{ + return __str2type(name, macvlan_modes, ARRAY_SIZE(macvlan_modes)); +} + +char *rtnl_link_macvlan_macmode2str(int mode, char *buf, size_t len) +{ + return __type2str(mode, buf, len, macvlan_macmodes, + ARRAY_SIZE(macvlan_macmodes)); +} + +int rtnl_link_macvlan_str2macmode(const char *name) +{ + return __str2type(name, macvlan_macmodes, ARRAY_SIZE(macvlan_macmodes)); +} + +char *rtnl_link_macvtap_mode2str(int mode, char *buf, size_t len) +{ + return __type2str(mode, buf, len, macvlan_modes, ARRAY_SIZE(macvlan_modes)); +} + +int rtnl_link_macvtap_str2mode(const char *name) +{ + return __str2type(name, macvlan_modes, ARRAY_SIZE(macvlan_modes)); +} + +/** @} */ + +static void _nl_init macvlan_init(void) +{ + rtnl_link_register_info(&macvlan_info_ops); + rtnl_link_register_info(&macvtap_info_ops); +} + +static void _nl_exit macvlan_exit(void) +{ + rtnl_link_unregister_info(&macvlan_info_ops); + rtnl_link_unregister_info(&macvtap_info_ops); +} + +/** @} */ diff --git a/lib/route/link/ppp.c b/lib/route/link/ppp.c new file mode 100644 index 0000000..34ca5f6 --- /dev/null +++ b/lib/route/link/ppp.c @@ -0,0 +1,219 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2016 Jonas Johansson + */ + +/** + * @ingroup link + * @defgroup ppp PPP + * + * @details + * \b Link Type Name: "ppp" + * + * @route_doc{link_ppp, PPP Documentation} + * @{ + */ + +#include "nl-default.h" + +#include +#include + +#include "nl-route.h" +#include "link-api.h" + +/** @cond SKIP */ +#define PPP_ATTR_FD (1<<0) + +struct ppp_info +{ + int32_t pi_fd; + uint32_t ce_mask; +}; + +/** @endcond */ + +static struct nla_policy ppp_nl_policy[IFLA_PPP_MAX+1] = { + [IFLA_PPP_DEV_FD] = { .type = NLA_S32 }, +}; + +static int ppp_alloc(struct rtnl_link *link) +{ + struct ppp_info *info; + + if (link->l_info) + memset(link->l_info, 0, sizeof(*info)); + else { + if ((info = calloc(1, sizeof(*info))) == NULL) + return -NLE_NOMEM; + + link->l_info = info; + } + + return 0; +} + +static int ppp_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_PPP_MAX+1]; + struct ppp_info *info; + int err; + + NL_DBG(3, "Parsing PPP link info\n"); + + if ((err = nla_parse_nested(tb, IFLA_PPP_MAX, data, ppp_nl_policy)) < 0) + goto errout; + + if ((err = ppp_alloc(link)) < 0) + goto errout; + + info = link->l_info; + + if (tb[IFLA_PPP_DEV_FD]) { + info->pi_fd = nla_get_s32(tb[IFLA_PPP_DEV_FD]); + info->ce_mask |= PPP_ATTR_FD; + } + + err = 0; +errout: + return err; +} + +static void ppp_free(struct rtnl_link *link) +{ + free(link->l_info); + link->l_info = NULL; +} + +static int ppp_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct ppp_info *vdst, *vsrc = src->l_info; + int err; + + dst->l_info = NULL; + if ((err = rtnl_link_set_type(dst, "ppp")) < 0) + return err; + vdst = dst->l_info; + + if (!vdst || !vsrc) + return -NLE_NOMEM; + + memcpy(vdst, vsrc, sizeof(struct ppp_info)); + + return 0; +} + +static int ppp_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct ppp_info *info = link->l_info; + struct nlattr *data; + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + return -NLE_MSGSIZE; + + if (info->ce_mask & PPP_ATTR_FD) + NLA_PUT_S32(msg, IFLA_PPP_DEV_FD, info->pi_fd); + + nla_nest_end(msg, data); + +nla_put_failure: + + return 0; +} + +static struct rtnl_link_info_ops ppp_info_ops = { + .io_name = "ppp", + .io_alloc = ppp_alloc, + .io_parse = ppp_parse, + .io_clone = ppp_clone, + .io_put_attrs = ppp_put_attrs, + .io_free = ppp_free, +}; + +/** @cond SKIP */ +#define IS_PPP_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &ppp_info_ops) { \ + APPBUG("Link is not a PPP link. set type \"ppp\" first."); \ + return -NLE_OPNOTSUPP; \ + } +/** @endcond */ + +/** + * @name PPP Object + * @{ + */ + +/** + * Allocate link object of type PPP + * + * @return Allocated link object or NULL. + */ +struct rtnl_link *rtnl_link_ppp_alloc(void) +{ + struct rtnl_link *link; + + if (!(link = rtnl_link_alloc())) + return NULL; + + if (rtnl_link_set_type(link, "ppp") < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Set PPP file descriptor + * @arg link Link object + * @arg flags PPP file descriptor + * + * @return 0 on success or a negative error code. + */ +int rtnl_link_ppp_set_fd(struct rtnl_link *link, int32_t fd) +{ + struct ppp_info *info = link->l_info; + + IS_PPP_LINK_ASSERT(link); + + info->pi_fd |= fd; + info->ce_mask |= PPP_ATTR_FD; + + return 0; +} + +/** + * Get PPP file descriptor + * @arg link Link object + * + * @return PPP file descriptor, 0 if not set or a negative error code. + */ +int rtnl_link_ppp_get_fd(struct rtnl_link *link, int32_t *fd) +{ + struct ppp_info *info = link->l_info; + + IS_PPP_LINK_ASSERT(link); + + if (!(info->ce_mask & PPP_ATTR_FD)) + return -NLE_NOATTR; + + if (fd) + *fd = info->pi_fd; + + return 0; +} + +/** @} */ + +static void _nl_init ppp_init(void) +{ + rtnl_link_register_info(&ppp_info_ops); +} + +static void _nl_exit ppp_exit(void) +{ + rtnl_link_unregister_info(&ppp_info_ops); +} + +/** @} */ diff --git a/lib/route/link/sit.c b/lib/route/link/sit.c new file mode 100644 index 0000000..69dd316 --- /dev/null +++ b/lib/route/link/sit.c @@ -0,0 +1,873 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2014 Susant Sahani + */ + +/** + * @ingroup link + * @defgroup sit SIT + * sit link module + * + * @details + * \b Link Type Name: "sit" + * + * @route_doc{link_sit, SIT Documentation} + * + * @{ + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "nl-route.h" +#include "link-api.h" + +#define SIT_ATTR_LINK (1 << 0) +#define SIT_ATTR_LOCAL (1 << 1) +#define SIT_ATTR_REMOTE (1 << 2) +#define SIT_ATTR_TTL (1 << 3) +#define SIT_ATTR_TOS (1 << 4) +#define SIT_ATTR_PMTUDISC (1 << 5) +#define SIT_ATTR_FLAGS (1 << 6) +#define SIT_ATTR_PROTO (1 << 7) +#define SIT_ATTR_6RD_PREFIX (1 << 8) +#define SIT_ATTR_6RD_RELAY_PREFIX (1 << 9) +#define SIT_ATTR_6RD_PREFIXLEN (1 << 10) +#define SIT_ATTR_6RD_RELAY_PREFIXLEN (1 << 11) +#define SIT_ATTR_FWMARK (1 << 12) + +struct sit_info +{ + uint8_t ttl; + uint8_t tos; + uint8_t pmtudisc; + uint8_t proto; + uint16_t flags; + uint32_t link; + uint32_t local; + uint32_t remote; + struct in6_addr ip6rd_prefix; + uint32_t ip6rd_relay_prefix; + uint16_t ip6rd_prefixlen; + uint16_t ip6rd_relay_prefixlen; + uint32_t fwmark; + uint32_t sit_mask; +}; + +static struct nla_policy sit_policy[IFLA_IPTUN_MAX + 1] = { + [IFLA_IPTUN_LINK] = { .type = NLA_U32 }, + [IFLA_IPTUN_LOCAL] = { .type = NLA_U32 }, + [IFLA_IPTUN_REMOTE] = { .type = NLA_U32 }, + [IFLA_IPTUN_TTL] = { .type = NLA_U8 }, + [IFLA_IPTUN_TOS] = { .type = NLA_U8 }, + [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 }, + [IFLA_IPTUN_FLAGS] = { .type = NLA_U16 }, + [IFLA_IPTUN_PROTO] = { .type = NLA_U8 }, + [IFLA_IPTUN_6RD_PREFIX] = { .minlen = sizeof(struct in6_addr) }, + [IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NLA_U32 }, + [IFLA_IPTUN_6RD_PREFIXLEN] = { .type = NLA_U16 }, + [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NLA_U16 }, + [IFLA_IPTUN_FWMARK] = { .type = NLA_U32 }, +}; + +static int sit_alloc(struct rtnl_link *link) +{ + struct sit_info *sit; + + if (link->l_info) + memset(link->l_info, 0, sizeof(*sit)); + else { + sit = calloc(1, sizeof(*sit)); + if (!sit) + return -NLE_NOMEM; + + link->l_info = sit; + } + + return 0; +} + +static int sit_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_IPTUN_MAX + 1]; + struct sit_info *sit; + int err; + + NL_DBG(3, "Parsing SIT link info\n"); + + err = nla_parse_nested(tb, IFLA_IPTUN_MAX, data, sit_policy); + if (err < 0) + goto errout; + + err = sit_alloc(link); + if (err < 0) + goto errout; + + sit = link->l_info; + + if (tb[IFLA_IPTUN_LINK]) { + sit->link = nla_get_u32(tb[IFLA_IPTUN_LINK]); + sit->sit_mask |= SIT_ATTR_LINK; + } + + if (tb[IFLA_IPTUN_LOCAL]) { + sit->local = nla_get_u32(tb[IFLA_IPTUN_LOCAL]); + sit->sit_mask |= SIT_ATTR_LOCAL; + } + + if (tb[IFLA_IPTUN_REMOTE]) { + sit->remote = nla_get_u32(tb[IFLA_IPTUN_REMOTE]); + sit->sit_mask |= SIT_ATTR_REMOTE; + } + + if (tb[IFLA_IPTUN_TTL]) { + sit->ttl = nla_get_u8(tb[IFLA_IPTUN_TTL]); + sit->sit_mask |= SIT_ATTR_TTL; + } + + if (tb[IFLA_IPTUN_TOS]) { + sit->tos = nla_get_u8(tb[IFLA_IPTUN_TOS]); + sit->sit_mask |= SIT_ATTR_TOS; + } + + if (tb[IFLA_IPTUN_PMTUDISC]) { + sit->pmtudisc = nla_get_u8(tb[IFLA_IPTUN_PMTUDISC]); + sit->sit_mask |= SIT_ATTR_PMTUDISC; + } + + if (tb[IFLA_IPTUN_FLAGS]) { + sit->flags = nla_get_u16(tb[IFLA_IPTUN_FLAGS]); + sit->sit_mask |= SIT_ATTR_FLAGS; + } + + if (tb[IFLA_IPTUN_PROTO]) { + sit->proto = nla_get_u8(tb[IFLA_IPTUN_PROTO]); + sit->sit_mask |= SIT_ATTR_PROTO; + } + + if (tb[IFLA_IPTUN_6RD_PREFIX]) { + nla_memcpy(&sit->ip6rd_prefix, tb[IFLA_IPTUN_6RD_PREFIX], + sizeof(struct in6_addr)); + sit->sit_mask |= SIT_ATTR_6RD_PREFIX; + } + + if (tb[IFLA_IPTUN_6RD_RELAY_PREFIX]) { + sit->ip6rd_relay_prefix = nla_get_u32(tb[IFLA_IPTUN_6RD_RELAY_PREFIX]); + sit->sit_mask |= SIT_ATTR_6RD_RELAY_PREFIX; + } + + if (tb[IFLA_IPTUN_6RD_PREFIXLEN]) { + sit->ip6rd_prefixlen = nla_get_u16(tb[IFLA_IPTUN_6RD_PREFIXLEN]); + sit->sit_mask |= SIT_ATTR_6RD_PREFIXLEN; + } + + if (tb[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]) { + sit->ip6rd_relay_prefixlen = nla_get_u16(tb[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]); + sit->sit_mask |= SIT_ATTR_6RD_RELAY_PREFIXLEN; + } + + if (tb[IFLA_IPTUN_FWMARK]) { + sit->fwmark = nla_get_u32(tb[IFLA_IPTUN_FWMARK]); + sit->sit_mask |= SIT_ATTR_FWMARK; + } + + err = 0; + +errout: + return err; +} + +static int sit_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct sit_info *sit = link->l_info; + struct nlattr *data; + + data = nla_nest_start(msg, IFLA_INFO_DATA); + if (!data) + return -NLE_MSGSIZE; + + if (sit->sit_mask & SIT_ATTR_LINK) + NLA_PUT_U32(msg, IFLA_IPTUN_LINK, sit->link); + + if (sit->sit_mask & SIT_ATTR_LOCAL) + NLA_PUT_U32(msg, IFLA_IPTUN_LOCAL, sit->local); + + if (sit->sit_mask & SIT_ATTR_REMOTE) + NLA_PUT_U32(msg, IFLA_IPTUN_REMOTE, sit->remote); + + if (sit->sit_mask & SIT_ATTR_TTL) + NLA_PUT_U8(msg, IFLA_IPTUN_TTL, sit->ttl); + + if (sit->sit_mask & SIT_ATTR_TOS) + NLA_PUT_U8(msg, IFLA_IPTUN_TOS, sit->tos); + + if (sit->sit_mask & SIT_ATTR_PMTUDISC) + NLA_PUT_U8(msg, IFLA_IPTUN_PMTUDISC, sit->pmtudisc); + + if (sit->sit_mask & SIT_ATTR_FLAGS) + NLA_PUT_U16(msg, IFLA_IPTUN_FLAGS, sit->flags); + + if (sit->sit_mask & SIT_ATTR_PROTO) + NLA_PUT_U8(msg, IFLA_IPTUN_PROTO, sit->proto); + + if (sit->sit_mask & SIT_ATTR_6RD_PREFIX) + NLA_PUT(msg, IFLA_IPTUN_6RD_PREFIX, sizeof(struct in6_addr), &sit->ip6rd_prefix); + + if (sit->sit_mask & SIT_ATTR_6RD_RELAY_PREFIX) + NLA_PUT_U32(msg, IFLA_IPTUN_6RD_RELAY_PREFIX, sit->ip6rd_relay_prefix); + + if (sit->sit_mask & SIT_ATTR_6RD_PREFIXLEN) + NLA_PUT_U16(msg, IFLA_IPTUN_6RD_PREFIXLEN, sit->ip6rd_prefixlen); + + if (sit->sit_mask & SIT_ATTR_6RD_RELAY_PREFIXLEN) + NLA_PUT_U16(msg, IFLA_IPTUN_6RD_RELAY_PREFIXLEN, sit->ip6rd_relay_prefixlen); + + if (sit->sit_mask & SIT_ATTR_FWMARK) + NLA_PUT_U32(msg, IFLA_IPTUN_FWMARK, sit->fwmark); + + nla_nest_end(msg, data); + +nla_put_failure: + + return 0; +} + +static void sit_free(struct rtnl_link *link) +{ + struct sit_info *sit = link->l_info; + + free(sit); + link->l_info = NULL; +} + +static void sit_dump_line(struct rtnl_link *link, struct nl_dump_params *p) +{ + nl_dump(p, "sit : %s", link->l_name); +} + +static void sit_dump_details(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct sit_info *sit = link->l_info; + char *name, addr[INET_ADDRSTRLEN], addr6[INET6_ADDRSTRLEN]; + struct rtnl_link *parent; + + if (sit->sit_mask & SIT_ATTR_LINK) { + nl_dump(p, " link "); + + name = NULL; + parent = link_lookup(link->ce_cache, sit->link); + if (parent) + name = rtnl_link_get_name(parent); + + if (name) + nl_dump_line(p, "%s\n", name); + else + nl_dump_line(p, "%u\n", sit->link); + } + + if (sit->sit_mask & SIT_ATTR_LOCAL) { + nl_dump(p, " local "); + if(inet_ntop(AF_INET, &sit->local, addr, sizeof(addr))) + nl_dump_line(p, "%s\n", addr); + else + nl_dump_line(p, "%#x\n", ntohs(sit->local)); + } + + if (sit->sit_mask & SIT_ATTR_REMOTE) { + nl_dump(p, " remote "); + if(inet_ntop(AF_INET, &sit->remote, addr, sizeof(addr))) + nl_dump_line(p, "%s\n", addr); + else + nl_dump_line(p, "%#x\n", ntohs(sit->remote)); + } + + if (sit->sit_mask & SIT_ATTR_TTL) { + nl_dump(p, " ttl "); + nl_dump_line(p, "%u\n", sit->ttl); + } + + if (sit->sit_mask & SIT_ATTR_TOS) { + nl_dump(p, " tos "); + nl_dump_line(p, "%u\n", sit->tos); + } + + if (sit->sit_mask & SIT_ATTR_FLAGS) { + nl_dump(p, " flags "); + nl_dump_line(p, " (%x)\n", sit->flags); + } + + if (sit->sit_mask & SIT_ATTR_PROTO) { + nl_dump(p, " proto "); + nl_dump_line(p, " (%x)\n", sit->proto); + } + + if (sit->sit_mask & SIT_ATTR_6RD_PREFIX) { + nl_dump(p, " 6rd_prefix "); + if(inet_ntop(AF_INET6, &sit->ip6rd_prefix, addr6, INET6_ADDRSTRLEN)) + nl_dump_line(p, "%s\n", addr6); + else + nl_dump_line(p, "[unknown]\n"); + } + + if (sit->sit_mask & SIT_ATTR_6RD_RELAY_PREFIX) { + nl_dump(p, " 6rd_relay_prefix "); + if(inet_ntop(AF_INET, &sit->ip6rd_relay_prefix, addr, sizeof(addr))) + nl_dump_line(p, "%s\n", addr); + else + nl_dump_line(p, "[unknown]\n"); + } + + if (sit->sit_mask & SIT_ATTR_6RD_PREFIXLEN) { + nl_dump(p, " 6rd_prefixlen "); + nl_dump_line(p, "%d\n", sit->ip6rd_prefixlen); + } + + if (sit->sit_mask & SIT_ATTR_6RD_RELAY_PREFIXLEN) { + nl_dump(p, " 6rd_relay_prefixlen "); + nl_dump_line(p, "%d\n", sit->ip6rd_relay_prefixlen); + } + + if (sit->sit_mask & SIT_ATTR_FWMARK) { + nl_dump(p, " fwmark "); + nl_dump_line(p, "%x\n", sit->fwmark); + } +} + +static int sit_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct sit_info *sit_dst, *sit_src = src->l_info; + int err; + + dst->l_info = NULL; + + err = rtnl_link_set_type(dst, "sit"); + if (err < 0) + return err; + + sit_dst = dst->l_info; + + if (!sit_dst || !sit_src) + return -NLE_NOMEM; + + memcpy(sit_dst, sit_src, sizeof(struct sit_info)); + + return 0; +} + +static struct rtnl_link_info_ops sit_info_ops = { + .io_name = "sit", + .io_alloc = sit_alloc, + .io_parse = sit_parse, + .io_dump = { + [NL_DUMP_LINE] = sit_dump_line, + [NL_DUMP_DETAILS] = sit_dump_details, + }, + .io_clone = sit_clone, + .io_put_attrs = sit_put_attrs, + .io_free = sit_free, +}; + +#define IS_SIT_LINK_ASSERT(link, sit) \ + struct sit_info *sit; \ + do { \ + const struct rtnl_link *_link = (link); \ + if (!_link || _link->l_info_ops != &sit_info_ops) { \ + APPBUG("Link is not a sit link. set type \"sit\" first."); \ + return -NLE_OPNOTSUPP; \ + } \ + (sit) = _link->l_info; \ + } while (0) + +struct rtnl_link *rtnl_link_sit_alloc(void) +{ + struct rtnl_link *link; + int err; + + link = rtnl_link_alloc(); + if (!link) + return NULL; + + err = rtnl_link_set_type(link, "sit"); + if (err < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if link is a SIT link + * @arg link Link object + * + * @return True if link is a SIT link, otherwise false is returned. + */ +int rtnl_link_is_sit(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "sit"); +} + +/** + * Create a new sit tunnel device + * @arg sock netlink socket + * @arg name name of the tunnel device + * + * Creates a new sit tunnel device in the kernel + * @return 0 on success or a negative error code + */ +int rtnl_link_sit_add(struct nl_sock *sk, const char *name) +{ + struct rtnl_link *link; + int err; + + link = rtnl_link_sit_alloc(); + if (!link) + return -NLE_NOMEM; + + if(name) + rtnl_link_set_name(link, name); + + err = rtnl_link_add(sk, link, NLM_F_CREATE); + rtnl_link_put(link); + + return err; +} + +/** + * Set SIT tunnel interface index + * @arg link Link object + * @arg index interface index + * + * @return 0 on success or a negative error code + */ +int rtnl_link_sit_set_link(struct rtnl_link *link, uint32_t index) +{ + IS_SIT_LINK_ASSERT(link, sit); + + sit->link = index; + sit->sit_mask |= SIT_ATTR_LINK; + + return 0; +} + +/** + * Get SIT tunnel interface index + * @arg link Link object + * + * @return interface index value + */ +uint32_t rtnl_link_sit_get_link(struct rtnl_link *link) +{ + IS_SIT_LINK_ASSERT(link, sit); + + return sit->link; +} + +/** + * Set SIT tunnel local address + * @arg link Link object + * @arg addr local address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_sit_set_local(struct rtnl_link *link, uint32_t addr) +{ + IS_SIT_LINK_ASSERT(link, sit); + + sit->local = addr; + sit->sit_mask |= SIT_ATTR_LOCAL; + + return 0; +} + +/** + * Get SIT tunnel local address + * @arg link Link object + * + * @return local address value + */ +uint32_t rtnl_link_sit_get_local(struct rtnl_link *link) +{ + IS_SIT_LINK_ASSERT(link, sit); + + return sit->local; +} + +/** + * Set SIT tunnel remote address + * @arg link Link object + * @arg remote remote address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_sit_set_remote(struct rtnl_link *link, uint32_t addr) +{ + IS_SIT_LINK_ASSERT(link, sit); + + sit->remote = addr; + sit->sit_mask |= SIT_ATTR_REMOTE; + + return 0; +} + +/** + * Get SIT tunnel remote address + * @arg link Link object + * + * @return remote address + */ +uint32_t rtnl_link_sit_get_remote(struct rtnl_link *link) +{ + IS_SIT_LINK_ASSERT(link, sit); + + return sit->remote; +} + +/** + * Set SIT tunnel ttl + * @arg link Link object + * @arg ttl tunnel ttl + * + * @return 0 on success or a negative error code + */ +int rtnl_link_sit_set_ttl(struct rtnl_link *link, uint8_t ttl) +{ + IS_SIT_LINK_ASSERT(link, sit); + + sit->ttl = ttl; + sit->sit_mask |= SIT_ATTR_TTL; + + return 0; +} + +/** + * Get SIT tunnel ttl + * @arg link Link object + * + * @return ttl value + */ +uint8_t rtnl_link_sit_get_ttl(struct rtnl_link *link) +{ + IS_SIT_LINK_ASSERT(link, sit); + + return sit->ttl; +} + +/** + * Set SIT tunnel tos + * @arg link Link object + * @arg tos tunnel tos + * + * @return 0 on success or a negative error code + */ +int rtnl_link_sit_set_tos(struct rtnl_link *link, uint8_t tos) +{ + IS_SIT_LINK_ASSERT(link, sit); + + sit->tos = tos; + sit->sit_mask |= SIT_ATTR_TOS; + + return 0; +} + +/** + * Get SIT tunnel tos + * @arg link Link object + * + * @return tos value + */ +uint8_t rtnl_link_sit_get_tos(struct rtnl_link *link) +{ + IS_SIT_LINK_ASSERT(link, sit); + + return sit->tos; +} + +/** + * Set SIT tunnel path MTU discovery + * @arg link Link object + * @arg pmtudisc path MTU discovery + * + * @return 0 on success or a negative error code + */ +int rtnl_link_sit_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc) +{ + IS_SIT_LINK_ASSERT(link, sit); + + sit->pmtudisc = pmtudisc; + sit->sit_mask |= SIT_ATTR_PMTUDISC; + + return 0; +} + +/** + * Get SIT path MTU discovery + * @arg link Link object + * + * @return pmtudisc value + */ +uint8_t rtnl_link_sit_get_pmtudisc(struct rtnl_link *link) +{ + IS_SIT_LINK_ASSERT(link, sit); + + return sit->pmtudisc; +} + +/** + * Set SIT tunnel flags + * @arg link Link object + * @arg flags tunnel flags + * + * @return 0 on success or a negative error code + */ +int rtnl_link_sit_set_flags(struct rtnl_link *link, uint16_t flags) +{ + IS_SIT_LINK_ASSERT(link, sit); + + sit->flags = flags; + sit->sit_mask |= SIT_ATTR_FLAGS; + + return 0; +} + +/** + * Get SIT path flags + * @arg link Link object + * + * @return flags value + */ +uint16_t rtnl_link_sit_get_flags(struct rtnl_link *link) +{ + IS_SIT_LINK_ASSERT(link, sit); + + return sit->flags; +} + +/** + * Set SIT tunnel proto + * @arg link Link object + * @arg proto tunnel proto + * + * @return 0 on success or a negative error code + */ +int rtnl_link_sit_set_proto(struct rtnl_link *link, uint8_t proto) +{ + IS_SIT_LINK_ASSERT(link, sit); + + sit->proto = proto; + sit->sit_mask |= SIT_ATTR_PROTO; + + return 0; +} + +/** + * Get SIT proto + * @arg link Link object + * + * @return proto value + */ +uint8_t rtnl_link_sit_get_proto(struct rtnl_link *link) +{ + IS_SIT_LINK_ASSERT(link, sit); + + return sit->proto; +} + +/** + * Set ip6rd prefix + * @arg link Link object + * @arg prefix The IPv6 prefix + * + * @return 0 on success or an error code. + */ +int rtnl_link_sit_set_ip6rd_prefix(struct rtnl_link *link, const struct in6_addr *prefix) +{ + IS_SIT_LINK_ASSERT(link, sit); + + sit->ip6rd_prefix = *prefix; + sit->sit_mask |= SIT_ATTR_6RD_PREFIX; + return 0; +} + +/** + * Get ip6rd prefix + * @arg link Link object + * @arg prefix The output IPv6 prefix + * + * @return 0 on success or an error code. If the property is unset, + * this call fails too. + */ +int rtnl_link_sit_get_ip6rd_prefix(const struct rtnl_link *link, struct in6_addr *prefix) +{ + IS_SIT_LINK_ASSERT(link, sit); + + if (!(sit->sit_mask & SIT_ATTR_6RD_PREFIX)) + return -NLE_NOATTR; + + if (prefix) + *prefix = sit->ip6rd_prefix; + return 0; +} + +/** + * Set ip6rd prefix length + * @arg link Link object + * @arg prefixlen The IPv6 prefix length + * + * @return 0 on success or an error code. + */ +int rtnl_link_sit_set_ip6rd_prefixlen(struct rtnl_link *link, uint16_t prefixlen) +{ + IS_SIT_LINK_ASSERT(link, sit); + + sit->sit_mask |= SIT_ATTR_6RD_PREFIXLEN; + sit->ip6rd_prefixlen = prefixlen; + return 0; +} + +/** + * Get ip6rd prefix length + * @arg link Link object + * @arg prefixlen Output pointer for the prefix length + * + * @return 0 on success or an error code. If the property is unset, + * this call fails. + */ +int rtnl_link_sit_get_ip6rd_prefixlen(struct rtnl_link *link, uint16_t *prefixlen) +{ + IS_SIT_LINK_ASSERT(link, sit); + + if (!(sit->sit_mask & SIT_ATTR_6RD_PREFIXLEN)) + return -NLE_NOATTR; + + if (prefixlen) + *prefixlen = sit->ip6rd_prefixlen; + return 0; +} + +/** + * Set ip6rd relay prefix + * @arg link Link object + * @arg prefix The IPv6 prefix length + * + * @return 0 on success or an error code. + */ +int rtnl_link_sit_set_ip6rd_relay_prefix(struct rtnl_link *link, uint32_t prefix) +{ + IS_SIT_LINK_ASSERT(link, sit); + + sit->sit_mask |= SIT_ATTR_6RD_RELAY_PREFIX; + sit->ip6rd_relay_prefix = prefix; + return 0; +} + +/** + * Get ip6rd prefix length + * @arg link Link object + * @arg prefixlen Output pointer for the prefix length + * + * @return 0 on success or an error code. If the property is unset, + * this call fails. + */ +int rtnl_link_sit_get_ip6rd_relay_prefix(const struct rtnl_link *link, uint32_t *prefix) +{ + IS_SIT_LINK_ASSERT(link, sit); + + if (!(sit->sit_mask & SIT_ATTR_6RD_RELAY_PREFIX)) + return -NLE_NOATTR; + + if (prefix) + *prefix = sit->ip6rd_relay_prefix; + return 0; +} + +/** + * Set ip6rd relay prefix length + * @arg link Link object + * @arg prefixlen The IPv6 prefix length + * + * @return 0 on success or an error code. + */ +int rtnl_link_sit_set_ip6rd_relay_prefixlen(struct rtnl_link *link, uint16_t prefixlen) +{ + IS_SIT_LINK_ASSERT(link, sit); + + sit->sit_mask |= SIT_ATTR_6RD_RELAY_PREFIXLEN; + sit->ip6rd_relay_prefixlen = prefixlen; + return 0; +} + +/** + * Get ip6rd relay prefix length + * @arg link Link object + * @arg prefixlen Output pointer for the prefix length + * + * @return 0 on success or an error code. If the property is unset, + * this call fails. + */ +int rtnl_link_sit_get_ip6rd_relay_prefixlen(struct rtnl_link *link, uint16_t *prefixlen) +{ + IS_SIT_LINK_ASSERT(link, sit); + + if (!(sit->sit_mask & SIT_ATTR_6RD_RELAY_PREFIX)) + return -NLE_NOATTR; + + if (prefixlen) + *prefixlen = sit->ip6rd_relay_prefixlen; + return 0; +} + +/** + * Set SIT tunnel fwmark + * @arg link Link object + * @arg fwmark fwmark + * + * @return 0 on success or a negative error code + */ +int rtnl_link_sit_set_fwmark(struct rtnl_link *link, uint32_t fwmark) +{ + IS_SIT_LINK_ASSERT(link, sit); + + sit->fwmark = fwmark; + sit->sit_mask |= SIT_ATTR_FWMARK; + + return 0; +} + +/** + * Get SIT tunnel fwmark + * @arg link Link object + * @arg fwmark addr to fill in with the fwmark + * + * @return 0 on success or a negative error code + */ +int rtnl_link_sit_get_fwmark(struct rtnl_link *link, uint32_t *fwmark) +{ + IS_SIT_LINK_ASSERT(link, sit); + + if (!(sit->sit_mask & SIT_ATTR_FWMARK)) + return -NLE_NOATTR; + + *fwmark = sit->fwmark; + + return 0; +} + +static void _nl_init sit_init(void) +{ + rtnl_link_register_info(&sit_info_ops); +} + +static void _nl_exit sit_exit(void) +{ + rtnl_link_unregister_info(&sit_info_ops); +} diff --git a/lib/route/link/sriov.c b/lib/route/link/sriov.c new file mode 100644 index 0000000..d47d1dd --- /dev/null +++ b/lib/route/link/sriov.c @@ -0,0 +1,1479 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2016 Intel Corp. All rights reserved. + * Copyright (c) 2016 Jef Oliver + */ + +/** + * @ingroup link + * @defgroup sriov SRIOV + * SR-IOV VF link module + * + * @details + * SR-IOV (Single Root Input/Output Virtualization) is a network interface + * that allows for the isolation of the PCI Express resources. In a virtual + * environment, SR-IOV allows multiple virtual machines can share a single + * PCI Express hardware interface. This is done via VFs (Virtual Functions), + * virtual hardware devices with their own PCI address. + * + * @{ + */ + +#include "nl-default.h" + +#include +#include + +#include +#include +#include + +#include "nl-route.h" +#include "link-sriov.h" +#include "link-api.h" + +/** @cond SKIP */ +struct rtnl_link_vf { + struct nl_list_head vf_list; + int ce_refcnt; + uint32_t ce_mask; + uint32_t vf_index; + uint64_t vf_guid_node; + uint64_t vf_guid_port; + uint32_t vf_linkstate; + struct nl_addr *vf_lladdr; + uint32_t vf_max_tx_rate; + uint32_t vf_min_tx_rate; + uint32_t vf_rate; + uint32_t vf_rss_query_en; + uint32_t vf_spoofchk; + uint64_t vf_stats[RTNL_LINK_VF_STATS_MAX + 1]; + uint32_t vf_trust; + struct nl_vf_vlans *vf_vlans; +}; + +#define SRIOVON "on" +#define SRIOVOFF "off" + +#define SET_VF_STAT(link, vf_num, stb, stat, attr) \ + vf_data->vf_stats[stat] = nla_get_u64(stb[attr]) + +/* SRIOV-VF Attributes */ +#define SRIOV_ATTR_INDEX (1 << 0) +#define SRIOV_ATTR_ADDR (1 << 1) +#define SRIOV_ATTR_VLAN (1 << 2) +#define SRIOV_ATTR_TX_RATE (1 << 3) +#define SRIOV_ATTR_SPOOFCHK (1 << 4) +#define SRIOV_ATTR_RATE_MAX (1 << 5) +#define SRIOV_ATTR_RATE_MIN (1 << 6) +#define SRIOV_ATTR_LINK_STATE (1 << 7) +#define SRIOV_ATTR_RSS_QUERY_EN (1 << 8) +#define SRIOV_ATTR_STATS (1 << 9) +#define SRIOV_ATTR_TRUST (1 << 10) +#define SRIOV_ATTR_IB_NODE_GUID (1 << 11) +#define SRIOV_ATTR_IB_PORT_GUID (1 << 12) + +static struct nla_policy sriov_info_policy[IFLA_VF_MAX+1] = { + [IFLA_VF_MAC] = { .minlen = sizeof(struct ifla_vf_mac) }, + [IFLA_VF_VLAN] = { .minlen = sizeof(struct ifla_vf_vlan) }, + [IFLA_VF_VLAN_LIST] = { .type = NLA_NESTED }, + [IFLA_VF_TX_RATE] = { .minlen = sizeof(struct ifla_vf_tx_rate) }, + [IFLA_VF_SPOOFCHK] = { .minlen = sizeof(struct ifla_vf_spoofchk) }, + [IFLA_VF_RATE] = { .minlen = sizeof(struct ifla_vf_rate) }, + [IFLA_VF_LINK_STATE] = { .minlen = sizeof(struct ifla_vf_link_state) }, + [IFLA_VF_RSS_QUERY_EN] = { .minlen = sizeof(struct ifla_vf_rss_query_en) }, + [IFLA_VF_STATS] = { .type = NLA_NESTED }, + [IFLA_VF_TRUST] = { .minlen = sizeof(struct ifla_vf_trust) }, + [IFLA_VF_IB_NODE_GUID] = { .minlen = sizeof(struct ifla_vf_guid) }, + [IFLA_VF_IB_PORT_GUID] = { .minlen = sizeof(struct ifla_vf_guid) }, +}; + +static struct nla_policy sriov_stats_policy[IFLA_VF_STATS_MAX+1] = { + [IFLA_VF_STATS_RX_PACKETS] = { .type = NLA_U64 }, + [IFLA_VF_STATS_TX_PACKETS] = { .type = NLA_U64 }, + [IFLA_VF_STATS_RX_BYTES] = { .type = NLA_U64 }, + [IFLA_VF_STATS_TX_BYTES] = { .type = NLA_U64 }, + [IFLA_VF_STATS_BROADCAST] = { .type = NLA_U64 }, + [IFLA_VF_STATS_MULTICAST] = { .type = NLA_U64 }, +}; + +/** @endcond */ + +/* Clone SRIOV VF list in link object */ +int rtnl_link_sriov_clone(struct rtnl_link *dst, struct rtnl_link *src) { + int err = 0; + struct nl_addr *vf_addr; + struct rtnl_link_vf *s_list, *d_vf, *s_vf, *next, *dest_h = NULL; + nl_vf_vlans_t *src_vlans = NULL, *dst_vlans = NULL; + nl_vf_vlan_info_t *src_vlan_info = NULL, *dst_vlan_info = NULL; + + if (!rtnl_link_has_vf_list(src)) + return 0; + + dst->l_vf_list = rtnl_link_vf_alloc(); + if (!dst->l_vf_list) + return -NLE_NOMEM; + dest_h = dst->l_vf_list; + s_list = src->l_vf_list; + + nl_list_for_each_entry_safe(s_vf, next, &s_list->vf_list, vf_list) { + if (!(d_vf = rtnl_link_vf_alloc())) + return -NLE_NOMEM; + + memcpy(d_vf, s_vf, sizeof(*s_vf)); + + if (s_vf->ce_mask & SRIOV_ATTR_ADDR) { + vf_addr = nl_addr_clone(s_vf->vf_lladdr); + if (!vf_addr) { + rtnl_link_vf_put(d_vf); + return -NLE_NOMEM; + } + d_vf->vf_lladdr = vf_addr; + } + + if (s_vf->ce_mask & SRIOV_ATTR_VLAN) { + src_vlans = s_vf->vf_vlans; + src_vlan_info = src_vlans->vlans; + + err = rtnl_link_vf_vlan_alloc(&dst_vlans, + src_vlans->size); + if (err < 0) { + rtnl_link_vf_put(d_vf); + return err; + } + dst_vlan_info = dst_vlans->vlans; + memcpy(dst_vlans, src_vlans, sizeof(nl_vf_vlans_t)); + memcpy(dst_vlan_info, src_vlan_info, + dst_vlans->size * sizeof(*dst_vlan_info)); + d_vf->vf_vlans = dst_vlans; + } + + nl_list_add_head(&d_vf->vf_list, &dest_h->vf_list); + dest_h = d_vf; + } + + return 0; +} + +/* Dump VLAN details for each SRIOV VF */ +static void dump_sriov_vlans(nl_vf_vlans_t *vlans, + struct nl_dump_params *p) { + char buf[64]; + int cur = 0; + nl_vf_vlan_info_t *vlan_data; + uint16_t prot; + + vlan_data = vlans->vlans; + nl_dump(p, "\t VLANS:\n"); + while (cur < vlans->size) { + nl_dump(p, "\t vlan %u", vlan_data[cur].vf_vlan); + if (vlan_data[cur].vf_vlan_qos) + nl_dump(p, " qos %u", vlan_data[cur].vf_vlan_qos); + if (vlan_data[cur].vf_vlan_proto) { + prot = vlan_data[cur].vf_vlan_proto; + nl_dump(p, " proto %s", + rtnl_link_vf_vlanproto2str(prot, buf, + sizeof(buf))); + } + nl_dump(p, "\n"); + cur++; + } + + return; +} + +/* Dump details for each SRIOV VF */ +static void dump_vf_details(struct rtnl_link_vf *vf_data, + struct nl_dump_params *p) { + char buf[64]; + int err = 0; + struct nl_vf_rate vf_rate; + uint32_t v = 0; + + nl_dump(p, "\tvf %u: ", vf_data->vf_index); + if (vf_data->ce_mask & SRIOV_ATTR_LINK_STATE) { + v = vf_data->vf_linkstate; + nl_dump(p, "state %s ", + rtnl_link_vf_linkstate2str(v, buf, sizeof(buf))); + } + if (vf_data->ce_mask & SRIOV_ATTR_ADDR) { + nl_dump(p, "addr %s ", + nl_addr2str(vf_data->vf_lladdr, buf, sizeof(buf))); + } + nl_dump(p, "\n"); + + v = vf_data->vf_spoofchk; + nl_dump(p, "\t spoofchk %s ", v ? SRIOVON : SRIOVOFF); + v = vf_data->vf_trust; + nl_dump(p, "trust %s ", v ? SRIOVON : SRIOVOFF); + v = vf_data->vf_rss_query_en; + nl_dump(p, "rss_query %s\n", v ? SRIOVON : SRIOVOFF); + + err = rtnl_link_vf_get_rate(vf_data, &vf_rate); + if (!err) { + if (vf_rate.api == RTNL_LINK_VF_RATE_API_OLD) + nl_dump(p, "\t rate_api old rate %u\n", + vf_rate.rate); + else if (vf_rate.api == RTNL_LINK_VF_RATE_API_NEW) + nl_dump(p, "\t rate_api new min_rate %u " + "max_rate %u\n", vf_rate.min_tx_rate, + vf_rate.max_tx_rate); + } + if (vf_data->ce_mask & SRIOV_ATTR_VLAN) + dump_sriov_vlans(vf_data->vf_vlans, p); + + return; +} + +/* Loop through SRIOV VF list dump details */ +void rtnl_link_sriov_dump_details(struct rtnl_link *link, + struct nl_dump_params *p) { + struct rtnl_link_vf *vf_data, *list, *next; + + if (!rtnl_link_has_vf_list(link)) + BUG(); + + nl_dump(p, " SRIOV VF List\n"); + list = link->l_vf_list; + nl_list_for_each_entry_safe(vf_data, next, &list->vf_list, vf_list) { + if (vf_data->ce_mask & SRIOV_ATTR_INDEX) + dump_vf_details(vf_data, p); + } + + return; +} + +/* Dump stats for each SRIOV VF */ +static void dump_vf_stats(struct rtnl_link_vf *vf_data, + struct nl_dump_params *p) { + char *unit; + float res; + + nl_dump(p, " VF %u Stats:\n", vf_data->vf_index); + nl_dump_line(p, "\tRX: %-14s %-10s %-10s %-10s\n", + "bytes", "packets", "multicast", "broadcast"); + + res = nl_cancel_down_bytes(vf_data->vf_stats[RTNL_LINK_VF_STATS_RX_BYTES], + &unit); + + nl_dump_line(p, + "\t%10.2f %3s %10" PRIu64 " %10" PRIu64 " %10" PRIu64 "\n", + res, unit, + vf_data->vf_stats[RTNL_LINK_VF_STATS_RX_PACKETS], + vf_data->vf_stats[RTNL_LINK_VF_STATS_MULTICAST], + vf_data->vf_stats[RTNL_LINK_VF_STATS_BROADCAST]); + + nl_dump_line(p, "\tTX: %-14s %-10s\n", "bytes", "packets"); + + res = nl_cancel_down_bytes(vf_data->vf_stats[RTNL_LINK_VF_STATS_TX_BYTES], + &unit); + + nl_dump_line(p, "\t%10.2f %3s %10" PRIu64 "\n", res, unit, + vf_data->vf_stats[RTNL_LINK_VF_STATS_TX_PACKETS]); + + return; +} + +/* Loop through SRIOV VF list dump stats */ +void rtnl_link_sriov_dump_stats(struct rtnl_link *link, + struct nl_dump_params *p) { + struct rtnl_link_vf *vf_data, *list, *next; + + list = link->l_vf_list; + nl_list_for_each_entry_safe(vf_data, next, &list->vf_list, vf_list) { + if (vf_data->ce_mask & SRIOV_ATTR_INDEX) + dump_vf_stats(vf_data, p); + } + nl_dump(p, "\n"); + + return; +} + +/* Free stored SRIOV VF data */ +void rtnl_link_sriov_free_data(struct rtnl_link *link) { + struct rtnl_link_vf *list, *vf, *next; + + if (!rtnl_link_has_vf_list(link)) + return; + + list = link->l_vf_list; + nl_list_for_each_entry_safe(vf, next, &list->vf_list, vf_list) { + nl_list_del(&vf->vf_list); + rtnl_link_vf_put(vf); + } + + rtnl_link_vf_put(link->l_vf_list); + + return; +} + +/* Fill VLAN info array */ +static int rtnl_link_vf_vlan_info(int len, struct ifla_vf_vlan_info **vi, + nl_vf_vlans_t **nvi) { + int cur = 0, err; + nl_vf_vlans_t *vlans; + + if (len <= 0) + return 0; + + if ((err = rtnl_link_vf_vlan_alloc(&vlans, len)) < 0) + return err; + + cur = 0; + while (cur < len) { + vlans->vlans[cur].vf_vlan = vi[cur]->vlan ? vi[cur]->vlan : 0; + vlans->vlans[cur].vf_vlan_qos = vi[cur]->qos ? vi[cur]->qos : 0; + if (vi[cur]->vlan_proto) { + vlans->vlans[cur].vf_vlan_proto = ntohs(vi[cur]->vlan_proto); + } else { + vlans->vlans[cur].vf_vlan_proto = ETH_P_8021Q; + } + cur++; + } + + *nvi = vlans; + return 0; +} + +/* Fill the IFLA_VF_VLAN attribute */ +static void sriov_fill_vf_vlan(struct nl_msg *msg, nl_vf_vlan_info_t *vinfo, + uint32_t index) { + struct ifla_vf_vlan vlan; + + vlan.vf = index; + vlan.vlan = vinfo[0].vf_vlan; + vlan.qos = vinfo[0].vf_vlan_qos; + NLA_PUT(msg, IFLA_VF_VLAN, sizeof(vlan), &vlan); + +nla_put_failure: + return; +} + +/* Fill the IFLA_VF_VLAN_LIST attribute */ +static int sriov_fill_vf_vlan_list(struct nl_msg *msg, nl_vf_vlans_t *vlans, + uint32_t index) { + int cur = 0; + nl_vf_vlan_info_t *vlan_info = vlans->vlans; + struct ifla_vf_vlan_info vlan; + struct nlattr *list; + + if (!(list = nla_nest_start(msg, IFLA_VF_VLAN_LIST))) + return -NLE_MSGSIZE; + + vlan.vf = index; + while (cur < vlans->size) { + vlan.vlan = vlan_info[cur].vf_vlan; + vlan.qos = vlan_info[cur].vf_vlan_qos; + vlan.vlan_proto = vlan_info[cur].vf_vlan_proto; + + NLA_PUT(msg, IFLA_VF_VLAN_INFO, sizeof(vlan), &vlan); + + cur++; + } + +nla_put_failure: + nla_nest_end(msg, list); + + return 0; +} + +/* Fill individual IFLA_VF_INFO attributes */ +static int sriov_fill_vfinfo(struct nl_msg *msg, + struct rtnl_link_vf *vf_data) { + int err = 0, new_rate = 0; + nl_vf_vlans_t *vlan_list; + nl_vf_vlan_info_t *vlan_info; + struct ifla_vf_guid vf_node_guid; + struct ifla_vf_guid vf_port_guid; + struct ifla_vf_link_state vf_link_state; + struct ifla_vf_mac vf_mac; + struct ifla_vf_rate new_vf_rate; + struct ifla_vf_rss_query_en vf_rss_query_en; + struct ifla_vf_spoofchk vf_spoofchk; + struct ifla_vf_trust vf_trust; + struct ifla_vf_tx_rate vf_rate; + struct nlattr *list; + uint16_t proto; + + if (!(vf_data->ce_mask & SRIOV_ATTR_INDEX)) + return -NLE_MISSING_ATTR; + + if (!(list = nla_nest_start(msg, IFLA_VF_INFO))) + return -NLE_MSGSIZE; + + /* IFLA_VF_MAC */ + if (vf_data->ce_mask & SRIOV_ATTR_ADDR) { + vf_mac.vf = vf_data->vf_index; + memset(vf_mac.mac, 0, sizeof(vf_mac.mac)); + memcpy(vf_mac.mac, nl_addr_get_binary_addr(vf_data->vf_lladdr), + nl_addr_get_len(vf_data->vf_lladdr)); + NLA_PUT(msg, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac); + } + + /* IFLA_VF_VLAN IFLA_VF_VLAN_LIST */ + if (vf_data->ce_mask & SRIOV_ATTR_VLAN) { + vlan_list = vf_data->vf_vlans; + vlan_info = vlan_list->vlans; + proto = vlan_info[0].vf_vlan_proto; + if (!proto) + proto = ETH_P_8021Q; + + if ((vlan_list->size == 1) && (proto == ETH_P_8021Q)) + sriov_fill_vf_vlan(msg, vlan_info, vf_data->vf_index); + else + err = sriov_fill_vf_vlan_list(msg, vlan_list, + vf_data->vf_index); + } + + /* IFLA_VF_TX_RATE */ + if (vf_data->ce_mask & SRIOV_ATTR_TX_RATE) { + vf_rate.vf = vf_data->vf_index; + vf_rate.rate = vf_data->vf_rate; + + NLA_PUT(msg, IFLA_VF_TX_RATE, sizeof(vf_rate), &vf_rate); + } + + /* IFLA_VF_RATE */ + new_vf_rate.min_tx_rate = 0; + new_vf_rate.max_tx_rate = 0; + new_vf_rate.vf = vf_data->vf_index; + if (vf_data->ce_mask & SRIOV_ATTR_RATE_MIN) { + new_vf_rate.min_tx_rate = vf_data->vf_min_tx_rate; + new_rate = 1; + } + if (vf_data->ce_mask & SRIOV_ATTR_RATE_MAX) { + new_vf_rate.max_tx_rate = vf_data->vf_max_tx_rate; + new_rate = 1; + } + if (new_rate) + NLA_PUT(msg, IFLA_VF_RATE, sizeof(new_vf_rate), &new_vf_rate); + + /* IFLA_VF_SPOOFCHK */ + if (vf_data->ce_mask & SRIOV_ATTR_SPOOFCHK) { + vf_spoofchk.vf = vf_data->vf_index; + vf_spoofchk.setting = vf_data->vf_spoofchk; + + NLA_PUT(msg, IFLA_VF_SPOOFCHK, sizeof(vf_spoofchk), + &vf_spoofchk); + } + + /* IFLA_VF_LINK_STATE */ + if (vf_data->ce_mask & SRIOV_ATTR_LINK_STATE) { + vf_link_state.vf = vf_data->vf_index; + vf_link_state.link_state = vf_data->vf_linkstate; + + NLA_PUT(msg, IFLA_VF_LINK_STATE, sizeof(vf_link_state), + &vf_link_state); + } + + /* IFLA_VF_RSS_QUERY_EN */ + if (vf_data->ce_mask & SRIOV_ATTR_RSS_QUERY_EN) { + vf_rss_query_en.vf = vf_data->vf_index; + vf_rss_query_en.setting = vf_data->vf_rss_query_en; + + NLA_PUT(msg, IFLA_VF_RSS_QUERY_EN, sizeof(vf_rss_query_en), + &vf_rss_query_en); + } + + /* IFLA_VF_TRUST */ + if (vf_data->ce_mask & SRIOV_ATTR_TRUST) { + vf_trust.vf = vf_data->vf_index; + vf_trust.setting = vf_data->vf_trust; + + NLA_PUT(msg, IFLA_VF_TRUST, sizeof(vf_trust), &vf_trust); + } + + /* IFLA_VF_IB_NODE_GUID */ + if (vf_data->ce_mask & SRIOV_ATTR_IB_NODE_GUID) { + vf_node_guid.vf = vf_data->vf_index; + vf_node_guid.guid = vf_data->vf_guid_node; + + NLA_PUT(msg, IFLA_VF_IB_NODE_GUID, sizeof(vf_node_guid), + &vf_node_guid); + } + + /* IFLA_VF_IB_PORT_GUID */ + if (vf_data->ce_mask & SRIOV_ATTR_IB_PORT_GUID) { + vf_port_guid.vf = vf_data->vf_index; + vf_port_guid.guid = vf_data->vf_guid_port; + + NLA_PUT(msg, IFLA_VF_IB_PORT_GUID, sizeof(vf_port_guid), + &vf_port_guid); + } + +nla_put_failure: + nla_nest_end(msg, list); + + return err; +} + +/* Fill the IFLA_VFINFO_LIST attribute */ +int rtnl_link_sriov_fill_vflist(struct nl_msg *msg, struct rtnl_link *link) { + int err = 0; + struct nlattr *data; + struct rtnl_link_vf *list, *vf, *next; + + if (!(err = rtnl_link_has_vf_list(link))) + return 0; + + if (!(data = nla_nest_start(msg, IFLA_VFINFO_LIST))) + return -NLE_MSGSIZE; + + list = link->l_vf_list; + nl_list_for_each_entry_safe(vf, next, &list->vf_list, vf_list) { + if (vf->ce_mask & SRIOV_ATTR_INDEX) { + if ((err = sriov_fill_vfinfo(msg, vf)) < 0) + goto nla_nest_list_failure; + } + } + +nla_nest_list_failure: + nla_nest_end(msg, data); + + return err; +} + +/* Parse IFLA_VFINFO_LIST and IFLA_VF_INFO attributes */ +int rtnl_link_sriov_parse_vflist(struct rtnl_link *link, struct nlattr **tb) { + int err, len, list_len, list_rem; + struct ifla_vf_mac *vf_lladdr; + struct ifla_vf_vlan *vf_vlan; + struct ifla_vf_vlan_info *vf_vlan_info[MAX_VLAN_LIST_LEN]; + struct ifla_vf_tx_rate *vf_tx_rate; + struct ifla_vf_spoofchk *vf_spoofchk; + struct ifla_vf_link_state *vf_linkstate; + struct ifla_vf_rate *vf_rate; + struct ifla_vf_rss_query_en *vf_rss_query; + struct ifla_vf_trust *vf_trust; + struct nlattr *nla, *nla_list, *t[IFLA_VF_MAX+1], + *stb[RTNL_LINK_VF_STATS_MAX+1]; + nl_vf_vlans_t *vf_vlans = NULL; + struct rtnl_link_vf *vf_data, *vf_head = NULL; + + len = nla_len(tb[IFLA_VFINFO_LIST]); + link->l_vf_list = rtnl_link_vf_alloc(); + if (!link->l_vf_list) + return -NLE_NOMEM; + vf_head = link->l_vf_list; + + for (nla = nla_data(tb[IFLA_VFINFO_LIST]); nla_ok(nla, len); + nla = nla_next(nla, &len)) { + err = nla_parse(t, IFLA_VF_MAX, nla_data(nla), nla_len(nla), + sriov_info_policy); + if (err < 0) + return err; + + vf_data = rtnl_link_vf_alloc(); + if (!vf_data) + return -NLE_NOMEM; + + if (t[IFLA_VF_MAC]) { + vf_lladdr = nla_data(t[IFLA_VF_MAC]); + + vf_data->vf_index = vf_lladdr->vf; + vf_data->ce_mask |= SRIOV_ATTR_INDEX; + + vf_data->vf_lladdr = nl_addr_build(AF_LLC, + vf_lladdr->mac, 6); + if (vf_data->vf_lladdr == NULL) { + rtnl_link_vf_put(vf_data); + return -NLE_NOMEM; + } + nl_addr_set_family(vf_data->vf_lladdr, AF_LLC); + vf_data->ce_mask |= SRIOV_ATTR_ADDR; + } + + if (t[IFLA_VF_VLAN_LIST]) { + list_len = 0; + nla_for_each_nested(nla_list, t[IFLA_VF_VLAN_LIST], + list_rem) { + if (list_len >= MAX_VLAN_LIST_LEN) + break; + vf_vlan_info[list_len] = nla_data(nla_list); + list_len++; + } + + err = rtnl_link_vf_vlan_info(list_len, vf_vlan_info, + &vf_vlans); + if (err < 0) { + rtnl_link_vf_put(vf_data); + return err; + } + + vf_data->vf_vlans = vf_vlans; + vf_data->ce_mask |= SRIOV_ATTR_VLAN; + } else if (t[IFLA_VF_VLAN]) { + vf_vlan = nla_data(t[IFLA_VF_VLAN]); + + if (vf_vlan->vlan) { + err = rtnl_link_vf_vlan_alloc(&vf_vlans, 1); + if (err < 0) { + rtnl_link_vf_put(vf_data); + return err; + } + + vf_vlans->vlans[0].vf_vlan = vf_vlan->vlan; + vf_vlans->vlans[0].vf_vlan_qos = vf_vlan->qos; + vf_vlans->vlans[0].vf_vlan_proto = ETH_P_8021Q; + + vf_data->vf_vlans = vf_vlans; + vf_data->ce_mask |= SRIOV_ATTR_VLAN; + } + } + + if (t[IFLA_VF_TX_RATE]) { + vf_tx_rate = nla_data(t[IFLA_VF_TX_RATE]); + + if (vf_tx_rate->rate) { + vf_data->vf_rate = vf_tx_rate->rate; + vf_data->ce_mask |= SRIOV_ATTR_TX_RATE; + } + } + + if (t[IFLA_VF_SPOOFCHK]) { + vf_spoofchk = nla_data(t[IFLA_VF_SPOOFCHK]); + + if (vf_spoofchk->setting != -1) { + vf_data->vf_spoofchk = vf_spoofchk->setting ? 1 : 0; + vf_data->ce_mask |= SRIOV_ATTR_SPOOFCHK; + } + } + + if (t[IFLA_VF_LINK_STATE]) { + vf_linkstate = nla_data(t[IFLA_VF_LINK_STATE]); + + vf_data->vf_linkstate = vf_linkstate->link_state; + vf_data->ce_mask |= SRIOV_ATTR_LINK_STATE; + } + + if (t[IFLA_VF_RATE]) { + vf_rate = nla_data(t[IFLA_VF_RATE]); + + if (vf_rate->max_tx_rate) { + vf_data->vf_max_tx_rate = vf_rate->max_tx_rate; + vf_data->ce_mask |= SRIOV_ATTR_RATE_MAX; + } + if (vf_rate->min_tx_rate) { + vf_data->vf_min_tx_rate = vf_rate->min_tx_rate; + vf_data->ce_mask |= SRIOV_ATTR_RATE_MIN; + } + } + + if (t[IFLA_VF_RSS_QUERY_EN]) { + vf_rss_query = nla_data(t[IFLA_VF_RSS_QUERY_EN]); + + if (vf_rss_query->setting != -1) { + vf_data->vf_rss_query_en = vf_rss_query->setting ? 1 : 0; + vf_data->ce_mask |= SRIOV_ATTR_RSS_QUERY_EN; + } + } + + if (t[IFLA_VF_STATS]) { + err = nla_parse_nested(stb, RTNL_LINK_VF_STATS_MAX, + t[IFLA_VF_STATS], + sriov_stats_policy); + if (err < 0) { + rtnl_link_vf_put(vf_data); + return err; + } + + SET_VF_STAT(link, cur, stb, + RTNL_LINK_VF_STATS_RX_PACKETS, + IFLA_VF_STATS_RX_PACKETS); + SET_VF_STAT(link, cur, stb, + RTNL_LINK_VF_STATS_TX_PACKETS, + IFLA_VF_STATS_TX_PACKETS); + SET_VF_STAT(link, cur, stb, + RTNL_LINK_VF_STATS_RX_BYTES, + IFLA_VF_STATS_RX_BYTES); + SET_VF_STAT(link, cur, stb, + RTNL_LINK_VF_STATS_TX_BYTES, + IFLA_VF_STATS_TX_BYTES); + SET_VF_STAT(link, cur, stb, + RTNL_LINK_VF_STATS_BROADCAST, + IFLA_VF_STATS_BROADCAST); + SET_VF_STAT(link, cur, stb, + RTNL_LINK_VF_STATS_MULTICAST, + IFLA_VF_STATS_MULTICAST); + + vf_data->ce_mask |= SRIOV_ATTR_STATS; + } + + if (t[IFLA_VF_TRUST]) { + vf_trust = nla_data(t[IFLA_VF_TRUST]); + + if (vf_trust->setting != -1) { + vf_data->vf_trust = vf_trust->setting ? 1 : 0; + vf_data->ce_mask |= SRIOV_ATTR_TRUST; + } + } + + nl_list_add_head(&vf_data->vf_list, &vf_head->vf_list); + vf_head = vf_data; + } + + return 0; +} + +/** + * @name SR-IOV Sub-Object + * @{ + */ + +/** + * Add a SRIOV VF object to a link object + * @param link Link object to add to + * @param vf_data SRIOV VF object to add + * + * @return 0 if SRIOV VF object added successfully + * @return -NLE_OBJ_NOTFOUND if \p link or \p vf_data not provided + * @return -NLE_NOMEM if out of memory + */ +int rtnl_link_vf_add(struct rtnl_link *link, struct rtnl_link_vf *vf_data) { + struct rtnl_link_vf *vf_head = NULL; + + if (!link||!vf_data) + return -NLE_OBJ_NOTFOUND; + + if (!link->l_vf_list) { + link->l_vf_list = rtnl_link_vf_alloc(); + if (!link->l_vf_list) + return -NLE_NOMEM; + } + + vf_head = vf_data; + vf_head->ce_refcnt++; + + vf_head = link->l_vf_list; + nl_list_add_head(&vf_data->vf_list, &vf_head->vf_list); + link->l_vf_list = vf_head; + + rtnl_link_set_vf_list(link); + + return 0; +} + +/** + * Allocate a new SRIOV VF object + * + * @return NULL if out of memory + * @return New VF Object + * + * @see rtnl_link_vf_put() + * + * The SRIOV VF object must be returned to the link object with + * rtnl_link_vf_put() when operations are done to prevent memory leaks. + */ +struct rtnl_link_vf *rtnl_link_vf_alloc(void) { + struct rtnl_link_vf *vf; + + if (!(vf = calloc(1, sizeof(*vf)))) + return NULL; + + NL_INIT_LIST_HEAD(&vf->vf_list); + vf->ce_refcnt = 1; + + NL_DBG(4, "Allocated new SRIOV VF object %p\n", vf); + + return vf; +} + +/** + * Free SRIOV VF object. + * @arg vf_data SRIOV VF data object + */ +void rtnl_link_vf_free(struct rtnl_link_vf *vf_data) { + if (!vf_data) + return; + + if (vf_data->ce_refcnt > 0) + NL_DBG(1, "Warning: Freeing SRIOV VF object in use...\n"); + + if (vf_data->ce_mask & SRIOV_ATTR_ADDR) + nl_addr_put(vf_data->vf_lladdr); + if (vf_data->ce_mask & SRIOV_ATTR_VLAN) + rtnl_link_vf_vlan_put(vf_data->vf_vlans); + + NL_DBG(4, "Freed SRIOV VF object %p\n", vf_data); + free(vf_data); + + return; +} + +/** + * Lookup SRIOV VF in link object by VF index. + * + * @return NULL if VF not found + * @return VF Object + * + * @see rtnl_link_vf_put() + * + * The SRIOV VF object must be returned to the link object with + * rtnl_link_vf_put() when operations are done to prevent memory leaks. + */ +struct rtnl_link_vf *rtnl_link_vf_get(struct rtnl_link *link, uint32_t vf_num) { + struct rtnl_link_vf *list, *vf, *next, *ret = NULL; + + list = link->l_vf_list; + nl_list_for_each_entry_safe(vf, next, &list->vf_list, vf_list) { + if (vf->vf_index == vf_num) { + ret = vf; + break; + } + } + + if (ret) { + ret->ce_refcnt++; + NL_DBG(4, "New reference to SRIOV VF object %p, total %i\n", + ret, ret->ce_refcnt); + } + + return ret; +} + +/** + * Return SRIOV VF object to the owning link object. + * @arg vf_data SRIOV VF data object + * + * @see rtnl_link_vf_alloc() + * @see rtnl_link_vf_get() + */ +void rtnl_link_vf_put(struct rtnl_link_vf *vf_data) { + if (!vf_data) + return; + + vf_data->ce_refcnt--; + NL_DBG(4, "Returned SRIOV VF object reference %p, %i remaining\n", + vf_data, vf_data->ce_refcnt); + + if (vf_data->ce_refcnt < 0) + BUG(); + + if (vf_data->ce_refcnt <= 0) + rtnl_link_vf_free(vf_data); + + return; +} + +/** + * Get link layer address of SRIOV Virtual Function + * @arg vf_data SRIOV VF object + * @arg addr Pointer to store Link Layer address + * + * @see rtnl_link_get_num_vf() + * @see rtnl_link_vf_set_addr() + * + * @copydoc pointer_lifetime_warning + * @return 0 if addr is present and addr is set to pointer containing address + * @return -NLE_OBJ_NOTFOUND if information for VF info is not found + * @return -NLE_NOATTR if the link layer address is not set + */ +int rtnl_link_vf_get_addr(struct rtnl_link_vf *vf_data, struct nl_addr **addr) +{ + if (!vf_data) + return -NLE_OBJ_NOTFOUND; + + if (vf_data->ce_mask & SRIOV_ATTR_ADDR) + *addr = vf_data->vf_lladdr; + else + return -NLE_NOATTR; + + return 0; +} + +/** + * Set link layer address of SRIOV Virtual Function object + * @param vf_data SRIOV VF object + * @param addr New link layer address + * + * This function increments the reference counter of the address object + * and overwrites any existing link layer address previously assigned. + * + * @see rtnl_link_vf_get_addr() + */ +void rtnl_link_vf_set_addr(struct rtnl_link_vf *vf_data, struct nl_addr *addr) { + if (vf_data->vf_lladdr) + nl_addr_put(vf_data->vf_lladdr); + + nl_addr_get(addr); + vf_data->vf_lladdr = addr; + vf_data->ce_mask |= SRIOV_ATTR_ADDR; + + return; +} + +/** + * Set the Infiniband node GUID for the SRIOV Virtual Function object + * @param vf_data SRIOV VF object + * @param guid node GUID + */ +void rtnl_link_vf_set_ib_node_guid(struct rtnl_link_vf *vf_data, + uint64_t guid) { + vf_data->vf_guid_node = guid; + vf_data->ce_mask |= SRIOV_ATTR_IB_NODE_GUID; + + return; +} + +/** + * Set the Infiniband port GUID for the SRIOV Virtual Function object + * @param vf_data SRIOV VF object + * @param guid port GUID + */ +void rtnl_link_vf_set_ib_port_guid(struct rtnl_link_vf *vf_data, + uint64_t guid) { + vf_data->vf_guid_port = guid; + vf_data->ce_mask |= SRIOV_ATTR_IB_PORT_GUID; + + return; +} + +/** + * Get index of SRIOV Virtual Function + * @arg vf_data SRIOV VF object + * @arg vf_index Pointer to store VF index + * + * @see rtnl_link_get_num_vf() + * + * @return 0 if index is present and vf_index is set + * @return -NLE_OBJ_NOTFOUND if information for VF info is not found + * @return -NLE_NOATTR if the VF index is not set + */ +int rtnl_link_vf_get_index(struct rtnl_link_vf *vf_data, uint32_t *vf_index) +{ + if (!vf_data) + return -NLE_OBJ_NOTFOUND; + + if (vf_data->ce_mask & SRIOV_ATTR_INDEX) + *vf_index = vf_data->vf_index; + else + return -NLE_NOATTR; + + return 0; +} + +/** + * Set index of SRIOV Virtual Function object + * @param vf_data SRIOV VF object + * @param vf_index Index value + * + * @see rtnl_link_vf_get_index() + */ +void rtnl_link_vf_set_index(struct rtnl_link_vf *vf_data, uint32_t vf_index) +{ + vf_data->vf_index = vf_index; + vf_data->ce_mask |= SRIOV_ATTR_INDEX; + + return; +} + +/** + * Get link state of SRIOV Virtual Function + * @arg vf_data SRIOV VF object + * @arg vf_linkstate Pointer to store VF link state + * + * @see rtnl_link_get_num_vf() + * @see rtnl_link_set_linkstate() + * + * @return 0 if link state is present and vf_linkstate is set + * @return -NLE_OBJ_NOTFOUND if information for VF info is not found + * @return -NLE_NOATTR if the VF link state is not set + */ +int rtnl_link_vf_get_linkstate(struct rtnl_link_vf *vf_data, + uint32_t *vf_linkstate) +{ + if (!vf_data) + return -NLE_OBJ_NOTFOUND; + + if (vf_data->ce_mask & SRIOV_ATTR_LINK_STATE) + *vf_linkstate = vf_data->vf_linkstate; + else + return -NLE_NOATTR; + + return 0; +} + +/** + * Set link state of SRIOV Virtual Function object + * @param vf_data SRIOV VF object + * @param vf_linkstate Link state value + * + * @see rtnl_link_get_linkstate() + * + * Not all hardware supports setting link state. If the feature is unsupported, + * the link change request will fail with -NLE_OPNOTSUPP + */ +void rtnl_link_vf_set_linkstate(struct rtnl_link_vf *vf_data, + uint32_t vf_linkstate) { + vf_data->vf_linkstate = vf_linkstate; + vf_data->ce_mask |= SRIOV_ATTR_LINK_STATE; + + return; +} + +/** + * Get TX Rate Limit of SRIOV Virtual Function + * @arg vf_data SRIOV VF object + * @arg vf_rate Pointer to store VF rate limiting data + * + * @see rtnl_link_get_num_vf() + * @see rtnl_link_set_rate() + * + * When the older rate API has been implemented, the rate member of the struct + * will be set, and the api member will be set to RTNL_LINK_VF_API_OLD. + * When the newer rate API has been implemented, the max_tx_rate + * and/or the minx_tx_rate will be set, and the api member will be set to + * RTNL_LINK_VF_API_NEW. + * + * Old rate API supports only a maximum TX rate. + * ip link set dev vf 0 rate + * New rate API supports minumum and maximum TX rates. + * ip link set dev vf 0 min_tx_rate + * ip link set dev vf 0 max_tx_rate + * + * @return 0 if rate is present and vf_rate is set + * @return -NLE_OBJ_NOTFOUND if information for VF info is not found + * @return -NLE_NOATTR if the VF rate is not set + */ +int rtnl_link_vf_get_rate(struct rtnl_link_vf *vf_data, + struct nl_vf_rate *vf_rate) +{ + int set = 0; + + if (!vf_data) + return -NLE_OBJ_NOTFOUND; + + vf_rate->api = RTNL_LINK_VF_RATE_API_UNSPEC; + vf_rate->rate = 0; + vf_rate->max_tx_rate = 0; + vf_rate->min_tx_rate = 0; + + if (vf_data->ce_mask & SRIOV_ATTR_RATE_MAX) { + if (vf_data->vf_max_tx_rate) { + vf_rate->api = RTNL_LINK_VF_RATE_API_NEW; + vf_rate->max_tx_rate = vf_data->vf_max_tx_rate; + set = 1; + } + } + if (vf_data->ce_mask & SRIOV_ATTR_RATE_MIN) { + if (vf_data->vf_min_tx_rate) { + vf_rate->api = RTNL_LINK_VF_RATE_API_NEW; + vf_rate->min_tx_rate = vf_data->vf_min_tx_rate; + set = 1; + } + } + if ((!set) && (vf_data->ce_mask & SRIOV_ATTR_TX_RATE)) { + if (vf_data->vf_rate) { + vf_rate->api = RTNL_LINK_VF_RATE_API_OLD; + vf_rate->rate = vf_data->vf_rate; + set = 1; + } + } + + if (!set) + return -NLE_NOATTR; + + return 0; +} + +/** + * Set TX Rate Limit of SRIOV Virtual Function object + * @param vf_data SRIOV VF object + * @param vf_rate Rate limiting structure + * + * @see rtnl_link_vf_get_rate() + * + * When setting the rate, the API level must be specificed. + * Valid API levels: + * RTNL_LINK_VF_RATE_API_NEW + * RTNL_LINK_VF_RATE_API_OLD + * + * When using the new API, if either the min_tx_rate or + * max_tx_rate has been set, and the other is being changed, + * you must specify the currently set values to preserve + * them. If this is not done, that setting will be disabled. + * + * Old rate API supports only a maximum TX rate. + * ip link set dev vf 0 rate + * New rate API supports minumum and maximum TX rates. + * ip link set dev vf 0 min_tx_rate + * ip link set dev vf 0 max_tx_rate + * + * Not all hardware supports min_tx_rate. + */ +void rtnl_link_vf_set_rate(struct rtnl_link_vf *vf_data, + struct nl_vf_rate *vf_rate) { + if (vf_rate->api == RTNL_LINK_VF_RATE_API_OLD) { + vf_data->vf_rate = vf_rate->rate; + vf_data->ce_mask |= SRIOV_ATTR_TX_RATE; + } else if (vf_rate->api == RTNL_LINK_VF_RATE_API_NEW) { + vf_data->vf_max_tx_rate = vf_rate->max_tx_rate; + vf_data->ce_mask |= SRIOV_ATTR_RATE_MAX; + + vf_data->vf_min_tx_rate = vf_rate->min_tx_rate; + vf_data->ce_mask |= SRIOV_ATTR_RATE_MIN; + } + + return; +} + +/** + * Get RSS Query EN value of SRIOV Virtual Function + * @arg vf_data SRIOV VF object + * @arg vf_rss_query_en Pointer to store VF RSS Query value + * + * @see rtnl_link_get_num_vf() + * @see rtnl_link_vf_set_rss_query_en() + * + * @return 0 if rss_query_en is present and vf_rss_query_en is set + * @return -NLE_OBJ_NOTFOUND if information for VF info is not found + * @return -NLE_NOATTR if the VF RSS Query EN value is not set + */ +int rtnl_link_vf_get_rss_query_en(struct rtnl_link_vf *vf_data, + uint32_t *vf_rss_query_en) +{ + if (!vf_data) + return -NLE_OBJ_NOTFOUND; + + if (vf_data->ce_mask & SRIOV_ATTR_RSS_QUERY_EN) + *vf_rss_query_en = vf_data->vf_rss_query_en; + else + return -NLE_NOATTR; + + return 0; +} + +/** + * Set RSS configuration querying of SRIOV Virtual Function Object + * @arg vf_data SRIOV VF object + * @arg vf_rss_query_en RSS Query value + * + * @see rtnl_link_vf_get_rss_query_en() + */ +void rtnl_link_vf_set_rss_query_en(struct rtnl_link_vf *vf_data, + uint32_t vf_rss_query_en) { + vf_data->vf_rss_query_en = vf_rss_query_en; + vf_data->ce_mask |= SRIOV_ATTR_RSS_QUERY_EN; + + return; +} + +/** + * Get spoof checking value of SRIOV Virtual Function + * @arg vf_data SRIOV VF object + * @arg vf_spoofchk Pointer to store VF spoofchk value + * + * @see rtnl_link_get_num_vf() + * @see rtnl_link_set_spoofchk() + * + * @return 0 if spoofchk is present and vf_spoofchk is set + * @return -NLE_OBJ_NOTFOUND if information for VF info is not found + * @return -NLE_NOATTR if the VF spoofcheck is not set + */ +int rtnl_link_vf_get_spoofchk(struct rtnl_link_vf *vf_data, + uint32_t *vf_spoofchk) +{ + if (!vf_data) + return -NLE_OBJ_NOTFOUND; + + if (vf_data->ce_mask & SRIOV_ATTR_SPOOFCHK) + *vf_spoofchk = vf_data->vf_spoofchk; + else + return -NLE_NOATTR; + + return 0; +} + +/** + * Set spoof checking value of SRIOV Virtual Function Object + * @param vf_data + * @param vf_spoofchk + * + * @see rtnl_link_vf_get_spoofchk() + */ +void rtnl_link_vf_set_spoofchk(struct rtnl_link_vf *vf_data, + uint32_t vf_spoofchk) { + vf_data->vf_spoofchk = vf_spoofchk; + vf_data->ce_mask |= SRIOV_ATTR_SPOOFCHK; + + return; +} + +/** + * Get value of stat counter for SRIOV Virtual Function + * @arg vf_data SRIOV VF object + * @arg stat Identifier of statistical counter + * @arg vf_stat Pointer to store VF stat value in + * + * @see rtnl_link_get_num_vf() + * + * @return 0 if stat is present and vf_stat is set + * @return -NLE_OBJ_NOTFOUND if information for VF info is not found + * @return -NLE_NOATTR if the VF stat is not set + */ +int rtnl_link_vf_get_stat(struct rtnl_link_vf *vf_data, + rtnl_link_vf_stats_t stat, uint64_t *vf_stat) +{ + if (!vf_data) + return -NLE_OBJ_NOTFOUND; + + if (vf_data->ce_mask & SRIOV_ATTR_STATS) + *vf_stat = vf_data->vf_stats[stat]; + else + return -NLE_NOATTR; + + return 0; +} + +/** + * Get trust setting of SRIOV Virtual Function + * @arg vf_data SRIOV VF object + * @arg vf_trust Pointer to store VF trust value + * + * @see rtnl_link_get_num_vf() + * @see rtnl_link_set_trust() + * + * @return 0 if trust is present and vf_trust is set + * @return -NLE_OBJ_NOTFOUND if information for VF info is not found + * @return -NLE_NOATTR if the VF trust setting is not set + */ +int rtnl_link_vf_get_trust(struct rtnl_link_vf *vf_data, uint32_t *vf_trust) +{ + if (!vf_data) + return -NLE_OBJ_NOTFOUND; + + if (vf_data->ce_mask & SRIOV_ATTR_TRUST) + *vf_trust = vf_data->vf_trust; + else + return -NLE_NOATTR; + + return 0; +} + +/** + * Set user trust setting on SRIOV Virtual Function Object + * @param vf_data + * @param vf_trust + * + * @see rtnl_link_vf_get_trust() + */ +void rtnl_link_vf_set_trust(struct rtnl_link_vf *vf_data, uint32_t vf_trust) { + vf_data->vf_trust = vf_trust; + vf_data->ce_mask |= SRIOV_ATTR_TRUST; + + return; +} + +/** + * Get an array of VLANS on SRIOV Virtual Function + * @arg vf_data SRIOV VF object + * @arg vf_vlans Pointer to nl_vf_vlans_t struct to store vlan info. + * + * @see rtnl_link_get_num_vf() + * + * The SRIOV VF VLANs object must be returned to the SRIOV VF object with + * rtnl_link_vf_vlans_put() when operations are done to prevent memory leaks. + * + * @copydoc pointer_lifetime_warning + * @return 0 if VLAN info is present and vf_vlans is set + * @return -NLE_OBJ_NOTFOUND if information for VF info is not found + * @return -NLE_NOATTR if the VF vlans is not set + */ +int rtnl_link_vf_get_vlans(struct rtnl_link_vf *vf_data, + nl_vf_vlans_t **vf_vlans) { + nl_vf_vlans_t *vf; + + if (!vf_data) + return -NLE_OBJ_NOTFOUND; + + if (vf_data->ce_mask & SRIOV_ATTR_VLAN) { + vf = vf_data->vf_vlans; + vf->ce_refcnt++; + *vf_vlans = vf; + } else + return -NLE_NOATTR; + + return 0; +} + +/** + * Add a SRIOV VF VLANs object to the SRIOV Virtual Function Object + * @param vf_data SRIOV VF object + * @param vf_vlans SRIOV VF VLANs object + * + * @see rtnl_link_vf_get_vlans() + * @see rtnl_link_vf_vlan_alloc() + * + * This function assigns ownership of the SRIOV VF object \p vf_vlans + * to the SRIOV Virtual Function object \p vf_data. Do not use + * rtnl_link_vf_vlan_put() on \p vf_vlans after this. + */ +void rtnl_link_vf_set_vlans(struct rtnl_link_vf *vf_data, + nl_vf_vlans_t *vf_vlans) { + if (!vf_data||!vf_vlans) + return; + + vf_data->vf_vlans = vf_vlans; + vf_data->vf_vlans->ce_refcnt++; + vf_data->ce_mask |= SRIOV_ATTR_VLAN; + + return; +} + +/** + * Allocate a SRIOV VF VLAN object + * @param vf_vlans Pointer to store VLAN object at + * @param vlan_count Number of VLANs that will be stored in VLAN object + * + * The SRIOV VF VLANs object must be returned to the sRIOV VF object with + * rtnl_link_vf_vlan_put() when operations are done to prevent memory leaks. + * + * @return 0 if VLAN object is created and vf_vlans is set. + * @return -NLE_NOMEM if object could not be allocated. + * @return -NLE_INVAL if vlan_count is more than supported by SRIOV VF + */ +int rtnl_link_vf_vlan_alloc(nl_vf_vlans_t **vf_vlans, int vlan_count) { + nl_vf_vlans_t *vlans; + nl_vf_vlan_info_t *vlan_info; + + if (vlan_count > MAX_VLAN_LIST_LEN) + return -NLE_INVAL; + + vlans = calloc(1, sizeof(*vlans)); + if (!vlans) + return -NLE_NOMEM; + + vlan_info = calloc(vlan_count+1, sizeof(*vlan_info)); + if (!vlan_info) { + free(vlans); + return -NLE_NOMEM; + } + + NL_DBG(4, "Allocated new SRIOV VF VLANs object %p\n", vlans); + + vlans->ce_refcnt = 1; + vlans->size = vlan_count; + vlans->vlans = vlan_info; + *vf_vlans = vlans; + + return 0; +} + +/** + * Free an allocated SRIOV VF VLANs object + * @param vf_vlans SRIOV VF VLANs object + */ +void rtnl_link_vf_vlan_free(nl_vf_vlans_t *vf_vlans) { + if (!vf_vlans) + return; + + if (vf_vlans->ce_refcnt > 0) + NL_DBG(1, "Warning: Freeing SRIOV VF VLANs object in use...\n"); + + NL_DBG(4, "Freed SRIOV VF object %p\n", vf_vlans); + free(vf_vlans->vlans); + free(vf_vlans); + + return; +} + +/** + * Return SRIOV VF VLANs object to the owning SRIOV VF object. + * @param vf_vlans SRIOV VF VLANs object + */ +void rtnl_link_vf_vlan_put(nl_vf_vlans_t *vf_vlans) { + if (!vf_vlans) + return; + + vf_vlans->ce_refcnt--; + NL_DBG(4, "Returned SRIOV VF VLANs object reference %p, %i remaining\n", + vf_vlans, vf_vlans->ce_refcnt); + + if (vf_vlans->ce_refcnt < 0) + BUG(); + + if (vf_vlans->ce_refcnt <= 0) + rtnl_link_vf_vlan_free(vf_vlans); + + return; +} + +/** @} */ + +/** + * @name Utilities + * @{ + */ + +static const struct trans_tbl vf_link_states[] = { + __ADD(IFLA_VF_LINK_STATE_AUTO, autodetect), + __ADD(IFLA_VF_LINK_STATE_ENABLE, up), + __ADD(IFLA_VF_LINK_STATE_DISABLE, down), +}; + +char *rtnl_link_vf_linkstate2str(uint32_t ls, char *buf, size_t len) +{ + return __type2str(ls, buf, len, vf_link_states, + ARRAY_SIZE(vf_link_states)); +} + +int rtnl_link_vf_str2linkstate(const char *name) +{ + return __str2type(name, vf_link_states, ARRAY_SIZE(vf_link_states)); +} + +static const struct trans_tbl vf_vlan_proto[] = { + __ADD(ETH_P_8021Q, 8021Q), + __ADD(ETH_P_8021AD, 8021AD), +}; + +char *rtnl_link_vf_vlanproto2str(uint16_t proto, char *buf, size_t len) +{ + return __type2str(proto, buf, len, vf_vlan_proto, + ARRAY_SIZE(vf_vlan_proto)); +} + +int rtnl_link_vf_str2vlanproto(const char *name) +{ + return __str2type(name, vf_vlan_proto, ARRAY_SIZE(vf_vlan_proto)); +} + +/* Return a guid from a format checked string. + * Format string must be xx:xx:xx:xx:xx:xx:xx:xx where XX can be an + * arbitrary hex digit + * + * Function modified from original at iproute2/lib/utils.c:get_guid() + * Original by Eli Cohen . + * iproute2 git commit d91fb3f4c7e4dba806541bdc90b1fb60a3581541 + */ +int rtnl_link_vf_str2guid(uint64_t *guid, const char *guid_s) { + unsigned long int tmp; + char *endptr; + int i; + + if (strlen(guid_s) != RTNL_VF_GUID_STR_LEN) + return -1; + + for (i = 0; i < 7; i++) { + if (guid_s[2 + i * 3] != ':') + return -1; + } + + *guid = 0; + for (i = 0; i < 8; i++) { + tmp = strtoul(guid_s + i * 3, &endptr, 16); + if (endptr != guid_s + i * 3 + 2) + return -1; + + if (tmp > 255) + return -1; + + *guid |= tmp << (56 - 8 * i); + } + + return 0; +} + +/** @} */ + +/** @} */ diff --git a/lib/route/link/team.c b/lib/route/link/team.c new file mode 100644 index 0000000..0f1161b --- /dev/null +++ b/lib/route/link/team.c @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2015 Jonas Johansson + */ + +/** + * @ingroup link + * @defgroup team Team + * + * @details + * \b Link Type Name: "team" + * + * @route_doc{link_team, Team Documentation} + * @{ + */ + +#include "nl-default.h" + +#include +#include + +#include "link-api.h" + +/** + * Allocate link object of type team + * + * @return Allocated link object or NULL. + */ +struct rtnl_link *rtnl_link_team_alloc(void) +{ + struct rtnl_link *link; + + if (!(link = rtnl_link_alloc())) + return NULL; + + if (rtnl_link_set_type(link, "team") < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Create a new kernel team device + * @arg sock netlink socket + * @arg name name of team device or NULL + * @arg opts team options (currently unused) + * + * Creates a new team device in the kernel. If no name is + * provided, the kernel will automatically pick a name of the + * form "type%d" (e.g. team0, vlan1, etc.) + * + * The \a opts argument is currently unused. In the future, it + * may be used to carry additional team options to be set + * when creating the team device. + * + * @note When letting the kernel assign a name, it will become + * difficult to retrieve the interface afterwards because + * you have to guess the name the kernel has chosen. It is + * therefore not recommended to not provide a device name. + * + * @see rtnl_link_team_enslave() + * @see rtnl_link_team_release() + * + * @return 0 on success or a negative error code + */ +int rtnl_link_team_add(struct nl_sock *sock, const char *name, + struct rtnl_link *opts) +{ + struct rtnl_link *link; + int err; + + if (!(link = rtnl_link_team_alloc())) + return -NLE_NOMEM; + + if (!name && opts) + name = rtnl_link_get_name(opts); + + if (name) + rtnl_link_set_name(link, name); + + err = rtnl_link_add(sock, link, NLM_F_CREATE); + + rtnl_link_put(link); + + return err; +} + +static struct rtnl_link_info_ops team_info_ops = { + .io_name = "team", +}; + +static void _nl_init team_init(void) +{ + rtnl_link_register_info(&team_info_ops); +} + +static void _nl_exit team_exit(void) +{ + rtnl_link_unregister_info(&team_info_ops); +} + +/** @} */ diff --git a/lib/route/link/veth.c b/lib/route/link/veth.c new file mode 100644 index 0000000..be4b795 --- /dev/null +++ b/lib/route/link/veth.c @@ -0,0 +1,305 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Cong Wang + */ + +/** + * @ingroup link + * @defgroup veth VETH + * Virtual Ethernet + * + * @details + * \b Link Type Name: "veth" + * + * @route_doc{link_veth, VETH Documentation} + * + * @{ + */ + +#include "nl-default.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "nl-route.h" +#include "link-api.h" + +static struct nla_policy veth_policy[VETH_INFO_MAX+1] = { + [VETH_INFO_PEER] = { .minlen = sizeof(struct ifinfomsg) }, +}; + +static int veth_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[VETH_INFO_MAX+1]; + struct nlattr *peer_tb[IFLA_MAX + 1]; + struct rtnl_link *peer = link->l_info; + int err; + + NL_DBG(3, "Parsing veth link info\n"); + + if ((err = nla_parse_nested(tb, VETH_INFO_MAX, data, veth_policy)) < 0) + goto errout; + + if (tb[VETH_INFO_PEER]) { + struct nlattr *nla_peer; + struct ifinfomsg *ifi; + + nla_peer = tb[VETH_INFO_PEER]; + ifi = nla_data(nla_peer); + + peer->l_family = ifi->ifi_family; + peer->l_arptype = ifi->ifi_type; + peer->l_index = ifi->ifi_index; + peer->l_flags = ifi->ifi_flags; + peer->l_change = ifi->ifi_change; + err = nla_parse(peer_tb, IFLA_MAX, (struct nlattr *) + ((char *) nla_data(nla_peer) + sizeof(struct ifinfomsg)), + nla_len(nla_peer) - sizeof(struct ifinfomsg), + rtln_link_policy); + if (err < 0) + goto errout; + + err = rtnl_link_info_parse(peer, peer_tb); + if (err < 0) + goto errout; + } + + err = 0; + +errout: + return err; +} + +static void veth_dump_line(struct rtnl_link *link, struct nl_dump_params *p) +{ +} + +static void veth_dump_details(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct rtnl_link *peer = link->l_info; + char *name; + name = rtnl_link_get_name(peer); + nl_dump(p, " peer "); + if (name) + nl_dump_line(p, "%s\n", name); + else + nl_dump_line(p, "%u\n", peer->l_index); +} + +static int veth_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct rtnl_link *dst_peer = NULL, *src_peer = src->l_info; + + /* we are calling nl_object_clone() recursively, this should + * happen only once */ + if (src_peer) { + src_peer->l_info = NULL; + dst_peer = (struct rtnl_link *)nl_object_clone(OBJ_CAST(src_peer)); + if (!dst_peer) + return -NLE_NOMEM; + src_peer->l_info = src; + dst_peer->l_info = dst; + } + dst->l_info = dst_peer; + return 0; +} + +static int veth_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct rtnl_link *peer = link->l_info; + struct ifinfomsg ifi; + struct nlattr *data, *info_peer; + + memset(&ifi, 0, sizeof ifi); + ifi.ifi_family = peer->l_family; + ifi.ifi_type = peer->l_arptype; + ifi.ifi_index = peer->l_index; + ifi.ifi_flags = peer->l_flags; + ifi.ifi_change = peer->l_change; + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + return -NLE_MSGSIZE; + if (!(info_peer = nla_nest_start(msg, VETH_INFO_PEER))) + return -NLE_MSGSIZE; + if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) + return -NLE_MSGSIZE; + rtnl_link_fill_info(msg, peer); + nla_nest_end(msg, info_peer); + nla_nest_end(msg, data); + + return 0; +} + +static int veth_alloc(struct rtnl_link *link) +{ + struct rtnl_link *peer; + int err; + + /* return early if we are in recursion */ + if (link->l_info) + return 0; + + if (!(peer = rtnl_link_alloc())) + return -NLE_NOMEM; + + /* We don't need to hold a reference here, as link and + * its peer should always be freed together. + */ + peer->l_info = link; + if ((err = rtnl_link_set_type(peer, "veth")) < 0) { + rtnl_link_put(peer); + return err; + } + + link->l_info = peer; + return 0; +} + +static void veth_free(struct rtnl_link *link) +{ + struct rtnl_link *peer = link->l_info; + if (peer) { + link->l_info = NULL; + /* avoid calling this recursively */ + peer->l_info = NULL; + rtnl_link_put(peer); + } + /* the caller should finally free link */ +} + +static struct rtnl_link_info_ops veth_info_ops = { + .io_name = "veth", + .io_parse = veth_parse, + .io_dump = { + [NL_DUMP_LINE] = veth_dump_line, + [NL_DUMP_DETAILS] = veth_dump_details, + }, + .io_alloc = veth_alloc, + .io_clone = veth_clone, + .io_put_attrs = veth_put_attrs, + .io_free = veth_free, +}; + +/** @cond SKIP */ + +#define IS_VETH_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &veth_info_ops) { \ + APPBUG("Link is not a veth link. set type \"veth\" first."); \ + return NULL; \ + } +/** @endcond */ + +/** + * @name VETH Object + * @{ + */ + +/** + * Allocate link object of type veth + * + * @return Allocated link object or NULL. + */ +struct rtnl_link *rtnl_link_veth_alloc(void) +{ + struct rtnl_link *link; + + if (!(link = rtnl_link_alloc())) + return NULL; + if (rtnl_link_set_type(link, "veth") < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Get the peer link of a veth link + * + * @return the peer link object. + */ +struct rtnl_link *rtnl_link_veth_get_peer(struct rtnl_link *link) +{ + IS_VETH_LINK_ASSERT(link); + nl_object_get(OBJ_CAST(link->l_info)); + return link->l_info; +} + +/** + * Release a veth link and its peer + * + */ +void rtnl_link_veth_release(struct rtnl_link *link) +{ + veth_free(link); + rtnl_link_put(link); +} + +/** + * Check if link is a veth link + * @arg link Link object + * + * @return True if link is a veth link, otherwise false is returned. + */ +int rtnl_link_is_veth(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "veth"); +} + +/** + * Create a new kernel veth device + * @arg sock netlink socket + * @arg name name of the veth device or NULL + * @arg peer_name name of its peer or NULL + * @arg pid pid of the process in the new netns + * + * Creates a new veth device pair in the kernel and move the peer + * to the network namespace where the process is. If no name is + * provided, the kernel will automatically pick a name of the + * form "veth%d" (e.g. veth0, veth1, etc.) + * + * @return 0 on success or a negative error code + */ +int rtnl_link_veth_add(struct nl_sock *sock, const char *name, + const char *peer_name, pid_t pid) +{ + struct rtnl_link *link, *peer; + int err = -NLE_NOMEM; + + if (!(link = rtnl_link_veth_alloc())) + return -NLE_NOMEM; + peer = link->l_info; + + if (name) + rtnl_link_set_name(link, name); + if (peer_name) + rtnl_link_set_name(peer, peer_name); + + rtnl_link_set_ns_pid(peer, pid); + err = rtnl_link_add(sock, link, NLM_F_CREATE | NLM_F_EXCL); + + rtnl_link_put(link); + return err; +} + +/** @} */ + +static void _nl_init veth_init(void) +{ + rtnl_link_register_info(&veth_info_ops); +} + +static void _nl_exit veth_exit(void) +{ + rtnl_link_unregister_info(&veth_info_ops); +} + +/** @} */ diff --git a/lib/route/link/vlan.c b/lib/route/link/vlan.c index 9bbe7d5..60e4358 100644 --- a/lib/route/link/vlan.c +++ b/lib/route/link/vlan.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/link/vlan.c VLAN Link Info - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2013 Thomas Graf */ @@ -22,26 +16,32 @@ * @{ */ -#include +#include "nl-default.h" + +#include + #include #include #include #include #include -#include #include -#include +#include "nl-route.h" +#include "link-api.h" /** @cond SKIP */ #define VLAN_HAS_ID (1<<0) #define VLAN_HAS_FLAGS (1<<1) #define VLAN_HAS_INGRESS_QOS (1<<2) #define VLAN_HAS_EGRESS_QOS (1<<3) +#define VLAN_HAS_PROTOCOL (1<<4) struct vlan_info { uint16_t vi_vlan_id; + uint16_t vi_protocol; + unsigned int vi_ingress_qos_mask:(VLAN_PRIO_MAX+1); uint32_t vi_flags; uint32_t vi_flags_mask; uint32_t vi_ingress_qos[VLAN_PRIO_MAX+1]; @@ -58,16 +58,23 @@ static struct nla_policy vlan_policy[IFLA_VLAN_MAX+1] = { [IFLA_VLAN_FLAGS] = { .minlen = sizeof(struct ifla_vlan_flags) }, [IFLA_VLAN_INGRESS_QOS] = { .type = NLA_NESTED }, [IFLA_VLAN_EGRESS_QOS] = { .type = NLA_NESTED }, + [IFLA_VLAN_PROTOCOL] = { .type = NLA_U16 }, }; static int vlan_alloc(struct rtnl_link *link) { struct vlan_info *vi; - if ((vi = calloc(1, sizeof(*vi))) == NULL) - return -NLE_NOMEM; + if (link->l_info) { + vi = link->l_info; + free(vi->vi_egress_qos); + memset(link->l_info, 0, sizeof(*vi)); + } else { + if ((vi = calloc(1, sizeof(*vi))) == NULL) + return -NLE_NOMEM; - link->l_info = vi; + link->l_info = vi; + } return 0; } @@ -79,7 +86,7 @@ static int vlan_parse(struct rtnl_link *link, struct nlattr *data, struct vlan_info *vi; int err; - NL_DBG(3, "Parsing VLAN link info"); + NL_DBG(3, "Parsing VLAN link info\n"); if ((err = nla_parse_nested(tb, IFLA_VLAN_MAX, data, vlan_policy)) < 0) goto errout; @@ -94,6 +101,11 @@ static int vlan_parse(struct rtnl_link *link, struct nlattr *data, vi->vi_mask |= VLAN_HAS_ID; } + if (tb[IFLA_VLAN_PROTOCOL]) { + vi->vi_protocol = nla_get_u16(tb[IFLA_VLAN_PROTOCOL]); + vi->vi_mask |= VLAN_HAS_PROTOCOL; + } + if (tb[IFLA_VLAN_FLAGS]) { struct ifla_vlan_flags flags; nla_memcpy(&flags, tb[IFLA_VLAN_FLAGS], sizeof(flags)); @@ -107,6 +119,7 @@ static int vlan_parse(struct rtnl_link *link, struct nlattr *data, struct nlattr *nla; int remaining; + vi->vi_ingress_qos_mask = 0; memset(vi->vi_ingress_qos, 0, sizeof(vi->vi_ingress_qos)); nla_for_each_nested(nla, tb[IFLA_VLAN_INGRESS_QOS], remaining) { @@ -118,6 +131,17 @@ static int vlan_parse(struct rtnl_link *link, struct nlattr *data, return -NLE_INVAL; } + /* Kernel will not explicitly serialize mappings with "to" zero + * (although they are implicitly set). + * + * Thus we only mark those as "set" which are explicitly sent. + * That is similar to what we do with the egress map and it preserves + * previous behavior before NL_CAPABILITY_RTNL_LINK_VLAN_INGRESS_MAP_CLEAR. + * + * It matters only when a received object is send back to kernel to modify + * the link. + */ + vi->vi_ingress_qos_mask |= (1 << map->from); vi->vi_ingress_qos[map->from] = map->to; } @@ -137,7 +161,7 @@ static int vlan_parse(struct rtnl_link *link, struct nlattr *data, /* align to have a little reserve */ vi->vi_egress_size = (i + 32) & ~31; - vi->vi_egress_qos = calloc(vi->vi_egress_size, sizeof(*map)); + vi->vi_egress_qos = calloc(vi->vi_egress_size, sizeof(*vi->vi_egress_qos)); if (vi->vi_egress_qos == NULL) return -NLE_NOMEM; @@ -186,13 +210,18 @@ static void vlan_dump_details(struct rtnl_link *link, struct nl_dump_params *p) char buf[64]; rtnl_link_vlan_flags2str(vi->vi_flags, buf, sizeof(buf)); - nl_dump_line(p, " vlan-info id %d <%s>\n", vi->vi_vlan_id, buf); + nl_dump_line(p, " vlan-info id %d <%s>", vi->vi_vlan_id, buf); + + if (vi->vi_mask & VLAN_HAS_PROTOCOL) + nl_dump_line(p, " vlan protocol <%d>", ntohs(vi->vi_protocol)); + + nl_dump(p, "\n"); if (vi->vi_mask & VLAN_HAS_INGRESS_QOS) { nl_dump_line(p, " ingress vlan prio -> qos/socket prio mapping:\n"); for (i = 0, printed = 0; i <= VLAN_PRIO_MAX; i++) { - if (vi->vi_ingress_qos[i]) { + if (vi->vi_ingress_qos_mask & (1 << i)) { if (printed == 0) nl_dump_line(p, " "); nl_dump(p, "%x -> %#08x, ", @@ -232,19 +261,28 @@ static int vlan_clone(struct rtnl_link *dst, struct rtnl_link *src) { struct vlan_info *vdst, *vsrc = src->l_info; int err; + struct vlan_map *p = NULL; dst->l_info = NULL; if ((err = rtnl_link_set_type(dst, "vlan")) < 0) return err; vdst = dst->l_info; - vdst->vi_egress_qos = calloc(vsrc->vi_egress_size, - sizeof(struct vlan_map)); - if (!vdst->vi_egress_qos) - return -NLE_NOMEM; + if (vsrc->vi_negress) { + p = calloc(vsrc->vi_negress, + sizeof(struct vlan_map)); + if (!p) + return -NLE_NOMEM; + } - memcpy(vdst->vi_egress_qos, vsrc->vi_egress_qos, - vsrc->vi_egress_size * sizeof(struct vlan_map)); + *vdst = *vsrc; + + if (vsrc->vi_negress) { + vdst->vi_egress_size = vsrc->vi_negress; + vdst->vi_egress_qos = p; + memcpy(vdst->vi_egress_qos, vsrc->vi_egress_qos, + vsrc->vi_negress * sizeof(struct vlan_map)); + } return 0; } @@ -253,13 +291,19 @@ static int vlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link) { struct vlan_info *vi = link->l_info; struct nlattr *data; + int nest_count = 0; if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) - return -NLE_MSGSIZE; + goto nla_put_failure; + + nest_count++; if (vi->vi_mask & VLAN_HAS_ID) NLA_PUT_U16(msg, IFLA_VLAN_ID, vi->vi_vlan_id); + if (vi->vi_mask & VLAN_HAS_PROTOCOL) + NLA_PUT_U16(msg, IFLA_VLAN_PROTOCOL, vi->vi_protocol); + if (vi->vi_mask & VLAN_HAS_FLAGS) { struct ifla_vlan_flags flags = { .flags = vi->vi_flags, @@ -277,8 +321,10 @@ static int vlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link) if (!(qos = nla_nest_start(msg, IFLA_VLAN_INGRESS_QOS))) goto nla_put_failure; + nest_count++; + for (i = 0; i <= VLAN_PRIO_MAX; i++) { - if (vi->vi_ingress_qos[i]) { + if (vi->vi_ingress_qos_mask & (1 << i)) { map.from = i; map.to = vi->vi_ingress_qos[i]; @@ -287,6 +333,7 @@ static int vlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link) } nla_nest_end(msg, qos); + nest_count--; } if (vi->vi_mask & VLAN_HAS_EGRESS_QOS) { @@ -297,6 +344,8 @@ static int vlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link) if (!(qos = nla_nest_start(msg, IFLA_VLAN_EGRESS_QOS))) goto nla_put_failure; + nest_count++; + for (i = 0; i < vi->vi_negress; i++) { map.from = vi->vi_egress_qos[i].vm_from; map.to = vi->vi_egress_qos[i].vm_to; @@ -305,13 +354,16 @@ static int vlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link) } nla_nest_end(msg, qos); + nest_count--; } nla_nest_end(msg, data); + return 0; nla_put_failure: - - return 0; + for (; nest_count > 0; nest_count--) + nla_nest_cancel(msg, data); + return -NLE_MSGSIZE; } static struct rtnl_link_info_ops vlan_info_ops = { @@ -348,12 +400,11 @@ static struct rtnl_link_info_ops vlan_info_ops = { struct rtnl_link *rtnl_link_vlan_alloc(void) { struct rtnl_link *link; - int err; if (!(link = rtnl_link_alloc())) return NULL; - if ((err = rtnl_link_set_type(link, "vlan")) < 0) { + if (rtnl_link_set_type(link, "vlan") < 0) { rtnl_link_put(link); return NULL; } @@ -410,6 +461,45 @@ int rtnl_link_vlan_get_id(struct rtnl_link *link) } /** + * Set VLAN protocol + * @arg link Link object + * @arg protocol VLAN protocol in network byte order. + * Probably you want to set it to something like htons(ETH_P_8021Q). + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vlan_set_protocol(struct rtnl_link *link, uint16_t protocol) +{ + struct vlan_info *vi = link->l_info; + + IS_VLAN_LINK_ASSERT(link); + + vi->vi_protocol = protocol; + vi->vi_mask |= VLAN_HAS_PROTOCOL; + + return 0; +} + +/** + * Get VLAN protocol + * @arg link Link object + * + * @return VLAN protocol in network byte order like htons(ETH_P_8021Q), + * 0 if not set or a negative error code. + */ +int rtnl_link_vlan_get_protocol(struct rtnl_link *link) +{ + struct vlan_info *vi = link->l_info; + + IS_VLAN_LINK_ASSERT(link); + + if (vi->vi_mask & VLAN_HAS_PROTOCOL) + return vi->vi_protocol; + else + return 0; +} + +/** * Set VLAN flags * @arg link Link object * @arg flags VLAN flags @@ -481,6 +571,7 @@ int rtnl_link_vlan_set_ingress_map(struct rtnl_link *link, int from, if (from < 0 || from > VLAN_PRIO_MAX) return -NLE_INVAL; + vi->vi_ingress_qos_mask |= (1 << from); vi->vi_ingress_qos[from] = to; vi->vi_mask |= VLAN_HAS_INGRESS_QOS; @@ -511,10 +602,16 @@ int rtnl_link_vlan_set_egress_map(struct rtnl_link *link, uint32_t from, int to) return -NLE_INVAL; if (vi->vi_negress >= vi->vi_egress_size) { - int new_size = vi->vi_egress_size + 32; + uint32_t new_size = vi->vi_egress_size + 1 + vi->vi_egress_size / 2; + size_t bytes; void *ptr; - ptr = realloc(vi->vi_egress_qos, new_size); + if (new_size < vi->vi_egress_size) + return -NLE_NOMEM; + bytes = (size_t) new_size * sizeof(struct vlan_map); + if (bytes / sizeof (struct vlan_map) != new_size) + return -NLE_NOMEM; + ptr = realloc(vi->vi_egress_qos, bytes); if (!ptr) return -NLE_NOMEM; @@ -553,7 +650,11 @@ struct vlan_map *rtnl_link_vlan_get_egress_map(struct rtnl_link *link, /** @} */ static const struct trans_tbl vlan_flags[] = { - __ADD(VLAN_FLAG_REORDER_HDR, reorder_hdr) + __ADD(VLAN_FLAG_REORDER_HDR, reorder_hdr), + __ADD(VLAN_FLAG_GVRP, gvrp), + __ADD(VLAN_FLAG_LOOSE_BINDING, loose_binding), + __ADD(VLAN_FLAG_MVRP, mvrp), + __ADD(VLAN_FLAG_BRIDGE_BINDING, bridge_binding), }; /** @@ -574,12 +675,12 @@ int rtnl_link_vlan_str2flags(const char *name) /** @} */ -static void __init vlan_init(void) +static void _nl_init vlan_init(void) { rtnl_link_register_info(&vlan_info_ops); } -static void __exit vlan_exit(void) +static void _nl_exit vlan_exit(void) { rtnl_link_unregister_info(&vlan_info_ops); } diff --git a/lib/route/link/vrf.c b/lib/route/link/vrf.c new file mode 100644 index 0000000..17cb3bd --- /dev/null +++ b/lib/route/link/vrf.c @@ -0,0 +1,260 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2015 Cumulus Networks. All rights reserved. + * Copyright (c) 2015 David Ahern + */ + +/** + * @ingroup link + * @defgroup vrf VRF + * Virtual Routing and Forwarding link module + * + * @details + * \b Link Type Name: "vrf" + * + * @route_doc{link_vrf, VRF Documentation} + * + * @{ + */ + +#include "nl-default.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "nl-route.h" +#include "link-api.h" + +#define VRF_TABLE_ID_MAX RT_TABLE_MAX + +/** @cond SKIP */ +#define VRF_HAS_TABLE_ID (1<<0) + +struct vrf_info { + uint32_t table_id; + uint32_t vi_mask; +}; + +/** @endcond */ + +static struct nla_policy vrf_policy[IFLA_VRF_MAX + 1] = { + [IFLA_VRF_TABLE] = { .type = NLA_U32 }, +}; + +static int vrf_alloc(struct rtnl_link *link) +{ + struct vrf_info *vi; + + if (link->l_info) { + memset(link->l_info, 0, sizeof (*vi)); + return 0; + } + + if ((vi = calloc(1, sizeof(*vi))) == NULL) + return -NLE_NOMEM; + + link->l_info = vi; + + return 0; +} + +static int vrf_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_VRF_MAX+1]; + struct vrf_info *vi; + int err; + + NL_DBG(3, "Parsing VRF link info"); + + if ((err = nla_parse_nested(tb, IFLA_VRF_MAX, data, vrf_policy)) < 0) + goto errout; + + if ((err = vrf_alloc(link)) < 0) + goto errout; + + vi = link->l_info; + + if (tb[IFLA_VRF_TABLE]) { + vi->table_id = nla_get_u32(tb[IFLA_VRF_TABLE]); + vi->vi_mask |= VRF_HAS_TABLE_ID; + } + + err = 0; + +errout: + return err; +} + +static void vrf_free(struct rtnl_link *link) +{ + free(link->l_info); + link->l_info = NULL; +} + +static int vrf_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct vrf_info *vdst, *vsrc = src->l_info; + int err; + + dst->l_info = NULL; + if ((err = rtnl_link_set_type(dst, "vrf")) < 0) + return err; + vdst = dst->l_info; + + BUG_ON(!vdst || !vsrc); + + memcpy(vdst, vsrc, sizeof(struct vrf_info)); + + return 0; +} + +static int vrf_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct vrf_info *vi = link->l_info; + struct nlattr *data; + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + return -NLE_NOMEM; + + if (vi->vi_mask & VRF_HAS_TABLE_ID) { + NLA_PUT_U32(msg, IFLA_VRF_TABLE, vi->table_id); + } + + nla_nest_end(msg, data); + +nla_put_failure: + + return 0; +} + +static void vrf_dump(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct vrf_info *vi = link->l_info; + + if (vi->vi_mask & VRF_HAS_TABLE_ID) { + nl_dump(p, "table-id %u", vi->table_id); + } +} + +static struct rtnl_link_info_ops vrf_info_ops = { + .io_name = "vrf", + .io_alloc = vrf_alloc, + .io_parse = vrf_parse, + .io_dump = { + [NL_DUMP_LINE] = vrf_dump, + [NL_DUMP_DETAILS] = vrf_dump, + }, + .io_clone = vrf_clone, + .io_put_attrs = vrf_put_attrs, + .io_free = vrf_free, +}; + +/** @cond SKIP */ +#define IS_VRF_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &vrf_info_ops) { \ + APPBUG("Link is not a VRF link. set type \"vrf\" first."); \ + return -NLE_OPNOTSUPP; \ + } +/** @endcond */ + +/** + * @name VRF Object + * @{ + */ + +/** + * Allocate link object of type VRF + * + * @return Allocated link object or NULL. + */ +struct rtnl_link *rtnl_link_vrf_alloc(void) +{ + struct rtnl_link *link; + + if (!(link = rtnl_link_alloc())) + return NULL; + + if (rtnl_link_set_type(link, "vrf") < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if link is a VRF link + * @arg link Link object + * + * @return True if link is a VRF link, otherwise false is returned. + */ +int rtnl_link_is_vrf(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "vrf"); +} + +/** + * Get VRF table id + * @arg link Link object + * @arg id Pointer to store table identifier + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vrf_get_tableid(struct rtnl_link *link, uint32_t *id) +{ + struct vrf_info *vi = link->l_info; + + IS_VRF_LINK_ASSERT(link); + if(!id) + return -NLE_INVAL; + + if (vi->vi_mask & VRF_HAS_TABLE_ID) + *id = vi->table_id; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set VRF table id + * @arg link Link object + * @arg id Table identifier associated with VRF link + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vrf_set_tableid(struct rtnl_link *link, uint32_t id) +{ + struct vrf_info *vi = link->l_info; + + IS_VRF_LINK_ASSERT(link); + + _NL_STATIC_ASSERT(VRF_TABLE_ID_MAX == UINT32_MAX); + + vi->table_id = id; + vi->vi_mask |= VRF_HAS_TABLE_ID; + + return 0; +} + +/** @} */ + +static void _nl_init vrf_init(void) +{ + rtnl_link_register_info(&vrf_info_ops); +} + +static void _nl_exit vrf_exit(void) +{ + rtnl_link_unregister_info(&vrf_info_ops); +} + +/** @} */ diff --git a/lib/route/link/vxlan.c b/lib/route/link/vxlan.c new file mode 100644 index 0000000..4606dd5 --- /dev/null +++ b/lib/route/link/vxlan.c @@ -0,0 +1,1787 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Yasunobu Chiba + */ + +/** + * @ingroup link + * @defgroup vxlan VXLAN + * Virtual eXtensible Local Area Network link module + * + * @details + * \b Link Type Name: "vxlan" + * + * @route_doc{link_vxlan, VXLAN Documentation} + * + * @{ + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "nl-route.h" +#include "link-api.h" + +/** @cond SKIP */ +#define VXLAN_ATTR_ID (1<<0) +#define VXLAN_ATTR_GROUP (1<<1) +#define VXLAN_ATTR_LINK (1<<2) +#define VXLAN_ATTR_LOCAL (1<<3) +#define VXLAN_ATTR_TTL (1<<4) +#define VXLAN_ATTR_TOS (1<<5) +#define VXLAN_ATTR_LEARNING (1<<6) +#define VXLAN_ATTR_AGEING (1<<7) +#define VXLAN_ATTR_LIMIT (1<<8) +#define VXLAN_ATTR_PORT_RANGE (1<<9) +#define VXLAN_ATTR_PROXY (1<<10) +#define VXLAN_ATTR_RSC (1<<11) +#define VXLAN_ATTR_L2MISS (1<<12) +#define VXLAN_ATTR_L3MISS (1<<13) +#define VXLAN_ATTR_GROUP6 (1<<14) +#define VXLAN_ATTR_LOCAL6 (1<<15) +#define VXLAN_ATTR_PORT (1<<16) +#define VXLAN_ATTR_UDP_CSUM (1<<17) +#define VXLAN_ATTR_UDP_ZERO_CSUM6_TX (1<<18) +#define VXLAN_ATTR_UDP_ZERO_CSUM6_RX (1<<19) +#define VXLAN_ATTR_REMCSUM_TX (1<<20) +#define VXLAN_ATTR_REMCSUM_RX (1<<21) +#define VXLAN_ATTR_COLLECT_METADATA (1<<22) +#define VXLAN_ATTR_LABEL (1<<23) +#define VXLAN_ATTR_FLAGS (1<<24) + +struct vxlan_info +{ + uint32_t vxi_id; + uint32_t vxi_group; + struct in6_addr vxi_group6; + uint32_t vxi_link; + uint32_t vxi_local; + struct in6_addr vxi_local6; + uint8_t vxi_ttl; + uint8_t vxi_tos; + uint8_t vxi_learning; + uint8_t vxi_flags; + uint32_t vxi_ageing; + uint32_t vxi_limit; + struct ifla_vxlan_port_range vxi_port_range; + uint8_t vxi_proxy; + uint8_t vxi_rsc; + uint8_t vxi_l2miss; + uint8_t vxi_l3miss; + uint16_t vxi_port; + uint8_t vxi_udp_csum; + uint8_t vxi_udp_zero_csum6_tx; + uint8_t vxi_udp_zero_csum6_rx; + uint8_t vxi_remcsum_tx; + uint8_t vxi_remcsum_rx; + uint8_t vxi_collect_metadata; + uint32_t vxi_label; + uint32_t ce_mask; +}; + +/** @endcond */ + +static struct nla_policy vxlan_policy[IFLA_VXLAN_MAX+1] = { + [IFLA_VXLAN_ID] = { .type = NLA_U32 }, + [IFLA_VXLAN_GROUP] = { .minlen = sizeof(uint32_t) }, + [IFLA_VXLAN_GROUP6] = { .minlen = sizeof(struct in6_addr) }, + [IFLA_VXLAN_LINK] = { .type = NLA_U32 }, + [IFLA_VXLAN_LOCAL] = { .minlen = sizeof(uint32_t) }, + [IFLA_VXLAN_LOCAL6] = { .minlen = sizeof(struct in6_addr) }, + [IFLA_VXLAN_TTL] = { .type = NLA_U8 }, + [IFLA_VXLAN_TOS] = { .type = NLA_U8 }, + [IFLA_VXLAN_LABEL] = { .type = NLA_U32 }, + [IFLA_VXLAN_LEARNING] = { .type = NLA_U8 }, + [IFLA_VXLAN_AGEING] = { .type = NLA_U32 }, + [IFLA_VXLAN_LIMIT] = { .type = NLA_U32 }, + [IFLA_VXLAN_PORT_RANGE] = { .minlen = sizeof(struct ifla_vxlan_port_range) }, + [IFLA_VXLAN_PROXY] = { .type = NLA_U8 }, + [IFLA_VXLAN_RSC] = { .type = NLA_U8 }, + [IFLA_VXLAN_L2MISS] = { .type = NLA_U8 }, + [IFLA_VXLAN_L3MISS] = { .type = NLA_U8 }, + [IFLA_VXLAN_COLLECT_METADATA] = { .type = NLA_U8 }, + [IFLA_VXLAN_PORT] = { .type = NLA_U16 }, + [IFLA_VXLAN_UDP_CSUM] = { .type = NLA_U8 }, + [IFLA_VXLAN_UDP_ZERO_CSUM6_TX] = { .type = NLA_U8 }, + [IFLA_VXLAN_UDP_ZERO_CSUM6_RX] = { .type = NLA_U8 }, + [IFLA_VXLAN_REMCSUM_TX] = { .type = NLA_U8 }, + [IFLA_VXLAN_REMCSUM_RX] = { .type = NLA_U8 }, + [IFLA_VXLAN_GBP] = { .type = NLA_FLAG, }, + [IFLA_VXLAN_GPE] = { .type = NLA_FLAG, }, + [IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG }, +}; + +static int vxlan_alloc(struct rtnl_link *link) +{ + struct vxlan_info *vxi; + + if (link->l_info) + memset(link->l_info, 0, sizeof(*vxi)); + else { + if ((vxi = calloc(1, sizeof(*vxi))) == NULL) + return -NLE_NOMEM; + + link->l_info = vxi; + } + + return 0; +} + +static int vxlan_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_VXLAN_MAX+1]; + struct vxlan_info *vxi; + int err; + + NL_DBG(3, "Parsing VXLAN link info\n"); + + if ((err = nla_parse_nested(tb, IFLA_VXLAN_MAX, data, vxlan_policy)) < 0) + goto errout; + + if ((err = vxlan_alloc(link)) < 0) + goto errout; + + vxi = link->l_info; + + if (tb[IFLA_VXLAN_ID]) { + vxi->vxi_id = nla_get_u32(tb[IFLA_VXLAN_ID]); + vxi->ce_mask |= VXLAN_ATTR_ID; + } + + if (tb[IFLA_VXLAN_GROUP6]) { + nla_memcpy(&vxi->vxi_group6, tb[IFLA_VXLAN_GROUP6], + sizeof(vxi->vxi_group6)); + vxi->ce_mask |= VXLAN_ATTR_GROUP6; + } + + if (tb[IFLA_VXLAN_GROUP]) { + nla_memcpy(&vxi->vxi_group, tb[IFLA_VXLAN_GROUP], + sizeof(vxi->vxi_group)); + vxi->ce_mask |= VXLAN_ATTR_GROUP; + vxi->ce_mask &= ~VXLAN_ATTR_GROUP6; + } + + if (tb[IFLA_VXLAN_LINK]) { + vxi->vxi_link = nla_get_u32(tb[IFLA_VXLAN_LINK]); + vxi->ce_mask |= VXLAN_ATTR_LINK; + } + + if (tb[IFLA_VXLAN_LOCAL6]) { + nla_memcpy(&vxi->vxi_local6, tb[IFLA_VXLAN_LOCAL6], + sizeof(vxi->vxi_local6)); + vxi->ce_mask |= VXLAN_ATTR_LOCAL6; + } + + if (tb[IFLA_VXLAN_LOCAL]) { + nla_memcpy(&vxi->vxi_local, tb[IFLA_VXLAN_LOCAL], + sizeof(vxi->vxi_local)); + vxi->ce_mask |= VXLAN_ATTR_LOCAL; + vxi->ce_mask &= ~VXLAN_ATTR_LOCAL6; + } + + if (tb[IFLA_VXLAN_TTL]) { + vxi->vxi_ttl = nla_get_u8(tb[IFLA_VXLAN_TTL]); + vxi->ce_mask |= VXLAN_ATTR_TTL; + } + + if (tb[IFLA_VXLAN_TOS]) { + vxi->vxi_tos = nla_get_u8(tb[IFLA_VXLAN_TOS]); + vxi->ce_mask |= VXLAN_ATTR_TOS; + } + + if (tb[IFLA_VXLAN_LEARNING]) { + vxi->vxi_learning = nla_get_u8(tb[IFLA_VXLAN_LEARNING]); + vxi->ce_mask |= VXLAN_ATTR_LEARNING; + } + + if (tb[IFLA_VXLAN_AGEING]) { + vxi->vxi_ageing = nla_get_u32(tb[IFLA_VXLAN_AGEING]); + vxi->ce_mask |= VXLAN_ATTR_AGEING; + } + + if (tb[IFLA_VXLAN_LIMIT]) { + vxi->vxi_limit = nla_get_u32(tb[IFLA_VXLAN_LIMIT]); + vxi->ce_mask |= VXLAN_ATTR_LIMIT; + } + + if (tb[IFLA_VXLAN_PORT_RANGE]) { + nla_memcpy(&vxi->vxi_port_range, tb[IFLA_VXLAN_PORT_RANGE], + sizeof(vxi->vxi_port_range)); + vxi->ce_mask |= VXLAN_ATTR_PORT_RANGE; + } + + if (tb[IFLA_VXLAN_PROXY]) { + vxi->vxi_proxy = nla_get_u8(tb[IFLA_VXLAN_PROXY]); + vxi->ce_mask |= VXLAN_ATTR_PROXY; + } + + if (tb[IFLA_VXLAN_RSC]) { + vxi->vxi_rsc = nla_get_u8(tb[IFLA_VXLAN_RSC]); + vxi->ce_mask |= VXLAN_ATTR_RSC; + } + + if (tb[IFLA_VXLAN_L2MISS]) { + vxi->vxi_l2miss = nla_get_u8(tb[IFLA_VXLAN_L2MISS]); + vxi->ce_mask |= VXLAN_ATTR_L2MISS; + } + + if (tb[IFLA_VXLAN_L3MISS]) { + vxi->vxi_l3miss = nla_get_u8(tb[IFLA_VXLAN_L3MISS]); + vxi->ce_mask |= VXLAN_ATTR_L3MISS; + } + + if (tb[IFLA_VXLAN_PORT]) { + vxi->vxi_port = nla_get_u16(tb[IFLA_VXLAN_PORT]); + vxi->ce_mask |= VXLAN_ATTR_PORT; + } + + if (tb[IFLA_VXLAN_UDP_CSUM]) { + vxi->vxi_udp_csum = nla_get_u8(tb[IFLA_VXLAN_UDP_CSUM]); + vxi->ce_mask |= VXLAN_ATTR_UDP_CSUM; + } + + if (tb[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]) { + vxi->vxi_udp_zero_csum6_tx = nla_get_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]); + vxi->ce_mask |= VXLAN_ATTR_UDP_ZERO_CSUM6_TX; + } + + if (tb[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]) { + vxi->vxi_udp_zero_csum6_rx = nla_get_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]); + vxi->ce_mask |= VXLAN_ATTR_UDP_ZERO_CSUM6_RX; + } + + if (tb[IFLA_VXLAN_REMCSUM_TX]) { + vxi->vxi_remcsum_tx = nla_get_u8(tb[IFLA_VXLAN_REMCSUM_TX]); + vxi->ce_mask |= VXLAN_ATTR_REMCSUM_TX; + } + + if (tb[IFLA_VXLAN_REMCSUM_RX]) { + vxi->vxi_remcsum_rx = nla_get_u8(tb[IFLA_VXLAN_REMCSUM_RX]); + vxi->ce_mask |= VXLAN_ATTR_REMCSUM_RX; + } + + if (tb[IFLA_VXLAN_GBP]) + vxi->vxi_flags |= RTNL_LINK_VXLAN_F_GBP; + + if (tb[IFLA_VXLAN_REMCSUM_NOPARTIAL]) + vxi->vxi_flags |= RTNL_LINK_VXLAN_F_REMCSUM_NOPARTIAL; + + if (tb[IFLA_VXLAN_COLLECT_METADATA]) { + vxi->vxi_collect_metadata = nla_get_u8(tb[IFLA_VXLAN_COLLECT_METADATA]); + vxi->ce_mask |= VXLAN_ATTR_COLLECT_METADATA; + } + + if (tb[IFLA_VXLAN_LABEL]) { + vxi->vxi_label = nla_get_u32(tb[IFLA_VXLAN_LABEL]); + vxi->ce_mask |= VXLAN_ATTR_LABEL; + } + + if (tb[IFLA_VXLAN_GPE]) + vxi->vxi_flags |= RTNL_LINK_VXLAN_F_GPE; + + err = 0; + +errout: + return err; +} + +static void vxlan_free(struct rtnl_link *link) +{ + struct vxlan_info *vxi = link->l_info; + + free(vxi); + link->l_info = NULL; +} + +static void vxlan_dump_line(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct vxlan_info *vxi = link->l_info; + + nl_dump(p, "vxlan-id %u", vxi->vxi_id); +} + +static void vxlan_dump_details(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct vxlan_info *vxi = link->l_info; + char *name, addr[INET6_ADDRSTRLEN]; + struct rtnl_link *parent; + + nl_dump_line(p, " vxlan-id %u\n", vxi->vxi_id); + + if (vxi->ce_mask & VXLAN_ATTR_GROUP) { + nl_dump(p, " group "); + nl_dump_line(p, "%s\n", + _nl_inet_ntop(AF_INET, &vxi->vxi_group, addr)); + } else if (vxi->ce_mask & VXLAN_ATTR_GROUP6) { + nl_dump(p, " group "); + nl_dump_line(p, "%s\n", + _nl_inet_ntop(AF_INET6, &vxi->vxi_group6, addr)); + } + + if (vxi->ce_mask & VXLAN_ATTR_LINK) { + nl_dump(p, " link "); + + name = NULL; + parent = link_lookup(link->ce_cache, vxi->vxi_link); + if (parent) + name = rtnl_link_get_name(parent); + + if (name) + nl_dump_line(p, "%s\n", name); + else + nl_dump_line(p, "%u\n", vxi->vxi_link); + } + + if (vxi->ce_mask & VXLAN_ATTR_LOCAL) { + nl_dump(p, " local "); + nl_dump_line(p, "%s\n", + _nl_inet_ntop(AF_INET, &vxi->vxi_local, addr)); + } else if (vxi->ce_mask & VXLAN_ATTR_LOCAL6) { + nl_dump(p, " local "); + nl_dump_line(p, "%s\n", + _nl_inet_ntop(AF_INET6, &vxi->vxi_local6, addr)); + } + + if (vxi->ce_mask & VXLAN_ATTR_TTL) { + nl_dump(p, " ttl "); + if(vxi->vxi_ttl) + nl_dump_line(p, "%u\n", vxi->vxi_ttl); + else + nl_dump_line(p, "inherit\n"); + } + + if (vxi->ce_mask & VXLAN_ATTR_TOS) { + nl_dump(p, " tos "); + if (vxi->vxi_tos == 1) + nl_dump_line(p, "inherit\n"); + else + nl_dump_line(p, "%#x\n", vxi->vxi_tos); + } + + if (vxi->ce_mask & VXLAN_ATTR_LEARNING) { + nl_dump(p, " learning "); + if (vxi->vxi_learning) + nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_learning); + else + nl_dump_line(p, "disabled\n"); + } + + if (vxi->ce_mask & VXLAN_ATTR_AGEING) { + nl_dump(p, " ageing "); + if (vxi->vxi_ageing) + nl_dump_line(p, "%u seconds\n", vxi->vxi_ageing); + else + nl_dump_line(p, "disabled\n"); + } + + if (vxi->ce_mask & VXLAN_ATTR_LIMIT) { + nl_dump(p, " limit "); + if (vxi->vxi_limit) + nl_dump_line(p, "%u\n", vxi->vxi_limit); + else + nl_dump_line(p, "unlimited\n"); + } + + if (vxi->ce_mask & VXLAN_ATTR_PORT_RANGE) + nl_dump_line(p, " port range %u - %u\n", + ntohs(vxi->vxi_port_range.low), + ntohs(vxi->vxi_port_range.high)); + + if (vxi->ce_mask & VXLAN_ATTR_PROXY) { + nl_dump(p, " proxy "); + if (vxi->vxi_proxy) + nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_proxy); + else + nl_dump_line(p, "disabled\n"); + } + + if (vxi->ce_mask & VXLAN_ATTR_RSC) { + nl_dump(p, " rsc "); + if (vxi->vxi_rsc) + nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_rsc); + else + nl_dump_line(p, "disabled\n"); + } + + if (vxi->ce_mask & VXLAN_ATTR_L2MISS) { + nl_dump(p, " l2miss "); + if (vxi->vxi_l2miss) + nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_l2miss); + else + nl_dump_line(p, "disabled\n"); + } + + if (vxi->ce_mask & VXLAN_ATTR_L3MISS) { + nl_dump(p, " l3miss "); + if (vxi->vxi_l3miss) + nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_l3miss); + else + nl_dump_line(p, "disabled\n"); + } + + if (vxi->ce_mask & VXLAN_ATTR_PORT) { + nl_dump(p, " port "); + nl_dump_line(p, "%u\n", ntohs(vxi->vxi_port)); + } + + if (vxi->ce_mask & VXLAN_ATTR_UDP_CSUM) { + nl_dump(p, " UDP checksums "); + if (vxi->vxi_udp_csum) + nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_udp_csum); + else + nl_dump_line(p, "disabled\n"); + } + + if (vxi->ce_mask & VXLAN_ATTR_UDP_ZERO_CSUM6_TX) { + nl_dump(p, " udp-zero-csum6-tx "); + if (vxi->vxi_udp_zero_csum6_tx) + nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_udp_zero_csum6_tx); + else + nl_dump_line(p, "disabled\n"); + } + + if (vxi->ce_mask & VXLAN_ATTR_UDP_ZERO_CSUM6_RX) { + nl_dump(p, " udp-zero-csum6-rx "); + if (vxi->vxi_udp_zero_csum6_rx) + nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_udp_zero_csum6_rx); + else + nl_dump_line(p, "disabled\n"); + } + + if (vxi->ce_mask & VXLAN_ATTR_REMCSUM_TX) { + nl_dump(p, " remcsum-tx "); + if (vxi->vxi_remcsum_tx) + nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_remcsum_tx); + else + nl_dump_line(p, "disabled\n"); + } + + if (vxi->ce_mask & VXLAN_ATTR_REMCSUM_RX) { + nl_dump(p, " remcsum-rx "); + if (vxi->vxi_remcsum_rx) + nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_remcsum_rx); + else + nl_dump_line(p, "disabled\n"); + } + + if (vxi->vxi_flags & RTNL_LINK_VXLAN_F_GBP) + nl_dump(p, " gbp\n"); + + if (vxi->vxi_flags & RTNL_LINK_VXLAN_F_REMCSUM_NOPARTIAL) + nl_dump(p, " rncsum-nopartial\n"); + + if (vxi->ce_mask & VXLAN_ATTR_COLLECT_METADATA) { + nl_dump(p, " remcsum-rx "); + if (vxi->vxi_collect_metadata) + nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_collect_metadata); + else + nl_dump_line(p, "disabled\n"); + } + + if (vxi->ce_mask & VXLAN_ATTR_LABEL) { + nl_dump(p, " label "); + nl_dump_line(p, "%u\n", ntohl(vxi->vxi_label)); + } + + if (vxi->vxi_flags & RTNL_LINK_VXLAN_F_GPE) + nl_dump(p, " gpe\n"); +} + +static int vxlan_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct vxlan_info *vdst, *vsrc = src->l_info; + int err; + + dst->l_info = NULL; + if ((err = rtnl_link_set_type(dst, "vxlan")) < 0) + return err; + vdst = dst->l_info; + + if (!vdst || !vsrc) + return -NLE_NOMEM; + + memcpy(vdst, vsrc, sizeof(struct vxlan_info)); + + return 0; +} + +static int vxlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct vxlan_info *vxi = link->l_info; + struct nlattr *data; + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + return -NLE_MSGSIZE; + + if (vxi->ce_mask & VXLAN_ATTR_ID) + NLA_PUT_U32(msg, IFLA_VXLAN_ID, vxi->vxi_id); + + if (vxi->ce_mask & VXLAN_ATTR_GROUP) + NLA_PUT(msg, IFLA_VXLAN_GROUP, sizeof(vxi->vxi_group), &vxi->vxi_group); + + if (vxi->ce_mask & VXLAN_ATTR_GROUP6) + NLA_PUT(msg, IFLA_VXLAN_GROUP6, sizeof(vxi->vxi_group6), &vxi->vxi_group6); + + if (vxi->ce_mask & VXLAN_ATTR_LINK) + NLA_PUT_U32(msg, IFLA_VXLAN_LINK, vxi->vxi_link); + + if (vxi->ce_mask & VXLAN_ATTR_LOCAL) + NLA_PUT(msg, IFLA_VXLAN_LOCAL, sizeof(vxi->vxi_local), &vxi->vxi_local); + + if (vxi->ce_mask & VXLAN_ATTR_LOCAL6) + NLA_PUT(msg, IFLA_VXLAN_LOCAL6, sizeof(vxi->vxi_local6), &vxi->vxi_local6); + + if (vxi->ce_mask & VXLAN_ATTR_TTL) + NLA_PUT_U8(msg, IFLA_VXLAN_TTL, vxi->vxi_ttl); + + if (vxi->ce_mask & VXLAN_ATTR_TOS) + NLA_PUT_U8(msg, IFLA_VXLAN_TOS, vxi->vxi_tos); + + if (vxi->ce_mask & VXLAN_ATTR_LEARNING) + NLA_PUT_U8(msg, IFLA_VXLAN_LEARNING, vxi->vxi_learning); + + if (vxi->ce_mask & VXLAN_ATTR_AGEING) + NLA_PUT_U32(msg, IFLA_VXLAN_AGEING, vxi->vxi_ageing); + + if (vxi->ce_mask & VXLAN_ATTR_LIMIT) + NLA_PUT_U32(msg, IFLA_VXLAN_LIMIT, vxi->vxi_limit); + + if (vxi->ce_mask & VXLAN_ATTR_PORT_RANGE) + NLA_PUT(msg, IFLA_VXLAN_PORT_RANGE, sizeof(vxi->vxi_port_range), + &vxi->vxi_port_range); + + if (vxi->ce_mask & VXLAN_ATTR_PROXY) + NLA_PUT_U8(msg, IFLA_VXLAN_PROXY, vxi->vxi_proxy); + + if (vxi->ce_mask & VXLAN_ATTR_RSC) + NLA_PUT_U8(msg, IFLA_VXLAN_RSC, vxi->vxi_rsc); + + if (vxi->ce_mask & VXLAN_ATTR_L2MISS) + NLA_PUT_U8(msg, IFLA_VXLAN_L2MISS, vxi->vxi_l2miss); + + if (vxi->ce_mask & VXLAN_ATTR_L3MISS) + NLA_PUT_U8(msg, IFLA_VXLAN_L3MISS, vxi->vxi_l3miss); + + if (vxi->ce_mask & VXLAN_ATTR_PORT) + NLA_PUT_U32(msg, IFLA_VXLAN_PORT, vxi->vxi_port); + + if (vxi->ce_mask & VXLAN_ATTR_UDP_CSUM) + NLA_PUT_U8(msg, IFLA_VXLAN_UDP_CSUM, vxi->vxi_udp_csum); + + if (vxi->ce_mask & VXLAN_ATTR_UDP_ZERO_CSUM6_TX) + NLA_PUT_U8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, vxi->vxi_udp_zero_csum6_tx); + + if (vxi->ce_mask & VXLAN_ATTR_UDP_ZERO_CSUM6_RX) + NLA_PUT_U8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, vxi->vxi_udp_zero_csum6_rx); + + if (vxi->ce_mask & VXLAN_ATTR_REMCSUM_TX) + NLA_PUT_U8(msg, IFLA_VXLAN_REMCSUM_TX, vxi->vxi_remcsum_tx); + + if (vxi->ce_mask & VXLAN_ATTR_REMCSUM_RX) + NLA_PUT_U8(msg, IFLA_VXLAN_REMCSUM_RX, vxi->vxi_remcsum_rx); + + if (vxi->vxi_flags & RTNL_LINK_VXLAN_F_GBP) + NLA_PUT_FLAG(msg, IFLA_VXLAN_GBP); + + if (vxi->vxi_flags & RTNL_LINK_VXLAN_F_REMCSUM_NOPARTIAL) + NLA_PUT_FLAG(msg, IFLA_VXLAN_REMCSUM_NOPARTIAL); + + if (vxi->ce_mask & VXLAN_ATTR_COLLECT_METADATA) + NLA_PUT_U8(msg, IFLA_VXLAN_COLLECT_METADATA, vxi->vxi_collect_metadata); + + if (vxi->ce_mask & VXLAN_ATTR_LABEL) + NLA_PUT_U32(msg, IFLA_VXLAN_LABEL, vxi->vxi_label); + + if (vxi->vxi_flags & RTNL_LINK_VXLAN_F_GPE) + NLA_PUT_FLAG(msg, IFLA_VXLAN_GPE); + + nla_nest_end(msg, data); + +nla_put_failure: + + return 0; +} + +static int vxlan_compare(struct rtnl_link *link_a, struct rtnl_link *link_b, + int flags) +{ + struct vxlan_info *a = link_a->l_info; + struct vxlan_info *b = link_b->l_info; + int diff = 0; + uint32_t attrs = flags & LOOSE_COMPARISON ? b->ce_mask : ~0; + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(VXLAN_ATTR_ID, a->vxi_id != b->vxi_id); + diff |= _DIFF(VXLAN_ATTR_GROUP, a->vxi_group != b->vxi_group); + diff |= _DIFF(VXLAN_ATTR_LINK, a->vxi_link != b->vxi_link); + diff |= _DIFF(VXLAN_ATTR_LOCAL, a->vxi_local != b->vxi_local); + diff |= _DIFF(VXLAN_ATTR_TOS, a->vxi_tos != b->vxi_tos); + diff |= _DIFF(VXLAN_ATTR_TTL, a->vxi_ttl != b->vxi_ttl); + diff |= _DIFF(VXLAN_ATTR_LEARNING, a->vxi_learning != b->vxi_learning); + diff |= _DIFF(VXLAN_ATTR_AGEING, a->vxi_ageing != b->vxi_ageing); + diff |= _DIFF(VXLAN_ATTR_LIMIT, a->vxi_limit != b->vxi_limit); + diff |= _DIFF(VXLAN_ATTR_PORT_RANGE, + a->vxi_port_range.low != b->vxi_port_range.low); + diff |= _DIFF(VXLAN_ATTR_PORT_RANGE, + a->vxi_port_range.high != b->vxi_port_range.high); + diff |= _DIFF(VXLAN_ATTR_PROXY, a->vxi_proxy != b->vxi_proxy); + diff |= _DIFF(VXLAN_ATTR_RSC, a->vxi_proxy != b->vxi_proxy); + diff |= _DIFF(VXLAN_ATTR_L2MISS, a->vxi_proxy != b->vxi_proxy); + diff |= _DIFF(VXLAN_ATTR_L3MISS, a->vxi_proxy != b->vxi_proxy); + diff |= _DIFF(VXLAN_ATTR_PORT, a->vxi_port != b->vxi_port); + diff |= _DIFF(VXLAN_ATTR_GROUP6, memcmp(&a->vxi_group6, &b->vxi_group6, + sizeof(a->vxi_group6)) != 0); + diff |= _DIFF(VXLAN_ATTR_LOCAL6, memcmp(&a->vxi_local6, &b->vxi_local6, + sizeof(a->vxi_local6)) != 0); + diff |= _DIFF(VXLAN_ATTR_UDP_CSUM, a->vxi_proxy != b->vxi_proxy); + diff |= _DIFF(VXLAN_ATTR_UDP_ZERO_CSUM6_TX, + a->vxi_proxy != b->vxi_proxy); + diff |= _DIFF(VXLAN_ATTR_UDP_ZERO_CSUM6_RX, + a->vxi_proxy != b->vxi_proxy); + diff |= _DIFF(VXLAN_ATTR_REMCSUM_TX, a->vxi_proxy != b->vxi_proxy); + diff |= _DIFF(VXLAN_ATTR_REMCSUM_RX, a->vxi_proxy != b->vxi_proxy); + diff |= _DIFF(VXLAN_ATTR_COLLECT_METADATA, + a->vxi_collect_metadata != b->vxi_collect_metadata); + diff |= _DIFF(VXLAN_ATTR_LABEL, a->vxi_label != b->vxi_label); + diff |= _DIFF(VXLAN_ATTR_FLAGS, a->vxi_flags != b->vxi_flags); +#undef _DIFF + + return diff; +} + +static struct rtnl_link_info_ops vxlan_info_ops = { + .io_name = "vxlan", + .io_alloc = vxlan_alloc, + .io_parse = vxlan_parse, + .io_dump = { + [NL_DUMP_LINE] = vxlan_dump_line, + [NL_DUMP_DETAILS] = vxlan_dump_details, + }, + .io_clone = vxlan_clone, + .io_put_attrs = vxlan_put_attrs, + .io_free = vxlan_free, + .io_compare = vxlan_compare, +}; + +/** @cond SKIP */ +#define IS_VXLAN_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &vxlan_info_ops) { \ + APPBUG("Link is not a vxlan link. set type \"vxlan\" first."); \ + return -NLE_OPNOTSUPP; \ + } +/** @endcond */ + +/** + * @name VXLAN Object + * @{ + */ + +/** + * Allocate link object of type VXLAN + * + * @return Allocated link object or NULL. + */ +struct rtnl_link *rtnl_link_vxlan_alloc(void) +{ + struct rtnl_link *link; + + if (!(link = rtnl_link_alloc())) + return NULL; + + if (rtnl_link_set_type(link, "vxlan") < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if link is a VXLAN link + * @arg link Link object + * + * @return True if link is a VXLAN link, otherwise false is returned. + */ +int rtnl_link_is_vxlan(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "vxlan"); +} + +/** + * Set VXLAN Network Identifier + * @arg link Link object + * @arg id VXLAN network identifier (or VXLAN segment identifier) + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_id(struct rtnl_link *link, uint32_t id) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (id > VXLAN_ID_MAX) + return -NLE_INVAL; + + vxi->vxi_id = id; + vxi->ce_mask |= VXLAN_ATTR_ID; + + return 0; +} + +/** + * Get VXLAN Network Identifier + * @arg link Link object + * @arg id Pointer to store network identifier + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_get_id(struct rtnl_link *link, uint32_t *id) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if(!id) + return -NLE_INVAL; + + if (vxi->ce_mask & VXLAN_ATTR_ID) + *id = vxi->vxi_id; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set VXLAN multicast IP address + * @arg link Link object + * @arg addr Multicast IP address to join + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_group(struct rtnl_link *link, struct nl_addr *addr) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if ((nl_addr_get_family(addr) == AF_INET) && + (nl_addr_get_len(addr) == sizeof(vxi->vxi_group))) { + memcpy(&vxi->vxi_group, nl_addr_get_binary_addr(addr), + sizeof(vxi->vxi_group)); + vxi->ce_mask |= VXLAN_ATTR_GROUP; + vxi->ce_mask &= ~VXLAN_ATTR_GROUP6; + } else if ((nl_addr_get_family(addr) == AF_INET6) && + (nl_addr_get_len(addr) == sizeof(vxi->vxi_group6))) { + memcpy(&vxi->vxi_group6, nl_addr_get_binary_addr(addr), + sizeof(vxi->vxi_group6)); + vxi->ce_mask |= VXLAN_ATTR_GROUP6; + vxi->ce_mask &= ~VXLAN_ATTR_GROUP; + } else + return -NLE_INVAL; + + return 0; +} + +/** + * Get VXLAN multicast IP address + * @arg link Link object + * @arg addr Pointer to store multicast IP address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_get_group(struct rtnl_link *link, struct nl_addr **addr) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!addr) + return -NLE_INVAL; + + if (vxi->ce_mask & VXLAN_ATTR_GROUP) + *addr = nl_addr_build(AF_INET, &vxi->vxi_group, sizeof(vxi->vxi_group)); + else if (vxi->ce_mask & VXLAN_ATTR_GROUP6) + *addr = nl_addr_build(AF_INET6, &vxi->vxi_group6, sizeof(vxi->vxi_group6)); + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set physical device to use for VXLAN + * @arg link Link object + * @arg index Interface index + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_link(struct rtnl_link *link, uint32_t index) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + vxi->vxi_link = index; + vxi->ce_mask |= VXLAN_ATTR_LINK; + + return 0; +} + +/** + * Get physical device to use for VXLAN + * @arg link Link object + * @arg index Pointer to store interface index + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_get_link(struct rtnl_link *link, uint32_t *index) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!index) + return -NLE_INVAL; + + if (!(vxi->ce_mask & VXLAN_ATTR_LINK)) + return -NLE_AGAIN; + + *index = vxi->vxi_link; + + return 0; +} + +/** + * Set source address to use for VXLAN + * @arg link Link object + * @arg addr Local address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_local(struct rtnl_link *link, struct nl_addr *addr) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if ((nl_addr_get_family(addr) == AF_INET) && + (nl_addr_get_len(addr) == sizeof(vxi->vxi_local))) { + memcpy(&vxi->vxi_local, nl_addr_get_binary_addr(addr), + sizeof(vxi->vxi_local)); + vxi->ce_mask |= VXLAN_ATTR_LOCAL; + vxi->ce_mask &= ~VXLAN_ATTR_LOCAL6; + } else if ((nl_addr_get_family(addr) == AF_INET6) && + (nl_addr_get_len(addr) == sizeof(vxi->vxi_local6))) { + memcpy(&vxi->vxi_local6, nl_addr_get_binary_addr(addr), + sizeof(vxi->vxi_local6)); + vxi->ce_mask |= VXLAN_ATTR_LOCAL6; + vxi->ce_mask &= ~VXLAN_ATTR_LOCAL; + } else + return -NLE_INVAL; + + return 0; +} + +/** + * Get source address to use for VXLAN + * @arg link Link object + * @arg addr Pointer to store local address + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_get_local(struct rtnl_link *link, struct nl_addr **addr) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!addr) + return -NLE_INVAL; + + if (vxi->ce_mask & VXLAN_ATTR_LOCAL) + *addr = nl_addr_build(AF_INET, &vxi->vxi_local, sizeof(vxi->vxi_local)); + else if (vxi->ce_mask & VXLAN_ATTR_LOCAL6) + *addr = nl_addr_build(AF_INET6, &vxi->vxi_local6, sizeof(vxi->vxi_local6)); + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set IP TTL value to use for VXLAN + * @arg link Link object + * @arg ttl TTL value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_ttl(struct rtnl_link *link, uint8_t ttl) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + vxi->vxi_ttl = ttl; + vxi->ce_mask |= VXLAN_ATTR_TTL; + + return 0; +} + +/** + * Get IP TTL value to use for VXLAN + * @arg link Link object + * + * @return TTL value on success or a negative error code + */ +int rtnl_link_vxlan_get_ttl(struct rtnl_link *link) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!(vxi->ce_mask & VXLAN_ATTR_TTL)) + return -NLE_AGAIN; + + return vxi->vxi_ttl; +} + +/** + * Set IP ToS value to use for VXLAN + * @arg link Link object + * @arg tos ToS value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_tos(struct rtnl_link *link, uint8_t tos) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + vxi->vxi_tos = tos; + vxi->ce_mask |= VXLAN_ATTR_TOS; + + return 0; +} + +/** + * Get IP ToS value to use for VXLAN + * @arg link Link object + * + * @return ToS value on success or a negative error code + */ +int rtnl_link_vxlan_get_tos(struct rtnl_link *link) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!(vxi->ce_mask & VXLAN_ATTR_TOS)) + return -NLE_AGAIN; + + return vxi->vxi_tos; +} + +/** + * Set VXLAN learning status + * @arg link Link object + * @arg learning Learning status value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_learning(struct rtnl_link *link, uint8_t learning) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + vxi->vxi_learning = learning; + vxi->ce_mask |= VXLAN_ATTR_LEARNING; + + return 0; +} + +/** + * Get VXLAN learning status + * @arg link Link object + * + * @return Learning status value on success or a negative error code + */ +int rtnl_link_vxlan_get_learning(struct rtnl_link *link) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!(vxi->ce_mask & VXLAN_ATTR_LEARNING)) + return -NLE_AGAIN; + + return vxi->vxi_learning; +} + +/** + * Enable VXLAN address learning + * @arg link Link object + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_enable_learning(struct rtnl_link *link) +{ + return rtnl_link_vxlan_set_learning(link, 1); +} + +/** + * Disable VXLAN address learning + * @arg link Link object + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_disable_learning(struct rtnl_link *link) +{ + return rtnl_link_vxlan_set_learning(link, 0); +} + +/** + * Set expiration timer value to use for VXLAN + * @arg link Link object + * @arg expiry Expiration timer value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_ageing(struct rtnl_link *link, uint32_t expiry) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + vxi->vxi_ageing = expiry; + vxi->ce_mask |= VXLAN_ATTR_AGEING; + + return 0; +} + +/** + * Get expiration timer value to use for VXLAN + * @arg link Link object + * @arg expiry Pointer to store expiration timer value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_get_ageing(struct rtnl_link *link, uint32_t *expiry) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!expiry) + return -NLE_INVAL; + + if (vxi->ce_mask & VXLAN_ATTR_AGEING) + *expiry = vxi->vxi_ageing; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set maximum number of forwarding database entries to use for VXLAN + * @arg link Link object + * @arg limit Maximum number + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_limit(struct rtnl_link *link, uint32_t limit) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + vxi->vxi_limit = limit; + vxi->ce_mask |= VXLAN_ATTR_LIMIT; + + return 0; +} + +/** + * Get maximum number of forwarding database entries to use for VXLAN + * @arg link Link object + * @arg limit Pointer to store maximum number + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_get_limit(struct rtnl_link *link, uint32_t *limit) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!limit) + return -NLE_INVAL; + + if (vxi->ce_mask & VXLAN_ATTR_LIMIT) + *limit = vxi->vxi_limit; + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set range of UDP port numbers to use for VXLAN + * @arg link Link object + * @arg range Port number range + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_port_range(struct rtnl_link *link, + struct ifla_vxlan_port_range *range) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!range) + return -NLE_INVAL; + + memcpy(&vxi->vxi_port_range, range, sizeof(vxi->vxi_port_range)); + vxi->ce_mask |= VXLAN_ATTR_PORT_RANGE; + + return 0; +} + +/** + * Get range of UDP port numbers to use for VXLAN + * @arg link Link object + * @arg range Pointer to store port range + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_get_port_range(struct rtnl_link *link, + struct ifla_vxlan_port_range *range) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!range) + return -NLE_INVAL; + + if (vxi->ce_mask & VXLAN_ATTR_PORT_RANGE) + memcpy(range, &vxi->vxi_port_range, sizeof(*range)); + else + return -NLE_AGAIN; + + return 0; +} + +/** + * Set ARP proxy status to use for VXLAN + * @arg link Link object + * @arg proxy Status value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_proxy(struct rtnl_link *link, uint8_t proxy) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + vxi->vxi_proxy = proxy; + vxi->ce_mask |= VXLAN_ATTR_PROXY; + + return 0; +} + +/** + * Get ARP proxy status to use for VXLAN + * @arg link Link object + * + * @return Status value on success or a negative error code + */ +int rtnl_link_vxlan_get_proxy(struct rtnl_link *link) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!(vxi->ce_mask & VXLAN_ATTR_PROXY)) + return -NLE_AGAIN; + + return vxi->vxi_proxy; +} + +/** + * Enable ARP proxy + * @arg link Link object + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_enable_proxy(struct rtnl_link *link) +{ + return rtnl_link_vxlan_set_proxy(link, 1); +} + +/** + * Disable ARP proxy + * @arg link Link object + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_disable_proxy(struct rtnl_link *link) +{ + return rtnl_link_vxlan_set_proxy(link, 0); +} + +/** + * Set Route Short Circuit status to use for VXLAN + * @arg link Link object + * @arg rsc Status value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_rsc(struct rtnl_link *link, uint8_t rsc) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + vxi->vxi_rsc = rsc; + vxi->ce_mask |= VXLAN_ATTR_RSC; + + return 0; +} + +/** + * Get Route Short Circuit status to use for VXLAN + * @arg link Link object + * + * @return Status value on success or a negative error code + */ +int rtnl_link_vxlan_get_rsc(struct rtnl_link *link) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!(vxi->ce_mask & VXLAN_ATTR_RSC)) + return -NLE_AGAIN; + + return vxi->vxi_rsc; +} + +/** + * Enable Route Short Circuit + * @arg link Link object + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_enable_rsc(struct rtnl_link *link) +{ + return rtnl_link_vxlan_set_rsc(link, 1); +} + +/** + * Disable Route Short Circuit + * @arg link Link object + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_disable_rsc(struct rtnl_link *link) +{ + return rtnl_link_vxlan_set_rsc(link, 0); +} + +/** + * Set netlink LLADDR miss notification status to use for VXLAN + * @arg link Link object + * @arg miss Status value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_l2miss(struct rtnl_link *link, uint8_t miss) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + vxi->vxi_l2miss = miss; + vxi->ce_mask |= VXLAN_ATTR_L2MISS; + + return 0; +} + +/** + * Get netlink LLADDR miss notification status to use for VXLAN + * @arg link Link object + * + * @return Status value on success or a negative error code + */ +int rtnl_link_vxlan_get_l2miss(struct rtnl_link *link) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!(vxi->ce_mask & VXLAN_ATTR_L2MISS)) + return -NLE_AGAIN; + + return vxi->vxi_l2miss; +} + +/** + * Enable netlink LLADDR miss notifications + * @arg link Link object + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_enable_l2miss(struct rtnl_link *link) +{ + return rtnl_link_vxlan_set_l2miss(link, 1); +} + +/** + * Disable netlink LLADDR miss notifications + * @arg link Link object + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_disable_l2miss(struct rtnl_link *link) +{ + return rtnl_link_vxlan_set_l2miss(link, 0); +} + +/** + * Set netlink IP ADDR miss notification status to use for VXLAN + * @arg link Link object + * @arg miss Status value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_l3miss(struct rtnl_link *link, uint8_t miss) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + vxi->vxi_l3miss = miss; + vxi->ce_mask |= VXLAN_ATTR_L3MISS; + + return 0; +} + +/** + * Get netlink IP ADDR miss notification status to use for VXLAN + * @arg link Link object + * + * @return Status value on success or a negative error code + */ +int rtnl_link_vxlan_get_l3miss(struct rtnl_link *link) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!(vxi->ce_mask & VXLAN_ATTR_L3MISS)) + return -NLE_AGAIN; + + return vxi->vxi_l3miss; +} + +/** + * Enable netlink IP ADDR miss notifications + * @arg link Link object + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_enable_l3miss(struct rtnl_link *link) +{ + return rtnl_link_vxlan_set_l3miss(link, 1); +} + +/** + * Disable netlink IP ADDR miss notifications + * @arg link Link object + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_disable_l3miss(struct rtnl_link *link) +{ + return rtnl_link_vxlan_set_l3miss(link, 0); +} + +/** + * Set UDP destination port to use for VXLAN + * @arg link Link object + * @arg port Destination port + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_port(struct rtnl_link *link, uint32_t port) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + vxi->vxi_port = htons(port); + vxi->ce_mask |= VXLAN_ATTR_PORT; + + return 0; +} + +/** + * Get UDP destination port to use for VXLAN + * @arg link Link object + * @arg port Pointer to store destination port + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_get_port(struct rtnl_link *link, uint32_t *port) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!port) + return -NLE_INVAL; + + if (!(vxi->ce_mask & VXLAN_ATTR_PORT)) + return -NLE_NOATTR; + + *port = ntohs(vxi->vxi_port); + + return 0; +} + +/** + * Set UDP checksum status to use for VXLAN + * @arg link Link object + * @arg csum Status value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_udp_csum(struct rtnl_link *link, uint8_t csum) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + vxi->vxi_udp_csum = csum; + vxi->ce_mask |= VXLAN_ATTR_UDP_CSUM; + + return 0; +} + +/** + * Get UDP checksum status to use for VXLAN + * @arg link Link object + * + * @return Status value on success or a negative error code + */ +int rtnl_link_vxlan_get_udp_csum(struct rtnl_link *link) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!(vxi->ce_mask & VXLAN_ATTR_UDP_CSUM)) + return -NLE_NOATTR; + + return vxi->vxi_udp_csum; +} + +/** + * Set skip UDP checksum transmitted over IPv6 status to use for VXLAN + * @arg link Link object + * @arg csum Status value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_udp_zero_csum6_tx(struct rtnl_link *link, uint8_t csum) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + vxi->vxi_udp_zero_csum6_tx = csum; + vxi->ce_mask |= VXLAN_ATTR_UDP_ZERO_CSUM6_TX; + + return 0; +} + +/** + * Get skip UDP checksum transmitted over IPv6 status to use for VXLAN + * @arg link Link object + * + * @return Status value on success or a negative error code + */ +int rtnl_link_vxlan_get_udp_zero_csum6_tx(struct rtnl_link *link) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!(vxi->ce_mask & VXLAN_ATTR_UDP_ZERO_CSUM6_TX)) + return -NLE_NOATTR; + + return vxi->vxi_udp_zero_csum6_tx; +} + +/** + * Set skip UDP checksum received over IPv6 status to use for VXLAN + * @arg link Link object + * @arg csum Status value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_udp_zero_csum6_rx(struct rtnl_link *link, uint8_t csum) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + vxi->vxi_udp_zero_csum6_rx = csum; + vxi->ce_mask |= VXLAN_ATTR_UDP_ZERO_CSUM6_RX; + + return 0; +} + +/** + * Get skip UDP checksum received over IPv6 status to use for VXLAN + * @arg link Link object + * + * @return Status value on success or a negative error code + */ +int rtnl_link_vxlan_get_udp_zero_csum6_rx(struct rtnl_link *link) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!(vxi->ce_mask & VXLAN_ATTR_UDP_ZERO_CSUM6_RX)) + return -NLE_NOATTR; + + return vxi->vxi_udp_zero_csum6_rx; +} + +/** + * Set remote offload transmit checksum status to use for VXLAN + * @arg link Link object + * @arg csum Status value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_remcsum_tx(struct rtnl_link *link, uint8_t csum) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + vxi->vxi_remcsum_tx = csum; + vxi->ce_mask |= VXLAN_ATTR_REMCSUM_TX; + + return 0; +} + +/** + * Get remote offload transmit checksum status to use for VXLAN + * @arg link Link object + * + * @return Status value on success or a negative error code + */ +int rtnl_link_vxlan_get_remcsum_tx(struct rtnl_link *link) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!(vxi->ce_mask & VXLAN_ATTR_REMCSUM_TX)) + return -NLE_NOATTR; + + return vxi->vxi_remcsum_tx; +} + +/** + * Set remote offload receive checksum status to use for VXLAN + * @arg link Link object + * @arg csum Status value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_remcsum_rx(struct rtnl_link *link, uint8_t csum) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + vxi->vxi_remcsum_rx = csum; + vxi->ce_mask |= VXLAN_ATTR_REMCSUM_RX; + + return 0; +} + +/** + * Get remote offload receive checksum status to use for VXLAN + * @arg link Link object + * + * @return Status value on success or a negative error code + */ +int rtnl_link_vxlan_get_remcsum_rx(struct rtnl_link *link) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!(vxi->ce_mask & VXLAN_ATTR_REMCSUM_RX)) + return -NLE_NOATTR; + + return vxi->vxi_remcsum_rx; +} + +/** + * Set collect metadata status to use for VXLAN + * @arg link Link object + * @arg collect Status value + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_collect_metadata(struct rtnl_link *link, uint8_t collect) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + vxi->vxi_collect_metadata = collect; + vxi->ce_mask |= VXLAN_ATTR_COLLECT_METADATA; + + return 0; +} + +/** + * Get collect metadata status to use for VXLAN + * @arg link Link object + * + * @return Status value on success or a negative error code + */ +int rtnl_link_vxlan_get_collect_metadata(struct rtnl_link *link) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!(vxi->ce_mask & VXLAN_ATTR_COLLECT_METADATA)) + return -NLE_NOATTR; + + return vxi->vxi_collect_metadata; +} + +/** + * Set flow label to use for VXLAN + * @arg link Link object + * @arg label Destination label + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_label(struct rtnl_link *link, uint32_t label) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + vxi->vxi_label = htonl(label); + vxi->ce_mask |= VXLAN_ATTR_LABEL; + + return 0; +} + +/** + * Get flow label to use for VXLAN + * @arg link Link object + * @arg label Pointer to store destination label + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_get_label(struct rtnl_link *link, uint32_t *label) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (!label) + return -NLE_INVAL; + + if (!(vxi->ce_mask & VXLAN_ATTR_LABEL)) + return -NLE_NOATTR; + + *label = ntohl(vxi->vxi_label); + + return 0; +} + +/** + * Set VXLAN flags RTNL_LINK_VXLAN_F_* + * @arg link Link object + * @flags Which flags to set + * @arg enable Boolean enabling or disabling flag + * + * @return 0 on success or a negative error code + */ +int rtnl_link_vxlan_set_flags(struct rtnl_link *link, uint32_t flags, int enable) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + if (flags & ~(RTNL_LINK_VXLAN_F_GBP | RTNL_LINK_VXLAN_F_GPE | RTNL_LINK_VXLAN_F_REMCSUM_NOPARTIAL)) + return -NLE_INVAL; + + if (enable) + vxi->vxi_flags |= flags; + else + vxi->vxi_flags &= ~flags; + + return 0; +} + +/** + * Get VXLAN flags RTNL_LINK_VXLAN_F_* + * @arg link Link object + * @arg out_flags Output value for flags. Must be present. + * + * @return Zero on success or a negative error code + */ +int rtnl_link_vxlan_get_flags(struct rtnl_link *link, uint32_t *out_flags) +{ + struct vxlan_info *vxi = link->l_info; + + IS_VXLAN_LINK_ASSERT(link); + + *out_flags = vxi->vxi_flags; + return 0; +} + +/** @} */ + +static void _nl_init vxlan_init(void) +{ + rtnl_link_register_info(&vxlan_info_ops); +} + +static void _nl_exit vxlan_exit(void) +{ + rtnl_link_unregister_info(&vxlan_info_ops); +} + +/** @} */ diff --git a/lib/route/link/xfrmi.c b/lib/route/link/xfrmi.c new file mode 100644 index 0000000..09ceb80 --- /dev/null +++ b/lib/route/link/xfrmi.c @@ -0,0 +1,316 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2019 Eyal Birger + * + * Based on lib/route/link/ipvti.c + */ + +/** + * @ingroup link + * @defgroup xfrmi XFRMI + * xfrmi link module + * + * @details + * \b Link Type Name: "xfrmi" + * + * @route_doc{link_xfrmi, XFRMI Documentation} + * + * @{ + */ + +#include "nl-default.h" + +#include +#include +#include +#include +#include +#include + +#include "nl-route.h" +#include "link-api.h" + +#define XFRMI_ATTR_LINK (1 << 0) +#define XFRMI_ATTR_IF_ID (1 << 1) + +#define XFRMI_LINK_TYPE_NAME "xfrm" + +struct xfrmi_info { + uint32_t link; + uint32_t if_id; + uint32_t xfrmi_mask; +}; + +static struct nla_policy xfrmi_policy[IFLA_XFRM_MAX + 1] = { + [IFLA_XFRM_LINK] = { .type = NLA_U32 }, + [IFLA_XFRM_IF_ID] = { .type = NLA_U32 }, +}; + +static int xfrmi_alloc(struct rtnl_link *link) +{ + struct xfrmi_info *xfrmi; + + if (link->l_info) + memset(link->l_info, 0, sizeof(*xfrmi)); + else { + xfrmi = calloc(1, sizeof(*xfrmi)); + if (!xfrmi) + return -NLE_NOMEM; + + link->l_info = xfrmi; + } + + return 0; +} + +static int xfrmi_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_XFRM_MAX + 1]; + struct xfrmi_info *xfrmi; + int err; + + NL_DBG(3, "Parsing XFRMI link info\n"); + + err = nla_parse_nested(tb, IFLA_XFRM_MAX, data, xfrmi_policy); + if (err < 0) + return err; + + err = xfrmi_alloc(link); + if (err < 0) + return err; + + xfrmi = link->l_info; + + if (tb[IFLA_XFRM_LINK]) { + xfrmi->link = nla_get_u32(tb[IFLA_XFRM_LINK]); + xfrmi->xfrmi_mask |= XFRMI_ATTR_LINK; + } + + if (tb[IFLA_XFRM_IF_ID]) { + xfrmi->if_id = nla_get_u32(tb[IFLA_XFRM_IF_ID]); + xfrmi->xfrmi_mask |= XFRMI_ATTR_IF_ID; + } + + return 0; +} + +static int xfrmi_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct xfrmi_info *xfrmi = link->l_info; + struct nlattr *data; + + data = nla_nest_start(msg, IFLA_INFO_DATA); + if (!data) + return -NLE_MSGSIZE; + + if (xfrmi->xfrmi_mask & XFRMI_ATTR_LINK) + NLA_PUT_U32(msg, IFLA_XFRM_LINK, xfrmi->link); + + if (xfrmi->xfrmi_mask & XFRMI_ATTR_IF_ID) + NLA_PUT_U32(msg, IFLA_XFRM_IF_ID, xfrmi->if_id); + + nla_nest_end(msg, data); + +nla_put_failure: + return 0; +} + +static void xfrmi_free(struct rtnl_link *link) +{ + struct xfrmi_info *xfrmi = link->l_info; + + free(xfrmi); + link->l_info = NULL; +} + +static void xfrmi_dump_line(struct rtnl_link *link, struct nl_dump_params *p) +{ + nl_dump(p, "xfrmi : %s", link->l_name); +} + +static void xfrmi_dump_details(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct xfrmi_info *xfrmi = link->l_info; + + if (xfrmi->xfrmi_mask & XFRMI_ATTR_LINK) { + struct rtnl_link *parent; + char *name; + + nl_dump(p, " link "); + + name = NULL; + parent = link_lookup(link->ce_cache, xfrmi->link); + if (parent) + name = rtnl_link_get_name(parent); + + if (name) + nl_dump_line(p, "%s\n", name); + else + nl_dump_line(p, "%u\n", xfrmi->link); + } + + if (xfrmi->xfrmi_mask & XFRMI_ATTR_IF_ID) { + nl_dump(p, " if_id "); + nl_dump_line(p, "%x\n", xfrmi->if_id); + } +} + +static int xfrmi_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct xfrmi_info *xfrmi_dst, *xfrmi_src = src->l_info; + int err; + + dst->l_info = NULL; + + err = rtnl_link_set_type(dst, XFRMI_LINK_TYPE_NAME); + if (err < 0) + return err; + + xfrmi_dst = dst->l_info; + + if (!xfrmi_dst || !xfrmi_src) + BUG(); + + memcpy(xfrmi_dst, xfrmi_src, sizeof(struct xfrmi_info)); + + return 0; +} + +static struct rtnl_link_info_ops xfrmi_info_ops = { + .io_name = XFRMI_LINK_TYPE_NAME, + .io_alloc = xfrmi_alloc, + .io_parse = xfrmi_parse, + .io_dump = { + [NL_DUMP_LINE] = xfrmi_dump_line, + [NL_DUMP_DETAILS] = xfrmi_dump_details, + }, + .io_clone = xfrmi_clone, + .io_put_attrs = xfrmi_put_attrs, + .io_free = xfrmi_free, +}; + +#define IS_XFRMI_LINK_ASSERT(link) do { \ + if ((link)->l_info_ops != &xfrmi_info_ops) { \ + APPBUG("Link is not a xfrmi link. set type \"xfrmi\" first."); \ + return -NLE_OPNOTSUPP; \ + } \ + } while(0) + +struct rtnl_link *rtnl_link_xfrmi_alloc(void) +{ + struct rtnl_link *link; + int err; + + link = rtnl_link_alloc(); + if (!link) + return NULL; + + err = rtnl_link_set_type(link, XFRMI_LINK_TYPE_NAME); + if (err < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if link is a XFRMI link + * @arg link Link object + * + * @return True if link is a IXFRMI link, otherwise 0 is returned. + */ +int rtnl_link_is_xfrmi(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, + XFRMI_LINK_TYPE_NAME); +} + +/** + * Set XFRMI link interface index + * @arg link Link object + * @arg index interface index + * + * @return 0 on success or a negative error code + */ +int rtnl_link_xfrmi_set_link(struct rtnl_link *link, uint32_t index) +{ + struct xfrmi_info *xfrmi = link->l_info; + + IS_XFRMI_LINK_ASSERT(link); + + xfrmi->link = index; + xfrmi->xfrmi_mask |= XFRMI_ATTR_LINK; + + return 0; +} + +/** + * Get XFRMI link interface index + * @arg link Link object + * @arg out_link The output value on success + * + * @return 0 on success or a negative error code + */ +int rtnl_link_xfrmi_get_link(struct rtnl_link *link, uint32_t *out_link) +{ + struct xfrmi_info *xfrmi = link->l_info; + + IS_XFRMI_LINK_ASSERT(link); + + if (!(xfrmi->xfrmi_mask & XFRMI_ATTR_LINK)) + return -NLE_NOATTR; + + *out_link = xfrmi->link; + return 0; +} + +/** + * Set XFRMI if_id + * @arg link Link object + * @arg if_id xfrm if_id + * + * @return 0 on success or a negative error code + */ +int rtnl_link_xfrmi_set_if_id(struct rtnl_link *link, uint32_t if_id) +{ + struct xfrmi_info *xfrmi = link->l_info; + + IS_XFRMI_LINK_ASSERT(link); + + xfrmi->if_id = if_id; + xfrmi->xfrmi_mask |= XFRMI_ATTR_IF_ID; + + return 0; +} + +/** + * Get XFRMI if_id + * @arg link Link object + * @arg out_if_id The output value on success + * + * @return 0 on success or a negative error code + */ +int rtnl_link_xfrmi_get_if_id(struct rtnl_link *link, uint32_t *out_if_id) +{ + struct xfrmi_info *xfrmi = link->l_info; + + IS_XFRMI_LINK_ASSERT(link); + + if (!(xfrmi->xfrmi_mask & XFRMI_ATTR_IF_ID)) + return -NLE_NOATTR; + + *out_if_id = xfrmi->if_id; + return 0; +} + +static void _nl_init xfrmi_init(void) +{ + rtnl_link_register_info(&xfrmi_info_ops); +} + +static void _nl_exit xfrmi_exit(void) +{ + rtnl_link_unregister_info(&xfrmi_info_ops); +} diff --git a/lib/route/mdb.c b/lib/route/mdb.c new file mode 100644 index 0000000..7749c16 --- /dev/null +++ b/lib/route/mdb.c @@ -0,0 +1,491 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * lib/route/mdb.c Multicast Database + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include +#include + +#include "nl-route.h" +#include "nl-aux-route/nl-route.h" +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-priv-dynamic-core/cache-api.h" + +/** @cond SKIP */ +#define MDB_ATTR_IFINDEX 0x000001 +#define MDB_ATTR_ENTRIES 0x000002 + +struct rtnl_mdb { + NLHDR_COMMON + uint32_t ifindex; + + struct nl_list_head mdb_entry_list; +}; + +struct rtnl_mdb_entry { + struct nl_list_head mdb_list; + struct nl_addr *addr; + uint32_t ifindex; + uint16_t vid; + uint16_t proto; + uint8_t state; +}; + +static struct rtnl_mdb_entry *rtnl_mdb_entry_alloc(void); +static void rtnl_mdb_entry_free(struct rtnl_mdb_entry *mdb_entry); + +static struct nl_cache_ops rtnl_mdb_ops; +static struct nl_object_ops mdb_obj_ops; +/** @endcond */ + +static void mdb_constructor(struct nl_object *obj) +{ + struct rtnl_mdb *_mdb = (struct rtnl_mdb *) obj; + + nl_init_list_head(&_mdb->mdb_entry_list); +} + +static void mdb_free_data(struct nl_object *obj) +{ + struct rtnl_mdb *mdb = (struct rtnl_mdb *)obj; + struct rtnl_mdb_entry *mdb_entry; + struct rtnl_mdb_entry *mdb_entry_safe; + + nl_list_for_each_entry_safe(mdb_entry, mdb_entry_safe, + &mdb->mdb_entry_list, mdb_list) + rtnl_mdb_entry_free(mdb_entry); +} + +static int mdb_entry_equal(struct rtnl_mdb_entry *a, struct rtnl_mdb_entry *b) +{ + return a->ifindex == b->ifindex + && a->vid == b->vid + && a->proto == b->proto + && a->state == b->state + && nl_addr_cmp(a->addr, b->addr) == 0; +} + +static uint64_t mdb_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) +{ + struct rtnl_mdb *a = (struct rtnl_mdb *) _a; + struct rtnl_mdb *b = (struct rtnl_mdb *) _b; + struct rtnl_mdb_entry *a_entry, *b_entry; + uint64_t diff = 0; + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(MDB_ATTR_IFINDEX, a->ifindex != b->ifindex); +#undef _DIFF + + a_entry = nl_list_entry(a->mdb_entry_list.next, struct rtnl_mdb_entry, mdb_list); + b_entry = nl_list_entry(b->mdb_entry_list.next, struct rtnl_mdb_entry, mdb_list); + while (1) { + if ( &a_entry->mdb_list == &a->mdb_entry_list + || &b_entry->mdb_list == &b->mdb_entry_list) { + if ( &a_entry->mdb_list != &a->mdb_entry_list + || &b_entry->mdb_list != &b->mdb_entry_list) + diff |= MDB_ATTR_ENTRIES; + break; + } + if (!mdb_entry_equal(a_entry, b_entry)) { + diff |= MDB_ATTR_ENTRIES; + break; + } + a_entry = nl_list_entry(a_entry->mdb_list.next, struct rtnl_mdb_entry, mdb_list); + b_entry = nl_list_entry(b_entry->mdb_list.next, struct rtnl_mdb_entry, mdb_list); + } + + return diff; +} + +static struct rtnl_mdb_entry *mdb_entry_clone(struct rtnl_mdb_entry *src) +{ + struct rtnl_mdb_entry *dst = rtnl_mdb_entry_alloc(); + if (!dst) + return NULL; + + dst->ifindex = src->ifindex; + dst->state = src->state; + dst->vid = src->vid; + dst->proto = src->proto; + + dst->addr = nl_addr_clone(src->addr); + if (dst->addr == NULL) { + free(dst); + return NULL; + } + + return dst; +} + +static int mdb_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct rtnl_mdb *dst = nl_object_priv(_dst); + struct rtnl_mdb *src = nl_object_priv(_src); + struct rtnl_mdb_entry *entry; + + nl_init_list_head(&dst->mdb_entry_list); + + nl_list_for_each_entry(entry, &src->mdb_entry_list, mdb_list) { + struct rtnl_mdb_entry *copy = mdb_entry_clone(entry); + + if (!copy) + return -NLE_NOMEM; + + rtnl_mdb_add_entry(dst, copy); + } + + return 0; +} + +static int mdb_update(struct nl_object *old_obj, struct nl_object *new_obj) +{ + struct rtnl_mdb *old = (struct rtnl_mdb *) old_obj; + struct rtnl_mdb *new = (struct rtnl_mdb *) new_obj; + struct rtnl_mdb_entry *entry, *old_entry; + int action = new_obj->ce_msgtype; + + if (new->ifindex != old->ifindex) + return -NLE_OPNOTSUPP; + + switch (action) { + case RTM_NEWMDB: + nl_list_for_each_entry(entry, &new->mdb_entry_list, mdb_list) { + struct rtnl_mdb_entry *copy = mdb_entry_clone(entry); + + if (!copy) + return -NLE_NOMEM; + + rtnl_mdb_add_entry(old, copy); + } + break; + case RTM_DELMDB: + entry = nl_list_first_entry(&new->mdb_entry_list, + struct rtnl_mdb_entry, + mdb_list); + nl_list_for_each_entry(old_entry, &old->mdb_entry_list, mdb_list) { + if ( old_entry->ifindex == entry->ifindex + && !nl_addr_cmp(old_entry->addr, entry->addr)) { + nl_list_del(&old_entry->mdb_list); + break; + } + } + break; + } + + return NLE_SUCCESS; +} + +static struct nla_policy mdb_policy[MDBA_MAX + 1] = { + [MDBA_MDB] = {.type = NLA_NESTED}, +}; + +static struct nla_policy mdb_db_policy[MDBA_MDB_MAX + 1] = { + [MDBA_MDB_ENTRY] = {.type = NLA_NESTED}, +}; + +static int mdb_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *nlh, struct nl_parser_param *pp) +{ + int err = 0; + int rem = 0; + struct nlattr *tb[MDBA_MAX + 1]; + struct br_port_msg *port; + struct nlattr *nla; + struct br_mdb_entry *e; + _nl_auto_rtnl_mdb struct rtnl_mdb *mdb = rtnl_mdb_alloc(); + + if (!mdb) + return -NLE_NOMEM; + + err = nlmsg_parse(nlh, sizeof(struct br_port_msg), tb, MDBA_MAX, + mdb_policy); + if (err < 0) + return err; + + mdb->ce_msgtype = nlh->nlmsg_type; + + port = nlmsg_data(nlh); + mdb->ifindex = port->ifindex; + mdb->ce_mask |= MDB_ATTR_IFINDEX; + + if (tb[MDBA_MDB]) { + struct nlattr *db_attr[MDBA_MDB_MAX+1]; + + err = nla_parse_nested(db_attr, MDBA_MDB_MAX, tb[MDBA_MDB], + mdb_db_policy); + if (err < 0) + return err; + rem = nla_len(tb[MDBA_MDB]); + + for (nla = nla_data(tb[MDBA_MDB]); nla_ok(nla, rem); + nla = nla_next(nla, &rem)) { + int rm = nla_len(nla); + struct nlattr *nla2; + + for (nla2 = nla_data(nla); nla_ok(nla2, rm); + nla2 = nla_next(nla2, &rm)) { + _nl_auto_nl_addr struct nl_addr *addr = NULL; + struct rtnl_mdb_entry *entry; + uint16_t proto; + + e = nla_data(nla2); + + proto = ntohs(e->addr.proto); + + if (proto == ETH_P_IP) { + addr = nl_addr_build( + AF_INET, &e->addr.u.ip4, + sizeof(e->addr.u.ip4)); + } else if (proto == ETH_P_IPV6) { + addr = nl_addr_build( + AF_INET6, &e->addr.u.ip6, + sizeof(e->addr.u.ip6)); + } else { + addr = nl_addr_build( + AF_LLC, e->addr.u.mac_addr, + sizeof(e->addr.u.mac_addr)); + } + if (!addr) + return -NLE_NOMEM; + + entry = rtnl_mdb_entry_alloc(); + if (!entry) + return -NLE_NOMEM; + + mdb->ce_mask |= MDB_ATTR_ENTRIES; + + entry->ifindex = e->ifindex; + entry->vid = e->vid; + entry->state = e->state; + entry->proto = ntohs(e->addr.proto); + entry->addr = _nl_steal_pointer(&addr); + rtnl_mdb_add_entry(mdb, entry); + } + } + } + + return pp->pp_cb((struct nl_object *) mdb, pp); +} + +static int mdb_request_update(struct nl_cache *cache, struct nl_sock *sk) +{ + return nl_rtgen_request(sk, RTM_GETMDB, AF_BRIDGE, NLM_F_DUMP); +} + +static void mdb_entry_dump_line(struct rtnl_mdb_entry *entry, + struct nl_dump_params *p) +{ + char buf[INET6_ADDRSTRLEN]; + + nl_dump(p, "port %d ", entry->ifindex); + nl_dump(p, "vid %d ", entry->vid); + nl_dump(p, "proto 0x%04x ", entry->proto); + nl_dump(p, "address %s\n", nl_addr2str(entry->addr, buf, sizeof(buf))); +} + +static void mdb_dump_line(struct nl_object *obj, struct nl_dump_params *p) +{ + struct rtnl_mdb *mdb = (struct rtnl_mdb *) obj; + struct rtnl_mdb_entry *_mdb; + + nl_dump(p, "dev %d \n", mdb->ifindex); + + nl_list_for_each_entry(_mdb, &mdb->mdb_entry_list, mdb_list) { + p->dp_ivar = NH_DUMP_FROM_ONELINE; + mdb_entry_dump_line(_mdb, p); + } +} + +static void mdb_dump_details(struct nl_object *obj, struct nl_dump_params *p) +{ + mdb_dump_line(obj, p); +} + +static void mdb_dump_stats(struct nl_object *obj, struct nl_dump_params *p) +{ + mdb_dump_details(obj, p); +} + +void rtnl_mdb_put(struct rtnl_mdb *mdb) +{ + nl_object_put((struct nl_object *) mdb); +} + +/** @} */ + +/** + * @name Cache Management + * @{ + */ +int rtnl_mdb_alloc_cache(struct nl_sock *sk, struct nl_cache **result) +{ + return nl_cache_alloc_and_fill(&rtnl_mdb_ops, sk, result); +} + +/** + * Build a neighbour cache including all MDB entries currently configured in the kernel. + * @arg sock Netlink socket. + * @arg result Pointer to store resulting cache. + * @arg flags Flags to apply to cache before filling + * + * Allocates a new MDB cache, initializes it properly and updates it + * to include all Multicast Database entries currently configured in the kernel. + * + * @return 0 on success or a negative error code. + */ +int rtnl_mdb_alloc_cache_flags(struct nl_sock *sock, struct nl_cache **result, + unsigned int flags) +{ + struct nl_cache *cache; + int err; + + cache = nl_cache_alloc(&rtnl_mdb_ops); + if (!cache) + return -NLE_NOMEM; + + nl_cache_set_flags(cache, flags); + + if (sock && (err = nl_cache_refill(sock, cache)) < 0) { + nl_cache_free(cache); + return err; + } + + *result = cache; + return 0; +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ +uint32_t rtnl_mdb_get_ifindex(struct rtnl_mdb *mdb) +{ + return mdb->ifindex; +} + +void rtnl_mdb_add_entry(struct rtnl_mdb *mdb, struct rtnl_mdb_entry *entry) +{ + nl_list_add_tail(&entry->mdb_list, &mdb->mdb_entry_list); +} + +void rtnl_mdb_foreach_entry(struct rtnl_mdb *mdb, + void (*cb)(struct rtnl_mdb_entry *, void *), + void *arg) +{ + struct rtnl_mdb_entry *entry; + + nl_list_for_each_entry(entry, &mdb->mdb_entry_list, mdb_list) { + cb(entry, arg); + } +} + +int rtnl_mdb_entry_get_ifindex(struct rtnl_mdb_entry *mdb_entry) +{ + return mdb_entry->ifindex; +} + +int rtnl_mdb_entry_get_vid(struct rtnl_mdb_entry *mdb_entry) +{ + return mdb_entry->vid; +} + +int rtnl_mdb_entry_get_state(struct rtnl_mdb_entry *mdb_entry) +{ + return mdb_entry->state; +} + +struct nl_addr *rtnl_mdb_entry_get_addr(struct rtnl_mdb_entry *mdb_entry) +{ + return mdb_entry->addr; +} + +uint16_t rtnl_mdb_entry_get_proto(struct rtnl_mdb_entry *mdb_entry) +{ + return mdb_entry->proto; +} + +/** @} */ + +static struct nl_object_ops mdb_obj_ops = { + .oo_name = "route/mdb", + .oo_size = sizeof(struct rtnl_mdb), + .oo_constructor = mdb_constructor, + .oo_dump = { + [NL_DUMP_LINE] = mdb_dump_line, + [NL_DUMP_DETAILS] = mdb_dump_details, + [NL_DUMP_STATS] = mdb_dump_stats, + }, + .oo_clone = mdb_clone, + .oo_compare = mdb_compare, + .oo_update = mdb_update, + .oo_free_data = mdb_free_data, +}; + +struct rtnl_mdb *rtnl_mdb_alloc(void) +{ + return (struct rtnl_mdb *) nl_object_alloc(&mdb_obj_ops); +} + +static struct rtnl_mdb_entry *rtnl_mdb_entry_alloc(void) +{ + struct rtnl_mdb_entry *mdb; + + mdb = calloc(1, sizeof(struct rtnl_mdb_entry)); + if (!mdb) + return NULL; + + nl_init_list_head(&mdb->mdb_list); + + return mdb; + +} + +static void rtnl_mdb_entry_free(struct rtnl_mdb_entry *mdb_entry) +{ + nl_list_del(&mdb_entry->mdb_list); + nl_addr_put(mdb_entry->addr); + free(mdb_entry); +} + +static struct nl_af_group mdb_groups[] = { + {AF_BRIDGE, RTNLGRP_MDB}, + {END_OF_GROUP_LIST}, +}; + +static struct nl_cache_ops rtnl_mdb_ops = { + .co_name = "route/mdb", + .co_hdrsize = sizeof(struct br_port_msg), + .co_msgtypes = { + { RTM_NEWMDB, NL_ACT_NEW, "new"}, + { RTM_DELMDB, NL_ACT_DEL, "del"}, + { RTM_GETMDB, NL_ACT_GET, "get"}, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_ROUTE, + .co_groups = mdb_groups, + .co_request_update = mdb_request_update, + .co_msg_parser = mdb_msg_parser, + .co_obj_ops = &mdb_obj_ops, +}; + +static void _nl_init mdb_init(void) +{ + nl_cache_mngt_register(&rtnl_mdb_ops); +} + +static void _nl_exit mdb_exit(void) +{ + nl_cache_mngt_unregister(&rtnl_mdb_ops); +} + +/** @} */ diff --git a/lib/route/neigh.c b/lib/route/neigh.c index ad26b4d..9150024 100644 --- a/lib/route/neigh.c +++ b/lib/route/neigh.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/neigh.c Neighbours - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf */ @@ -35,6 +29,7 @@ * NTF_USE * NTF_PROXY * NTF_ROUTER + * NTF_SELF * @endcode * * @par Neighbour Identification @@ -67,7 +62,7 @@ * // Neighbours can then be looked up by the interface and destination * // address: * struct rtnl_neigh *neigh = rtnl_neigh_get(cache, ifindex, dst_addr); - * + * * // After successful usage, the object must be given back to the cache * rtnl_neigh_put(neigh); * @endcode @@ -148,7 +143,8 @@ * @{ */ -#include +#include "nl-default.h" + #include #include #include @@ -157,7 +153,36 @@ #include #include +#include "nl-route.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" + /** @cond SKIP */ +struct rtnl_ncacheinfo { + uint32_t nci_confirmed; /**< Time since neighbour validty was last confirmed */ + uint32_t nci_used; /**< Time since neighbour entry was last ued */ + uint32_t nci_updated; /**< Time since last update */ + uint32_t nci_refcnt; /**< Reference counter */ +}; + +struct rtnl_neigh { + NLHDR_COMMON + uint32_t n_family; + uint32_t n_ifindex; + uint16_t n_state; + uint8_t n_flags; + uint8_t n_type; + struct nl_addr *n_lladdr; + struct nl_addr *n_dst; + uint32_t n_nhid; + uint32_t n_probes; + struct rtnl_ncacheinfo n_cacheinfo; + uint32_t n_state_mask; + uint32_t n_flag_mask; + uint32_t n_master; + uint16_t n_vlan; +}; + #define NEIGH_ATTR_FLAGS 0x01 #define NEIGH_ATTR_STATE 0x02 #define NEIGH_ATTR_LLADDR 0x04 @@ -168,6 +193,8 @@ #define NEIGH_ATTR_TYPE 0x80 #define NEIGH_ATTR_PROBES 0x100 #define NEIGH_ATTR_MASTER 0x200 +#define NEIGH_ATTR_VLAN 0x400 +#define NEIGH_ATTR_NHID 0x800 static struct nl_cache_ops rtnl_neigh_ops; static struct nl_object_ops neigh_obj_ops; @@ -189,6 +216,9 @@ static int neigh_clone(struct nl_object *_dst, struct nl_object *_src) struct rtnl_neigh *dst = nl_object_priv(_dst); struct rtnl_neigh *src = nl_object_priv(_src); + dst->n_lladdr = NULL; + dst->n_dst = NULL; + if (src->n_lladdr) if (!(dst->n_lladdr = nl_addr_clone(src->n_lladdr))) return -NLE_NOMEM; @@ -209,8 +239,9 @@ static void neigh_keygen(struct nl_object *obj, uint32_t *hashkey, struct neigh_hash_key { uint32_t n_family; uint32_t n_ifindex; + uint16_t n_vlan; char n_addr[0]; - } __attribute__((packed)) *nkey; + } _nl_packed *nkey; #ifdef NL_DEBUG char buf[INET6_ADDRSTRLEN+5]; #endif @@ -232,10 +263,15 @@ static void neigh_keygen(struct nl_object *obj, uint32_t *hashkey, return; } nkey->n_family = neigh->n_family; - if (neigh->n_family == AF_BRIDGE) - nkey->n_ifindex = neigh->n_master; - else + if (neigh->n_family == AF_BRIDGE) { + nkey->n_vlan = neigh->n_vlan; + if (neigh->n_flags & NTF_SELF) + nkey->n_ifindex = neigh->n_ifindex; + else + nkey->n_ifindex = neigh->n_master; + } else nkey->n_ifindex = neigh->n_ifindex; + if (addr) memcpy(nkey->n_addr, nl_addr_get_binary_addr(addr), @@ -253,47 +289,50 @@ static void neigh_keygen(struct nl_object *obj, uint32_t *hashkey, return; } -static int neigh_compare(struct nl_object *_a, struct nl_object *_b, - uint32_t attrs, int flags) +static uint64_t neigh_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) { struct rtnl_neigh *a = (struct rtnl_neigh *) _a; struct rtnl_neigh *b = (struct rtnl_neigh *) _b; - int diff = 0; - -#define NEIGH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGH_ATTR_##ATTR, a, b, EXPR) - - diff |= NEIGH_DIFF(IFINDEX, a->n_ifindex != b->n_ifindex); - diff |= NEIGH_DIFF(FAMILY, a->n_family != b->n_family); - diff |= NEIGH_DIFF(TYPE, a->n_type != b->n_type); - diff |= NEIGH_DIFF(LLADDR, nl_addr_cmp(a->n_lladdr, b->n_lladdr)); - diff |= NEIGH_DIFF(DST, nl_addr_cmp(a->n_dst, b->n_dst)); - diff |= NEIGH_DIFF(MASTER, a->n_master != b->n_master); + uint64_t diff = 0; + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(NEIGH_ATTR_IFINDEX, a->n_ifindex != b->n_ifindex); + diff |= _DIFF(NEIGH_ATTR_FAMILY, a->n_family != b->n_family); + diff |= _DIFF(NEIGH_ATTR_TYPE, a->n_type != b->n_type); + diff |= _DIFF(NEIGH_ATTR_LLADDR, nl_addr_cmp(a->n_lladdr, b->n_lladdr)); + diff |= _DIFF(NEIGH_ATTR_DST, nl_addr_cmp(a->n_dst, b->n_dst)); + diff |= _DIFF(NEIGH_ATTR_MASTER, a->n_master != b->n_master); + diff |= _DIFF(NEIGH_ATTR_VLAN, a->n_vlan != b->n_vlan); + diff |= _DIFF(NEIGH_ATTR_NHID, a->n_nhid != b->n_nhid); if (flags & LOOSE_COMPARISON) { - diff |= NEIGH_DIFF(STATE, - (a->n_state ^ b->n_state) & b->n_state_mask); - diff |= NEIGH_DIFF(FLAGS, - (a->n_flags ^ b->n_flags) & b->n_flag_mask); + diff |= _DIFF(NEIGH_ATTR_STATE, + (a->n_state ^ b->n_state) & b->n_state_mask); + diff |= _DIFF(NEIGH_ATTR_FLAGS, + (a->n_flags ^ b->n_flags) & b->n_flag_mask); } else { - diff |= NEIGH_DIFF(STATE, a->n_state != b->n_state); - diff |= NEIGH_DIFF(FLAGS, a->n_flags != b->n_flags); + diff |= _DIFF(NEIGH_ATTR_STATE, a->n_state != b->n_state); + diff |= _DIFF(NEIGH_ATTR_FLAGS, a->n_flags != b->n_flags); } - -#undef NEIGH_DIFF +#undef _DIFF return diff; } static const struct trans_tbl neigh_attrs[] = { - __ADD(NEIGH_ATTR_FLAGS, flags) - __ADD(NEIGH_ATTR_STATE, state) - __ADD(NEIGH_ATTR_LLADDR, lladdr) - __ADD(NEIGH_ATTR_DST, dst) - __ADD(NEIGH_ATTR_CACHEINFO, cacheinfo) - __ADD(NEIGH_ATTR_IFINDEX, ifindex) - __ADD(NEIGH_ATTR_FAMILY, family) - __ADD(NEIGH_ATTR_TYPE, type) - __ADD(NEIGH_ATTR_PROBES, probes) + __ADD(NEIGH_ATTR_FLAGS, flags), + __ADD(NEIGH_ATTR_STATE, state), + __ADD(NEIGH_ATTR_LLADDR, lladdr), + __ADD(NEIGH_ATTR_DST, dst), + __ADD(NEIGH_ATTR_CACHEINFO, cacheinfo), + __ADD(NEIGH_ATTR_IFINDEX, ifindex), + __ADD(NEIGH_ATTR_FAMILY, family), + __ADD(NEIGH_ATTR_TYPE, type), + __ADD(NEIGH_ATTR_PROBES, probes), + __ADD(NEIGH_ATTR_MASTER, master), + __ADD(NEIGH_ATTR_VLAN, vlan), + __ADD(NEIGH_ATTR_NHID, nhid), }; static char *neigh_attrs2str(int attrs, char *buf, size_t len) @@ -306,10 +345,16 @@ static uint32_t neigh_id_attrs_get(struct nl_object *obj) { struct rtnl_neigh *neigh = (struct rtnl_neigh *)obj; - if (neigh->n_family == AF_BRIDGE) - return (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY | NEIGH_ATTR_MASTER); - else - return (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY); + if (neigh->n_family == AF_BRIDGE) { + if (neigh->n_flags & NTF_SELF) + return (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY | NEIGH_ATTR_IFINDEX | + ((neigh->ce_mask & NEIGH_ATTR_DST) ? NEIGH_ATTR_DST: 0) | + ((neigh->ce_mask & NEIGH_ATTR_NHID) ? NEIGH_ATTR_NHID: 0) | + ((neigh->ce_mask & NEIGH_ATTR_VLAN) ? NEIGH_ATTR_VLAN : 0)); + else + return (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY | NEIGH_ATTR_MASTER | NEIGH_ATTR_VLAN); + } else + return neigh_obj_ops.oo_id_attrs; } static struct nla_policy neigh_policy[NDA_MAX+1] = { @@ -375,11 +420,13 @@ int rtnl_neigh_parse(struct nlmsghdr *n, struct rtnl_neigh **result) } if (tb[NDA_DST]) { - neigh->n_dst = nl_addr_alloc_attr(tb[NDA_DST], neigh->n_family); + neigh->n_dst = nl_addr_alloc_attr(tb[NDA_DST], AF_UNSPEC); if (!neigh->n_dst) { err = -NLE_NOMEM; goto errout; } + nl_addr_set_family(neigh->n_dst, + nl_addr_guess_family(neigh->n_dst)); neigh->ce_mask |= NEIGH_ATTR_DST; } @@ -390,7 +437,7 @@ int rtnl_neigh_parse(struct nlmsghdr *n, struct rtnl_neigh **result) neigh->n_cacheinfo.nci_used = ci->ndm_used; neigh->n_cacheinfo.nci_updated = ci->ndm_updated; neigh->n_cacheinfo.nci_refcnt = ci->ndm_refcnt; - + neigh->ce_mask |= NEIGH_ATTR_CACHEINFO; } @@ -399,21 +446,35 @@ int rtnl_neigh_parse(struct nlmsghdr *n, struct rtnl_neigh **result) neigh->ce_mask |= NEIGH_ATTR_PROBES; } + if (tb[NDA_VLAN]) { + neigh->n_vlan = nla_get_u16(tb[NDA_VLAN]); + neigh->ce_mask |= NEIGH_ATTR_VLAN; + } + + if (tb[NDA_NH_ID]) { + neigh->n_nhid = nla_get_u32(tb[NDA_NH_ID]); + neigh->ce_mask |= NEIGH_ATTR_NHID; + } + /* * Get the bridge index for AF_BRIDGE family entries */ if (neigh->n_family == AF_BRIDGE) { - struct nl_cache *lcache = nl_cache_mngt_require_safe("route/link"); - if (lcache ) { - struct rtnl_link *link = rtnl_link_get(lcache, - neigh->n_ifindex); - if (link) { - neigh->n_master = link->l_master; - rtnl_link_put(link); - neigh->ce_mask |= NEIGH_ATTR_MASTER; + if (tb[NDA_MASTER]) { + neigh->n_master = nla_get_u32(tb[NDA_MASTER]); + neigh->ce_mask |= NEIGH_ATTR_MASTER; + } else { + struct nl_cache *lcache = nl_cache_mngt_require_safe("route/link"); + if (lcache ) { + struct rtnl_link *link = rtnl_link_get(lcache, + neigh->n_ifindex); + if (link) { + neigh->n_master = link->l_master; + rtnl_link_put(link); + neigh->ce_mask |= NEIGH_ATTR_MASTER; + } + nl_cache_put(lcache); } - - nl_cache_put(lcache); } } @@ -429,7 +490,31 @@ static int neigh_request_update(struct nl_cache *c, struct nl_sock *h) { int family = c->c_iarg1; - return nl_rtgen_request(h, RTM_GETNEIGH, family, NLM_F_DUMP); + if (family == AF_UNSPEC) { + return nl_rtgen_request(h, RTM_GETNEIGH, family, NLM_F_DUMP); + } else if (family == AF_BRIDGE) { + struct ifinfomsg hdr = {.ifi_family = family}; + struct nl_msg *msg; + int err; + + msg = nlmsg_alloc_simple(RTM_GETNEIGH, NLM_F_REQUEST | NLM_F_DUMP); + if (!msg) + return -NLE_NOMEM; + + err = -NLE_MSGSIZE; + if (nlmsg_append(msg, &hdr, sizeof(hdr), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + err = nl_send_auto(h, msg); + if (err > 0) + err = 0; + + nla_put_failure: + nlmsg_free(msg); + return err; + } + + return -NLE_INVAL; } @@ -439,10 +524,14 @@ static void neigh_dump_line(struct nl_object *a, struct nl_dump_params *p) struct rtnl_neigh *n = (struct rtnl_neigh *) a; struct nl_cache *link_cache; char state[128], flags[64]; + char buf[128]; link_cache = nl_cache_mngt_require_safe("route/link"); - if (n->n_family != AF_BRIDGE) + if (n->n_family != AF_UNSPEC) + nl_dump_line(p, "%s ", nl_af2str(n->n_family, buf, sizeof(buf))); + + if (n->ce_mask & NEIGH_ATTR_DST) nl_dump_line(p, "%s ", nl_addr2str(n->n_dst, dst, sizeof(dst))); if (link_cache) @@ -456,6 +545,20 @@ static void neigh_dump_line(struct nl_object *a, struct nl_dump_params *p) nl_dump(p, "lladdr %s ", nl_addr2str(n->n_lladdr, lladdr, sizeof(lladdr))); + if (n->ce_mask & NEIGH_ATTR_VLAN) + nl_dump(p, "vlan %d ", n->n_vlan); + + if (n->ce_mask & NEIGH_ATTR_NHID) + nl_dump(p, "nhid %u ", n->n_nhid); + + if (n->ce_mask & NEIGH_ATTR_MASTER) { + if (link_cache) + nl_dump(p, "%s ", rtnl_link_i2name(link_cache, n->n_master, + state, sizeof(state))); + else + nl_dump(p, "%d ", n->n_master); + } + rtnl_neigh_state2str(n->n_state, state, sizeof(state)); rtnl_neigh_flags2str(n->n_flags, flags, sizeof(flags)); @@ -530,6 +633,38 @@ int rtnl_neigh_alloc_cache(struct nl_sock *sock, struct nl_cache **result) } /** + * Build a neighbour cache including all neighbours currently configured in the kernel. + * @arg sock Netlink socket. + * @arg result Pointer to store resulting cache. + * @arg flags Flags to apply to cache before filling + * + * Allocates a new neighbour cache, initializes it properly and updates it + * to include all neighbours currently configured in the kernel. + * + * @return 0 on success or a negative error code. + */ +int rtnl_neigh_alloc_cache_flags(struct nl_sock *sock, struct nl_cache **result, + unsigned int flags) +{ + struct nl_cache * cache; + int err; + + cache = nl_cache_alloc(&rtnl_neigh_ops); + if (!cache) + return -NLE_NOMEM; + + nl_cache_set_flags(cache, flags); + + if (sock && (err = nl_cache_refill(sock, cache)) < 0) { + nl_cache_free(cache); + return err; + } + + *result = cache; + return 0; +} + +/** * Look up a neighbour by interface index and destination address * @arg cache neighbour cache * @arg ifindex interface index the neighbour is on @@ -544,6 +679,7 @@ struct rtnl_neigh * rtnl_neigh_get(struct nl_cache *cache, int ifindex, nl_list_for_each_entry(neigh, &cache->c_items, ce_list) { if (neigh->n_ifindex == ifindex && + neigh->n_family == dst->a_family && !nl_addr_cmp(neigh->n_dst, dst)) { nl_object_get((struct nl_object *) neigh); return neigh; @@ -553,6 +689,32 @@ struct rtnl_neigh * rtnl_neigh_get(struct nl_cache *cache, int ifindex, return NULL; } +/** + * Look up a neighbour by interface index, link layer address and vlan id + * @arg cache neighbour cache + * @arg ifindex interface index the neighbour is on + * @arg lladdr link layer address of the neighbour + * @arg vlan vlan id of the neighbour + * + * @return neighbour handle or NULL if no match was found. + */ +struct rtnl_neigh * rtnl_neigh_get_by_vlan(struct nl_cache *cache, int ifindex, + struct nl_addr *lladdr, int vlan) +{ + struct rtnl_neigh *neigh; + + nl_list_for_each_entry(neigh, &cache->c_items, ce_list) { + if (neigh->n_ifindex == ifindex && + neigh->n_vlan == vlan && + neigh->n_lladdr && !nl_addr_cmp(neigh->n_lladdr, lladdr)) { + nl_object_get((struct nl_object *) neigh); + return neigh; + } + } + + return NULL; +} + /** @} */ /** @@ -590,12 +752,18 @@ static int build_neigh_msg(struct rtnl_neigh *tmpl, int cmd, int flags, if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0) goto nla_put_failure; - if (tmpl->n_family != AF_BRIDGE) + if (tmpl->ce_mask & NEIGH_ATTR_DST) NLA_PUT_ADDR(msg, NDA_DST, tmpl->n_dst); if (tmpl->ce_mask & NEIGH_ATTR_LLADDR) NLA_PUT_ADDR(msg, NDA_LLADDR, tmpl->n_lladdr); + if (tmpl->ce_mask & NEIGH_ATTR_VLAN) + NLA_PUT_U16(msg, NDA_VLAN, tmpl->n_vlan); + + if (tmpl->ce_mask & NEIGH_ATTR_NHID) + NLA_PUT_U32(msg, NDA_NH_ID, tmpl->n_nhid); + *result = msg; return 0; @@ -615,7 +783,7 @@ nla_put_failure: * all relevant fields and must thus be sent out via nl_send_auto_complete() * or supplemented as needed. \a tmpl must contain the attributes of the new * neighbour set via \c rtnl_neigh_set_* functions. - * + * * The following attributes must be set in the template: * - Interface index (rtnl_neigh_set_ifindex()) * - State (rtnl_neigh_set_state()) @@ -646,13 +814,13 @@ int rtnl_neigh_build_add_request(struct rtnl_neigh *tmpl, int flags, * - Destination address (rtnl_neigh_set_dst()) * - Link layer address (rtnl_neigh_set_lladdr()) * - * @return 0 on sucess or a negative error if an error occured. + * @return 0 on success or a negative error if an error occured. */ int rtnl_neigh_add(struct nl_sock *sk, struct rtnl_neigh *tmpl, int flags) { int err; struct nl_msg *msg; - + if ((err = rtnl_neigh_build_add_request(tmpl, flags, &msg)) < 0) return err; @@ -701,14 +869,14 @@ int rtnl_neigh_build_delete_request(struct rtnl_neigh *neigh, int flags, * sends the request to the kernel and waits for the next ACK to be * received and thus blocks until the request has been fullfilled. * - * @return 0 on sucess or a negative error if an error occured. + * @return 0 on success or a negative error if an error occured. */ int rtnl_neigh_delete(struct nl_sock *sk, struct rtnl_neigh *neigh, int flags) { struct nl_msg *msg; int err; - + if ((err = rtnl_neigh_build_delete_request(neigh, flags, &msg)) < 0) return err; @@ -728,20 +896,25 @@ int rtnl_neigh_delete(struct nl_sock *sk, struct rtnl_neigh *neigh, */ static const struct trans_tbl neigh_states[] = { - __ADD(NUD_INCOMPLETE, incomplete) - __ADD(NUD_REACHABLE, reachable) - __ADD(NUD_STALE, stale) - __ADD(NUD_DELAY, delay) - __ADD(NUD_PROBE, probe) - __ADD(NUD_FAILED, failed) - __ADD(NUD_NOARP, norarp) - __ADD(NUD_PERMANENT, permanent) + __ADD(NUD_INCOMPLETE, incomplete), + __ADD(NUD_REACHABLE, reachable), + __ADD(NUD_STALE, stale), + __ADD(NUD_DELAY, delay), + __ADD(NUD_PROBE, probe), + __ADD(NUD_FAILED, failed), + __ADD(NUD_NOARP, noarp), + __ADD(NUD_PERMANENT, permanent), + + /* Accept this value for backward compatibility. Originally + * there was a typo in the string value. This was fixed later, + * but we still want to successfully parse "norarp". */ + __ADD(NUD_NOARP, norarp), }; char * rtnl_neigh_state2str(int state, char *buf, size_t len) { return __flags2str(state, buf, len, neigh_states, - ARRAY_SIZE(neigh_states)); + ARRAY_SIZE(neigh_states) - 1); } int rtnl_neigh_str2state(const char *name) @@ -757,9 +930,13 @@ int rtnl_neigh_str2state(const char *name) */ static const struct trans_tbl neigh_flags[] = { - __ADD(NTF_USE, use) - __ADD(NTF_PROXY, proxy) - __ADD(NTF_ROUTER, router) + __ADD(NTF_USE, use), + __ADD(NTF_PROXY, proxy), + __ADD(NTF_ROUTER, router), + __ADD(NTF_SELF, self), + __ADD(NTF_MASTER, master), + __ADD(NTF_EXT_LEARNED, ext_learned), + __ADD(NTF_OFFLOADED, offloaded), }; char * rtnl_neigh_flags2str(int flags, char *buf, size_t len) @@ -908,6 +1085,44 @@ int rtnl_neigh_get_type(struct rtnl_neigh *neigh) return -1; } +void rtnl_neigh_set_vlan(struct rtnl_neigh *neigh, int vlan) +{ + neigh->n_vlan = vlan; + neigh->ce_mask |= NEIGH_ATTR_VLAN; +} + +int rtnl_neigh_get_vlan(struct rtnl_neigh *neigh) +{ + if (neigh->ce_mask & NEIGH_ATTR_VLAN) + return neigh->n_vlan; + else + return -1; +} + +void rtnl_neigh_set_master(struct rtnl_neigh *neigh, int ifindex) +{ + neigh->n_master = ifindex; + neigh->ce_mask |= NEIGH_ATTR_MASTER; +} + +int rtnl_neigh_get_master(struct rtnl_neigh *neigh) { + return neigh->n_master; +} + +void rtnl_neigh_set_nhid(struct rtnl_neigh *neigh, uint32_t nhid) +{ + neigh->n_nhid = nhid; + neigh->ce_mask |= NEIGH_ATTR_NHID; +} + +int rtnl_neigh_get_nhid(struct rtnl_neigh *neigh, uint32_t *out_val) { + if (!(neigh->ce_mask & NEIGH_ATTR_NHID)) + return -NLE_NOATTR; + + *out_val = neigh->n_nhid; + return NLE_SUCCESS; +} + /** @} */ static struct nl_object_ops neigh_obj_ops = { @@ -949,12 +1164,12 @@ static struct nl_cache_ops rtnl_neigh_ops = { .co_obj_ops = &neigh_obj_ops, }; -static void __init neigh_init(void) +static void _nl_init neigh_init(void) { nl_cache_mngt_register(&rtnl_neigh_ops); } -static void __exit neigh_exit(void) +static void _nl_exit neigh_exit(void) { nl_cache_mngt_unregister(&rtnl_neigh_ops); } diff --git a/lib/route/neightbl.c b/lib/route/neightbl.c index f9c9c27..a699867 100644 --- a/lib/route/neightbl.c +++ b/lib/route/neightbl.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/neightbl.c neighbour tables - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf */ @@ -16,68 +10,186 @@ * @{ */ -#include +#include "nl-default.h" + #include #include #include #include #include +#include "nl-route.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" + +struct rtnl_neightbl_parms { + /** + * Interface index of the device this parameter set is assigned + * to or 0 for the default set. + */ + uint32_t ntp_ifindex; + + /** + * Number of references to this parameter set. + */ + uint32_t ntp_refcnt; + + /** + * Queue length for pending arp requests, i.e. the number of + * packets which are accepted from other layers while the + * neighbour address is still being resolved + */ + uint32_t ntp_queue_len; + + /** + * Number of requests to send to the user level ARP daemon. + * Specify 0 to disable. + */ + uint32_t ntp_app_probes; + + /** + * Maximum number of retries for unicast solicitation. + */ + uint32_t ntp_ucast_probes; + + /** + * Maximum number of retries for multicast solicitation. + */ + uint32_t ntp_mcast_probes; + + /** + * Base value in milliseconds to ompute reachable time, see RFC2461. + */ + uint64_t ntp_base_reachable_time; + + /** + * Actual reachable time (read-only) + */ + uint64_t ntp_reachable_time; /* secs */ + + /** + * The time in milliseconds between retransmitted Neighbor + * Solicitation messages. + */ + uint64_t ntp_retrans_time; + + /** + * Interval in milliseconds to check for stale neighbour + * entries. + */ + uint64_t ntp_gc_stale_time; /* secs */ + + /** + * Delay in milliseconds for the first time probe if + * the neighbour is reachable. + */ + uint64_t ntp_probe_delay; /* secs */ + + /** + * Maximum delay in milliseconds of an answer to a neighbour + * solicitation message. + */ + uint64_t ntp_anycast_delay; + + /** + * Minimum age in milliseconds before a neighbour entry + * may be replaced. + */ + uint64_t ntp_locktime; + + /** + * Delay in milliseconds before answering to an ARP request + * for which a proxy ARP entry exists. + */ + uint64_t ntp_proxy_delay; + + /** + * Queue length for the delayed proxy arp requests. + */ + uint32_t ntp_proxy_qlen; + + /** + * Mask of available parameter attributes + */ + uint32_t ntp_mask; +}; + +#define NTBLNAMSIZ 32 + +/** + * Neighbour table + * @ingroup neightbl + */ +struct rtnl_neightbl { + NLHDR_COMMON + + char nt_name[NTBLNAMSIZ]; + uint32_t nt_family; + uint32_t nt_gc_thresh1; + uint32_t nt_gc_thresh2; + uint32_t nt_gc_thresh3; + uint64_t nt_gc_interval; + struct ndt_config nt_config; + struct rtnl_neightbl_parms nt_parms; + struct ndt_stats nt_stats; +}; + /** @cond SKIP */ -#define NEIGHTBL_ATTR_FAMILY 0x001 -#define NEIGHTBL_ATTR_STATS 0x002 -#define NEIGHTBL_ATTR_NAME 0x004 -#define NEIGHTBL_ATTR_THRESH1 0x008 -#define NEIGHTBL_ATTR_THRESH2 0x010 -#define NEIGHTBL_ATTR_THRESH3 0x020 -#define NEIGHTBL_ATTR_CONFIG 0x040 -#define NEIGHTBL_ATTR_PARMS 0x080 -#define NEIGHTBL_ATTR_GC_INTERVAL 0x100 - -#define NEIGHTBLPARM_ATTR_IFINDEX 0x0001 -#define NEIGHTBLPARM_ATTR_REFCNT 0x0002 -#define NEIGHTBLPARM_ATTR_QUEUE_LEN 0x0004 -#define NEIGHTBLPARM_ATTR_APP_PROBES 0x0008 -#define NEIGHTBLPARM_ATTR_UCAST_PROBES 0x0010 -#define NEIGHTBLPARM_ATTR_MCAST_PROBES 0x0020 -#define NEIGHTBLPARM_ATTR_PROXY_QLEN 0x0040 -#define NEIGHTBLPARM_ATTR_REACHABLE_TIME 0x0080 +#define NEIGHTBL_ATTR_FAMILY 0x001 +#define NEIGHTBL_ATTR_STATS 0x002 +#define NEIGHTBL_ATTR_NAME 0x004 +#define NEIGHTBL_ATTR_THRESH1 0x008 +#define NEIGHTBL_ATTR_THRESH2 0x010 +#define NEIGHTBL_ATTR_THRESH3 0x020 +#define NEIGHTBL_ATTR_CONFIG 0x040 +#define NEIGHTBL_ATTR_PARMS 0x080 +#define NEIGHTBL_ATTR_GC_INTERVAL 0x100 + +#define NEIGHTBLPARM_ATTR_IFINDEX 0x0001 +#define NEIGHTBLPARM_ATTR_REFCNT 0x0002 +#define NEIGHTBLPARM_ATTR_QUEUE_LEN 0x0004 +#define NEIGHTBLPARM_ATTR_APP_PROBES 0x0008 +#define NEIGHTBLPARM_ATTR_UCAST_PROBES 0x0010 +#define NEIGHTBLPARM_ATTR_MCAST_PROBES 0x0020 +#define NEIGHTBLPARM_ATTR_PROXY_QLEN 0x0040 +#define NEIGHTBLPARM_ATTR_REACHABLE_TIME 0x0080 #define NEIGHTBLPARM_ATTR_BASE_REACHABLE_TIME 0x0100 -#define NEIGHTBLPARM_ATTR_RETRANS_TIME 0x0200 -#define NEIGHTBLPARM_ATTR_GC_STALETIME 0x0400 +#define NEIGHTBLPARM_ATTR_RETRANS_TIME 0x0200 +#define NEIGHTBLPARM_ATTR_GC_STALETIME 0x0400 #define NEIGHTBLPARM_ATTR_DELAY_PROBE_TIME 0x0800 -#define NEIGHTBLPARM_ATTR_ANYCAST_DELAY 0x1000 -#define NEIGHTBLPARM_ATTR_PROXY_DELAY 0x2000 -#define NEIGHTBLPARM_ATTR_LOCKTIME 0x4000 +#define NEIGHTBLPARM_ATTR_ANYCAST_DELAY 0x1000 +#define NEIGHTBLPARM_ATTR_PROXY_DELAY 0x2000 +#define NEIGHTBLPARM_ATTR_LOCKTIME 0x4000 static struct nl_cache_ops rtnl_neightbl_ops; static struct nl_object_ops neightbl_obj_ops; /** @endcond */ -static int neightbl_compare(struct nl_object *_a, struct nl_object *_b, - uint32_t attrs, int flags) -{ - struct rtnl_neightbl *a = (struct rtnl_neightbl *) _a; - struct rtnl_neightbl *b = (struct rtnl_neightbl *) _b; - int diff = 0; - -#define NT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGHTBL_ATTR_##ATTR, a, b, EXPR) - - diff |= NT_DIFF(FAMILY, a->nt_family != b->nt_family); - diff |= NT_DIFF(NAME, strcmp(a->nt_name, b->nt_name)); - diff |= NT_DIFF(THRESH1, a->nt_gc_thresh1 != b->nt_gc_thresh1); - diff |= NT_DIFF(THRESH2, a->nt_gc_thresh2 != b->nt_gc_thresh2); - diff |= NT_DIFF(THRESH3, a->nt_gc_thresh3 != b->nt_gc_thresh3); - diff |= NT_DIFF(GC_INTERVAL, a->nt_gc_interval != b->nt_gc_interval); - -#undef NT_DIFF +static uint64_t neightbl_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) +{ + struct rtnl_neightbl *a = (struct rtnl_neightbl *)_a; + struct rtnl_neightbl *b = (struct rtnl_neightbl *)_b; + uint64_t diff = 0; + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(NEIGHTBL_ATTR_FAMILY, a->nt_family != b->nt_family); + diff |= _DIFF(NEIGHTBL_ATTR_NAME, strcmp(a->nt_name, b->nt_name)); + diff |= _DIFF(NEIGHTBL_ATTR_THRESH1, + a->nt_gc_thresh1 != b->nt_gc_thresh1); + diff |= _DIFF(NEIGHTBL_ATTR_THRESH2, + a->nt_gc_thresh2 != b->nt_gc_thresh2); + diff |= _DIFF(NEIGHTBL_ATTR_THRESH3, + a->nt_gc_thresh3 != b->nt_gc_thresh3); + diff |= _DIFF(NEIGHTBL_ATTR_GC_INTERVAL, + a->nt_gc_interval != b->nt_gc_interval); +#undef _DIFF if (!(a->ce_mask & NEIGHTBL_ATTR_PARMS) && !(b->ce_mask & NEIGHTBL_ATTR_PARMS)) return diff; - /* XXX: FIXME: Compare parameter table */ - + /* XXX: FIXME: Compare parameter table */ #if 0 #define REQ(F) (fp->ntp_mask & NEIGHTBLPARM_ATTR_##F) @@ -105,17 +217,15 @@ static int neightbl_compare(struct nl_object *_a, struct nl_object *_b, return diff; } - -static struct nla_policy neightbl_policy[NDTA_MAX+1] = { - [NDTA_NAME] = { .type = NLA_STRING, - .maxlen = NTBLNAMSIZ }, - [NDTA_THRESH1] = { .type = NLA_U32 }, - [NDTA_THRESH2] = { .type = NLA_U32 }, - [NDTA_THRESH3] = { .type = NLA_U32 }, - [NDTA_GC_INTERVAL] = { .type = NLA_U32 }, - [NDTA_CONFIG] = { .minlen = sizeof(struct ndt_config) }, - [NDTA_STATS] = { .minlen = sizeof(struct ndt_stats) }, - [NDTA_PARMS] = { .type = NLA_NESTED }, +static struct nla_policy neightbl_policy[NDTA_MAX + 1] = { + [NDTA_NAME] = { .type = NLA_STRING, .maxlen = NTBLNAMSIZ }, + [NDTA_THRESH1] = { .type = NLA_U32 }, + [NDTA_THRESH2] = { .type = NLA_U32 }, + [NDTA_THRESH3] = { .type = NLA_U32 }, + [NDTA_GC_INTERVAL] = { .type = NLA_U32 }, + [NDTA_CONFIG] = { .minlen = sizeof(struct ndt_config) }, + [NDTA_STATS] = { .minlen = sizeof(struct ndt_stats) }, + [NDTA_PARMS] = { .type = NLA_NESTED }, }; static int neightbl_msg_parser(struct nl_cache_ops *ops, @@ -135,7 +245,7 @@ static int neightbl_msg_parser(struct nl_cache_ops *ops, ntbl->ce_msgtype = n->nlmsg_type; rtmsg = nlmsg_data(n); - + err = nlmsg_parse(n, sizeof(*rtmsg), tb, NDTA_MAX, neightbl_policy); if (err < 0) goto errout; @@ -190,11 +300,11 @@ static int neightbl_msg_parser(struct nl_cache_ops *ops, if (err < 0) goto errout; -#define COPY_ENTRY(name, var) \ - if (tbp[NDTPA_ ##name]) { \ - p->ntp_ ##var = nla_get_u32(tbp[NDTPA_ ##name]); \ - p->ntp_mask |= NEIGHTBLPARM_ATTR_ ##name; \ - } +#define COPY_ENTRY(name, var) \ + if (tbp[NDTPA_##name]) { \ + p->ntp_##var = nla_get_u32(tbp[NDTPA_##name]); \ + p->ntp_mask |= NEIGHTBLPARM_ATTR_##name; \ + } COPY_ENTRY(IFINDEX, ifindex); COPY_ENTRY(REFCNT, refcnt); @@ -216,7 +326,7 @@ static int neightbl_msg_parser(struct nl_cache_ops *ops, ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; } - err = pp->pp_cb((struct nl_object *) ntbl, pp); + err = pp->pp_cb((struct nl_object *)ntbl, pp); errout: rtnl_neightbl_put(ntbl); return err; @@ -227,16 +337,15 @@ static int neightbl_request_update(struct nl_cache *c, struct nl_sock *h) return nl_rtgen_request(h, RTM_GETNEIGHTBL, AF_UNSPEC, NLM_F_DUMP); } - static void neightbl_dump_line(struct nl_object *arg, struct nl_dump_params *p) { - struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *) arg; + struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *)arg; nl_dump_line(p, "%s", ntbl->nt_name); if (ntbl->nt_parms.ntp_mask & NEIGHTBLPARM_ATTR_IFINDEX) { struct nl_cache *link_cache; - + link_cache = nl_cache_mngt_require_safe("route/link"); if (link_cache) { @@ -266,101 +375,102 @@ static void neightbl_dump_line(struct nl_object *arg, struct nl_dump_params *p) nl_dump(p, "\n"); } -static void neightbl_dump_details(struct nl_object *arg, struct nl_dump_params *p) +static void neightbl_dump_details(struct nl_object *arg, + struct nl_dump_params *p) { char x[32], y[32], z[32]; - struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *) arg; + struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *)arg; neightbl_dump_line(arg, p); if (ntbl->ce_mask & NEIGHTBL_ATTR_CONFIG) { nl_dump_line(p, " key-len %u entry-size %u last-flush %s\n", - ntbl->nt_config.ndtc_key_len, - ntbl->nt_config.ndtc_entry_size, - nl_msec2str(ntbl->nt_config.ndtc_last_flush, - x, sizeof(x))); - - nl_dump_line(p, " gc threshold %u/%u/%u interval %s " \ - "chain-position %u\n", - ntbl->nt_gc_thresh1, ntbl->nt_gc_thresh2, - ntbl->nt_gc_thresh3, - nl_msec2str(ntbl->nt_gc_interval, x, sizeof(x)), - ntbl->nt_config.ndtc_hash_chain_gc); + ntbl->nt_config.ndtc_key_len, + ntbl->nt_config.ndtc_entry_size, + nl_msec2str(ntbl->nt_config.ndtc_last_flush, x, + sizeof(x))); + + nl_dump_line(p, + " gc threshold %u/%u/%u interval %s " + "chain-position %u\n", + ntbl->nt_gc_thresh1, ntbl->nt_gc_thresh2, + ntbl->nt_gc_thresh3, + nl_msec2str(ntbl->nt_gc_interval, x, sizeof(x)), + ntbl->nt_config.ndtc_hash_chain_gc); nl_dump_line(p, " hash-rand 0x%08X/0x%08X last-rand %s\n", - ntbl->nt_config.ndtc_hash_rnd, - ntbl->nt_config.ndtc_hash_mask, - nl_msec2str(ntbl->nt_config.ndtc_last_rand, - x, sizeof(x))); + ntbl->nt_config.ndtc_hash_rnd, + ntbl->nt_config.ndtc_hash_mask, + nl_msec2str(ntbl->nt_config.ndtc_last_rand, x, + sizeof(x))); } if (ntbl->ce_mask & NEIGHTBL_ATTR_PARMS) { struct rtnl_neightbl_parms *pa = &ntbl->nt_parms; - nl_dump_line(p, " refcnt %u pending-queue-limit %u " \ - "proxy-delayed-queue-limit %u\n", - pa->ntp_refcnt, - pa->ntp_queue_len, - pa->ntp_proxy_qlen); - - nl_dump_line(p, " num-userspace-probes %u num-unicast-probes " \ - "%u num-multicast-probes %u\n", - pa->ntp_app_probes, - pa->ntp_ucast_probes, - pa->ntp_mcast_probes); - - nl_dump_line(p, " min-age %s base-reachable-time %s " \ - "stale-check-interval %s\n", - nl_msec2str(pa->ntp_locktime, x, sizeof(x)), - nl_msec2str(pa->ntp_base_reachable_time, - y, sizeof(y)), - nl_msec2str(pa->ntp_gc_stale_time, z, sizeof(z))); - - nl_dump_line(p, " initial-probe-delay %s answer-delay %s " \ - "proxy-answer-delay %s\n", - nl_msec2str(pa->ntp_probe_delay, x, sizeof(x)), - nl_msec2str(pa->ntp_anycast_delay, y, sizeof(y)), - nl_msec2str(pa->ntp_proxy_delay, z, sizeof(z))); + nl_dump_line(p, + " refcnt %u pending-queue-limit %u " + "proxy-delayed-queue-limit %u\n", + pa->ntp_refcnt, pa->ntp_queue_len, + pa->ntp_proxy_qlen); + + nl_dump_line(p, + " num-userspace-probes %u num-unicast-probes " + "%u num-multicast-probes %u\n", + pa->ntp_app_probes, pa->ntp_ucast_probes, + pa->ntp_mcast_probes); + + nl_dump_line(p, + " min-age %s base-reachable-time %s " + "stale-check-interval %s\n", + nl_msec2str(pa->ntp_locktime, x, sizeof(x)), + nl_msec2str(pa->ntp_base_reachable_time, y, + sizeof(y)), + nl_msec2str(pa->ntp_gc_stale_time, z, sizeof(z))); + + nl_dump_line(p, + " initial-probe-delay %s answer-delay %s " + "proxy-answer-delay %s\n", + nl_msec2str(pa->ntp_probe_delay, x, sizeof(x)), + nl_msec2str(pa->ntp_anycast_delay, y, sizeof(y)), + nl_msec2str(pa->ntp_proxy_delay, z, sizeof(z))); } } static void neightbl_dump_stats(struct nl_object *arg, struct nl_dump_params *p) { - struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *) arg; + struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *)arg; neightbl_dump_details(arg, p); if (!(ntbl->ce_mask & NEIGHTBL_ATTR_STATS)) return; - nl_dump_line(p, " " \ - " lookups %" PRIu64 \ - " hits %" PRIu64 \ - " failed %" PRIu64 \ - " allocations %" PRIu64 \ - " destroys %" PRIu64 \ - "\n", - ntbl->nt_stats.ndts_lookups, - ntbl->nt_stats.ndts_hits, - ntbl->nt_stats.ndts_res_failed, - ntbl->nt_stats.ndts_allocs, - ntbl->nt_stats.ndts_destroys); - - nl_dump_line(p, " " \ - " hash-grows %" PRIu64 \ - " forced-gc-runs %" PRIu64 \ - " periodic-gc-runs %" PRIu64 \ - "\n", - ntbl->nt_stats.ndts_hash_grows, - ntbl->nt_stats.ndts_forced_gc_runs, - ntbl->nt_stats.ndts_periodic_gc_runs); - - nl_dump_line(p, " " \ - " rcv-unicast-probes %" PRIu64 \ - " rcv-multicast-probes %" PRIu64 \ - "\n", - ntbl->nt_stats.ndts_rcv_probes_ucast, - ntbl->nt_stats.ndts_rcv_probes_mcast); + nl_dump_line(p, + " " + " lookups %llu hits %llu failed %llu" + " allocations %llu destroys %llu\n", + (long long unsigned)ntbl->nt_stats.ndts_lookups, + (long long unsigned)ntbl->nt_stats.ndts_hits, + (long long unsigned)ntbl->nt_stats.ndts_res_failed, + (long long unsigned)ntbl->nt_stats.ndts_allocs, + (long long unsigned)ntbl->nt_stats.ndts_destroys); + + nl_dump_line(p, + " " + " hash-grows %llu forced-gc-runs %llu" + " periodic-gc-runs %llu\n", + (long long unsigned)ntbl->nt_stats.ndts_hash_grows, + (long long unsigned)ntbl->nt_stats.ndts_forced_gc_runs, + (long long unsigned)ntbl->nt_stats.ndts_periodic_gc_runs); + + nl_dump_line(p, + " " + " rcv-unicast-probes %llu" + " rcv-multicast-probes %llu" + "\n", + (long long unsigned)ntbl->nt_stats.ndts_rcv_probes_ucast, + (long long unsigned)ntbl->nt_stats.ndts_rcv_probes_mcast); } /** @@ -370,12 +480,12 @@ static void neightbl_dump_stats(struct nl_object *arg, struct nl_dump_params *p) struct rtnl_neightbl *rtnl_neightbl_alloc(void) { - return (struct rtnl_neightbl *) nl_object_alloc(&neightbl_obj_ops); + return (struct rtnl_neightbl *)nl_object_alloc(&neightbl_obj_ops); } void rtnl_neightbl_put(struct rtnl_neightbl *neightbl) { - nl_object_put((struct nl_object *) neightbl); + nl_object_put((struct nl_object *)neightbl); } /** @} */ @@ -426,7 +536,7 @@ struct rtnl_neightbl *rtnl_neightbl_get(struct nl_cache *cache, if (!strcasecmp(nt->nt_name, name) && ((!ifindex && !nt->nt_parms.ntp_ifindex) || (ifindex && ifindex == nt->nt_parms.ntp_ifindex))) { - nl_object_get((struct nl_object *) nt); + nl_object_get((struct nl_object *)nt); return nt; } } @@ -485,8 +595,7 @@ int rtnl_neightbl_build_change_request(struct rtnl_neightbl *old, NLA_PUT_U32(m, NDTA_THRESH2, tmpl->nt_gc_thresh2); if (tmpl->ce_mask & NEIGHTBL_ATTR_GC_INTERVAL) - NLA_PUT_U64(m, NDTA_GC_INTERVAL, - tmpl->nt_gc_interval); + NLA_PUT_U64(m, NDTA_GC_INTERVAL, tmpl->nt_gc_interval); if (tmpl->ce_mask & NEIGHTBL_ATTR_PARMS) { struct rtnl_neightbl_parms *p = &tmpl->nt_parms; @@ -497,8 +606,7 @@ int rtnl_neightbl_build_change_request(struct rtnl_neightbl *old, if (old->nt_parms.ntp_mask & NEIGHTBLPARM_ATTR_IFINDEX) NLA_PUT_U32(parms, NDTPA_IFINDEX, - old->nt_parms.ntp_ifindex); - + old->nt_parms.ntp_ifindex); if (p->ntp_mask & NEIGHTBLPARM_ATTR_QUEUE_LEN) NLA_PUT_U32(parms, NDTPA_QUEUE_LEN, p->ntp_queue_len); @@ -515,8 +623,7 @@ int rtnl_neightbl_build_change_request(struct rtnl_neightbl *old, p->ntp_mcast_probes); if (p->ntp_mask & NEIGHTBLPARM_ATTR_PROXY_QLEN) - NLA_PUT_U32(parms, NDTPA_PROXY_QLEN, - p->ntp_proxy_qlen); + NLA_PUT_U32(parms, NDTPA_PROXY_QLEN, p->ntp_proxy_qlen); if (p->ntp_mask & NEIGHTBLPARM_ATTR_BASE_REACHABLE_TIME) NLA_PUT_U64(parms, NDTPA_BASE_REACHABLE_TIME, @@ -540,7 +647,7 @@ int rtnl_neightbl_build_change_request(struct rtnl_neightbl *old, if (p->ntp_mask & NEIGHTBLPARM_ATTR_PROXY_DELAY) NLA_PUT_U64(parms, NDTPA_PROXY_DELAY, - p->ntp_proxy_delay); + p->ntp_proxy_delay); if (p->ntp_mask & NEIGHTBLPARM_ATTR_LOCKTIME) NLA_PUT_U64(parms, NDTPA_LOCKTIME, p->ntp_locktime); @@ -579,7 +686,7 @@ int rtnl_neightbl_change(struct nl_sock *sk, struct rtnl_neightbl *old, { struct nl_msg *msg; int err; - + if ((err = rtnl_neightbl_build_change_request(old, tmpl, &msg)) < 0) return err; @@ -630,7 +737,7 @@ void rtnl_neightbl_set_gc_tresh3(struct rtnl_neightbl *ntbl, int thresh) void rtnl_neightbl_set_name(struct rtnl_neightbl *ntbl, const char *name) { - strncpy(ntbl->nt_name, name, sizeof(ntbl->nt_name) - 1); + _nl_strncpy_trunc(ntbl->nt_name, name, sizeof(ntbl->nt_name)); ntbl->ce_mask |= NEIGHTBL_ATTR_NAME; } @@ -814,12 +921,12 @@ static struct nl_cache_ops rtnl_neightbl_ops = { .co_obj_ops = &neightbl_obj_ops, }; -static void __init neightbl_init(void) +static void _nl_init neightbl_init(void) { nl_cache_mngt_register(&rtnl_neightbl_ops); } -static void __exit neightbl_exit(void) +static void _nl_exit neightbl_exit(void) { nl_cache_mngt_unregister(&rtnl_neightbl_ops); } diff --git a/lib/route/netconf.c b/lib/route/netconf.c new file mode 100644 index 0000000..7863da6 --- /dev/null +++ b/lib/route/netconf.c @@ -0,0 +1,573 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2017 David Ahern + */ + +/** + * @ingroup rtnl + * @defgroup netconf Netconf + * @brief + * + * @{ + */ + +#include "nl-default.h" + +#include +#include + +#include +#include +#include +#include + +#include "nl-route.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" +#include "nl-priv-dynamic-core/object-api.h" + +/** @cond SKIP */ +#define NETCONF_ATTR_FAMILY 0x0001 +#define NETCONF_ATTR_IFINDEX 0x0002 +#define NETCONF_ATTR_RP_FILTER 0x0004 +#define NETCONF_ATTR_FWDING 0x0008 +#define NETCONF_ATTR_MC_FWDING 0x0010 +#define NETCONF_ATTR_PROXY_NEIGH 0x0020 +#define NETCONF_ATTR_IGNORE_RT_LINKDWN 0x0040 +#define NETCONF_ATTR_INPUT 0x0080 + +struct rtnl_netconf +{ + NLHDR_COMMON + + int family; + int ifindex; + int rp_filter; + int forwarding; + int mc_forwarding; + int proxy_neigh; + int ignore_routes_linkdown; + int input; +}; + +static struct nl_cache_ops rtnl_netconf_ops; +static struct nl_object_ops netconf_obj_ops; +/** @endcond */ + +static struct nla_policy devconf_ipv4_policy[NETCONFA_MAX+1] = { + [NETCONFA_IFINDEX] = { .type = NLA_S32 }, + [NETCONFA_FORWARDING] = { .type = NLA_S32 }, + [NETCONFA_MC_FORWARDING] = { .type = NLA_S32 }, + [NETCONFA_RP_FILTER] = { .type = NLA_S32 }, + [NETCONFA_PROXY_NEIGH] = { .type = NLA_S32 }, + [NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN] = { .type = NLA_S32 }, +}; + +static struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = { + [NETCONFA_IFINDEX] = { .type = NLA_S32 }, + [NETCONFA_FORWARDING] = { .type = NLA_S32 }, + [NETCONFA_MC_FORWARDING] = { .type = NLA_S32 }, + [NETCONFA_PROXY_NEIGH] = { .type = NLA_S32 }, + [NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN] = { .type = NLA_S32 }, +}; + +static struct nla_policy devconf_mpls_policy[NETCONFA_MAX+1] = { + [NETCONFA_IFINDEX] = { .type = NLA_S32 }, + [NETCONFA_INPUT] = { .type = NLA_S32 }, +}; + +static struct rtnl_netconf *rtnl_netconf_alloc(void) +{ + return (struct rtnl_netconf *) nl_object_alloc(&netconf_obj_ops); +} + +static int netconf_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *nlh, struct nl_parser_param *pp) +{ + struct nlattr *tb[NETCONFA_MAX+1], *attr; + struct rtnl_netconf *nc; + struct netconfmsg *ncm; + int err; + + ncm = nlmsg_data(nlh); + switch (ncm->ncm_family) { + case AF_INET: + err = nlmsg_parse(nlh, sizeof(*ncm), tb, NETCONFA_MAX, + devconf_ipv4_policy); + if (err < 0) + return err; + break; + case AF_INET6: + err = nlmsg_parse(nlh, sizeof(*ncm), tb, NETCONFA_MAX, + devconf_ipv6_policy); + if (err < 0) + return err; + break; + case AF_MPLS: + err = nlmsg_parse(nlh, sizeof(*ncm), tb, NETCONFA_MAX, + devconf_mpls_policy); + if (err < 0) + return err; + break; + default: + printf("unexpected netconf family: %d\n", ncm->ncm_family); + return -1; + } + + if (!tb[NETCONFA_IFINDEX]) + return -1; + + nc = rtnl_netconf_alloc(); + if (!nc) + return -NLE_NOMEM; + + nc->ce_msgtype = nlh->nlmsg_type; + nc->family = ncm->ncm_family; + nc->ifindex = nla_get_s32(tb[NETCONFA_IFINDEX]); + + nc->ce_mask = NETCONF_ATTR_FAMILY | NETCONF_ATTR_IFINDEX; + + + if (tb[NETCONFA_RP_FILTER]) { + attr = tb[NETCONFA_RP_FILTER]; + nc->rp_filter = nla_get_s32(attr); + nc->ce_mask |= NETCONF_ATTR_RP_FILTER; + } + + if (tb[NETCONFA_FORWARDING]) { + attr = tb[NETCONFA_FORWARDING]; + nc->forwarding = nla_get_s32(attr); + nc->ce_mask |= NETCONF_ATTR_FWDING; + } + + if (tb[NETCONFA_MC_FORWARDING]) { + attr = tb[NETCONFA_MC_FORWARDING]; + nc->mc_forwarding = nla_get_s32(attr); + nc->ce_mask |= NETCONF_ATTR_MC_FWDING; + } + + if (tb[NETCONFA_PROXY_NEIGH]) { + attr = tb[NETCONFA_PROXY_NEIGH]; + nc->proxy_neigh = nla_get_s32(attr); + nc->ce_mask |= NETCONF_ATTR_PROXY_NEIGH; + } + + if (tb[NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN]) { + attr = tb[NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN]; + nc->ignore_routes_linkdown = nla_get_s32(attr); + nc->ce_mask |= NETCONF_ATTR_IGNORE_RT_LINKDWN; + } + + if (tb[NETCONFA_INPUT]) { + attr = tb[NETCONFA_INPUT]; + nc->input = nla_get_s32(attr); + nc->ce_mask |= NETCONF_ATTR_INPUT; + } + + err = pp->pp_cb((struct nl_object *) nc, pp); + + rtnl_netconf_put(nc); + return err; +} + +static int netconf_request_update(struct nl_cache *cache, struct nl_sock *sk) +{ + struct netconfmsg nc = { + .ncm_family = cache->c_iarg1, + }; + + return nl_send_simple(sk, RTM_GETNETCONF, NLM_F_DUMP, &nc, sizeof(nc)); +} + +static void netconf_dump_line(struct nl_object *obj, struct nl_dump_params *p) +{ + struct rtnl_netconf *nc = (struct rtnl_netconf *) obj; + struct nl_cache *link_cache; + char buf[64]; + + switch(nc->family) { + case AF_INET: + nl_dump(p, "ipv4 "); + break; + case AF_INET6: + nl_dump(p, "ipv6 "); + break; + case AF_MPLS: + nl_dump(p, "mpls "); + break; + default: + return; + } + + switch(nc->ifindex) { + case NETCONFA_IFINDEX_ALL: + nl_dump(p, "all "); + break; + case NETCONFA_IFINDEX_DEFAULT: + nl_dump(p, "default "); + break; + default: + link_cache = nl_cache_mngt_require_safe("route/link"); + if (link_cache) { + nl_dump(p, "dev %s ", + rtnl_link_i2name(link_cache, nc->ifindex, + buf, sizeof(buf))); + nl_cache_put(link_cache); + } else + nl_dump(p, "dev %d ", nc->ifindex); + } + + if (nc->ce_mask & NETCONF_ATTR_FWDING) { + nl_dump(p, "forwarding %s ", + nc->forwarding ? "on" : "off"); + } + + if (nc->ce_mask & NETCONF_ATTR_RP_FILTER) { + if (nc->rp_filter == 0) + nl_dump(p, "rp_filter off "); + else if (nc->rp_filter == 1) + nl_dump(p, "rp_filter strict "); + else if (nc->rp_filter == 2) + nl_dump(p, "rp_filter loose "); + else + nl_dump(p, "rp_filter unknown-mode "); + } + + if (nc->ce_mask & NETCONF_ATTR_MC_FWDING) { + nl_dump(p, "mc_forwarding %s ", + nc->mc_forwarding ? "on" : "off"); + } + + if (nc->ce_mask & NETCONF_ATTR_PROXY_NEIGH) + nl_dump(p, "proxy_neigh %d ", nc->proxy_neigh); + + if (nc->ce_mask & NETCONF_ATTR_IGNORE_RT_LINKDWN) { + nl_dump(p, "ignore_routes_with_linkdown %s ", + nc->ignore_routes_linkdown ? "on" : "off"); + } + + if (nc->ce_mask & NETCONF_ATTR_INPUT) + nl_dump(p, "input %s ", nc->input ? "on" : "off"); + + nl_dump(p, "\n"); +} + +static const struct trans_tbl netconf_attrs[] = { + __ADD(NETCONF_ATTR_FAMILY, family), + __ADD(NETCONF_ATTR_IFINDEX, ifindex), + __ADD(NETCONF_ATTR_RP_FILTER, rp_filter), + __ADD(NETCONF_ATTR_FWDING, forwarding), + __ADD(NETCONF_ATTR_MC_FWDING, mc_forwarding), + __ADD(NETCONF_ATTR_PROXY_NEIGH, proxy_neigh), + __ADD(NETCONF_ATTR_IGNORE_RT_LINKDWN, ignore_routes_with_linkdown), + __ADD(NETCONF_ATTR_INPUT, input), +}; + +static char *netconf_attrs2str(int attrs, char *buf, size_t len) +{ + return __flags2str(attrs, buf, len, netconf_attrs, + ARRAY_SIZE(netconf_attrs)); +} + +static void netconf_keygen(struct nl_object *obj, uint32_t *hashkey, + uint32_t table_sz) +{ + struct rtnl_netconf *nc = (struct rtnl_netconf *) obj; + unsigned int nckey_sz; + struct nc_hash_key { + int nc_family; + int nc_index; + } _nl_packed nckey; + + nckey_sz = sizeof(nckey); + nckey.nc_family = nc->family; + nckey.nc_index = nc->ifindex; + + *hashkey = nl_hash(&nckey, nckey_sz, 0) % table_sz; + + NL_DBG(5, "netconf %p key (dev %d fam %d) keysz %d, hash 0x%x\n", + nc, nckey.nc_index, nckey.nc_family, nckey_sz, *hashkey); +} + +static uint64_t netconf_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) +{ + struct rtnl_netconf *a = (struct rtnl_netconf *) _a; + struct rtnl_netconf *b = (struct rtnl_netconf *) _b; + uint64_t diff = 0; + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(NETCONF_ATTR_FAMILY, a->family != b->family); + diff |= _DIFF(NETCONF_ATTR_IFINDEX, a->ifindex != b->ifindex); + diff |= _DIFF(NETCONF_ATTR_RP_FILTER, a->rp_filter != b->rp_filter); + diff |= _DIFF(NETCONF_ATTR_FWDING, a->forwarding != b->forwarding); + diff |= _DIFF(NETCONF_ATTR_MC_FWDING, + a->mc_forwarding != b->mc_forwarding); + diff |= _DIFF(NETCONF_ATTR_PROXY_NEIGH, + a->proxy_neigh != b->proxy_neigh); + diff |= _DIFF(NETCONF_ATTR_IGNORE_RT_LINKDWN, + a->ignore_routes_linkdown != b->ignore_routes_linkdown); + diff |= _DIFF(NETCONF_ATTR_INPUT, a->input != b->input); +#undef _DIFF + + return diff; +} + +static int netconf_update(struct nl_object *old_obj, struct nl_object *new_obj) +{ + struct rtnl_netconf *new_nc = (struct rtnl_netconf *) new_obj; + struct rtnl_netconf *old_nc = (struct rtnl_netconf *) old_obj; + int action = new_obj->ce_msgtype; + + switch(action) { + case RTM_NEWNETCONF: + if (new_nc->family != old_nc->family || + new_nc->ifindex != old_nc->ifindex) + return -NLE_OPNOTSUPP; + + if (new_nc->ce_mask & NETCONF_ATTR_RP_FILTER) + old_nc->rp_filter = new_nc->rp_filter; + if (new_nc->ce_mask & NETCONF_ATTR_FWDING) + old_nc->forwarding = new_nc->forwarding; + if (new_nc->ce_mask & NETCONF_ATTR_MC_FWDING) + old_nc->mc_forwarding = new_nc->mc_forwarding; + if (new_nc->ce_mask & NETCONF_ATTR_PROXY_NEIGH) + old_nc->proxy_neigh = new_nc->proxy_neigh; + if (new_nc->ce_mask & NETCONF_ATTR_IGNORE_RT_LINKDWN) + old_nc->ignore_routes_linkdown = new_nc->ignore_routes_linkdown; + + break; + default: + return -NLE_OPNOTSUPP; + } + + return NLE_SUCCESS; +} + +/** + * @name Cache Management + * @{ + */ + +int rtnl_netconf_alloc_cache(struct nl_sock *sk, struct nl_cache **result) +{ + return nl_cache_alloc_and_fill(&rtnl_netconf_ops, sk, result); +} + +/** + * Search netconf in cache + * @arg cache netconf cache + * @arg family Address family of interest + * @arg ifindex Interface index of interest + * + * Searches netconf cache previously allocated with rtnl_netconf_alloc_cache() + * for given index and family + * + * The reference counter is incremented before returning the netconf entry, + * therefore the reference must be given back with rtnl_netconf_put() after + * usage. + * + * @return netconf object or NULL if no match was found. + */ +struct rtnl_netconf *rtnl_netconf_get_by_idx(struct nl_cache *cache, int family, + int ifindex) +{ + struct rtnl_netconf *nc; + + if (!ifindex || !family || cache->c_ops != &rtnl_netconf_ops) + return NULL; + + nl_list_for_each_entry(nc, &cache->c_items, ce_list) { + if (nc->ifindex == ifindex && + nc->family == family) { + nl_object_get((struct nl_object *) nc); + return nc; + } + } + + return NULL; +} + +void rtnl_netconf_put(struct rtnl_netconf *nc) +{ + nl_object_put((struct nl_object *) nc); +} + +/** + * Search netconf in cache + * @arg cache netconf cache + * @arg family Address family of interest + * + * Searches netconf cache previously allocated with rtnl_netconf_alloc_cache() + * for "all" netconf settings for given family + * + * The reference counter is incremented before returning the netconf entry, + * therefore the reference must be given back with rtnl_netconf_put() after + * usage. + * + * @return netconf object or NULL if no match was found. + */ +struct rtnl_netconf *rtnl_netconf_get_all(struct nl_cache *cache, int family) +{ + return rtnl_netconf_get_by_idx(cache, family, NETCONFA_IFINDEX_ALL); +} + +/** + * Search netconf in cache + * @arg cache netconf cache + * @arg family Address family of interest + * + * Searches netconf cache previously allocated with rtnl_netconf_alloc_cache() + * for "default" netconf settings for given family + * + * The reference counter is incremented before returning the netconf entry, + * therefore the reference must be given back with rtnl_netconf_put() after + * usage. + * + * @return netconf object or NULL if no match was found. + */ +struct rtnl_netconf *rtnl_netconf_get_default(struct nl_cache *cache, int family) +{ + return rtnl_netconf_get_by_idx(cache, family, NETCONFA_IFINDEX_DEFAULT); +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ + +int rtnl_netconf_get_family(struct rtnl_netconf *nc, int *val) +{ + if (!nc) + return -NLE_INVAL; + if (!(nc->ce_mask & NETCONF_ATTR_FAMILY)) + return -NLE_MISSING_ATTR; + if (val) + *val = nc->family; + return 0; +} +int rtnl_netconf_get_ifindex(struct rtnl_netconf *nc, int *val) +{ + if (!nc) + return -NLE_INVAL; + if (!(nc->ce_mask & NETCONF_ATTR_IFINDEX)) + return -NLE_MISSING_ATTR; + if (val) + *val = nc->ifindex; + return 0; +} +int rtnl_netconf_get_forwarding(struct rtnl_netconf *nc, int *val) +{ + if (!nc) + return -NLE_INVAL; + if (!(nc->ce_mask & NETCONF_ATTR_FWDING)) + return -NLE_MISSING_ATTR; + if (val) + *val = nc->forwarding; + return 0; +} +int rtnl_netconf_get_mc_forwarding(struct rtnl_netconf *nc, int *val) +{ + if (!nc) + return -NLE_INVAL; + if (!(nc->ce_mask & NETCONF_ATTR_MC_FWDING)) + return -NLE_MISSING_ATTR; + if (val) + *val = nc->mc_forwarding; + return 0; +} +int rtnl_netconf_get_rp_filter(struct rtnl_netconf *nc, int *val) +{ + if (!nc) + return -NLE_INVAL; + if (!(nc->ce_mask & NETCONF_ATTR_RP_FILTER)) + return -NLE_MISSING_ATTR; + if (val) + *val = nc->rp_filter; + return 0; +} +int rtnl_netconf_get_proxy_neigh(struct rtnl_netconf *nc, int *val) +{ + if (!nc) + return -NLE_INVAL; + if (!(nc->ce_mask & NETCONF_ATTR_PROXY_NEIGH)) + return -NLE_MISSING_ATTR; + if (val) + *val = nc->proxy_neigh; + return 0; +} +int rtnl_netconf_get_ignore_routes_linkdown(struct rtnl_netconf *nc, int *val) +{ + if (!nc) + return -NLE_INVAL; + if (!(nc->ce_mask & NETCONF_ATTR_IGNORE_RT_LINKDWN)) + return -NLE_MISSING_ATTR; + if (val) + *val = nc->ignore_routes_linkdown; + return 0; +} +int rtnl_netconf_get_input(struct rtnl_netconf *nc, int *val) +{ + if (!nc) + return -NLE_INVAL; + if (!(nc->ce_mask & NETCONF_ATTR_INPUT)) + return -NLE_MISSING_ATTR; + if (val) + *val = nc->input; + return 0; +} + + +/** @} */ + +static struct nl_object_ops netconf_obj_ops = { + .oo_name = "route/netconf", + .oo_size = sizeof(struct rtnl_netconf), + .oo_dump = { + [NL_DUMP_LINE] = netconf_dump_line, + [NL_DUMP_DETAILS] = netconf_dump_line, + }, + .oo_compare = netconf_compare, + .oo_keygen = netconf_keygen, + .oo_update = netconf_update, + .oo_attrs2str = netconf_attrs2str, + .oo_id_attrs = (NETCONF_ATTR_FAMILY | + NETCONF_ATTR_IFINDEX) +}; + +static struct nl_af_group netconf_groups[] = { + { AF_INET, RTNLGRP_IPV4_NETCONF }, + { AF_INET6, RTNLGRP_IPV6_NETCONF }, + { AF_MPLS, RTNLGRP_MPLS_NETCONF }, + { END_OF_GROUP_LIST }, +}; + +static struct nl_cache_ops rtnl_netconf_ops = { + .co_name = "route/netconf", + .co_hdrsize = sizeof(struct netconfmsg), + .co_msgtypes = { + { RTM_NEWNETCONF, NL_ACT_NEW, "new" }, + { RTM_DELNETCONF, NL_ACT_DEL, "del" }, + { RTM_GETNETCONF, NL_ACT_GET, "get" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_ROUTE, + .co_groups = netconf_groups, + .co_request_update = netconf_request_update, + .co_msg_parser = netconf_msg_parser, + .co_obj_ops = &netconf_obj_ops, +}; + +static void _nl_init netconf_init(void) +{ + nl_cache_mngt_register(&rtnl_netconf_ops); +} + +static void _nl_exit netconf_exit(void) +{ + nl_cache_mngt_unregister(&rtnl_netconf_ops); +} + +/** @} */ diff --git a/lib/route/nexthop-encap.h b/lib/route/nexthop-encap.h new file mode 100644 index 0000000..dde1bfb --- /dev/null +++ b/lib/route/nexthop-encap.h @@ -0,0 +1,35 @@ +#ifndef NETLINK_NEXTHOP_ENCAP_H_ +#define NETLINK_NEXTHOP_ENCAP_H_ + +struct nh_encap_ops { + uint16_t encap_type; + + int (*build_msg)(struct nl_msg *msg, void *priv); + int (*parse_msg)(struct nlattr *nla, struct rtnl_nexthop *rtnh); + + int (*compare)(void *a, void *b); + + void (*dump)(void *priv, struct nl_dump_params *dp); + void (*destructor)(void *priv); +}; + +struct rtnl_nh_encap; + +/* + * generic nexthop encap + */ +void nh_set_encap(struct rtnl_nexthop *nh, struct rtnl_nh_encap *rtnh_encap); + +int nh_encap_parse_msg(struct nlattr *encap, struct nlattr *encap_type, + struct rtnl_nexthop *rtnh); +int nh_encap_build_msg(struct nl_msg *msg, struct rtnl_nh_encap *rtnh_encap); + +void nh_encap_dump(struct rtnl_nh_encap *rtnh_encap, struct nl_dump_params *dp); + +int nh_encap_compare(struct rtnl_nh_encap *a, struct rtnl_nh_encap *b); + +/* + * MPLS encap + */ +extern struct nh_encap_ops mpls_encap_ops; +#endif diff --git a/lib/route/nexthop.c b/lib/route/nexthop.c index d3ca499..962f2ba 100644 --- a/lib/route/nexthop.c +++ b/lib/route/nexthop.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/nexthop.c Routing Nexthop - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf */ @@ -15,18 +9,26 @@ * @{ */ -#include +#include "nl-default.h" + #include #include #include #include +#include "nexthop-encap.h" +#include "nl-route.h" +#include "nl-priv-dynamic-core/nl-core.h" + /** @cond SKIP */ #define NH_ATTR_FLAGS 0x000001 #define NH_ATTR_WEIGHT 0x000002 #define NH_ATTR_IFINDEX 0x000004 #define NH_ATTR_GATEWAY 0x000008 #define NH_ATTR_REALMS 0x000010 +#define NH_ATTR_NEWDST 0x000020 +#define NH_ATTR_VIA 0x000040 +#define NH_ATTR_ENCAP 0x000080 /** @endcond */ /** @@ -69,12 +71,39 @@ struct rtnl_nexthop *rtnl_route_nh_clone(struct rtnl_nexthop *src) } } + if (src->rtnh_newdst) { + nh->rtnh_newdst = nl_addr_clone(src->rtnh_newdst); + if (!nh->rtnh_newdst) { + nl_addr_put(nh->rtnh_gateway); + free(nh); + return NULL; + } + } + + if (src->rtnh_via) { + nh->rtnh_via = nl_addr_clone(src->rtnh_via); + if (!nh->rtnh_via) { + nl_addr_put(nh->rtnh_gateway); + nl_addr_put(nh->rtnh_newdst); + free(nh); + return NULL; + } + } + return nh; } void rtnl_route_nh_free(struct rtnl_nexthop *nh) { nl_addr_put(nh->rtnh_gateway); + nl_addr_put(nh->rtnh_newdst); + nl_addr_put(nh->rtnh_via); + if (nh->rtnh_encap) { + if (nh->rtnh_encap->ops && nh->rtnh_encap->ops->destructor) + nh->rtnh_encap->ops->destructor(nh->rtnh_encap->priv); + free(nh->rtnh_encap->priv); + free(nh->rtnh_encap); + } free(nh); } @@ -83,23 +112,26 @@ void rtnl_route_nh_free(struct rtnl_nexthop *nh) int rtnl_route_nh_compare(struct rtnl_nexthop *a, struct rtnl_nexthop *b, uint32_t attrs, int loose) { - int diff = 0; - -#define NH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NH_ATTR_##ATTR, a, b, EXPR) - - diff |= NH_DIFF(IFINDEX, a->rtnh_ifindex != b->rtnh_ifindex); - diff |= NH_DIFF(WEIGHT, a->rtnh_weight != b->rtnh_weight); - diff |= NH_DIFF(REALMS, a->rtnh_realms != b->rtnh_realms); - diff |= NH_DIFF(GATEWAY, nl_addr_cmp(a->rtnh_gateway, - b->rtnh_gateway)); + uint32_t diff = 0; + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(NH_ATTR_IFINDEX, a->rtnh_ifindex != b->rtnh_ifindex); + diff |= _DIFF(NH_ATTR_WEIGHT, a->rtnh_weight != b->rtnh_weight); + diff |= _DIFF(NH_ATTR_REALMS, a->rtnh_realms != b->rtnh_realms); + diff |= _DIFF(NH_ATTR_GATEWAY, + nl_addr_cmp(a->rtnh_gateway, b->rtnh_gateway)); + diff |= _DIFF(NH_ATTR_NEWDST, + nl_addr_cmp(a->rtnh_newdst, b->rtnh_newdst)); + diff |= _DIFF(NH_ATTR_VIA, nl_addr_cmp(a->rtnh_via, b->rtnh_via)); + diff |= _DIFF(NH_ATTR_ENCAP, + nh_encap_compare(a->rtnh_encap, b->rtnh_encap)); if (loose) - diff |= NH_DIFF(FLAGS, - (a->rtnh_flags ^ b->rtnh_flags) & b->rtnh_flag_mask); + diff |= _DIFF(NH_ATTR_FLAGS, (a->rtnh_flags ^ b->rtnh_flags) & + b->rtnh_flag_mask); else - diff |= NH_DIFF(FLAGS, a->rtnh_flags != b->rtnh_flags); - -#undef NH_DIFF + diff |= _DIFF(NH_ATTR_FLAGS, a->rtnh_flags != b->rtnh_flags); +#undef _DIFF return diff; } @@ -111,8 +143,19 @@ static void nh_dump_line(struct rtnl_nexthop *nh, struct nl_dump_params *dp) link_cache = nl_cache_mngt_require_safe("route/link"); + if (nh->ce_mask & NH_ATTR_ENCAP) + nh_encap_dump(nh->rtnh_encap, dp); + + if (nh->ce_mask & NH_ATTR_NEWDST) + nl_dump(dp, "as to %s ", + nl_addr2str(nh->rtnh_newdst, buf, sizeof(buf))); + nl_dump(dp, "via"); + if (nh->ce_mask & NH_ATTR_VIA) + nl_dump(dp, " %s", + nl_addr2str(nh->rtnh_via, buf, sizeof(buf))); + if (nh->ce_mask & NH_ATTR_GATEWAY) nl_dump(dp, " %s", nl_addr2str(nh->rtnh_gateway, buf, sizeof(buf))); @@ -142,6 +185,17 @@ static void nh_dump_details(struct rtnl_nexthop *nh, struct nl_dump_params *dp) nl_dump(dp, "nexthop"); + if (nh->ce_mask & NH_ATTR_ENCAP) + nh_encap_dump(nh->rtnh_encap, dp); + + if (nh->ce_mask & NH_ATTR_NEWDST) + nl_dump(dp, " as to %s", + nl_addr2str(nh->rtnh_newdst, buf, sizeof(buf))); + + if (nh->ce_mask & NH_ATTR_VIA) + nl_dump(dp, " via %s", + nl_addr2str(nh->rtnh_via, buf, sizeof(buf))); + if (nh->ce_mask & NH_ATTR_GATEWAY) nl_dump(dp, " via %s", nl_addr2str(nh->rtnh_gateway, buf, sizeof(buf))); @@ -190,6 +244,24 @@ void rtnl_route_nh_dump(struct rtnl_nexthop *nh, struct nl_dump_params *dp) } } +void nh_set_encap(struct rtnl_nexthop *nh, struct rtnl_nh_encap *rtnh_encap) +{ + if (nh->rtnh_encap) { + if (nh->rtnh_encap->ops && nh->rtnh_encap->ops->destructor) + nh->rtnh_encap->ops->destructor(nh->rtnh_encap->priv); + free(nh->rtnh_encap->priv); + free(nh->rtnh_encap); + } + + if (rtnh_encap) { + nh->rtnh_encap = rtnh_encap; + nh->ce_mask |= NH_ATTR_ENCAP; + } else { + nh->rtnh_encap = NULL; + nh->ce_mask &= ~NH_ATTR_ENCAP; + } +} + /** * @name Attributes * @{ @@ -269,6 +341,52 @@ uint32_t rtnl_route_nh_get_realms(struct rtnl_nexthop *nh) return nh->rtnh_realms; } +int rtnl_route_nh_set_newdst(struct rtnl_nexthop *nh, struct nl_addr *addr) +{ + struct nl_addr *old = nh->rtnh_newdst; + + if (addr) { + nh->rtnh_newdst = nl_addr_get(addr); + nh->ce_mask |= NH_ATTR_NEWDST; + } else { + nh->ce_mask &= ~NH_ATTR_NEWDST; + nh->rtnh_newdst = NULL; + } + + if (old) + nl_addr_put(old); + + return 0; +} + +struct nl_addr *rtnl_route_nh_get_newdst(struct rtnl_nexthop *nh) +{ + return nh->rtnh_newdst; +} + +int rtnl_route_nh_set_via(struct rtnl_nexthop *nh, struct nl_addr *addr) +{ + struct nl_addr *old = nh->rtnh_via; + + if (addr) { + nh->rtnh_via = nl_addr_get(addr); + nh->ce_mask |= NH_ATTR_VIA; + } else { + nh->ce_mask &= ~NH_ATTR_VIA; + nh->rtnh_via= NULL; + } + + if (old) + nl_addr_put(old); + + return 0; +} + +struct nl_addr *rtnl_route_nh_get_via(struct rtnl_nexthop *nh) +{ + return nh->rtnh_via; +} + /** @} */ /** @@ -277,9 +395,9 @@ uint32_t rtnl_route_nh_get_realms(struct rtnl_nexthop *nh) */ static const struct trans_tbl nh_flags[] = { - __ADD(RTNH_F_DEAD, dead) - __ADD(RTNH_F_PERVASIVE, pervasive) - __ADD(RTNH_F_ONLINK, onlink) + __ADD(RTNH_F_DEAD, dead), + __ADD(RTNH_F_PERVASIVE, pervasive), + __ADD(RTNH_F_ONLINK, onlink), }; char *rtnl_route_nh_flags2str(int flags, char *buf, size_t len) diff --git a/lib/route/nexthop_encap.c b/lib/route/nexthop_encap.c new file mode 100644 index 0000000..226b901 --- /dev/null +++ b/lib/route/nexthop_encap.c @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +#include "nl-route.h" +#include "nexthop-encap.h" + +static struct lwtunnel_encap_type { + const char *name; + struct nh_encap_ops *ops; +} lwtunnel_encap_types[__LWTUNNEL_ENCAP_MAX] = { + [LWTUNNEL_ENCAP_NONE] = { .name = "none" }, + [LWTUNNEL_ENCAP_MPLS] = { .name = "mpls", .ops = &mpls_encap_ops }, + [LWTUNNEL_ENCAP_IP] = { .name = "ip" }, + [LWTUNNEL_ENCAP_IP6] = { .name = "ip6" }, + [LWTUNNEL_ENCAP_ILA] = { .name = "ila" }, + [LWTUNNEL_ENCAP_BPF] = { .name = "bpf" }, +}; + +static const char *nh_encap_type2str(unsigned int type) +{ + const char *name; + + if (type > LWTUNNEL_ENCAP_MAX) + return "unknown"; + + name = lwtunnel_encap_types[type].name; + + return name ? name : "unknown"; +} + +void nh_encap_dump(struct rtnl_nh_encap *rtnh_encap, struct nl_dump_params *dp) +{ + if (!rtnh_encap->ops) + return; + + nl_dump(dp, " encap %s ", + nh_encap_type2str(rtnh_encap->ops->encap_type)); + + if (rtnh_encap->ops->dump) + rtnh_encap->ops->dump(rtnh_encap->priv, dp); +} + +int nh_encap_build_msg(struct nl_msg *msg, struct rtnl_nh_encap *rtnh_encap) +{ + struct nlattr *encap; + int err; + + if (!rtnh_encap->ops || !rtnh_encap->ops->build_msg) { + NL_DBG(2, "Nexthop encap type not implemented\n"); + return -NLE_INVAL; + } + + NLA_PUT_U16(msg, RTA_ENCAP_TYPE, rtnh_encap->ops->encap_type); + + encap = nla_nest_start(msg, RTA_ENCAP); + if (!encap) + goto nla_put_failure; + + err = rtnh_encap->ops->build_msg(msg, rtnh_encap->priv); + if (err < 0) + return err; + + nla_nest_end(msg, encap); + + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +int nh_encap_parse_msg(struct nlattr *encap, struct nlattr *encap_type, + struct rtnl_nexthop *rtnh) +{ + uint16_t e_type = nla_get_u16(encap_type); + + if (e_type == LWTUNNEL_ENCAP_NONE) { + NL_DBG(2, "RTA_ENCAP_TYPE should not be LWTUNNEL_ENCAP_NONE\n"); + return -NLE_INVAL; + } + if (e_type > LWTUNNEL_ENCAP_MAX) { + NL_DBG(2, "Unknown RTA_ENCAP_TYPE: %d\n", e_type); + return -NLE_INVAL; + } + + if (!lwtunnel_encap_types[e_type].ops) { + NL_DBG(2, "RTA_ENCAP_TYPE %s is not implemented\n", + lwtunnel_encap_types[e_type].name); + return -NLE_MSGTYPE_NOSUPPORT; + } + + return lwtunnel_encap_types[e_type].ops->parse_msg(encap, rtnh); +} + +int nh_encap_compare(struct rtnl_nh_encap *a, struct rtnl_nh_encap *b) +{ + if (!a && !b) + return 0; + + if ((a && !b) || (!a && b) || (a->ops != b->ops)) + return 1; + + if (!a->ops || !a->ops->compare) + return 0; + + return a->ops->compare(a->priv, b->priv); +} diff --git a/lib/route/nh.c b/lib/route/nh.c new file mode 100644 index 0000000..1072172 --- /dev/null +++ b/lib/route/nh.c @@ -0,0 +1,590 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2022 Stanislav Zaikin + */ + +#include "nl-default.h" + +#include + +#include +#include +#include + +#include "nl-aux-route/nl-route.h" +#include "nl-route.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" + +/** @cond SKIP */ +struct rtnl_nh { + NLHDR_COMMON + + uint8_t nh_family; + uint32_t nh_flags; + + uint32_t nh_id; + uint32_t nh_group_type; + nl_nh_group_t *nh_group; + uint32_t nh_oif; + struct nl_addr *nh_gateway; +}; + +#define NH_ATTR_FLAGS (1 << 0) +#define NH_ATTR_ID (1 << 1) +#define NH_ATTR_GROUP (1 << 2) +#define NH_ATTR_FLAG_BLACKHOLE (1 << 3) +#define NH_ATTR_OIF (1 << 4) +#define NH_ATTR_GATEWAY (1 << 5) +#define NH_ATTR_FLAG_GROUPS (1 << 6) +#define NH_ATTR_FLAG_FDB (1 << 8) +/** @endcond */ + +struct nla_policy rtnl_nh_policy[NHA_MAX + 1] = { + [NHA_UNSPEC] = { .type = NLA_UNSPEC }, + [NHA_ID] = { .type = NLA_U32 }, + [NHA_GROUP] = { .type = NLA_NESTED }, + [NHA_GROUP_TYPE] = { .type = NLA_U16 }, + [NHA_BLACKHOLE] = { .type = NLA_UNSPEC }, + [NHA_OIF] = { .type = NLA_U32 }, +}; + +static struct nl_cache_ops rtnl_nh_ops; +static struct nl_object_ops nh_obj_ops; + +static nl_nh_group_t *rtnl_nh_grp_alloc(unsigned size) +{ + nl_nh_group_t *nhg; + + _nl_assert(size <= (unsigned)INT_MAX); + + if (!(nhg = calloc(1, sizeof(*nhg)))) + return NULL; + + nhg->size = size; + + if (!(nhg->entries = calloc(size, sizeof(*nhg->entries)))) { + free(nhg); + return NULL; + } + + nhg->ce_refcnt = 1; + + return nhg; +} + +static void rtnl_nh_grp_put(nl_nh_group_t *nhg) +{ + if (!nhg) + return; + + _nl_assert(nhg->ce_refcnt > 0); + + nhg->ce_refcnt--; + + if (nhg->ce_refcnt > 0) + return; + + free(nhg); +} + +static int rtnh_nh_grp_cmp(const nl_nh_group_t *a, const nl_nh_group_t *b) +{ + unsigned i; + + _NL_CMP_SELF(a, b); + _NL_CMP_DIRECT(a->size, b->size); + for (i = 0; i < a->size; i++) { + _NL_CMP_DIRECT(a->entries[i].nh_id, b->entries[i].nh_id); + _NL_CMP_DIRECT(a->entries[i].weight, b->entries[i].weight); + } + return 0; +} + +static int rtnh_nh_grp_clone(nl_nh_group_t *src, nl_nh_group_t **dst) +{ + nl_nh_group_t *ret; + unsigned i; + + ret = rtnl_nh_grp_alloc(src->size); + + if (!ret) + return -NLE_NOMEM; + + for (i = 0; i < src->size; i++) { + ret->entries[i].nh_id = src->entries[i].nh_id; + ret->entries[i].weight = src->entries[i].weight; + } + + *dst = ret; + + return NLE_SUCCESS; +} + +struct rtnl_nh *rtnl_nh_alloc(void) +{ + return (struct rtnl_nh *)nl_object_alloc(&nh_obj_ops); +} + +static int nh_clone(struct nl_object *_src, struct nl_object *_dst) +{ + struct rtnl_nh *dst = nl_object_priv(_dst); + struct rtnl_nh *src = nl_object_priv(_src); + + dst->nh_flags = src->nh_flags; + dst->nh_family = src->nh_family; + dst->nh_id = src->nh_id; + dst->nh_oif = src->nh_oif; + dst->ce_mask = src->ce_mask; + + if (src->nh_gateway) { + dst->nh_gateway = nl_addr_clone(src->nh_gateway); + if (!dst->nh_gateway) { + return -NLE_NOMEM; + } + } + + if (src->nh_group) { + if (rtnh_nh_grp_clone(src->nh_group, &dst->nh_group) < 0) { + return -NLE_NOMEM; + } + } + + return 0; +} + +static void nh_free(struct nl_object *obj) +{ + struct rtnl_nh *nh = nl_object_priv(obj); + nl_addr_put(nh->nh_gateway); + + if (nh->nh_group) + rtnl_nh_grp_put(nh->nh_group); +} + +void rtnl_nh_put(struct rtnl_nh *nh) +{ + struct nl_object *obj = (struct nl_object *)nh; + + nl_object_put(obj); +} + +static void nexthop_keygen(struct nl_object *obj, uint32_t *hashkey, + uint32_t table_sz) +{ + struct rtnl_nh *nexthop = nl_object_priv(obj); + unsigned int lkey_sz; + struct nexthop_hash_key { + uint32_t nh_id; + } __attribute__((packed)) lkey; + + lkey_sz = sizeof(lkey); + lkey.nh_id = nexthop->nh_id; + + *hashkey = nl_hash(&lkey, lkey_sz, 0) % table_sz; + + return; +} + +int rtnl_nh_set_gateway(struct rtnl_nh *nexthop, struct nl_addr *addr) +{ + if (nexthop->ce_mask & NH_ATTR_GATEWAY) { + nl_addr_put(nexthop->nh_gateway); + } + + nexthop->nh_gateway = nl_addr_clone(addr); + nexthop->ce_mask |= NH_ATTR_GATEWAY; + + return 0; +} + +struct nl_addr *rtnl_nh_get_gateway(struct rtnl_nh *nexthop) +{ + return nexthop->nh_gateway; +} + +int rtnl_nh_set_fdb(struct rtnl_nh *nexthop, int value) +{ + if (value) + nexthop->ce_mask |= NH_ATTR_FLAG_FDB; + else + nexthop->ce_mask &= ~NH_ATTR_FLAG_FDB; + + return 0; +} + +int rtnl_nh_get_oif(struct rtnl_nh *nexthop) +{ + if (nexthop->ce_mask & NH_ATTR_OIF) + return nexthop->nh_oif; + + return 0; +} + +int rtnl_nh_get_fdb(struct rtnl_nh *nexthop) +{ + return nexthop->ce_mask & NH_ATTR_FLAG_FDB; +} + +int rtnl_nh_get_group_entry(struct rtnl_nh *nexthop, int n) +{ + if (!(nexthop->ce_mask & NH_ATTR_GROUP) || !nexthop->nh_group) + return -NLE_MISSING_ATTR; + + if (n < 0 || ((unsigned)n) >= nexthop->nh_group->size) + return -NLE_INVAL; + + return nexthop->nh_group->entries[n].nh_id; +} + +int rtnl_nh_get_group_size(struct rtnl_nh *nexthop) +{ + if (!(nexthop->ce_mask & NH_ATTR_GROUP) || !nexthop->nh_group) + return -NLE_MISSING_ATTR; + + _nl_assert(nexthop->nh_group->size <= INT_MAX); + + return (int)nexthop->nh_group->size; +} + +static int rtnl_nh_grp_info(unsigned size, const struct nexthop_grp *vi, + nl_nh_group_t **nvi) +{ + nl_nh_group_t *ret; + unsigned i; + + if (!(ret = rtnl_nh_grp_alloc(size))) + return -NLE_NOMEM; + + for (i = 0; i < size; i++) { + ret->entries[i].nh_id = vi[i].id; + ret->entries[i].weight = vi[i].weight; + } + + *nvi = ret; + return NLE_SUCCESS; +} + +int rtnl_nh_get_id(struct rtnl_nh *nh) +{ + if (nh->ce_mask & NH_ATTR_ID) + return nh->nh_id; + + return -NLE_INVAL; +} + +static int nexthop_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *n, struct nl_parser_param *pp) +{ + _nl_auto_rtnl_nh struct rtnl_nh *nexthop = NULL; + struct nhmsg *ifi; + struct nlattr *tb[NHA_MAX + 1]; + int err; + int family; + + nexthop = rtnl_nh_alloc(); + if (nexthop == NULL) + return -NLE_NOMEM; + + nexthop->ce_msgtype = n->nlmsg_type; + + if (!nlmsg_valid_hdr(n, sizeof(*ifi))) + return -NLE_MSG_TOOSHORT; + + ifi = nlmsg_data(n); + family = ifi->nh_family; + nexthop->nh_family = family; + nexthop->nh_flags = ifi->nh_flags; + nexthop->ce_mask = (NH_ATTR_FLAGS); + + err = nlmsg_parse(n, sizeof(*ifi), tb, NHA_MAX, rtnl_nh_policy); + if (err < 0) + return err; + + if (tb[NHA_ID]) { + nexthop->nh_id = nla_get_u32(tb[NHA_ID]); + nexthop->ce_mask |= NH_ATTR_ID; + } + + if (tb[NHA_OIF]) { + nexthop->nh_oif = nla_get_u32(tb[NHA_OIF]); + nexthop->ce_mask |= NH_ATTR_OIF; + } + + if (tb[NHA_GATEWAY]) { + nexthop->nh_gateway = + nl_addr_alloc_attr(tb[NHA_GATEWAY], family); + nexthop->ce_mask |= NH_ATTR_GATEWAY; + } + + if (tb[NHA_BLACKHOLE]) { + nexthop->ce_mask |= NH_ATTR_FLAG_BLACKHOLE; + } + + if (tb[NHA_GROUPS]) { + nexthop->ce_mask |= NH_ATTR_FLAG_GROUPS; + } + + if (tb[NHA_FDB]) { + nexthop->ce_mask |= NH_ATTR_FLAG_FDB; + } + + if (tb[NHA_GROUP]) { + nl_nh_group_t *nh_group = NULL; + const void *data; + unsigned size; + unsigned len; + + data = nla_data(tb[NHA_GROUP]); + len = nla_len(tb[NHA_GROUP]); + size = len / sizeof(struct nexthop_grp); + + err = rtnl_nh_grp_info(size, (const struct nexthop_grp *)data, + &nh_group); + if (err < 0) { + return err; + } + + nexthop->nh_group = nh_group; + nexthop->ce_mask |= NH_ATTR_GROUP; + } + + return pp->pp_cb((struct nl_object *)nexthop, pp); +} + +static int nexthop_request_update(struct nl_cache *cache, struct nl_sock *sk) +{ + _nl_auto_nl_msg struct nl_msg *msg = NULL; + int family = cache->c_iarg1; + struct nhmsg hdr = { .nh_family = family }; + int err; + + msg = nlmsg_alloc_simple(RTM_GETNEXTHOP, NLM_F_DUMP); + if (!msg) + return -NLE_NOMEM; + + if (nlmsg_append(msg, &hdr, sizeof(hdr), NLMSG_ALIGNTO) < 0) + return -NLE_MSGSIZE; + + err = nl_send_auto(sk, msg); + if (err < 0) + return err; + + return NLE_SUCCESS; +} + +static void dump_nh_group(nl_nh_group_t *group, struct nl_dump_params *dp) +{ + unsigned i; + + nl_dump(dp, " nh_grp:"); + for (i = 0; i < group->size; i++) { + nl_dump(dp, " %u", group->entries[i].nh_id); + } +} + +static void nh_dump_line(struct nl_object *obj, struct nl_dump_params *dp) +{ + struct nl_cache *cache; + char buf[128]; + struct rtnl_nh *nh = nl_object_priv(obj); + + cache = nl_cache_mngt_require_safe("route/nh"); + + if (nh->ce_mask & NH_ATTR_ID) + nl_dump(dp, "nhid %u", nh->nh_id); + + if (nh->ce_mask & NH_ATTR_OIF) + nl_dump(dp, " oif %d", nh->nh_oif); + + if (nh->ce_mask & NH_ATTR_GATEWAY) + nl_dump(dp, " via %s", + nl_addr2str(nh->nh_gateway, buf, sizeof(buf))); + + if (nh->ce_mask & NH_ATTR_FLAG_BLACKHOLE) + nl_dump(dp, " blackhole"); + + if (nh->ce_mask & NH_ATTR_FLAG_GROUPS) + nl_dump(dp, " groups"); + + if (nh->ce_mask & NH_ATTR_GROUP) + dump_nh_group(nh->nh_group, dp); + + if (nh->ce_mask & NH_ATTR_FLAG_FDB) + nl_dump(dp, " fdb"); + + nl_dump(dp, "\n"); + + if (cache) + nl_cache_put(cache); +} + +static void nh_dump_details(struct nl_object *nh, struct nl_dump_params *dp) +{ + nh_dump_line(nh, dp); +} + +static uint64_t nh_compare(struct nl_object *a, struct nl_object *b, + uint64_t attrs, int loose) +{ + int diff = 0; + struct rtnl_nh *src = nl_object_priv(a); + struct rtnl_nh *dst = nl_object_priv(b); + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(NH_ATTR_ID, src->nh_id != dst->nh_id); + diff |= _DIFF(NH_ATTR_GATEWAY, + nl_addr_cmp(src->nh_gateway, dst->nh_gateway)); + diff |= _DIFF(NH_ATTR_OIF, src->nh_oif != dst->nh_oif); + diff |= _DIFF(NH_ATTR_GROUP, + rtnh_nh_grp_cmp(src->nh_group, dst->nh_group)); + diff |= _DIFF(NH_ATTR_FLAG_FDB, false); + diff |= _DIFF(NH_ATTR_FLAG_GROUPS, false); + diff |= _DIFF(NH_ATTR_FLAG_BLACKHOLE, false); +#undef _DIFF + + return diff; +} + +struct rtnl_nh *rtnl_nh_get(struct nl_cache *cache, int nhid) +{ + struct rtnl_nh *nh; + + if (cache->c_ops != &rtnl_nh_ops) + return NULL; + + nl_list_for_each_entry(nh, &cache->c_items, ce_list) { + if (nh->nh_id == nhid) { + nl_object_get((struct nl_object *)nh); + return nh; + } + } + + return NULL; +} + +/** + * Allocate nexthop cache and fill in all configured nexthops. + * @arg sk Netnexthop socket. + * @arg family nexthop address family or AF_UNSPEC + * @arg result Pointer to store resulting cache. + * @arg flags Flags to set in nexthop cache before filling + * + * Allocates and initializes a new nexthop cache. If \c sk is valid, a netnexthop + * message is sent to the kernel requesting a full dump of all configured + * nexthops. The returned messages are parsed and filled into the cache. If + * the operation succeeds, the resulting cache will contain a nexthop object for + * each nexthop configured in the kernel. If \c sk is NULL, returns 0 but the + * cache is still empty. + * + * If \c family is set to an address family other than \c AF_UNSPEC the + * contents of the cache can be limited to a specific address family. + * Currently the following address families are supported: + * - AF_BRIDGE + * - AF_INET6 + * + * @route_doc{nexthop_list, Get List of nexthops} + * @see rtnl_nh_get() + * @see rtnl_nh_get_by_name() + * @return 0 on success or a negative error code. + */ +static int rtnl_nh_alloc_cache_flags(struct nl_sock *sk, int family, + struct nl_cache **result, + unsigned int flags) +{ + struct nl_cache *cache; + int err; + + cache = nl_cache_alloc(&rtnl_nh_ops); + if (!cache) + return -NLE_NOMEM; + + cache->c_iarg1 = family; + + if (flags) + nl_cache_set_flags(cache, flags); + + if (sk && (err = nl_cache_refill(sk, cache)) < 0) { + nl_cache_free(cache); + return err; + } + + *result = cache; + return 0; +} + +/** + * Allocate nexthop cache and fill in all configured nexthops. + * @arg sk Netnexthop socket. + * @arg family nexthop address family or AF_UNSPEC + * @arg result Pointer to store resulting cache. + * + * Allocates and initializes a new nexthop cache. If \c sk is valid, a netnexthop + * message is sent to the kernel requesting a full dump of all configured + * nexthops. The returned messages are parsed and filled into the cache. If + * the operation succeeds, the resulting cache will contain a nexthop object for + * each nexthop configured in the kernel. If \c sk is NULL, returns 0 but the + * cache is still empty. + * + * If \c family is set to an address family other than \c AF_UNSPEC the + * contents of the cache can be limited to a specific address family. + * Currently the following address families are supported: + * - AF_BRIDGE + * - AF_INET6 + * + * @route_doc{nexthop_list, Get List of nexthops} + * @see rtnl_nh_get() + * @see rtnl_nh_get_by_name() + * @return 0 on success or a negative error code. + */ +int rtnl_nh_alloc_cache(struct nl_sock *sk, int family, + struct nl_cache **result) +{ + return rtnl_nh_alloc_cache_flags(sk, family, result, 0); +} + +static struct nl_object_ops nh_obj_ops = { + .oo_name = "route/nh", + .oo_size = sizeof(struct rtnl_nh), + .oo_free_data = nh_free, + .oo_clone = nh_clone, + .oo_dump = { + [NL_DUMP_LINE] = nh_dump_line, + [NL_DUMP_DETAILS] = nh_dump_details, + }, + .oo_compare = nh_compare, + .oo_keygen = nexthop_keygen, + .oo_attrs2str = rtnl_route_nh_flags2str, + .oo_id_attrs = NH_ATTR_ID, +}; + +static struct nl_af_group nh_groups[] = { + { AF_UNSPEC, RTNLGRP_NEXTHOP }, + { END_OF_GROUP_LIST }, +}; + +static struct nl_cache_ops rtnl_nh_ops = { + .co_name = "route/nh", + .co_hdrsize = sizeof(struct nhmsg), + .co_msgtypes = { + { RTM_NEWNEXTHOP, NL_ACT_NEW, "new" }, + { RTM_DELNEXTHOP, NL_ACT_DEL, "del" }, + { RTM_GETNEXTHOP, NL_ACT_GET, "get" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_ROUTE, + .co_groups = nh_groups, + .co_request_update = nexthop_request_update, + .co_msg_parser = nexthop_msg_parser, + .co_obj_ops = &nh_obj_ops, +}; + +static void _nl_init nexthop_init(void) +{ + nl_cache_mngt_register(&rtnl_nh_ops); +} + +static void _nl_exit nexthop_exit(void) +{ + nl_cache_mngt_unregister(&rtnl_nh_ops); +} diff --git a/lib/route/nh_encap_mpls.c b/lib/route/nh_encap_mpls.c new file mode 100644 index 0000000..a780291 --- /dev/null +++ b/lib/route/nh_encap_mpls.c @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include +#include + +#include + +#include "nl-route.h" +#include "nexthop-encap.h" + +struct mpls_iptunnel_encap { + struct nl_addr *dst; + uint8_t ttl; +}; + +static void mpls_encap_dump(void *priv, struct nl_dump_params *dp) +{ + struct mpls_iptunnel_encap *encap_info = priv; + char buf[256]; + + nl_dump(dp, "%s ", nl_addr2str(encap_info->dst, buf, sizeof(buf))); + + if (encap_info->ttl) + nl_dump(dp, "ttl %u ", encap_info->ttl); +} + +static int mpls_encap_build_msg(struct nl_msg *msg, void *priv) +{ + struct mpls_iptunnel_encap *encap_info = priv; + + NLA_PUT_ADDR(msg, MPLS_IPTUNNEL_DST, encap_info->dst); + if (encap_info->ttl) + NLA_PUT_U8(msg, MPLS_IPTUNNEL_TTL, encap_info->ttl); + + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +static void mpls_encap_destructor(void *priv) +{ + struct mpls_iptunnel_encap *encap_info = priv; + + nl_addr_put(encap_info->dst); +} + +static struct nla_policy mpls_encap_policy[MPLS_IPTUNNEL_MAX + 1] = { + [MPLS_IPTUNNEL_DST] = { .type = NLA_U32 }, + [MPLS_IPTUNNEL_TTL] = { .type = NLA_U8 }, +}; + +static int mpls_encap_parse_msg(struct nlattr *nla, struct rtnl_nexthop *nh) +{ + struct nlattr *tb[MPLS_IPTUNNEL_MAX + 1]; + struct nl_addr *labels; + uint8_t ttl = 0; + int err; + + err = nla_parse_nested(tb, MPLS_IPTUNNEL_MAX, nla, mpls_encap_policy); + if (err < 0) + return err; + + if (!tb[MPLS_IPTUNNEL_DST]) + return -NLE_INVAL; + + labels = nl_addr_alloc_attr(tb[MPLS_IPTUNNEL_DST], AF_MPLS); + if (!labels) + return -NLE_NOMEM; + + if (tb[MPLS_IPTUNNEL_TTL]) + ttl = nla_get_u8(tb[MPLS_IPTUNNEL_TTL]); + + err = rtnl_route_nh_encap_mpls(nh, labels, ttl); + + nl_addr_put(labels); + + return err; +} + +static int mpls_encap_compare(void *_a, void *_b) +{ + struct mpls_iptunnel_encap *a = _a; + struct mpls_iptunnel_encap *b = _b; + int diff = 0; + + diff |= (a->ttl != b->ttl); + diff |= nl_addr_cmp(a->dst, b->dst); + + return diff; +} + +struct nh_encap_ops mpls_encap_ops = { + .encap_type = LWTUNNEL_ENCAP_MPLS, + .build_msg = mpls_encap_build_msg, + .parse_msg = mpls_encap_parse_msg, + .compare = mpls_encap_compare, + .dump = mpls_encap_dump, + .destructor = mpls_encap_destructor, +}; + +int rtnl_route_nh_encap_mpls(struct rtnl_nexthop *nh, + struct nl_addr *addr, + uint8_t ttl) +{ + struct mpls_iptunnel_encap *mpls_encap; + struct rtnl_nh_encap *rtnh_encap; + + if (!addr) + return -NLE_INVAL; + + rtnh_encap = calloc(1, sizeof(*rtnh_encap)); + if (!rtnh_encap) + return -NLE_NOMEM; + + mpls_encap = calloc(1, sizeof(*mpls_encap)); + if (!mpls_encap) { + free(rtnh_encap); + return -NLE_NOMEM; + } + + mpls_encap->dst = nl_addr_get(addr); + mpls_encap->ttl = ttl; + + rtnh_encap->priv = mpls_encap; + rtnh_encap->ops = &mpls_encap_ops; + + nh_set_encap(nh, rtnh_encap); + + return 0; +} + +struct nl_addr *rtnl_route_nh_get_encap_mpls_dst(struct rtnl_nexthop *nh) +{ + struct mpls_iptunnel_encap *mpls_encap; + + if (!nh->rtnh_encap || nh->rtnh_encap->ops->encap_type != LWTUNNEL_ENCAP_MPLS) + return NULL; + + mpls_encap = (struct mpls_iptunnel_encap *)nh->rtnh_encap->priv; + if (!mpls_encap) + return NULL; + + return mpls_encap->dst; +} + +uint8_t rtnl_route_nh_get_encap_mpls_ttl(struct rtnl_nexthop *nh) +{ + struct mpls_iptunnel_encap *mpls_encap; + + if (!nh->rtnh_encap || nh->rtnh_encap->ops->encap_type != LWTUNNEL_ENCAP_MPLS) + return 0; + + mpls_encap = (struct mpls_iptunnel_encap *)nh->rtnh_encap->priv; + if (!mpls_encap) + return 0; + + return mpls_encap->ttl; +} diff --git a/lib/route/nl-route.h b/lib/route/nl-route.h new file mode 100644 index 0000000..28d0166 --- /dev/null +++ b/lib/route/nl-route.h @@ -0,0 +1,191 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2003-2013 Thomas Graf + * Copyright (c) 2013 Sassano Systems LLC + */ + +#ifndef __LIB_ROUTE_NL_ROUTE_H__ +#define __LIB_ROUTE_NL_ROUTE_H__ + +#include + +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-priv-dynamic-route/nl-priv-dynamic-route.h" +#include "nl-aux-core/nl-core.h" + +/*****************************************************************************/ + +struct rtnl_link_map { + uint64_t lm_mem_start; + uint64_t lm_mem_end; + uint64_t lm_base_addr; + uint16_t lm_irq; + uint8_t lm_dma; + uint8_t lm_port; +}; + +#define IFQDISCSIZ 32 + +struct rtnl_link { + NLHDR_COMMON + + char l_name[IFNAMSIZ]; + uint32_t l_family; + uint32_t l_arptype; + uint32_t l_index; + uint32_t l_flags; + uint32_t l_change; + uint32_t l_mtu; + uint32_t l_link; + int32_t l_link_netnsid; + uint32_t l_txqlen; + uint32_t l_weight; + uint32_t l_master; + struct nl_addr *l_addr; + struct nl_addr *l_bcast; + char l_qdisc[IFQDISCSIZ]; + struct rtnl_link_map l_map; + uint64_t l_stats[RTNL_LINK_STATS_MAX + 1]; + uint32_t l_flag_mask; + uint32_t l_num_vf; + uint8_t l_operstate; + uint8_t l_linkmode; + /* 2 byte hole */ + char *l_info_kind; + char *l_info_slave_kind; + struct rtnl_link_info_ops *l_info_ops; + void *l_af_data[AF_MAX]; + void *l_info; + char *l_ifalias; + uint32_t l_promiscuity; + uint32_t l_num_tx_queues; + uint32_t l_num_rx_queues; + uint32_t l_gso_max_segs; + uint32_t l_gso_max_size; + uint32_t l_group; + uint8_t l_carrier; + /* 3 byte hole */ + uint32_t l_carrier_changes; + struct rtnl_link_af_ops *l_af_ops; + struct nl_data *l_phys_port_id; + char l_phys_port_name[IFNAMSIZ]; + struct nl_data *l_phys_switch_id; + int l_ns_fd; + pid_t l_ns_pid; + struct rtnl_link_vf *l_vf_list; +}; + +struct rtnl_nh_encap { + struct nh_encap_ops *ops; + void *priv; /* private data for encap type */ +}; + +struct rtnl_nexthop { + uint8_t rtnh_flags; + uint8_t rtnh_flag_mask; + uint8_t rtnh_weight; + /* 1 byte spare */ + uint32_t rtnh_ifindex; + struct nl_addr *rtnh_gateway; + uint32_t ce_mask; /* HACK to support attr macros */ + struct nl_list_head rtnh_list; + uint32_t rtnh_realms; + struct nl_addr *rtnh_newdst; + struct nl_addr *rtnh_via; + struct rtnl_nh_encap *rtnh_encap; +}; + +struct rtnl_ratespec { + uint64_t rs_rate64; + uint16_t rs_overhead; + int16_t rs_cell_align; + uint16_t rs_mpu; + uint8_t rs_cell_log; +}; + +#define TCKINDSIZ 32 + +#define NL_TC_GENERIC(pre) \ + NLHDR_COMMON \ + uint32_t pre##_family; \ + uint32_t pre##_ifindex; \ + uint32_t pre##_handle; \ + uint32_t pre##_parent; \ + uint32_t pre##_info; \ + uint32_t pre##_mtu; \ + uint32_t pre##_mpu; \ + uint32_t pre##_overhead; \ + uint32_t pre##_linktype; \ + char pre##_kind[TCKINDSIZ]; \ + struct nl_data *pre##_opts; \ + uint64_t pre##_stats[RTNL_TC_STATS_MAX + 1]; \ + struct nl_data *pre##_xstats; \ + struct nl_data *pre##_subdata; \ + struct rtnl_link *pre##_link; \ + struct rtnl_tc_ops *pre##_ops; \ + enum rtnl_tc_type pre##_type; \ + uint32_t pre##_chain + +struct rtnl_tc { + NL_TC_GENERIC(tc); +}; + +struct rtnl_qdisc { + NL_TC_GENERIC(q); +}; + +struct rtnl_act { + NL_TC_GENERIC(c); + struct rtnl_act *a_next; +}; + +/*****************************************************************************/ + +static inline void rtnl_copy_ratespec(struct rtnl_ratespec *dst, + struct tc_ratespec *src) +{ + dst->rs_cell_log = src->cell_log; + dst->rs_overhead = src->overhead; + dst->rs_cell_align = src->cell_align; + dst->rs_mpu = src->mpu; + dst->rs_rate64 = src->rate; +} + +static inline void rtnl_rcopy_ratespec(struct tc_ratespec *dst, + struct rtnl_ratespec *src) +{ + dst->cell_log = src->rs_cell_log; + dst->overhead = src->rs_overhead; + dst->cell_align = src->rs_cell_align; + dst->mpu = src->rs_mpu; + dst->rate = src->rs_rate64 > 0xFFFFFFFFull ? 0xFFFFFFFFull : + (uint32_t)src->rs_rate64; +} + +/*****************************************************************************/ + +static inline int build_sysconf_path(char **strp, const char *filename) +{ + char *sysconfdir; + + sysconfdir = getenv("NLSYSCONFDIR"); + + if (!sysconfdir) + sysconfdir = SYSCONFDIR; + + return asprintf(strp, "%s/%s", sysconfdir, filename); +} + +/*****************************************************************************/ + +static inline int rtnl_tc_calc_txtime64(int bufsize, uint64_t rate) +{ + return ((double)bufsize / (double)rate) * 1000000.0; +} + +static inline int rtnl_tc_calc_bufsize64(int txtime, uint64_t rate) +{ + return ((double)txtime * (double)rate) / 1000000.0; +} + +#endif /* __LIB_ROUTE_NL_ROUTE_H__ */ diff --git a/lib/route/pktloc.c b/lib/route/pktloc.c index 9fcf4a4..7f320d9 100644 --- a/lib/route/pktloc.c +++ b/lib/route/pktloc.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/pktloc.c Packet Location Aliasing - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2008-2013 Thomas Graf */ @@ -31,12 +25,16 @@ * @{ */ -#include -#include +#include "nl-default.h" + +#include + #include #include #include +#include "nl-route.h" + #include "pktloc_syntax.h" #include "pktloc_grammar.h" @@ -101,13 +99,15 @@ static int read_pktlocs(void) /* if stat fails, just try to read the file */ if (stat(path, &st) == 0) { /* Don't re-read file if file is unchanged */ - if (last_read == st.st_mtime) - return 0; + if (last_read == st.st_mtime) { + err = 0; + goto errout; + } } NL_DBG(2, "Reading packet location file \"%s\"\n", path); - if (!(fd = fopen(path, "r"))) { + if (!(fd = fopen(path, "re"))) { err = -NLE_PKTLOC_FILE; goto errout; } @@ -121,7 +121,7 @@ static int read_pktlocs(void) nl_init_list_head(&pktloc_name_ht[i]); } - if ((err = pktloc_lex_init(&scanner)) < 0) { + if (pktloc_lex_init(&scanner) < 0) { err = -NLE_FAILURE; goto errout_close; } @@ -138,14 +138,13 @@ static int read_pktlocs(void) last_read = st.st_mtime; errout_scanner: - if (scanner) - pktloc_lex_destroy(scanner); + pktloc_lex_destroy(scanner); errout_close: fclose(fd); errout: free(path); - return 0; + return err; } /** @endcond */ @@ -247,7 +246,7 @@ void rtnl_pktloc_foreach(void (*cb)(struct rtnl_pktloc *, void *), void *arg) cb(loc, arg); } -static int __init pktloc_init(void) +static int _nl_init pktloc_init(void) { int i; diff --git a/lib/route/pktloc_grammar.l b/lib/route/pktloc_grammar.l index cbb42b3..2db229d 100644 --- a/lib/route/pktloc_grammar.l +++ b/lib/route/pktloc_grammar.l @@ -1,10 +1,14 @@ %{ - #include - #include + #include + #include #include #include + #include "pktloc_syntax.h" + + int pktloc_get_column(yyscan_t); + void pktloc_set_column(int, yyscan_t); %} %option 8bit diff --git a/lib/route/pktloc_syntax.y b/lib/route/pktloc_syntax.y index 25d8710..661463a 100644 --- a/lib/route/pktloc_syntax.y +++ b/lib/route/pktloc_syntax.y @@ -1,9 +1,9 @@ %{ -#include -#include #include #include #include + +#include "nl-route.h" %} %locations @@ -24,6 +24,7 @@ %{ extern int pktloc_lex(YYSTYPE *, YYLTYPE *, void *); +#define pktloc_error yyerror static void yyerror(YYLTYPE *locp, void *scanner, const char *msg) { NL_DBG(1, "Error while parsing packet location file: %s\n", msg); diff --git a/lib/route/qdisc.c b/lib/route/qdisc.c index 250d191..67ea358 100644 --- a/lib/route/qdisc.c +++ b/lib/route/qdisc.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/qdisc.c 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-2011 Thomas Graf */ @@ -15,16 +9,17 @@ * @{ */ -#include -#include +#include "nl-default.h" + #include #include #include -#include #include #include #include +#include "tc-api.h" + static struct nl_cache_ops rtnl_qdisc_ops; static struct nl_object_ops qdisc_obj_ops; @@ -403,6 +398,38 @@ struct rtnl_qdisc *rtnl_qdisc_get_by_parent(struct nl_cache *cache, } /** + * Search qdisc by kind + * @arg cache Qdisc cache + * @arg ifindex Interface index + * @arg kind Qdisc kind (tbf, htb, cbq, etc) + * + * Searches a qdisc cache previously allocated with rtnl_qdisc_alloc_cache() + * and searches for a qdisc matching the interface index and kind. + * + * The reference counter is incremented before returning the qdisc, therefore + * the reference must be given back with rtnl_qdisc_put() after usage. + * + * @return pointer to qdisc inside the cache or NULL if no match was found. + */ +struct rtnl_qdisc *rtnl_qdisc_get_by_kind(struct nl_cache *cache, + int ifindex, char *kind) +{ + struct rtnl_qdisc *q; + + if (cache->c_ops != &rtnl_qdisc_ops) + return NULL; + + nl_list_for_each_entry(q, &cache->c_items, ce_list) { + if ((q->q_ifindex == ifindex) && (!strcmp(q->q_kind, kind))) { + nl_object_get((struct nl_object *) q); + return q; + } + } + + return NULL; +} + +/** * Search qdisc by interface index and handle * @arg cache Qdisc cache * @arg ifindex Interface index @@ -520,7 +547,7 @@ static void qdisc_dump_details(struct rtnl_tc *tc, struct nl_dump_params *p) { struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc; - nl_dump(p, "refcnt %u ", qdisc->q_info); + nl_dump(p, "refcnt %u", qdisc->q_info); } static struct rtnl_tc_type_ops qdisc_ops = { @@ -541,6 +568,7 @@ static struct nl_cache_ops rtnl_qdisc_ops = { END_OF_MSGTYPES_LIST, }, .co_protocol = NETLINK_ROUTE, + .co_groups = tc_groups, .co_request_update = qdisc_request_update, .co_msg_parser = qdisc_msg_parser, .co_obj_ops = &qdisc_obj_ops, @@ -560,13 +588,13 @@ static struct nl_object_ops qdisc_obj_ops = { .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE), }; -static void __init qdisc_init(void) +static void _nl_init qdisc_init(void) { rtnl_tc_type_register(&qdisc_ops); nl_cache_mngt_register(&rtnl_qdisc_ops); } -static void __exit qdisc_exit(void) +static void _nl_exit qdisc_exit(void) { nl_cache_mngt_unregister(&rtnl_qdisc_ops); rtnl_tc_type_unregister(&qdisc_ops); diff --git a/lib/route/qdisc/blackhole.c b/lib/route/qdisc/blackhole.c index 339cf78..8d8f4ba 100644 --- a/lib/route/qdisc/blackhole.c +++ b/lib/route/qdisc/blackhole.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/qdisc/blackhole.c Blackhole Qdisc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf */ @@ -15,21 +9,23 @@ * @{ */ -#include +#include "nl-default.h" + #include -#include + +#include "tc-api.h" static struct rtnl_tc_ops blackhole_ops = { .to_kind = "blackhole", .to_type = RTNL_TC_TYPE_QDISC, }; -static void __init blackhole_init(void) +static void _nl_init blackhole_init(void) { rtnl_tc_register(&blackhole_ops); } -static void __exit blackhole_exit(void) +static void _nl_exit blackhole_exit(void) { rtnl_tc_unregister(&blackhole_ops); } diff --git a/lib/route/qdisc/cbq.c b/lib/route/qdisc/cbq.c index 95f1761..b9a6696 100644 --- a/lib/route/qdisc/cbq.c +++ b/lib/route/qdisc/cbq.c @@ -1,25 +1,29 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/qdisc/cbq.c Class Based Queueing - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf */ -#include -#include +#include "nl-default.h" + #include #include -#include #include #include #include #include #include +#include "tc-api.h" + +struct rtnl_cbq { + struct tc_cbq_lssopt cbq_lss; + struct tc_ratespec cbq_rate; + struct tc_cbq_wrropt cbq_wrr; + struct tc_cbq_ovl cbq_ovl; + struct tc_cbq_fopt cbq_fopt; + struct tc_cbq_police cbq_police; +}; + /** * @ingroup qdisc * @ingroup class @@ -28,11 +32,11 @@ */ static const struct trans_tbl ovl_strategies[] = { - __ADD(TC_CBQ_OVL_CLASSIC,classic) - __ADD(TC_CBQ_OVL_DELAY,delay) - __ADD(TC_CBQ_OVL_LOWPRIO,lowprio) - __ADD(TC_CBQ_OVL_DROP,drop) - __ADD(TC_CBQ_OVL_RCLASSIC,rclassic) + __ADD(TC_CBQ_OVL_CLASSIC,classic), + __ADD(TC_CBQ_OVL_DELAY,delay), + __ADD(TC_CBQ_OVL_LOWPRIO,lowprio), + __ADD(TC_CBQ_OVL_DROP,drop), + __ADD(TC_CBQ_OVL_RCLASSIC,rclassic), }; /** @@ -189,13 +193,13 @@ static struct rtnl_tc_ops cbq_class_ops = { }, }; -static void __init cbq_init(void) +static void _nl_init cbq_init(void) { rtnl_tc_register(&cbq_qdisc_ops); rtnl_tc_register(&cbq_class_ops); } -static void __exit cbq_exit(void) +static void _nl_exit cbq_exit(void) { rtnl_tc_unregister(&cbq_qdisc_ops); rtnl_tc_unregister(&cbq_class_ops); diff --git a/lib/route/qdisc/dsmark.c b/lib/route/qdisc/dsmark.c index fd9553d..f5718f9 100644 --- a/lib/route/qdisc/dsmark.c +++ b/lib/route/qdisc/dsmark.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/qdisc/dsmark.c DSMARK - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf */ @@ -16,16 +10,30 @@ * @{ */ -#include -#include +#include "nl-default.h" + #include #include #include -#include #include #include +#include "tc-api.h" + /** @cond SKIP */ +struct rtnl_dsmark_qdisc { + uint16_t qdm_indices; + uint16_t qdm_default_index; + uint32_t qdm_set_tc_index; + uint32_t qdm_mask; +}; + +struct rtnl_dsmark_class { + uint8_t cdm_bmask; + uint8_t cdm_value; + uint32_t cdm_mask; +}; + #define SCH_DSMARK_ATTR_INDICES 0x1 #define SCH_DSMARK_ATTR_DEFAULT_INDEX 0x2 #define SCH_DSMARK_ATTR_SET_TC_INDEX 0x4 @@ -398,13 +406,13 @@ static struct rtnl_tc_ops dsmark_class_ops = { .to_msg_fill = dsmark_class_msg_fill, }; -static void __init dsmark_init(void) +static void _nl_init dsmark_init(void) { rtnl_tc_register(&dsmark_qdisc_ops); rtnl_tc_register(&dsmark_class_ops); } -static void __exit dsmark_exit(void) +static void _nl_exit dsmark_exit(void) { rtnl_tc_unregister(&dsmark_qdisc_ops); rtnl_tc_unregister(&dsmark_class_ops); diff --git a/lib/route/qdisc/fifo.c b/lib/route/qdisc/fifo.c index d94c007..9976803 100644 --- a/lib/route/qdisc/fifo.c +++ b/lib/route/qdisc/fifo.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/qdisc/fifo.c (p|b)fifo - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf */ @@ -29,15 +23,21 @@ * @{ */ -#include -#include +#include "nl-default.h" + #include -#include #include #include #include +#include "tc-api.h" + /** @cond SKIP */ +struct rtnl_fifo { + uint32_t qf_limit; + uint32_t qf_mask; +}; + #define SCH_FIFO_ATTR_LIMIT 1 /** @endcond */ @@ -154,13 +154,13 @@ static struct rtnl_tc_ops bfifo_ops = { .to_msg_fill = fifo_msg_fill, }; -static void __init fifo_init(void) +static void _nl_init fifo_init(void) { rtnl_tc_register(&pfifo_ops); rtnl_tc_register(&bfifo_ops); } -static void __exit fifo_exit(void) +static void _nl_exit fifo_exit(void) { rtnl_tc_unregister(&pfifo_ops); rtnl_tc_unregister(&bfifo_ops); diff --git a/lib/route/qdisc/fq_codel.c b/lib/route/qdisc/fq_codel.c new file mode 100644 index 0000000..a44ab22 --- /dev/null +++ b/lib/route/qdisc/fq_codel.c @@ -0,0 +1,382 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Cong Wang + */ + +/** + * @ingroup qdisc + * @defgroup qdisc_fq_codel Fair Queue CoDel + * @brief + * + * @{ + */ + +#include "nl-default.h" + +#include +#include +#include +#include + +#include "tc-api.h" + +/** @cond SKIP */ +struct rtnl_fq_codel { + int fq_limit; + uint32_t fq_target; + uint32_t fq_interval; + int fq_flows; + uint32_t fq_quantum; + int fq_ecn; + uint32_t fq_mask; +}; + +#define SCH_FQ_CODEL_ATTR_TARGET 0x1 +#define SCH_FQ_CODEL_ATTR_LIMIT 0x2 +#define SCH_FQ_CODEL_ATTR_INTERVAL 0x4 +#define SCH_FQ_CODEL_ATTR_FLOWS 0x8 +#define SCH_FQ_CODEL_ATTR_QUANTUM 0x10 +#define SCH_FQ_CODEL_ATTR_ECN 0x20 +/** @endcond */ + +static struct nla_policy fq_codel_policy[TCA_FQ_CODEL_MAX + 1] = { + [TCA_FQ_CODEL_TARGET] = { .type = NLA_U32 }, + [TCA_FQ_CODEL_LIMIT] = { .type = NLA_U32 }, + [TCA_FQ_CODEL_INTERVAL] = { .type = NLA_U32 }, + [TCA_FQ_CODEL_ECN] = { .type = NLA_U32 }, + [TCA_FQ_CODEL_FLOWS] = { .type = NLA_U32 }, + [TCA_FQ_CODEL_QUANTUM] = { .type = NLA_U32 }, +}; + +static int fq_codel_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct rtnl_fq_codel *fq_codel = data; + struct nlattr *tb[TCA_FQ_CODEL_MAX + 1]; + int err; + + err = tca_parse(tb, TCA_FQ_CODEL_MAX, tc, fq_codel_policy); + if (err < 0) + return err; + + if (tb[TCA_FQ_CODEL_TARGET]) { + fq_codel->fq_target = nla_get_u32(tb[TCA_FQ_CODEL_TARGET]); + fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_TARGET; + } + + if (tb[TCA_FQ_CODEL_INTERVAL]) { + fq_codel->fq_interval = nla_get_u32(tb[TCA_FQ_CODEL_INTERVAL]); + fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_INTERVAL; + } + + if (tb[TCA_FQ_CODEL_LIMIT]) { + fq_codel->fq_limit = nla_get_u32(tb[TCA_FQ_CODEL_LIMIT]); + fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_LIMIT; + } + + if (tb[TCA_FQ_CODEL_QUANTUM]) { + fq_codel->fq_quantum = nla_get_u32(tb[TCA_FQ_CODEL_QUANTUM]); + fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_QUANTUM; + } + + if (tb[TCA_FQ_CODEL_FLOWS]) { + fq_codel->fq_flows = nla_get_u32(tb[TCA_FQ_CODEL_FLOWS]); + fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_FLOWS; + } + + if (tb[TCA_FQ_CODEL_ECN]) { + fq_codel->fq_ecn = nla_get_u32(tb[TCA_FQ_CODEL_ECN]); + fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_ECN; + } + + return 0; +} + +static void fq_codel_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_fq_codel *fq_codel = data; + + if (!fq_codel) + return; + + if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_LIMIT) + nl_dump(p, " limit %u packets", fq_codel->fq_limit); + if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_TARGET) + nl_dump(p, " target %u", fq_codel->fq_target); + if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_INTERVAL) + nl_dump(p, " interval %u", fq_codel->fq_interval); + if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_ECN) + nl_dump(p, " ecn %u", fq_codel->fq_ecn); + if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_FLOWS) + nl_dump(p, " flows %u", fq_codel->fq_flows); + if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_QUANTUM) + nl_dump(p, " quantum %u", fq_codel->fq_quantum); +} + +static int fq_codel_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + struct rtnl_fq_codel *fq_codel = data; + + if (!fq_codel) + return -NLE_INVAL; + + if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_LIMIT) + NLA_PUT_U32(msg, TCA_FQ_CODEL_LIMIT, fq_codel->fq_limit); + if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_INTERVAL) + NLA_PUT_U32(msg, TCA_FQ_CODEL_INTERVAL, fq_codel->fq_interval); + if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_TARGET) + NLA_PUT_U32(msg, TCA_FQ_CODEL_TARGET, fq_codel->fq_target); + if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_QUANTUM) + NLA_PUT_U32(msg, TCA_FQ_CODEL_QUANTUM, fq_codel->fq_quantum); + if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_FLOWS) + NLA_PUT_U32(msg, TCA_FQ_CODEL_FLOWS, fq_codel->fq_flows); + if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_ECN) + NLA_PUT_U32(msg, TCA_FQ_CODEL_ECN, fq_codel->fq_ecn); + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; + +} + +/** + * @name Attribute Modification + * @{ + */ + +/** + * Set limit of fq_codel qdisc. + * @arg qdisc fq_codel qdisc to be modified. + * @arg limit New limit. + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_fq_codel_set_limit(struct rtnl_qdisc *qdisc, int limit) +{ + struct rtnl_fq_codel *fq_codel; + + if (!(fq_codel = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + fq_codel->fq_limit = limit; + fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_LIMIT; + + return 0; +} + +/** + * Get limit of a fq_codel qdisc. + * @arg qdisc fq_codel qdisc. + * @return Numeric limit or a negative error code. + */ +int rtnl_qdisc_fq_codel_get_limit(struct rtnl_qdisc *qdisc) +{ + struct rtnl_fq_codel *fq_codel; + + if (!(fq_codel = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_LIMIT) + return fq_codel->fq_limit; + else + return -NLE_NOATTR; +} + +/** + * Set target of fq_codel qdisc. + * @arg qdisc fq_codel qdisc to be modified. + * @arg target New target. + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_fq_codel_set_target(struct rtnl_qdisc *qdisc, uint32_t target) +{ + struct rtnl_fq_codel *fq_codel; + + if (!(fq_codel = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + fq_codel->fq_target = target; + fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_TARGET; + + return 0; +} + +/** + * Get target of a fq_codel qdisc. + * @arg qdisc fq_codel qdisc. + * @return Numeric target or zero. + */ +uint32_t rtnl_qdisc_fq_codel_get_target(struct rtnl_qdisc *qdisc) +{ + struct rtnl_fq_codel *fq_codel; + + if ((fq_codel = rtnl_tc_data(TC_CAST(qdisc))) && + fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_TARGET) + return fq_codel->fq_target; + else + return 0; +} + +/** + * Set interval of fq_codel qdisc. + * @arg qdisc fq_codel qdisc to be modified. + * @arg interval New interval. + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_fq_codel_set_interval(struct rtnl_qdisc *qdisc, uint32_t interval) +{ + struct rtnl_fq_codel *fq_codel; + + if (!(fq_codel = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + fq_codel->fq_interval = interval; + fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_INTERVAL; + + return 0; +} + +/** + * Get target of a fq_codel qdisc. + * @arg qdisc fq_codel qdisc. + * @return Numeric interval or zero. + */ +uint32_t rtnl_qdisc_fq_codel_get_interval(struct rtnl_qdisc *qdisc) +{ + struct rtnl_fq_codel *fq_codel; + + if ((fq_codel = rtnl_tc_data(TC_CAST(qdisc))) && + fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_INTERVAL) + return fq_codel->fq_interval; + else + return 0; +} + +/** + * Set quantum of fq_codel qdisc. + * @arg qdisc fq_codel qdisc to be modified. + * @arg quantum New quantum. + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_fq_codel_set_quantum(struct rtnl_qdisc *qdisc, uint32_t quantum) +{ + struct rtnl_fq_codel *fq_codel; + + if (!(fq_codel = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + fq_codel->fq_quantum = quantum; + fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_QUANTUM; + + return 0; +} + +/** + * Get quantum of a fq_codel qdisc. + * @arg qdisc fq_codel qdisc. + * @return Numeric quantum or zero. + */ +uint32_t rtnl_qdisc_fq_codel_get_quantum(struct rtnl_qdisc *qdisc) +{ + struct rtnl_fq_codel *fq_codel; + + if ((fq_codel = rtnl_tc_data(TC_CAST(qdisc))) && + (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_QUANTUM)) + return fq_codel->fq_quantum; + else + return 0; +} + +/** + * Set flows of fq_codel qdisc. + * @arg qdisc fq_codel qdisc to be modified. + * @arg flows New flows value. + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_fq_codel_set_flows(struct rtnl_qdisc *qdisc, int flows) +{ + struct rtnl_fq_codel *fq_codel; + + if (!(fq_codel = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + fq_codel->fq_flows = flows; + fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_FLOWS; + + return 0; +} + +/** + * Get flows of a fq_codel qdisc. + * @arg qdisc fq_codel qdisc. + * @return Numeric flows or a negative error code. + */ +int rtnl_qdisc_fq_codel_get_flows(struct rtnl_qdisc *qdisc) +{ + struct rtnl_fq_codel *fq_codel; + + if (!(fq_codel = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_FLOWS) + return fq_codel->fq_flows; + else + return -NLE_NOATTR; +} +/** + * Set ecn of fq_codel qdisc. + * @arg qdisc fq_codel qdisc to be modified. + * @arg ecn New ecn value. + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_fq_codel_set_ecn(struct rtnl_qdisc *qdisc, int ecn) +{ + struct rtnl_fq_codel *fq_codel; + + if (!(fq_codel = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + fq_codel->fq_ecn = ecn; + fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_ECN; + + return 0; +} + +/** + * Get ecn of a fq_codel qdisc. + * @arg qdisc fq_codel qdisc. + * @return Numeric ecn or a negative error code. + */ +int rtnl_qdisc_fq_codel_get_ecn(struct rtnl_qdisc *qdisc) +{ + struct rtnl_fq_codel *fq_codel; + + if (!(fq_codel = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_ECN) + return fq_codel->fq_ecn; + else + return -NLE_NOATTR; +} +/** @} */ + +static struct rtnl_tc_ops fq_codel_ops = { + .to_kind = "fq_codel", + .to_type = RTNL_TC_TYPE_QDISC, + .to_size = sizeof(struct rtnl_fq_codel), + .to_msg_parser = fq_codel_msg_parser, + .to_dump[NL_DUMP_LINE] = fq_codel_dump_line, + .to_msg_fill = fq_codel_msg_fill, +}; + +static void _nl_init fq_codel_init(void) +{ + rtnl_tc_register(&fq_codel_ops); +} + +static void _nl_exit fq_codel_exit(void) +{ + rtnl_tc_unregister(&fq_codel_ops); +} + +/** @} */ diff --git a/lib/route/qdisc/hfsc.c b/lib/route/qdisc/hfsc.c new file mode 100644 index 0000000..49c24c7 --- /dev/null +++ b/lib/route/qdisc/hfsc.c @@ -0,0 +1,358 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2014 Cong Wang + */ + +/** + * @ingroup qdisc + * @ingroup class + * @defgroup qdisc_hfsc Hierarchical Fair Service Curve (HFSC) + * @{ + */ + +#include "nl-default.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "tc-api.h" + +/** @cond SKIP */ +struct rtnl_hfsc_qdisc { + uint32_t qh_defcls; + uint32_t qh_mask; +}; + +struct rtnl_hfsc_class { + struct tc_service_curve ch_rsc; + struct tc_service_curve ch_fsc; + struct tc_service_curve ch_usc; + uint32_t ch_mask; +}; + +#define SCH_HFSC_CLS_HAS_RSC 0x001 +#define SCH_HFSC_CLS_HAS_FSC 0x002 +#define SCH_HFSC_CLS_HAS_USC 0x004 + +#define SCH_HFSC_QD_HAS_DEFCLS 0x01 +/** @endcond */ + +static struct nla_policy hfsc_policy[TCA_HFSC_MAX + 1] = { + [TCA_HFSC_RSC] = { .minlen = sizeof(struct tc_service_curve) }, + [TCA_HFSC_FSC] = { .minlen = sizeof(struct tc_service_curve) }, + [TCA_HFSC_USC] = { .minlen = sizeof(struct tc_service_curve) }, +}; + +static int hfsc_qdisc_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct rtnl_hfsc_qdisc *hfsc = data; + struct tc_hfsc_qopt *opts; + + opts = (struct tc_hfsc_qopt *) tc->tc_opts->d_data; + hfsc->qh_defcls = opts->defcls; + hfsc->qh_mask |= SCH_HFSC_QD_HAS_DEFCLS; + return 0; +} + +static int hfsc_class_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct nlattr *tb[TCA_HFSC_MAX + 1]; + struct rtnl_hfsc_class *hfsc = data; + int err; + + if ((err = tca_parse(tb, TCA_HFSC_MAX, tc, hfsc_policy)) < 0) + return err; + + if (tb[TCA_HFSC_RSC]) { + struct tc_service_curve tsc; + + nla_memcpy(&tsc, tb[TCA_HFSC_RSC], sizeof(tsc)); + hfsc->ch_rsc = tsc; + hfsc->ch_mask |= SCH_HFSC_CLS_HAS_RSC; + } + + if (tb[TCA_HFSC_FSC]) { + struct tc_service_curve tsc; + + nla_memcpy(&tsc, tb[TCA_HFSC_FSC], sizeof(tsc)); + hfsc->ch_fsc = tsc; + hfsc->ch_mask |= SCH_HFSC_CLS_HAS_FSC; + } + + if (tb[TCA_HFSC_USC]) { + struct tc_service_curve tsc; + + nla_memcpy(&tsc, tb[TCA_HFSC_USC], sizeof(tsc)); + hfsc->ch_usc = tsc; + hfsc->ch_mask |= SCH_HFSC_CLS_HAS_USC; + } + + return 0; +} + +static void hfsc_qdisc_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_hfsc_qdisc *hfsc = data; + + if (!hfsc) + return; + + if (hfsc->qh_mask & SCH_HFSC_QD_HAS_DEFCLS) { + char buf[64]; + nl_dump(p, " default-class %s", + rtnl_tc_handle2str(hfsc->qh_defcls, buf, sizeof(buf))); + } +} + +static void hfsc_dump_tsc(struct nl_dump_params *p, struct tc_service_curve *tsc) +{ + nl_dump(p, " m1 %u d %u m2 %u\n", tsc->m1, tsc->d, tsc->m2); +} + +static void hfsc_class_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_hfsc_class *hfsc = data; + + if (!hfsc) + return; + if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_RSC) + hfsc_dump_tsc(p, &hfsc->ch_rsc); + if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_FSC) + hfsc_dump_tsc(p, &hfsc->ch_fsc); + if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_USC) + hfsc_dump_tsc(p, &hfsc->ch_usc); +} + +static void hfsc_class_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + return; +} + +static int hfsc_qdisc_msg_fill(struct rtnl_tc *tc, void *data, + struct nl_msg *msg) +{ + struct rtnl_hfsc_qdisc *hfsc = data; + struct tc_hfsc_qopt opts = {0}; + + if (!hfsc) + BUG(); + + opts.defcls = hfsc->qh_defcls; + return nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD); +} + +static int hfsc_class_msg_fill(struct rtnl_tc *tc, void *data, + struct nl_msg *msg) +{ + struct rtnl_hfsc_class *hfsc = data; + struct tc_service_curve tsc; + + if (!hfsc) + BUG(); + + if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_RSC) { + tsc = hfsc->ch_rsc; + NLA_PUT(msg, TCA_HFSC_RSC, sizeof(tsc), &tsc); + } + + if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_FSC) { + tsc = hfsc->ch_fsc; + NLA_PUT(msg, TCA_HFSC_FSC, sizeof(tsc), &tsc); + } + + if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_USC) { + tsc = hfsc->ch_usc; + NLA_PUT(msg, TCA_HFSC_USC, sizeof(tsc), &tsc); + } + + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +static struct rtnl_tc_ops hfsc_qdisc_ops; +static struct rtnl_tc_ops hfsc_class_ops; + +static struct rtnl_hfsc_qdisc *hfsc_qdisc_data(const struct rtnl_qdisc *qdisc, int *err) +{ + return rtnl_tc_data_check(TC_CAST(qdisc), &hfsc_qdisc_ops, err); +} + +static struct rtnl_hfsc_class *hfsc_class_data(const struct rtnl_class *class, int *err) +{ + return rtnl_tc_data_check(TC_CAST(class), &hfsc_class_ops, err); +} + +/** + * @name Attribute Modifications + * @{ + */ + +/** + * Return default class of HFSC qdisc + * @arg qdisc hfsc qdisc object + * + * Returns the classid of the class where all unclassified traffic + * goes to. + * + * @return classid or TC_H_UNSPEC if unspecified. + */ +uint32_t rtnl_qdisc_hfsc_get_defcls(const struct rtnl_qdisc *qdisc) +{ + struct rtnl_hfsc_qdisc *hfsc; + + if ((hfsc = hfsc_qdisc_data(qdisc, NULL)) && + (hfsc->qh_mask & SCH_HFSC_QD_HAS_DEFCLS)) + return hfsc->qh_defcls; + + return TC_H_UNSPEC; +} + +/** + * Set default class of the hfsc qdisc to the specified value + * @arg qdisc qdisc to change + * @arg defcls new default class + */ +int rtnl_qdisc_hfsc_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls) +{ + struct rtnl_hfsc_qdisc *hfsc; + int err; + + if (!(hfsc = hfsc_qdisc_data(qdisc, &err))) + return err; + + hfsc->qh_defcls = defcls; + hfsc->qh_mask |= SCH_HFSC_QD_HAS_DEFCLS; + + return 0; +} + +int rtnl_class_hfsc_get_rsc(const struct rtnl_class *class, struct tc_service_curve *tsc) +{ + struct rtnl_hfsc_class *hfsc; + int err = -NLE_OPNOTSUPP; + + if ((hfsc = hfsc_class_data(class, &err)) && + (hfsc->ch_mask & SCH_HFSC_CLS_HAS_RSC)) { + *tsc = hfsc->ch_rsc; + return 0; + } + + return err; +} + +int rtnl_class_hfsc_set_rsc(struct rtnl_class *class, const struct tc_service_curve *tsc) +{ + struct rtnl_hfsc_class *hfsc; + int err; + + if (!(hfsc = hfsc_class_data(class, &err))) + return err; + + hfsc->ch_rsc = *tsc; + hfsc->ch_mask |= SCH_HFSC_CLS_HAS_RSC; + + return 0; +} + +int rtnl_class_hfsc_get_fsc(const struct rtnl_class *class, struct tc_service_curve *tsc) +{ + struct rtnl_hfsc_class *hfsc; + int err = -NLE_OPNOTSUPP; + + if ((hfsc = hfsc_class_data(class, &err)) && + (hfsc->ch_mask & SCH_HFSC_CLS_HAS_FSC)) { + *tsc = hfsc->ch_fsc; + return 0; + } + + return err; +} + +int rtnl_class_hfsc_set_fsc(struct rtnl_class *class, const struct tc_service_curve *tsc) +{ + struct rtnl_hfsc_class *hfsc; + int err; + + if (!(hfsc = hfsc_class_data(class, &err))) + return err; + + hfsc->ch_fsc = *tsc; + hfsc->ch_mask |= SCH_HFSC_CLS_HAS_FSC; + + return 0; +} + +int rtnl_class_hfsc_get_usc(const struct rtnl_class *class, struct tc_service_curve *tsc) +{ + struct rtnl_hfsc_class *hfsc; + int err = -NLE_OPNOTSUPP; + + if ((hfsc = hfsc_class_data(class, &err)) && + (hfsc->ch_mask & SCH_HFSC_CLS_HAS_USC)) { + *tsc = hfsc->ch_usc; + return 0; + } + + return err; +} + +int rtnl_class_hfsc_set_usc(struct rtnl_class *class, const struct tc_service_curve *tsc) +{ + struct rtnl_hfsc_class *hfsc; + int err; + + if (!(hfsc = hfsc_class_data(class, &err))) + return err; + + hfsc->ch_usc = *tsc; + hfsc->ch_mask |= SCH_HFSC_CLS_HAS_USC; + + return 0; +} + +/** @} */ + +static struct rtnl_tc_ops hfsc_qdisc_ops = { + .to_kind = "hfsc", + .to_type = RTNL_TC_TYPE_QDISC, + .to_size = sizeof(struct rtnl_hfsc_qdisc), + .to_msg_parser = hfsc_qdisc_msg_parser, + .to_dump[NL_DUMP_LINE] = hfsc_qdisc_dump_line, + .to_msg_fill = hfsc_qdisc_msg_fill, +}; + +static struct rtnl_tc_ops hfsc_class_ops = { + .to_kind = "hfsc", + .to_type = RTNL_TC_TYPE_CLASS, + .to_size = sizeof(struct rtnl_hfsc_class), + .to_msg_parser = hfsc_class_msg_parser, + .to_dump = { + [NL_DUMP_LINE] = hfsc_class_dump_line, + [NL_DUMP_DETAILS] = hfsc_class_dump_details, + }, + .to_msg_fill = hfsc_class_msg_fill, +}; + +static void _nl_init hfsc_init(void) +{ + rtnl_tc_register(&hfsc_qdisc_ops); + rtnl_tc_register(&hfsc_class_ops); +} + +static void _nl_exit hfsc_exit(void) +{ + rtnl_tc_unregister(&hfsc_qdisc_ops); + rtnl_tc_unregister(&hfsc_class_ops); +} + +/** @} */ diff --git a/lib/route/qdisc/htb.c b/lib/route/qdisc/htb.c index 5a61a4e..28061b9 100644 --- a/lib/route/qdisc/htb.c +++ b/lib/route/qdisc/htb.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/qdisc/htb.c HTB Qdisc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf * Copyright (c) 2005-2006 Petr Gotthard * Copyright (c) 2005-2006 Siemens AG Oesterreich @@ -18,18 +12,37 @@ * @{ */ -#include -#include +#include "nl-default.h" + #include #include #include -#include #include #include #include #include +#include "tc-api.h" + /** @cond SKIP */ +struct rtnl_htb_qdisc { + uint32_t qh_rate2quantum; + uint32_t qh_defcls; + uint32_t qh_mask; + uint32_t qh_direct_pkts; +}; + +struct rtnl_htb_class { + uint32_t ch_prio; + struct rtnl_ratespec ch_rate; + struct rtnl_ratespec ch_ceil; + uint32_t ch_rbuffer; + uint32_t ch_cbuffer; + uint32_t ch_quantum; + uint32_t ch_mask; + uint32_t ch_level; +}; + #define SCH_HTB_HAS_RATE2QUANTUM 0x01 #define SCH_HTB_HAS_DEFCLS 0x02 @@ -45,6 +58,8 @@ static struct nla_policy htb_policy[TCA_HTB_MAX+1] = { [TCA_HTB_INIT] = { .minlen = sizeof(struct tc_htb_glob) }, [TCA_HTB_PARMS] = { .minlen = sizeof(struct tc_htb_opt) }, + [TCA_HTB_RATE64] = { .minlen = sizeof(uint64_t) }, + [TCA_HTB_CEIL64] = { .minlen = sizeof(uint64_t) }, }; static int htb_qdisc_msg_parser(struct rtnl_tc *tc, void *data) @@ -55,7 +70,7 @@ static int htb_qdisc_msg_parser(struct rtnl_tc *tc, void *data) if ((err = tca_parse(tb, TCA_HTB_MAX, tc, htb_policy)) < 0) return err; - + if (tb[TCA_HTB_INIT]) { struct tc_htb_glob opts; @@ -78,7 +93,7 @@ static int htb_class_msg_parser(struct rtnl_tc *tc, void *data) if ((err = tca_parse(tb, TCA_HTB_MAX, tc, htb_policy)) < 0) return err; - + if (tb[TCA_HTB_PARMS]) { struct tc_htb_opt opts; @@ -86,10 +101,16 @@ static int htb_class_msg_parser(struct rtnl_tc *tc, void *data) htb->ch_prio = opts.prio; rtnl_copy_ratespec(&htb->ch_rate, &opts.rate); rtnl_copy_ratespec(&htb->ch_ceil, &opts.ceil); - htb->ch_rbuffer = rtnl_tc_calc_bufsize(nl_ticks2us(opts.buffer), - opts.rate.rate); - htb->ch_cbuffer = rtnl_tc_calc_bufsize(nl_ticks2us(opts.cbuffer), - opts.ceil.rate); + + if (tb[TCA_HTB_RATE64]) + nla_memcpy(&htb->ch_rate.rs_rate64, tb[TCA_HTB_RATE64], sizeof(uint64_t)); + if (tb[TCA_HTB_CEIL64]) + nla_memcpy(&htb->ch_ceil.rs_rate64, tb[TCA_HTB_CEIL64], sizeof(uint64_t)); + + htb->ch_rbuffer = rtnl_tc_calc_bufsize64(nl_ticks2us(opts.buffer), + htb->ch_rate.rs_rate64); + htb->ch_cbuffer = rtnl_tc_calc_bufsize64(nl_ticks2us(opts.cbuffer), + htb->ch_ceil.rs_rate64); htb->ch_quantum = opts.quantum; htb->ch_level = opts.level; @@ -135,8 +156,8 @@ static void htb_class_dump_line(struct rtnl_tc *tc, void *data, double r, rbit; char *ru, *rubit; - r = nl_cancel_down_bytes(htb->ch_rate.rs_rate, &ru); - rbit = nl_cancel_down_bits(htb->ch_rate.rs_rate*8, &rubit); + r = nl_cancel_down_bytes(htb->ch_rate.rs_rate64, &ru); + rbit = nl_cancel_down_bits(htb->ch_rate.rs_rate64*8, &rubit); nl_dump(p, " rate %.2f%s/s (%.0f%s) log %u", r, ru, rbit, rubit, 1<ch_rate.rs_cell_log); @@ -156,8 +177,8 @@ static void htb_class_dump_details(struct rtnl_tc *tc, void *data, double r, rbit; char *ru, *rubit; - r = nl_cancel_down_bytes(htb->ch_ceil.rs_rate, &ru); - rbit = nl_cancel_down_bits(htb->ch_ceil.rs_rate*8, &rubit); + r = nl_cancel_down_bytes(htb->ch_ceil.rs_rate64, &ru); + rbit = nl_cancel_down_bits(htb->ch_ceil.rs_rate64*8, &rubit); nl_dump(p, " ceil %.2f%s/s (%.0f%s) log %u", r, ru, rbit, rubit, 1<ch_ceil.rs_cell_log); @@ -191,9 +212,9 @@ static int htb_qdisc_msg_fill(struct rtnl_tc *tc, void *data, { struct rtnl_htb_qdisc *htb = data; struct tc_htb_glob opts = { - .version = TC_HTB_PROTOVER, - .rate2quantum = 10, - }; + .version = TC_HTB_PROTOVER, + .rate2quantum = 10, + }; if (htb) { if (htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM) @@ -213,6 +234,8 @@ static int htb_class_msg_fill(struct rtnl_tc *tc, void *data, uint32_t mtu, rtable[RTNL_TC_RTABLE_SIZE], ctable[RTNL_TC_RTABLE_SIZE]; struct tc_htb_opt opts; int buffer, cbuffer; + uint64_t rate64; + uint64_t ceil64; if (!htb || !(htb->ch_mask & SCH_HTB_HAS_RATE)) BUG(); @@ -227,36 +250,43 @@ static int htb_class_msg_fill(struct rtnl_tc *tc, void *data, rtnl_tc_build_rate_table(tc, &htb->ch_rate, rtable); rtnl_rcopy_ratespec(&opts.rate, &htb->ch_rate); + rate64 = htb->ch_rate.rs_rate64; if (htb->ch_mask & SCH_HTB_HAS_CEIL) { rtnl_tc_build_rate_table(tc, &htb->ch_ceil, ctable); rtnl_rcopy_ratespec(&opts.ceil, &htb->ch_ceil); + ceil64 = htb->ch_ceil.rs_rate64; } else { /* * If not set, configured rate is used as ceil, which implies * no borrowing. */ memcpy(&opts.ceil, &opts.rate, sizeof(struct tc_ratespec)); + ceil64 = rate64; } if (htb->ch_mask & SCH_HTB_HAS_RBUFFER) buffer = htb->ch_rbuffer; else - buffer = opts.rate.rate / nl_get_psched_hz() + mtu; /* XXX */ + buffer = rate64 / nl_get_psched_hz() + mtu; /* XXX */ - opts.buffer = nl_us2ticks(rtnl_tc_calc_txtime(buffer, opts.rate.rate)); + opts.buffer = nl_us2ticks(rtnl_tc_calc_txtime64(buffer, rate64)); if (htb->ch_mask & SCH_HTB_HAS_CBUFFER) cbuffer = htb->ch_cbuffer; else - cbuffer = opts.ceil.rate / nl_get_psched_hz() + mtu; /* XXX */ + cbuffer = ceil64 / nl_get_psched_hz() + mtu; /* XXX */ - opts.cbuffer = nl_us2ticks(rtnl_tc_calc_txtime(cbuffer, opts.ceil.rate)); + opts.cbuffer = nl_us2ticks(rtnl_tc_calc_txtime64(cbuffer, ceil64)); if (htb->ch_mask & SCH_HTB_HAS_QUANTUM) opts.quantum = htb->ch_quantum; NLA_PUT(msg, TCA_HTB_PARMS, sizeof(opts), &opts); + if (rate64 > 0xFFFFFFFFull) + NLA_PUT(msg, TCA_HTB_RATE64, sizeof(uint64_t), &rate64); + if (ceil64 > 0xFFFFFFFFull) + NLA_PUT(msg, TCA_HTB_CEIL64, sizeof(uint64_t), &ceil64); NLA_PUT(msg, TCA_HTB_RTAB, sizeof(rtable), &rtable); NLA_PUT(msg, TCA_HTB_CTAB, sizeof(ctable), &ctable); @@ -269,14 +299,14 @@ nla_put_failure: static struct rtnl_tc_ops htb_qdisc_ops; static struct rtnl_tc_ops htb_class_ops; -static struct rtnl_htb_qdisc *htb_qdisc_data(struct rtnl_qdisc *qdisc) +static struct rtnl_htb_qdisc *htb_qdisc_data(struct rtnl_qdisc *qdisc, int *err) { - return rtnl_tc_data_check(TC_CAST(qdisc), &htb_qdisc_ops); + return rtnl_tc_data_check(TC_CAST(qdisc), &htb_qdisc_ops, err); } -static struct rtnl_htb_class *htb_class_data(struct rtnl_class *class) +static struct rtnl_htb_class *htb_class_data(struct rtnl_class *class, int *err) { - return rtnl_tc_data_check(TC_CAST(class), &htb_class_ops); + return rtnl_tc_data_check(TC_CAST(class), &htb_class_ops, err); } /** @@ -294,8 +324,8 @@ uint32_t rtnl_htb_get_rate2quantum(struct rtnl_qdisc *qdisc) { struct rtnl_htb_qdisc *htb; - if ((htb = htb_qdisc_data(qdisc)) && - htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM) + if ((htb = htb_qdisc_data(qdisc, NULL)) && + (htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM)) return htb->qh_rate2quantum; return 0; @@ -304,9 +334,10 @@ uint32_t rtnl_htb_get_rate2quantum(struct rtnl_qdisc *qdisc) int rtnl_htb_set_rate2quantum(struct rtnl_qdisc *qdisc, uint32_t rate2quantum) { struct rtnl_htb_qdisc *htb; + int err; - if (!(htb = htb_qdisc_data(qdisc))) - return -NLE_OPNOTSUPP; + if (!(htb = htb_qdisc_data(qdisc, &err))) + return err; htb->qh_rate2quantum = rate2quantum; htb->qh_mask |= SCH_HTB_HAS_RATE2QUANTUM; @@ -327,7 +358,7 @@ uint32_t rtnl_htb_get_defcls(struct rtnl_qdisc *qdisc) { struct rtnl_htb_qdisc *htb; - if ((htb = htb_qdisc_data(qdisc)) && + if ((htb = htb_qdisc_data(qdisc, NULL)) && htb->qh_mask & SCH_HTB_HAS_DEFCLS) return htb->qh_defcls; @@ -342,9 +373,10 @@ uint32_t rtnl_htb_get_defcls(struct rtnl_qdisc *qdisc) int rtnl_htb_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls) { struct rtnl_htb_qdisc *htb; + int err; - if (!(htb = htb_qdisc_data(qdisc))) - return -NLE_OPNOTSUPP; + if (!(htb = htb_qdisc_data(qdisc, &err))) + return err; htb->qh_defcls = defcls; htb->qh_mask |= SCH_HTB_HAS_DEFCLS; @@ -356,7 +388,8 @@ uint32_t rtnl_htb_get_prio(struct rtnl_class *class) { struct rtnl_htb_class *htb; - if ((htb = htb_class_data(class)) && htb->ch_mask & SCH_HTB_HAS_PRIO) + if ((htb = htb_class_data(class, NULL)) && + (htb->ch_mask & SCH_HTB_HAS_PRIO)) return htb->ch_prio; return 0; @@ -365,9 +398,10 @@ uint32_t rtnl_htb_get_prio(struct rtnl_class *class) int rtnl_htb_set_prio(struct rtnl_class *class, uint32_t prio) { struct rtnl_htb_class *htb; + int err; - if (!(htb = htb_class_data(class))) - return -NLE_OPNOTSUPP; + if (!(htb = htb_class_data(class, &err))) + return err; htb->ch_prio = prio; htb->ch_mask |= SCH_HTB_HAS_PRIO; @@ -379,15 +413,41 @@ int rtnl_htb_set_prio(struct rtnl_class *class, uint32_t prio) * Return rate of HTB class * @arg class htb class object * - * @return Rate in bytes/s or 0 if unspecified. + * @return Rate in bytes/s or 0 if unspecified. If the value + * cannot be represented as 32 bit integer, (1<<32) is returned. + * Use rtnl_htb_get_rate64() instead. */ uint32_t rtnl_htb_get_rate(struct rtnl_class *class) { struct rtnl_htb_class *htb; - if ((htb = htb_class_data(class)) && htb->ch_mask & SCH_HTB_HAS_RATE) - return htb->ch_rate.rs_rate; + if ( !(htb = htb_class_data(class, NULL)) + || !(htb->ch_mask & SCH_HTB_HAS_RATE)) + return 0; + + if (htb->ch_rate.rs_rate64 > 0xFFFFFFFFull) + return 0xFFFFFFFFull; + + return htb->ch_rate.rs_rate64; +} + +/** + * Return rate of HTB class + * @arg class htb class object + * @arg out_rate64 on success, the set rate. + * + * @return 0 on success or a negative error code. + */ +int rtnl_htb_get_rate64(struct rtnl_class *class, uint64_t *out_rate64) +{ + struct rtnl_htb_class *htb; + + if (!(htb = htb_class_data(class, NULL))) + return -NLE_INVAL; + if (!(htb->ch_mask & SCH_HTB_HAS_RATE)) + return -NLE_NOATTR; + *out_rate64 = htb->ch_rate.rs_rate64; return 0; } @@ -400,13 +460,26 @@ uint32_t rtnl_htb_get_rate(struct rtnl_class *class) */ int rtnl_htb_set_rate(struct rtnl_class *class, uint32_t rate) { + return rtnl_htb_set_rate64(class, rate); +} + +/** + * Set rate of HTB class + * @arg class htb class object + * @arg rate new rate in bytes per second + * + * @return 0 on success or a negative error code. + */ +int rtnl_htb_set_rate64(struct rtnl_class *class, uint64_t rate) +{ struct rtnl_htb_class *htb; + int err; - if (!(htb = htb_class_data(class))) - return -NLE_OPNOTSUPP; + if (!(htb = htb_class_data(class, &err))) + return err; htb->ch_rate.rs_cell_log = UINT8_MAX; /* use default value */ - htb->ch_rate.rs_rate = rate; + htb->ch_rate.rs_rate64 = rate; htb->ch_mask |= SCH_HTB_HAS_RATE; return 0; @@ -416,15 +489,41 @@ int rtnl_htb_set_rate(struct rtnl_class *class, uint32_t rate) * Return ceil rate of HTB class * @arg class htb class object * - * @return Ceil rate in bytes/s or 0 if unspecified + * @return Ceil rate in bytes/s or 0 if unspecified. If the value + * cannot be represented as 32 bit integer, (1<<32) is returned. + * Use rtnl_htb_get_ceil64() instead. */ uint32_t rtnl_htb_get_ceil(struct rtnl_class *class) { struct rtnl_htb_class *htb; - if ((htb = htb_class_data(class)) && htb->ch_mask & SCH_HTB_HAS_CEIL) - return htb->ch_ceil.rs_rate; + if ( !(htb = htb_class_data(class, NULL)) + || !(htb->ch_mask & SCH_HTB_HAS_CEIL)) + return 0; + if (htb->ch_ceil.rs_rate64 > 0xFFFFFFFFull) + return 0xFFFFFFFFull; + + return htb->ch_ceil.rs_rate64; +} + +/** + * Return ceil rate of HTB class + * @arg class htb class object + * @arg out_ceil64 on success, the set ceil value. + * + * @return 0 on success or a negative error code. + */ +int rtnl_htb_get_ceil64(struct rtnl_class *class, uint64_t *out_ceil64) +{ + struct rtnl_htb_class *htb; + + if (!(htb = htb_class_data(class, NULL))) + return -NLE_INVAL; + if (!(htb->ch_mask & SCH_HTB_HAS_CEIL)) + return -NLE_NOATTR; + + *out_ceil64 = htb->ch_ceil.rs_rate64; return 0; } @@ -437,13 +536,26 @@ uint32_t rtnl_htb_get_ceil(struct rtnl_class *class) */ int rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil) { + return rtnl_htb_set_ceil64(class, ceil); +} + +/** + * Set ceil rate of HTB class + * @arg class htb class object + * @arg ceil64 new ceil rate number of bytes per second + * + * @return 0 on success or a negative error code. + */ +int rtnl_htb_set_ceil64(struct rtnl_class *class, uint64_t ceil64) +{ struct rtnl_htb_class *htb; + int err; - if (!(htb = htb_class_data(class))) - return -NLE_OPNOTSUPP; + if (!(htb = htb_class_data(class, &err))) + return err; htb->ch_ceil.rs_cell_log = UINT8_MAX; /* use default value */ - htb->ch_ceil.rs_rate = ceil; + htb->ch_ceil.rs_rate64 = ceil64; htb->ch_mask |= SCH_HTB_HAS_CEIL; return 0; @@ -459,7 +571,7 @@ uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *class) { struct rtnl_htb_class *htb; - if ((htb = htb_class_data(class)) && + if ((htb = htb_class_data(class, NULL)) && htb->ch_mask & SCH_HTB_HAS_RBUFFER) return htb->ch_rbuffer; @@ -474,9 +586,10 @@ uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *class) int rtnl_htb_set_rbuffer(struct rtnl_class *class, uint32_t rbuffer) { struct rtnl_htb_class *htb; + int err; - if (!(htb = htb_class_data(class))) - return -NLE_OPNOTSUPP; + if (!(htb = htb_class_data(class, &err))) + return err; htb->ch_rbuffer = rbuffer; htb->ch_mask |= SCH_HTB_HAS_RBUFFER; @@ -494,7 +607,7 @@ uint32_t rtnl_htb_get_cbuffer(struct rtnl_class *class) { struct rtnl_htb_class *htb; - if ((htb = htb_class_data(class)) && + if ((htb = htb_class_data(class, NULL)) && htb->ch_mask & SCH_HTB_HAS_CBUFFER) return htb->ch_cbuffer; @@ -509,9 +622,10 @@ uint32_t rtnl_htb_get_cbuffer(struct rtnl_class *class) int rtnl_htb_set_cbuffer(struct rtnl_class *class, uint32_t cbuffer) { struct rtnl_htb_class *htb; + int err; - if (!(htb = htb_class_data(class))) - return -NLE_OPNOTSUPP; + if (!(htb = htb_class_data(class, &err))) + return err; htb->ch_cbuffer = cbuffer; htb->ch_mask |= SCH_HTB_HAS_CBUFFER; @@ -531,7 +645,7 @@ uint32_t rtnl_htb_get_quantum(struct rtnl_class *class) { struct rtnl_htb_class *htb; - if ((htb = htb_class_data(class)) && + if ((htb = htb_class_data(class, NULL)) && htb->ch_mask & SCH_HTB_HAS_QUANTUM) return htb->ch_quantum; @@ -550,9 +664,10 @@ uint32_t rtnl_htb_get_quantum(struct rtnl_class *class) int rtnl_htb_set_quantum(struct rtnl_class *class, uint32_t quantum) { struct rtnl_htb_class *htb; + int err; - if (!(htb = htb_class_data(class))) - return -NLE_OPNOTSUPP; + if (!(htb = htb_class_data(class, &err))) + return err; htb->ch_quantum = quantum; htb->ch_mask |= SCH_HTB_HAS_QUANTUM; @@ -568,16 +683,18 @@ int rtnl_htb_set_quantum(struct rtnl_class *class, uint32_t quantum) * 0, root classes have level (TC_HTB_MAXDEPTH - 1). Interior classes * have a level of one less than their parent. * - * @return Level or -NLE_OPNOTSUPP + * @return Level or a negative error code. */ int rtnl_htb_get_level(struct rtnl_class *class) { struct rtnl_htb_class *htb; + int err = -NLE_OPNOTSUPP; - if ((htb = htb_class_data(class)) && htb->ch_mask & SCH_HTB_HAS_LEVEL) + if ((htb = htb_class_data(class, &err)) && + (htb->ch_mask & SCH_HTB_HAS_LEVEL)) return htb->ch_level; - return -NLE_OPNOTSUPP; + return err; } /** @@ -595,9 +712,10 @@ int rtnl_htb_get_level(struct rtnl_class *class) int rtnl_htb_set_level(struct rtnl_class *class, int level) { struct rtnl_htb_class *htb; + int err; - if (!(htb = htb_class_data(class))) - return -NLE_OPNOTSUPP; + if (!(htb = htb_class_data(class, &err))) + return err; htb->ch_level = level; htb->ch_mask |= SCH_HTB_HAS_LEVEL; @@ -628,13 +746,13 @@ static struct rtnl_tc_ops htb_class_ops = { .to_msg_fill = htb_class_msg_fill, }; -static void __init htb_init(void) +static void _nl_init htb_init(void) { rtnl_tc_register(&htb_qdisc_ops); rtnl_tc_register(&htb_class_ops); } -static void __exit htb_exit(void) +static void _nl_exit htb_exit(void) { rtnl_tc_unregister(&htb_qdisc_ops); rtnl_tc_unregister(&htb_class_ops); diff --git a/lib/route/qdisc/ingress.c b/lib/route/qdisc/ingress.c new file mode 100644 index 0000000..5363c26 --- /dev/null +++ b/lib/route/qdisc/ingress.c @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Cong Wang + */ + +/** + * @ingroup qdisc + * @defgroup qdisc_ingress Ingress qdisc + * + * @{ + */ + +#include "nl-default.h" + +#include +#include +#include + +#include "tc-api.h" + +struct dumb { + uint32_t foo; +}; + +static int dumb_msg_parser(struct rtnl_tc *tc, void *data) +{ + return 0; +} + +static void dumb_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ +} + +static int dumb_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + return 0; +} + +static struct rtnl_tc_ops ingress_ops = { + .to_kind = "ingress", + .to_type = RTNL_TC_TYPE_QDISC, + .to_size = sizeof(struct dumb), + .to_msg_parser = dumb_msg_parser, + .to_dump[NL_DUMP_LINE] = dumb_dump_line, + .to_msg_fill = dumb_msg_fill, +}; + +static void _nl_init ingress_init(void) +{ + rtnl_tc_register(&ingress_ops); +} + +static void _nl_exit ingress_exit(void) +{ + rtnl_tc_unregister(&ingress_ops); +} + +/** @} */ diff --git a/lib/route/qdisc/mqprio.c b/lib/route/qdisc/mqprio.c new file mode 100644 index 0000000..5e9d08f --- /dev/null +++ b/lib/route/qdisc/mqprio.c @@ -0,0 +1,618 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2018 Volodymyr Bendiuga + */ + +#include "nl-default.h" + +#include +#include +#include +#include + +#include "tc-api.h" + +/** @cond SKIP */ +struct rtnl_mqprio { + uint8_t qm_num_tc; + uint8_t qm_prio_map[TC_QOPT_BITMASK + 1]; + uint8_t qm_hw; + uint16_t qm_count[TC_QOPT_MAX_QUEUE]; + uint16_t qm_offset[TC_QOPT_MAX_QUEUE]; + uint16_t qm_mode; + uint16_t qm_shaper; + uint64_t qm_min_rate[TC_QOPT_MAX_QUEUE]; + uint64_t qm_max_rate[TC_QOPT_MAX_QUEUE]; + uint32_t qm_mask; +}; + +#define SCH_MQPRIO_ATTR_NUMTC (1 << 0) +#define SCH_MQPRIO_ATTR_PRIOMAP (1 << 1) +#define SCH_MQPRIO_ATTR_HW (1 << 2) +#define SCH_MQPRIO_ATTR_QUEUE (1 << 3) +#define SCH_MQPRIO_ATTR_MODE (1 << 4) +#define SCH_MQPRIO_ATTR_SHAPER (1 << 5) +#define SCH_MQPRIO_ATTR_MIN_RATE (1 << 6) +#define SCH_MQPRIO_ATTR_MAX_RATE (1 << 7) +/** @endcond */ + +static struct nla_policy mqprio_policy[TCA_MQPRIO_MAX + 1] = { + [TCA_MQPRIO_MODE] = { .minlen = sizeof(uint16_t) }, + [TCA_MQPRIO_SHAPER] = { .minlen = sizeof(uint16_t) }, + [TCA_MQPRIO_MIN_RATE64] = { .type = NLA_NESTED }, + [TCA_MQPRIO_MAX_RATE64] = { .type = NLA_NESTED }, +}; + +static int mqprio_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct rtnl_mqprio *mqprio = data; + struct tc_mqprio_qopt *qopt; + struct nlattr *attr; + int len, rem, i, err; + + if (tc->tc_opts->d_size < sizeof(*qopt)) + return -NLE_INVAL; + + qopt = (struct tc_mqprio_qopt *) tc->tc_opts->d_data; + mqprio->qm_num_tc = qopt->num_tc; + mqprio->qm_hw = qopt->hw; + memcpy(mqprio->qm_prio_map, qopt->prio_tc_map, + TC_QOPT_MAX_QUEUE * sizeof(uint8_t)); + memcpy(mqprio->qm_count, qopt->count, + TC_QOPT_MAX_QUEUE * sizeof(uint16_t)); + memcpy(mqprio->qm_offset, qopt->offset, + TC_QOPT_MAX_QUEUE * sizeof(uint16_t)); + mqprio->qm_mask = (SCH_MQPRIO_ATTR_NUMTC | SCH_MQPRIO_ATTR_PRIOMAP | + SCH_MQPRIO_ATTR_QUEUE | SCH_MQPRIO_ATTR_HW); + + len = tc->tc_opts->d_size - NLA_ALIGN(sizeof(*qopt)); + + if (len > 0) { + struct nlattr *tb[TCA_MQPRIO_MAX + 1]; + + err = nla_parse(tb, TCA_MQPRIO_MAX, (struct nlattr *) + ((char *) tc->tc_opts->d_data + NLA_ALIGN(sizeof(*qopt))), + len, mqprio_policy); + if (err < 0) + return err; + + if (tb[TCA_MQPRIO_MODE]) { + mqprio->qm_mode = nla_get_u16(tb[TCA_MQPRIO_MODE]); + mqprio->qm_mask |= SCH_MQPRIO_ATTR_MODE; + } + + if (tb[TCA_MQPRIO_SHAPER]) { + mqprio->qm_shaper = nla_get_u16(tb[TCA_MQPRIO_SHAPER]); + mqprio->qm_mask |= SCH_MQPRIO_ATTR_SHAPER; + } + + if (tb[TCA_MQPRIO_MIN_RATE64]) { + i = 0; + nla_for_each_nested(attr, tb[TCA_MQPRIO_MIN_RATE64], rem) { + if (nla_type(attr) != TCA_MQPRIO_MIN_RATE64) + return -EINVAL; + + if (i >= mqprio->qm_num_tc) + break; + + mqprio->qm_min_rate[i] = nla_get_u64(attr); + } + + mqprio->qm_mask |= SCH_MQPRIO_ATTR_MIN_RATE; + } + + if (tb[TCA_MQPRIO_MAX_RATE64]) { + i = 0; + nla_for_each_nested(attr, tb[TCA_MQPRIO_MAX_RATE64], rem) { + if (nla_type(attr) != TCA_MQPRIO_MAX_RATE64) + return -EINVAL; + + if (i >= mqprio->qm_num_tc) + break; + + mqprio->qm_max_rate[i] = nla_get_u64(attr); + } + + mqprio->qm_mask |= SCH_MQPRIO_ATTR_MAX_RATE; + } + } + + return 0; +} + +static int mqprio_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + struct rtnl_mqprio *mqprio = data; + struct tc_mqprio_qopt qopt = { 0 }; + struct nlattr *nest = NULL; + int i; + + if (!mqprio || + !(mqprio->qm_mask & SCH_MQPRIO_ATTR_NUMTC) || + !(mqprio->qm_mask & SCH_MQPRIO_ATTR_PRIOMAP) || + !(mqprio->qm_mask & SCH_MQPRIO_ATTR_QUEUE)) + return -NLE_INVAL; + + if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_HW)) + qopt.hw = 0; + else + qopt.hw = mqprio->qm_hw; + + qopt.num_tc = mqprio->qm_num_tc; + memcpy(qopt.count, mqprio->qm_count, TC_QOPT_MAX_QUEUE * sizeof(uint16_t)); + memcpy(qopt.offset, mqprio->qm_offset, TC_QOPT_MAX_QUEUE * sizeof(uint16_t)); + memcpy(qopt.prio_tc_map, mqprio->qm_prio_map, TC_QOPT_MAX_QUEUE * sizeof(uint8_t)); + + nlmsg_append(msg, &qopt, sizeof(qopt), NL_DONTPAD); + + if (mqprio->qm_hw) { + if (mqprio->qm_mask & SCH_MQPRIO_ATTR_MODE) + NLA_PUT_U16(msg, TCA_MQPRIO_MODE, mqprio->qm_mode); + + if (mqprio->qm_mask & SCH_MQPRIO_ATTR_SHAPER) + NLA_PUT_U16(msg, TCA_MQPRIO_SHAPER, mqprio->qm_shaper); + + if (mqprio->qm_mask & SCH_MQPRIO_ATTR_MIN_RATE) { + nest = nla_nest_start(msg, TCA_MQPRIO_MIN_RATE64); + if (!nest) + goto nla_put_failure; + + for (i = 0; i < mqprio->qm_num_tc; i++) { + if (nla_put(msg, TCA_MQPRIO_MIN_RATE64, + sizeof(mqprio->qm_min_rate[i]), + &mqprio->qm_min_rate[i]) < 0) + goto nla_nest_cancel; + } + nla_nest_end(msg, nest); + } + + if (mqprio->qm_mask & SCH_MQPRIO_ATTR_MAX_RATE) { + nest = nla_nest_start(msg, TCA_MQPRIO_MAX_RATE64); + if (!nest) + goto nla_put_failure; + + for (i = 0; i < mqprio->qm_num_tc; i++) { + if (nla_put(msg, TCA_MQPRIO_MAX_RATE64, + sizeof(mqprio->qm_max_rate[i]), + &mqprio->qm_max_rate[i]) < 0) + goto nla_nest_cancel; + } + nla_nest_end(msg, nest); + } + } + + return 0; + +nla_nest_cancel: + nla_nest_cancel(msg, nest); + return -NLE_MSGSIZE; + +nla_put_failure: + return -NLE_MSGSIZE; +} + +static void mqprio_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_mqprio *mqprio = data; + + if (mqprio) + nl_dump(p, " num_tc %u", mqprio->qm_num_tc); +} + +static void mqprio_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_mqprio *mqprio = data; + int i; + + if (!mqprio) + return; + + nl_dump(p, "map ["); + + for (i = 0; i <= TC_QOPT_BITMASK; i++) + nl_dump(p, "%u%s", mqprio->qm_prio_map[i], + i < TC_QOPT_BITMASK ? " " : ""); + + nl_dump(p, "]\n"); + nl_new_line(p); +} + +/** + * @name Attribute Modification + * @{ + */ + +/** + * Set number of traffic classes. + * @arg qdisc MQPRIO qdisc to be modified. + * @arg num_tc Number of traffic classes to create. + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_mqprio_set_num_tc(struct rtnl_qdisc *qdisc, int num_tc) +{ + struct rtnl_mqprio *mqprio; + + if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + mqprio->qm_num_tc = num_tc; + mqprio->qm_mask |= SCH_MQPRIO_ATTR_NUMTC; + return 0; +} + +/** + * Get number of traffic classes of MQPRIO qdisc. + * @arg qdisc MQPRIO qdisc. + * @return Number of traffic classes or a negative error code. + */ +int rtnl_qdisc_mqprio_get_num_tc(struct rtnl_qdisc *qdisc) +{ + struct rtnl_mqprio *mqprio; + + if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc)))) + return -NLE_INVAL; + + if (mqprio->qm_mask & SCH_MQPRIO_ATTR_NUMTC) + return mqprio->qm_num_tc; + else + return -NLE_MISSING_ATTR; +} + +/** + * Set priomap of the MQPRIO qdisc. + * @arg qdisc MQPRIO qdisc to be modified. + * @arg priomap New priority mapping. + * @arg len Length of priomap (# of elements). + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_mqprio_set_priomap(struct rtnl_qdisc *qdisc, uint8_t priomap[], + int len) +{ + struct rtnl_mqprio *mqprio; + int i; + + if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_NUMTC)) + return -NLE_MISSING_ATTR; + + if (len > TC_QOPT_BITMASK + 1) + return -NLE_RANGE; + + for (i = 0; i < len; i++) { + if (priomap[i] > mqprio->qm_num_tc) + return -NLE_RANGE; + } + + memset(mqprio->qm_prio_map, 0, sizeof(mqprio->qm_prio_map)); + memcpy(mqprio->qm_prio_map, priomap, len * sizeof(uint8_t)); + mqprio->qm_mask |= SCH_MQPRIO_ATTR_PRIOMAP; + + return 0; +} + +/** + * Get priomap of MQPRIO qdisc. + * @arg qdisc MQPRIO qdisc. + * @return Priority mapping as array of size TC_QOPT_BANDS+1 + * or NULL if an error occured. + */ +uint8_t *rtnl_qdisc_mqprio_get_priomap(struct rtnl_qdisc *qdisc) +{ + struct rtnl_mqprio *mqprio; + + if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc)))) + return NULL; + + if (mqprio->qm_mask & SCH_MQPRIO_ATTR_PRIOMAP) + return mqprio->qm_prio_map; + else + return NULL; +} + +/** + * Offload to HW or run in SW (default). + * @arg qdisc MQPRIO qdisc to be modified. + * @arg offload 1 - offload to HW, 0 - run in SW only (default). + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_mqprio_hw_offload(struct rtnl_qdisc *qdisc, int offload) +{ + struct rtnl_mqprio *mqprio; + + if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + switch (offload) { + case 0: + case 1: + mqprio->qm_hw = offload; + break; + default: + return -NLE_INVAL; + } + + mqprio->qm_mask |= SCH_MQPRIO_ATTR_HW; + return 0; +} + +/** + * Check whether running in HW or SW. + * @arg qdisc MQPRIO qdisc to be modified. + * @return 0 if running in SW, otherwise 1 (HW) + */ +int rtnl_qdisc_mqprio_get_hw_offload(struct rtnl_qdisc *qdisc) +{ + struct rtnl_mqprio *mqprio; + + if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc)))) + return -NLE_INVAL; + + if (mqprio->qm_mask & SCH_MQPRIO_ATTR_HW) + return mqprio->qm_hw; + + return 0; +} + +/** + * Set tc queue of the MQPRIO qdisc. + * @arg qdisc MQPRIO qdisc to be modified. + * @arg count count of queue range for each traffic class + * @arg offset offset of queue range for each traffic class + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_mqprio_set_queue(struct rtnl_qdisc *qdisc, uint16_t count[], + uint16_t offset[], int len) +{ + struct rtnl_mqprio *mqprio; + + if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_NUMTC)) + return -NLE_MISSING_ATTR; + + if (len < 0 || len > TC_QOPT_MAX_QUEUE) + return -NLE_RANGE; + + memset(mqprio->qm_count, 0, sizeof(mqprio->qm_count)); + memset(mqprio->qm_offset, 0, sizeof(mqprio->qm_offset)); + memcpy(mqprio->qm_count, count, len * sizeof(uint16_t)); + memcpy(mqprio->qm_offset, offset, len * sizeof(uint16_t)); + mqprio->qm_mask |= SCH_MQPRIO_ATTR_QUEUE; + + return 0; +} + +/** + * Get tc queue of the MQPRIO qdisc. + * @arg qdisc MQPRIO qdisc to be modified. + * @arg count count of queue range for each traffic class + * @arg offset offset of queue range for each traffic class + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_mqprio_get_queue(struct rtnl_qdisc *qdisc, uint16_t *count, + uint16_t *offset) +{ + struct rtnl_mqprio *mqprio; + + if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc)))) + return -NLE_INVAL; + + if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_QUEUE)) + return -NLE_MISSING_ATTR; + + memcpy(count, mqprio->qm_count, TC_QOPT_MAX_QUEUE * sizeof(uint16_t)); + memcpy(offset, mqprio->qm_offset, TC_QOPT_MAX_QUEUE * sizeof(uint16_t)); + + return 0; +} + +/** + * Set mode of mqprio Qdisc + * @arg qdisc MQPRIO qdisc to be modified. + * @arg mode one of: TC_MQPRIO_MODE_DCB, TC_MQPRIO_MODE_CHANNEL + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_mqprio_set_mode(struct rtnl_qdisc *qdisc, uint16_t mode) +{ + struct rtnl_mqprio *mqprio; + + if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_HW)) + return -NLE_MISSING_ATTR; + + mqprio->qm_mode = mode; + mqprio->qm_mask |= SCH_MQPRIO_ATTR_MODE; + + return 0; +} + +/** + * Get mode of mqprio Qdisc + * @arg qdisc MQPRIO qdisc. + * @return mode on success or negative error code. + */ +int rtnl_qdisc_mqprio_get_mode(struct rtnl_qdisc *qdisc) +{ + struct rtnl_mqprio *mqprio; + + if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc)))) + return -NLE_INVAL; + + if (mqprio->qm_mask & SCH_MQPRIO_ATTR_MODE) + return mqprio->qm_mode; + else + return -NLE_MISSING_ATTR; +} + +/** + * Set shaper of mqprio Qdisc + * @arg qdisc MQPRIO qdisc to be modified. + * @arg shaper one of: TC_MQPRIO_SHAPER_DCB, TC_MQPRIO_SHAPER_BW_RATE + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_mqprio_set_shaper(struct rtnl_qdisc *qdisc, uint16_t shaper) +{ + struct rtnl_mqprio *mqprio; + + if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_HW)) + return -NLE_MISSING_ATTR; + + mqprio->qm_shaper = shaper; + mqprio->qm_mask |= SCH_MQPRIO_ATTR_SHAPER; + + return 0; +} + +/** + * Get shaper of mqprio Qdisc + * @arg qdisc MQPRIO qdisc. + * @return shaper on success or negative error code. + */ +int rtnl_qdisc_mqprio_get_shaper(struct rtnl_qdisc *qdisc) +{ + struct rtnl_mqprio *mqprio; + + if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc)))) + return -NLE_INVAL; + + if (mqprio->qm_mask & SCH_MQPRIO_ATTR_SHAPER) + return mqprio->qm_shaper; + else + return -NLE_MISSING_ATTR; +} + +/** + * Set minimum value of bandwidth rate limit for each traffic class + * @arg qdisc MQPRIO qdisc. + * @arg min minimum rate for each traffic class + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_mqprio_set_min_rate(struct rtnl_qdisc *qdisc, uint64_t min[], int len) +{ + struct rtnl_mqprio *mqprio; + + if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_SHAPER)) + return -NLE_MISSING_ATTR; + + if (mqprio->qm_shaper != TC_MQPRIO_SHAPER_BW_RATE) + return -NLE_INVAL; + + if (len < 0 || len > TC_QOPT_MAX_QUEUE) + return -NLE_RANGE; + + memset(mqprio->qm_min_rate, 0, sizeof(mqprio->qm_min_rate)); + memcpy(mqprio->qm_min_rate, min, len * sizeof(uint64_t)); + mqprio->qm_mask |= SCH_MQPRIO_ATTR_MIN_RATE; + + return 0; +} + +/** + * Get minimum value of bandwidth rate limit for each traffic class + * @arg qdisc MQPRIO qdisc. + * @arg min minimum rate for each traffic class + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_mqprio_get_min_rate(struct rtnl_qdisc *qdisc, uint64_t *min) +{ + struct rtnl_mqprio *mqprio; + + if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc)))) + return -NLE_INVAL; + + if (mqprio->qm_mask & SCH_MQPRIO_ATTR_MIN_RATE) { + memcpy(min, mqprio->qm_min_rate, TC_QOPT_MAX_QUEUE * sizeof(uint64_t)); + return 0; + } + + return -NLE_MISSING_ATTR; +} + +/** + * Set maximum value of bandwidth rate limit for each traffic class + * @arg qdisc MQPRIO qdisc. + * @arg max maximum rate for each traffic class + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_mqprio_set_max_rate(struct rtnl_qdisc *qdisc, uint64_t max[], int len) +{ + struct rtnl_mqprio *mqprio; + + if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc)))) + return -NLE_NOMEM; + + if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_SHAPER)) + return -NLE_MISSING_ATTR; + + if (mqprio->qm_shaper != TC_MQPRIO_SHAPER_BW_RATE) + return -NLE_INVAL; + + if (len < 0 || len > TC_QOPT_MAX_QUEUE) + return -NLE_RANGE; + + memset(mqprio->qm_max_rate, 0, sizeof(mqprio->qm_max_rate)); + memcpy(mqprio->qm_max_rate, max, len * sizeof(uint64_t)); + mqprio->qm_mask |= SCH_MQPRIO_ATTR_MAX_RATE; + + return 0; +} + +/** + * Get maximum value of bandwidth rate limit for each traffic class + * @arg qdisc MQPRIO qdisc. + * @arg min maximum rate for each traffic class + * @return 0 on success or a negative error code. + */ +int rtnl_qdisc_mqprio_get_max_rate(struct rtnl_qdisc *qdisc, uint64_t *max) +{ + struct rtnl_mqprio *mqprio; + + if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc)))) + return -NLE_INVAL; + + if (mqprio->qm_mask & SCH_MQPRIO_ATTR_MAX_RATE) { + memcpy(max, mqprio->qm_max_rate, TC_QOPT_MAX_QUEUE * sizeof(uint64_t)); + return 0; + } + + return -NLE_MISSING_ATTR; +} + +/** @} */ + +static struct rtnl_tc_ops mqprio_ops = { + .to_kind = "mqprio", + .to_type = RTNL_TC_TYPE_QDISC, + .to_size = sizeof(struct rtnl_mqprio), + .to_msg_parser = mqprio_msg_parser, + .to_dump = { + [NL_DUMP_LINE] = mqprio_dump_line, + [NL_DUMP_DETAILS] = mqprio_dump_details, + }, + .to_msg_fill = mqprio_msg_fill, +}; + +static void _nl_init mqprio_init(void) +{ + rtnl_tc_register(&mqprio_ops); +} + +static void _nl_exit mqprio_exit(void) +{ + rtnl_tc_unregister(&mqprio_ops); +} + +/** @} */ diff --git a/lib/route/qdisc/netem.c b/lib/route/qdisc/netem.c index 06d9fe8..6dde4f0 100644 --- a/lib/route/qdisc/netem.c +++ b/lib/route/qdisc/netem.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/qdisc/netem.c Network Emulator Qdisc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf */ @@ -18,19 +12,56 @@ * @{ */ -#include -#include +#include "nl-default.h" + #include #include -#include #include #include +#include "tc-api.h" +#include "nl-priv-dynamic-core/nl-core.h" + /** @cond SKIP */ +struct rtnl_netem_corr { + uint32_t nmc_delay; + uint32_t nmc_loss; + uint32_t nmc_duplicate; +}; + +struct rtnl_netem_reo { + uint32_t nmro_probability; + uint32_t nmro_correlation; +}; + +struct rtnl_netem_crpt { + uint32_t nmcr_probability; + uint32_t nmcr_correlation; +}; + +struct rtnl_netem_dist { + int16_t *dist_data; + size_t dist_size; +}; + +struct rtnl_netem { + uint32_t qnm_latency; + uint32_t qnm_limit; + uint32_t qnm_loss; + uint32_t qnm_gap; + uint32_t qnm_duplicate; + uint32_t qnm_jitter; + uint32_t qnm_mask; + struct rtnl_netem_corr qnm_corr; + struct rtnl_netem_reo qnm_ro; + struct rtnl_netem_crpt qnm_crpt; + struct rtnl_netem_dist qnm_dist; +}; + #define SCH_NETEM_ATTR_LATENCY 0x0001 #define SCH_NETEM_ATTR_LIMIT 0x0002 -#define SCH_NETEM_ATTR_LOSS 0x0004 -#define SCH_NETEM_ATTR_GAP 0x0008 +#define SCH_NETEM_ATTR_LOSS 0x0004 +#define SCH_NETEM_ATTR_GAP 0x0008 #define SCH_NETEM_ATTR_DUPLICATE 0x0010 #define SCH_NETEM_ATTR_JITTER 0x0020 #define SCH_NETEM_ATTR_DELAY_CORR 0x0040 @@ -40,7 +71,7 @@ #define SCH_NETEM_ATTR_RO_CORR 0x0400 #define SCH_NETEM_ATTR_CORRUPT_PROB 0x0800 #define SCH_NETEM_ATTR_CORRUPT_CORR 0x1000 -#define SCH_NETEM_ATTR_DIST 0x2000 +#define SCH_NETEM_ATTR_DIST 0x2000 /** @endcond */ static struct nla_policy netem_policy[TCA_NETEM_MAX+1] = { @@ -76,7 +107,7 @@ static int netem_msg_parser(struct rtnl_tc *tc, void *data) struct nlattr *tb[TCA_NETEM_MAX+1]; err = nla_parse(tb, TCA_NETEM_MAX, (struct nlattr *) - (tc->tc_opts->d_data + sizeof(*opts)), + ((char *) tc->tc_opts->d_data + sizeof(*opts)), len, netem_policy); if (err < 0) { free(netem); @@ -106,18 +137,18 @@ static int netem_msg_parser(struct rtnl_tc *tc, void *data) netem->qnm_mask |= (SCH_NETEM_ATTR_RO_PROB | SCH_NETEM_ATTR_RO_CORR); } - + if (tb[TCA_NETEM_CORRUPT]) { struct tc_netem_corrupt corrupt; - + nla_memcpy(&corrupt, tb[TCA_NETEM_CORRUPT], sizeof(corrupt)); netem->qnm_crpt.nmcr_probability = corrupt.probability; netem->qnm_crpt.nmcr_correlation = corrupt.correlation; - + netem->qnm_mask |= (SCH_NETEM_ATTR_CORRUPT_PROB | SCH_NETEM_ATTR_CORRUPT_CORR); } - + /* sch_netem does not currently dump TCA_NETEM_DELAY_DIST */ netem->qnm_dist.dist_data = NULL; netem->qnm_dist.dist_size = 0; @@ -129,10 +160,10 @@ static int netem_msg_parser(struct rtnl_tc *tc, void *data) static void netem_free_data(struct rtnl_tc *tc, void *data) { struct rtnl_netem *netem = data; - + if (!netem) return; - + free(netem->qnm_dist.dist_data); } @@ -141,12 +172,69 @@ static void netem_dump_line(struct rtnl_tc *tc, void *data, { struct rtnl_netem *netem = data; - if (netem) - nl_dump(p, "limit %d", netem->qnm_limit); + if (netem) { + if (netem->qnm_mask & SCH_NETEM_ATTR_LIMIT && netem->qnm_limit > 0) + nl_dump(p, " limit %dpkts", netem->qnm_limit); + else + nl_dump(p, " no limit"); + } +} + +static void netem_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_netem *netem = data; + char buf[32]; + + if (netem) { + if (netem->qnm_mask & SCH_NETEM_ATTR_LATENCY && netem->qnm_latency > 0) { + nl_msec2str(nl_ticks2us(netem->qnm_latency) / 1000, buf, sizeof(buf)); + nl_dump(p, " latency %s", buf); + + if (netem->qnm_mask & SCH_NETEM_ATTR_JITTER && netem->qnm_jitter > 0) { + nl_msec2str(nl_ticks2us(netem->qnm_jitter) / 1000, buf, sizeof(buf)); + nl_dump(p, " jitter %s", buf); + + if (netem->qnm_mask & SCH_NETEM_ATTR_DELAY_CORR && netem->qnm_corr.nmc_delay > 0) + nl_dump(p, " %d", netem->qnm_corr.nmc_delay); + } + } + + if (netem->qnm_mask & SCH_NETEM_ATTR_LOSS && netem->qnm_loss > 0) { + nl_dump(p, " loss %d", netem->qnm_loss); + + if (netem->qnm_mask & SCH_NETEM_ATTR_LOSS_CORR && netem->qnm_corr.nmc_loss > 0) + nl_dump(p, " %d", netem->qnm_corr.nmc_loss); + } + + if (netem->qnm_mask & SCH_NETEM_ATTR_DUPLICATE && netem->qnm_duplicate > 0) { + nl_dump(p, " duplicate %d", netem->qnm_duplicate); + + if (netem->qnm_mask & SCH_NETEM_ATTR_DUP_CORR && netem->qnm_corr.nmc_duplicate > 0) + nl_dump(p, " %d", netem->qnm_corr.nmc_duplicate); + } + + if (netem->qnm_mask & SCH_NETEM_ATTR_RO_PROB && netem->qnm_ro.nmro_probability > 0) { + nl_dump(p, " reorder %d", netem->qnm_ro.nmro_probability); + + if (netem->qnm_mask & SCH_NETEM_ATTR_RO_CORR && netem->qnm_ro.nmro_correlation > 0) + nl_dump(p, " %d", netem->qnm_ro.nmro_correlation); + + if (netem->qnm_mask & SCH_NETEM_ATTR_GAP && netem->qnm_gap > 0) + nl_dump(p, " gap %d", netem->qnm_gap); + } + + if (netem->qnm_mask & SCH_NETEM_ATTR_CORRUPT_PROB && netem->qnm_crpt.nmcr_probability > 0) { + nl_dump(p, " reorder %d", netem->qnm_crpt.nmcr_probability); + + if (netem->qnm_mask & SCH_NETEM_ATTR_CORRUPT_CORR && netem->qnm_crpt.nmcr_correlation > 0) + nl_dump(p, " %d", netem->qnm_crpt.nmcr_correlation); + } + } } static int netem_msg_fill_raw(struct rtnl_tc *tc, void *data, - struct nl_msg *msg) + struct nl_msg *msg) { int err = 0; struct tc_netem_qopt opts; @@ -154,9 +242,13 @@ static int netem_msg_fill_raw(struct rtnl_tc *tc, void *data, struct tc_netem_reorder reorder; struct tc_netem_corrupt corrupt; struct rtnl_netem *netem = data; - - unsigned char set_correlation = 0, set_reorder = 0, - set_corrupt = 0, set_dist = 0; + + unsigned char set_correlation = 0, set_reorder = 0; + unsigned char set_corrupt = 0, set_dist = 0; + + struct nlattr* head; + struct nlattr* tail; + int old_len; if (!netem) BUG(); @@ -167,116 +259,111 @@ static int netem_msg_fill_raw(struct rtnl_tc *tc, void *data, memset(&corrupt, 0, sizeof(corrupt)); msg->nm_nlh->nlmsg_flags |= NLM_F_REQUEST; - - if ( netem->qnm_ro.nmro_probability != 0 ) { - if (netem->qnm_latency == 0) { + + if (netem->qnm_ro.nmro_probability != 0) { + if (netem->qnm_latency == 0) return -NLE_MISSING_ATTR; - } - if (netem->qnm_gap == 0) netem->qnm_gap = 1; - } - else if ( netem->qnm_gap ) { + if (netem->qnm_gap == 0) + netem->qnm_gap = 1; + } else if (netem->qnm_gap) return -NLE_MISSING_ATTR; - } - if ( netem->qnm_corr.nmc_delay != 0 ) { - if ( netem->qnm_latency == 0 || netem->qnm_jitter == 0) { + if (netem->qnm_corr.nmc_delay != 0) { + if (netem->qnm_latency == 0 || netem->qnm_jitter == 0) return -NLE_MISSING_ATTR; - } set_correlation = 1; } - - if ( netem->qnm_corr.nmc_loss != 0 ) { - if ( netem->qnm_loss == 0 ) { + + if (netem->qnm_corr.nmc_loss != 0) { + if (netem->qnm_loss == 0) return -NLE_MISSING_ATTR; - } set_correlation = 1; } - if ( netem->qnm_corr.nmc_duplicate != 0 ) { - if ( netem->qnm_duplicate == 0 ) { + if (netem->qnm_corr.nmc_duplicate != 0) { + if (netem->qnm_duplicate == 0) return -NLE_MISSING_ATTR; - } set_correlation = 1; } - - if ( netem->qnm_ro.nmro_probability != 0 ) set_reorder = 1; - else if ( netem->qnm_ro.nmro_correlation != 0 ) { - return -NLE_MISSING_ATTR; - } - - if ( netem->qnm_crpt.nmcr_probability != 0 ) set_corrupt = 1; - else if ( netem->qnm_crpt.nmcr_correlation != 0 ) { - return -NLE_MISSING_ATTR; - } - - if ( netem->qnm_dist.dist_data && netem->qnm_dist.dist_size ) { - if (netem->qnm_latency == 0 || netem->qnm_jitter == 0) { + + if (netem->qnm_ro.nmro_probability != 0) + set_reorder = 1; + else if (netem->qnm_ro.nmro_correlation != 0) + return -NLE_MISSING_ATTR; + + if (netem->qnm_crpt.nmcr_probability != 0) + set_corrupt = 1; + else if (netem->qnm_crpt.nmcr_correlation != 0) + return -NLE_MISSING_ATTR; + + if (netem->qnm_dist.dist_data && netem->qnm_dist.dist_size) { + if (netem->qnm_latency == 0 || netem->qnm_jitter == 0) return -NLE_MISSING_ATTR; - } - else { - /* Resize to accomodate the large distribution table */ - int new_msg_len = msg->nm_size + netem->qnm_dist.dist_size * - sizeof(netem->qnm_dist.dist_data[0]); - - msg->nm_nlh = (struct nlmsghdr *) realloc(msg->nm_nlh, new_msg_len); - if ( msg->nm_nlh == NULL ) - return -NLE_NOMEM; - msg->nm_size = new_msg_len; + else { + /* Resize to accomodate the large distribution table */ + int new_msg_len = msg->nm_size + netem->qnm_dist.dist_size * + sizeof(netem->qnm_dist.dist_data[0]); + struct nlmsghdr *new_nlh = realloc(msg->nm_nlh, new_msg_len); + + if (new_nlh == NULL) + return -NLE_NOMEM; + msg->nm_nlh = new_nlh; + msg->nm_size = new_msg_len; set_dist = 1; } } - + opts.latency = netem->qnm_latency; opts.limit = netem->qnm_limit ? netem->qnm_limit : 1000; opts.loss = netem->qnm_loss; opts.gap = netem->qnm_gap; opts.duplicate = netem->qnm_duplicate; opts.jitter = netem->qnm_jitter; - + NLA_PUT(msg, TCA_OPTIONS, sizeof(opts), &opts); - - if ( set_correlation ) { + + if (set_correlation) { cor.delay_corr = netem->qnm_corr.nmc_delay; cor.loss_corr = netem->qnm_corr.nmc_loss; cor.dup_corr = netem->qnm_corr.nmc_duplicate; NLA_PUT(msg, TCA_NETEM_CORR, sizeof(cor), &cor); } - - if ( set_reorder ) { + + if (set_reorder) { reorder.probability = netem->qnm_ro.nmro_probability; reorder.correlation = netem->qnm_ro.nmro_correlation; NLA_PUT(msg, TCA_NETEM_REORDER, sizeof(reorder), &reorder); } - - if ( set_corrupt ) { + + if (set_corrupt) { corrupt.probability = netem->qnm_crpt.nmcr_probability; corrupt.correlation = netem->qnm_crpt.nmcr_correlation; NLA_PUT(msg, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt); } - - if ( set_dist ) { + + if (set_dist) { NLA_PUT(msg, TCA_NETEM_DELAY_DIST, - netem->qnm_dist.dist_size * sizeof(netem->qnm_dist.dist_data[0]), - netem->qnm_dist.dist_data); + netem->qnm_dist.dist_size * sizeof(netem->qnm_dist.dist_data[0]), + netem->qnm_dist.dist_data); } /* Length specified in the TCA_OPTIONS section must span the entire * remainder of the message. That's just the way that sch_netem expects it. * Maybe there's a more succinct way to do this at a higher level. */ - struct nlattr* head = (struct nlattr *)(NLMSG_DATA(msg->nm_nlh) + - NLMSG_LENGTH(sizeof(struct tcmsg)) - NLMSG_ALIGNTO); - - struct nlattr* tail = (struct nlattr *)(((void *) (msg->nm_nlh)) + - NLMSG_ALIGN(msg->nm_nlh->nlmsg_len)); - - int old_len = head->nla_len; - head->nla_len = (void *)tail - (void *)head; + head = (struct nlattr *)(((char *) NLMSG_DATA(msg->nm_nlh)) + + NLMSG_LENGTH(sizeof(struct tcmsg)) - NLMSG_ALIGNTO); + + tail = (struct nlattr *)(((char *) (msg->nm_nlh)) + + NLMSG_ALIGN(msg->nm_nlh->nlmsg_len)); + + old_len = head->nla_len; + head->nla_len = (char *)tail - (char *)head; msg->nm_nlh->nlmsg_len += (head->nla_len - old_len); - + return err; nla_put_failure: return -NLE_MSGSIZE; @@ -299,7 +386,7 @@ void rtnl_netem_set_limit(struct rtnl_qdisc *qdisc, int limit) if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) BUG(); - + netem->qnm_limit = limit; netem->qnm_mask |= SCH_NETEM_ATTR_LIMIT; } @@ -440,7 +527,7 @@ int rtnl_netem_get_reorder_correlation(struct rtnl_qdisc *qdisc) * @name Corruption * @{ */ - + /** * Set corruption probability of netem qdisc. * @arg qdisc Netem qdisc to be modified. @@ -634,7 +721,7 @@ int rtnl_netem_get_duplicate(struct rtnl_qdisc *qdisc) * Set packet duplication correlation probability of netem qdisc. * @arg qdisc Netem qdisc to be modified. * @arg prob New packet duplication correlation probability. - * @return 0 on sucess or a negative error code. + * @return 0 on success or a negative error code. */ void rtnl_netem_set_duplicate_correlation(struct rtnl_qdisc *qdisc, int prob) { @@ -815,49 +902,85 @@ int rtnl_netem_get_delay_distribution(struct rtnl_qdisc *qdisc, int16_t **dist_p } /** - * Set the delay distribution. Latency/jitter must be set before applying. + * Set the delay distribution data. Latency/jitter must be set before applying. * @arg qdisc Netem qdisc. - * @arg dist_type The name of the distribution (type, file, path/file). * @return 0 on success, error code on failure. */ -int rtnl_netem_set_delay_distribution(struct rtnl_qdisc *qdisc, const char *dist_type) { +int rtnl_netem_set_delay_distribution_data(struct rtnl_qdisc *qdisc, const int16_t *data, size_t len) { struct rtnl_netem *netem; + int16_t *new_data; if (!(netem = rtnl_tc_data(TC_CAST(qdisc)))) BUG(); - + + if (len > MAXDIST) + return -NLE_INVAL; + + new_data = (int16_t *) calloc(len, sizeof(int16_t)); + if (!new_data) + return -NLE_NOMEM; + + free (netem->qnm_dist.dist_data); + netem->qnm_dist.dist_data = new_data; + + memcpy(netem->qnm_dist.dist_data, data, len * sizeof(int16_t)); + + netem->qnm_dist.dist_size = len; + netem->qnm_mask |= SCH_NETEM_ATTR_DIST; + + return 0; +} + +/** + * Load the delay distribution from a file. Latency/jitter must be set before applying. + * @arg qdisc Netem qdisc. + * @arg dist_type The name of the distribution (type, file, path/file). + * @return 0 on success, error code on failure. + */ +int rtnl_netem_set_delay_distribution(struct rtnl_qdisc *qdisc, const char *dist_type) { FILE *f; int n = 0; size_t i; size_t len = 2048; - char *line; + _nl_auto_free char *line = NULL; char name[NAME_MAX]; char dist_suffix[] = ".dist"; - + _nl_auto_free int16_t *data = NULL; + char *test_suffix; + + /* Check several locations for the dist file */ + char *test_path[] = { + "", + "./", + "/usr/lib/tc/", + "/usr/lib64/tc/", + "/usr/local/lib/tc/", + }; + /* If the given filename already ends in .dist, don't append it later */ - char *test_suffix = strstr(dist_type, dist_suffix); + test_suffix = strstr(dist_type, dist_suffix); if (test_suffix != NULL && strlen(test_suffix) == 5) strcpy(dist_suffix, ""); - - /* Check several locations for the dist file */ - char *test_path[] = { "", "./", "/usr/lib/tc/", "/usr/local/lib/tc/" }; - + for (i = 0; i < ARRAY_SIZE(test_path); i++) { snprintf(name, NAME_MAX, "%s%s%s", test_path[i], dist_type, dist_suffix); - if ((f = fopen(name, "r"))) + if ((f = fopen(name, "re"))) break; } - - if ( f == NULL ) + + if (f == NULL) return -nl_syserr2nlerr(errno); - - netem->qnm_dist.dist_data = (int16_t *) calloc (MAXDIST, sizeof(int16_t)); - - line = (char *) calloc (sizeof(char), len + 1); - + + data = (int16_t *) calloc(MAXDIST, sizeof(int16_t)); + line = (char *) calloc(sizeof(char), len + 1); + if (!data || !line) { + fclose(f); + return -NLE_NOMEM; + } + while (getline(&line, &len, f) != -1) { char *p, *endp; - + if (*line == '\n' || *line == '#') continue; @@ -866,21 +989,16 @@ int rtnl_netem_set_delay_distribution(struct rtnl_qdisc *qdisc, const char *dist if (endp == p) break; if (n >= MAXDIST) { - free(line); fclose(f); return -NLE_INVAL; } - netem->qnm_dist.dist_data[n++] = x; - } + data[n++] = x; + } } - - free(line); - - netem->qnm_dist.dist_size = n; - netem->qnm_mask |= SCH_NETEM_ATTR_DIST; - + fclose(f); - return 0; + i = rtnl_netem_set_delay_distribution_data(qdisc, data, n); + return i; } /** @} */ @@ -892,15 +1010,16 @@ static struct rtnl_tc_ops netem_ops = { .to_msg_parser = netem_msg_parser, .to_free_data = netem_free_data, .to_dump[NL_DUMP_LINE] = netem_dump_line, + .to_dump[NL_DUMP_DETAILS] = netem_dump_details, .to_msg_fill_raw = netem_msg_fill_raw, }; -static void __init netem_init(void) +static void _nl_init netem_init(void) { rtnl_tc_register(&netem_ops); } -static void __exit netem_exit(void) +static void _nl_exit netem_exit(void) { rtnl_tc_unregister(&netem_ops); } diff --git a/lib/route/qdisc/plug.c b/lib/route/qdisc/plug.c index 9f53637..f010802 100644 --- a/lib/route/qdisc/plug.c +++ b/lib/route/qdisc/plug.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/qdisc/plug.c PLUG Qdisc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2012 Shriram Rajagopalan */ @@ -60,13 +54,19 @@ * @{ */ -#include -#include +#include "nl-default.h" + #include #include -#include #include +#include "tc-api.h" + +struct rtnl_plug { + int action; + uint32_t limit; +}; + static int plug_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) { struct rtnl_plug *plug = data; @@ -164,12 +164,12 @@ static struct rtnl_tc_ops plug_ops = { .to_msg_fill = plug_msg_fill, }; -static void __init plug_init(void) +static void _nl_init plug_init(void) { rtnl_tc_register(&plug_ops); } -static void __exit plug_exit(void) +static void _nl_exit plug_exit(void) { rtnl_tc_unregister(&plug_ops); } diff --git a/lib/route/qdisc/prio.c b/lib/route/qdisc/prio.c index 54a46f0..e733845 100644 --- a/lib/route/qdisc/prio.c +++ b/lib/route/qdisc/prio.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/qdisc/prio.c PRIO Qdisc/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) 2003-2011 Thomas Graf */ @@ -26,15 +20,22 @@ * @{ */ -#include -#include +#include "nl-default.h" + #include #include -#include #include #include +#include "tc-api.h" + /** @cond SKIP */ +struct rtnl_prio { + uint32_t qp_bands; + uint8_t qp_priomap[TC_PRIO_MAX + 1]; + uint32_t qp_mask; +}; + #define SCH_PRIO_ATTR_BANDS 1 #define SCH_PRIO_ATTR_PRIOMAP 2 /** @endcond */ @@ -215,12 +216,12 @@ uint8_t *rtnl_qdisc_prio_get_priomap(struct rtnl_qdisc *qdisc) */ static const struct trans_tbl prios[] = { - __ADD(TC_PRIO_BESTEFFORT,besteffort) - __ADD(TC_PRIO_FILLER,filler) - __ADD(TC_PRIO_BULK,bulk) - __ADD(TC_PRIO_INTERACTIVE_BULK,interactive_bulk) - __ADD(TC_PRIO_INTERACTIVE,interactive) - __ADD(TC_PRIO_CONTROL,control) + __ADD(TC_PRIO_BESTEFFORT,besteffort), + __ADD(TC_PRIO_FILLER,filler), + __ADD(TC_PRIO_BULK,bulk), + __ADD(TC_PRIO_INTERACTIVE_BULK,interactive_bulk), + __ADD(TC_PRIO_INTERACTIVE,interactive), + __ADD(TC_PRIO_CONTROL,control), }; /** @@ -279,13 +280,13 @@ static struct rtnl_tc_ops pfifo_fast_ops = { .to_msg_fill = prio_msg_fill, }; -static void __init prio_init(void) +static void _nl_init prio_init(void) { rtnl_tc_register(&prio_ops); rtnl_tc_register(&pfifo_fast_ops); } -static void __exit prio_exit(void) +static void _nl_exit prio_exit(void) { rtnl_tc_unregister(&prio_ops); rtnl_tc_unregister(&pfifo_fast_ops); diff --git a/lib/route/qdisc/red.c b/lib/route/qdisc/red.c index f05626e..e793b78 100644 --- a/lib/route/qdisc/red.c +++ b/lib/route/qdisc/red.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/qdisc/red.c RED Qdisc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf */ @@ -16,15 +10,27 @@ * @{ */ -#include -#include +#include "nl-default.h" + #include #include -#include #include #include +#include "tc-api.h" + /** @cond SKIP */ +struct rtnl_red { + uint32_t qr_limit; + uint32_t qr_qth_min; + uint32_t qr_qth_max; + uint8_t qr_flags; + uint8_t qr_wlog; + uint8_t qr_plog; + uint8_t qr_scell_log; + uint32_t qr_mask; +}; + #define RED_ATTR_LIMIT 0x01 #define RED_ATTR_QTH_MIN 0x02 #define RED_ATTR_QTH_MAX 0x04 @@ -177,12 +183,12 @@ static struct rtnl_tc_ops red_ops = { .to_msg_fill = red_msg_fill, }; -static void __init red_init(void) +static void _nl_init red_init(void) { rtnl_tc_register(&red_ops); } -static void __exit red_exit(void) +static void _nl_exit red_exit(void) { rtnl_tc_unregister(&red_ops); } diff --git a/lib/route/qdisc/sfq.c b/lib/route/qdisc/sfq.c index acbb4ef..4379889 100644 --- a/lib/route/qdisc/sfq.c +++ b/lib/route/qdisc/sfq.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/qdisc/sfq.c SFQ Qdisc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf */ @@ -23,15 +17,25 @@ * @{ */ -#include -#include +#include "nl-default.h" + #include #include -#include #include #include +#include "tc-api.h" + /** @cond SKIP */ +struct rtnl_sfq { + uint32_t qs_quantum; + uint32_t qs_perturb; + uint32_t qs_limit; + uint32_t qs_divisor; + uint32_t qs_flows; + uint32_t qs_mask; +}; + #define SCH_SFQ_ATTR_QUANTUM 0x01 #define SCH_SFQ_ATTR_PERTURB 0x02 #define SCH_SFQ_ATTR_LIMIT 0x04 @@ -243,12 +247,12 @@ static struct rtnl_tc_ops sfq_ops = { .to_msg_fill = sfq_msg_fill, }; -static void __init sfq_init(void) +static void _nl_init sfq_init(void) { rtnl_tc_register(&sfq_ops); } -static void __exit sfq_exit(void) +static void _nl_exit sfq_exit(void) { rtnl_tc_unregister(&sfq_ops); } diff --git a/lib/route/qdisc/tbf.c b/lib/route/qdisc/tbf.c index eb574d9..67996eb 100644 --- a/lib/route/qdisc/tbf.c +++ b/lib/route/qdisc/tbf.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/qdisc/tbf.c TBF Qdisc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf */ @@ -15,18 +9,30 @@ * @{ */ -#include -#include +#include "nl-default.h" + #include #include #include -#include #include #include #include #include +#include "tc-api.h" + /** @cond SKIP */ +struct rtnl_tbf { + uint32_t qt_limit; + struct rtnl_ratespec qt_rate; + uint32_t qt_rate_bucket; + uint32_t qt_rate_txtime; + struct rtnl_ratespec qt_peakrate; + uint32_t qt_peakrate_bucket; + uint32_t qt_peakrate_txtime; + uint32_t qt_mask; +}; + #define TBF_ATTR_LIMIT 0x01 #define TBF_ATTR_RATE 0x02 #define TBF_ATTR_PEAKRATE 0x10 @@ -44,24 +50,24 @@ static int tbf_msg_parser(struct rtnl_tc *tc, void *data) if ((err = tca_parse(tb, TCA_TBF_MAX, tc, tbf_policy)) < 0) return err; - + if (tb[TCA_TBF_PARMS]) { struct tc_tbf_qopt opts; int bufsize; nla_memcpy(&opts, tb[TCA_TBF_PARMS], sizeof(opts)); tbf->qt_limit = opts.limit; - + rtnl_copy_ratespec(&tbf->qt_rate, &opts.rate); tbf->qt_rate_txtime = opts.buffer; - bufsize = rtnl_tc_calc_bufsize(nl_ticks2us(opts.buffer), - opts.rate.rate); + bufsize = rtnl_tc_calc_bufsize64(nl_ticks2us(opts.buffer), + tbf->qt_rate.rs_rate64); tbf->qt_rate_bucket = bufsize; rtnl_copy_ratespec(&tbf->qt_peakrate, &opts.peakrate); tbf->qt_peakrate_txtime = opts.mtu; - bufsize = rtnl_tc_calc_bufsize(nl_ticks2us(opts.mtu), - opts.peakrate.rate); + bufsize = rtnl_tc_calc_bufsize64(nl_ticks2us(opts.mtu), + tbf->qt_peakrate.rs_rate64); tbf->qt_peakrate_bucket = bufsize; rtnl_tc_set_mpu(tc, tbf->qt_rate.rs_mpu); @@ -83,8 +89,8 @@ static void tbf_dump_line(struct rtnl_tc *tc, void *data, if (!tbf) return; - r = nl_cancel_down_bytes(tbf->qt_rate.rs_rate, &ru); - rbit = nl_cancel_down_bits(tbf->qt_rate.rs_rate*8, &rubit); + r = nl_cancel_down_bytes(tbf->qt_rate.rs_rate64, &ru); + rbit = nl_cancel_down_bits(tbf->qt_rate.rs_rate64*8, &rubit); lim = nl_cancel_down_bytes(tbf->qt_limit, &limu); nl_dump(p, " rate %.2f%s/s (%.0f%s) limit %.2f%s", @@ -114,16 +120,16 @@ static void tbf_dump_details(struct rtnl_tc *tc, void *data, if (tbf->qt_mask & TBF_ATTR_PEAKRATE) { char *pru, *prbu, *bsu, *clu; double pr, prb, bs, cl; - - pr = nl_cancel_down_bytes(tbf->qt_peakrate.rs_rate, &pru); - prb = nl_cancel_down_bits(tbf->qt_peakrate.rs_rate * 8, &prbu); + + pr = nl_cancel_down_bytes(tbf->qt_peakrate.rs_rate64, &pru); + prb = nl_cancel_down_bits(tbf->qt_peakrate.rs_rate64 * 8, &prbu); bs = nl_cancel_down_bits(tbf->qt_peakrate_bucket, &bsu); cl = nl_cancel_down_bits(1 << tbf->qt_peakrate.rs_cell_log, &clu); - nl_dump_line(p, " peak-rate %.2f%s/s (%.0f%s) " - "bucket-size %.1f%s cell-size %.1f%s" - "latency %.1f%s", + nl_dump_line(p, + " peak-rate %.2f%s/s (%.0f%s) " + "bucket-size %.1f%s cell-size %.1f%s", pr, pru, prb, prbu, bs, bsu, cl, clu); } } @@ -191,7 +197,7 @@ static inline double calc_limit(struct rtnl_ratespec *spec, int latency, { double limit; - limit = (double) spec->rs_rate * ((double) latency / 1000000.); + limit = (double) spec->rs_rate64 * ((double) latency / 1000000.); limit += bucket; return limit; @@ -278,7 +284,7 @@ void rtnl_qdisc_tbf_set_rate(struct rtnl_qdisc *qdisc, int rate, int bucket, { struct rtnl_tbf *tbf; int cell_log; - + if (!(tbf = rtnl_tc_data(TC_CAST(qdisc)))) BUG(); @@ -287,10 +293,10 @@ void rtnl_qdisc_tbf_set_rate(struct rtnl_qdisc *qdisc, int rate, int bucket, else cell_log = rtnl_tc_calc_cell_log(cell); - tbf->qt_rate.rs_rate = rate; + tbf->qt_rate.rs_rate64 = (uint32_t)rate; tbf->qt_rate_bucket = bucket; tbf->qt_rate.rs_cell_log = cell_log; - tbf->qt_rate_txtime = nl_us2ticks(rtnl_tc_calc_txtime(bucket, rate)); + tbf->qt_rate_txtime = nl_us2ticks(rtnl_tc_calc_txtime64(bucket, tbf->qt_rate.rs_rate64)); tbf->qt_mask |= TBF_ATTR_RATE; } @@ -307,7 +313,7 @@ int rtnl_qdisc_tbf_get_rate(struct rtnl_qdisc *qdisc) BUG(); if (tbf->qt_mask & TBF_ATTR_RATE) - return tbf->qt_rate.rs_rate; + return tbf->qt_rate.rs_rate64; else return -1; } @@ -361,7 +367,7 @@ int rtnl_qdisc_tbf_set_peakrate(struct rtnl_qdisc *qdisc, int rate, int bucket, { struct rtnl_tbf *tbf; int cell_log; - + if (!(tbf = rtnl_tc_data(TC_CAST(qdisc)))) BUG(); @@ -369,11 +375,11 @@ int rtnl_qdisc_tbf_set_peakrate(struct rtnl_qdisc *qdisc, int rate, int bucket, if (cell_log < 0) return cell_log; - tbf->qt_peakrate.rs_rate = rate; + tbf->qt_peakrate.rs_rate64 = (uint32_t)rate; tbf->qt_peakrate_bucket = bucket; tbf->qt_peakrate.rs_cell_log = cell_log; - tbf->qt_peakrate_txtime = nl_us2ticks(rtnl_tc_calc_txtime(bucket, rate)); - + tbf->qt_peakrate_txtime = nl_us2ticks(rtnl_tc_calc_txtime64(bucket, tbf->qt_peakrate.rs_rate64)); + tbf->qt_mask |= TBF_ATTR_PEAKRATE; return 0; @@ -392,7 +398,7 @@ int rtnl_qdisc_tbf_get_peakrate(struct rtnl_qdisc *qdisc) BUG(); if (tbf->qt_mask & TBF_ATTR_PEAKRATE) - return tbf->qt_peakrate.rs_rate; + return tbf->qt_peakrate.rs_rate64; else return -1; } @@ -447,12 +453,12 @@ static struct rtnl_tc_ops tbf_tc_ops = { .to_msg_fill = tbf_msg_fill, }; -static void __init tbf_init(void) +static void _nl_init tbf_init(void) { rtnl_tc_register(&tbf_tc_ops); } -static void __exit tbf_exit(void) +static void _nl_exit tbf_exit(void) { rtnl_tc_unregister(&tbf_tc_ops); } diff --git a/lib/route/route.c b/lib/route/route.c index 2985187..0a16ff4 100644 --- a/lib/route/route.c +++ b/lib/route/route.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/route.c Routes - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf */ @@ -16,7 +10,8 @@ * @{ */ -#include +#include "nl-default.h" + #include #include #include @@ -25,6 +20,11 @@ #include #include +#include "nl-route.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" +#include "nl-aux-route/nl-route.h" + static struct nl_cache_ops rtnl_route_ops; static int route_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, @@ -130,6 +130,32 @@ int rtnl_route_build_add_request(struct rtnl_route *tmpl, int flags, result); } +int rtnl_route_lookup(struct nl_sock *sk, struct nl_addr *dst, + struct rtnl_route **result) +{ + _nl_auto_nl_msg struct nl_msg *msg = NULL; + _nl_auto_rtnl_route struct rtnl_route *tmpl = NULL; + struct nl_object *obj; + int err; + + tmpl = rtnl_route_alloc(); + rtnl_route_set_dst(tmpl, dst); + err = build_route_msg(tmpl, RTM_GETROUTE, 0, &msg); + if (err < 0) + return err; + + err = nl_send_auto(sk, msg); + if (err < 0) + return err; + + if ((err = nl_pickup(sk, route_msg_parser, &obj)) < 0) + return err; + + *result = (struct rtnl_route *)obj; + wait_for_ack(sk); + return 0; +} + int rtnl_route_add(struct nl_sock *sk, struct rtnl_route *route, int flags) { struct nl_msg *msg; @@ -173,6 +199,7 @@ int rtnl_route_delete(struct nl_sock *sk, struct rtnl_route *route, int flags) static struct nl_af_group route_groups[] = { { AF_INET, RTNLGRP_IPV4_ROUTE }, { AF_INET6, RTNLGRP_IPV6_ROUTE }, + { AF_MPLS, RTNLGRP_MPLS_ROUTE }, { AF_DECnet, RTNLGRP_DECnet_ROUTE }, { END_OF_GROUP_LIST }, }; @@ -193,12 +220,12 @@ static struct nl_cache_ops rtnl_route_ops = { .co_obj_ops = &route_obj_ops, }; -static void __init route_init(void) +static void _nl_init route_init(void) { nl_cache_mngt_register(&rtnl_route_ops); } -static void __exit route_exit(void) +static void _nl_exit route_exit(void) { nl_cache_mngt_unregister(&rtnl_route_ops); } diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index f2de523..ce68259 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/route_obj.c Route Object - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf */ @@ -30,7 +24,10 @@ * @{ */ -#include +#include "nl-default.h" + +#include + #include #include #include @@ -41,7 +38,39 @@ #include #include +#include "nl-route.h" +#include "nl-aux-route/nl-route.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nexthop-encap.h" + /** @cond SKIP */ +struct rtnl_route { + NLHDR_COMMON + + uint8_t rt_family; + uint8_t rt_dst_len; + uint8_t rt_src_len; + uint8_t rt_tos; + uint8_t rt_protocol; + uint8_t rt_scope; + uint8_t rt_type; + uint8_t rt_nmetrics; + uint8_t rt_ttl_propagate; + uint32_t rt_flags; + struct nl_addr *rt_dst; + struct nl_addr *rt_src; + uint32_t rt_table; + uint32_t rt_iif; + uint32_t rt_prio; + uint32_t rt_metrics[RTAX_MAX]; + uint32_t rt_metrics_mask; + uint32_t rt_nr_nh; + struct nl_addr *rt_pref_src; + struct nl_list_head rt_nexthops; + struct rtnl_rtcacheinfo rt_cacheinfo; + uint32_t rt_flag_mask; +}; + #define ROUTE_ATTR_FAMILY 0x000001 #define ROUTE_ATTR_TOS 0x000002 #define ROUTE_ATTR_TABLE 0x000004 @@ -60,6 +89,7 @@ #define ROUTE_ATTR_MULTIPATH 0x008000 #define ROUTE_ATTR_REALMS 0x010000 #define ROUTE_ATTR_CACHEINFO 0x020000 +#define ROUTE_ATTR_TTL_PROPAGATE 0x040000 /** @endcond */ static void route_constructor(struct nl_object *c) @@ -100,22 +130,27 @@ static int route_clone(struct nl_object *_dst, struct nl_object *_src) struct rtnl_route *src = (struct rtnl_route *) _src; struct rtnl_nexthop *nh, *new; - if (src->rt_dst) + dst->rt_dst = NULL; + dst->rt_src = NULL; + dst->rt_pref_src = NULL; + nl_init_list_head(&dst->rt_nexthops); + dst->rt_nr_nh = 0; + + if (src->rt_dst) { if (!(dst->rt_dst = nl_addr_clone(src->rt_dst))) return -NLE_NOMEM; + } - if (src->rt_src) + if (src->rt_src) { if (!(dst->rt_src = nl_addr_clone(src->rt_src))) return -NLE_NOMEM; + } - if (src->rt_pref_src) + if (src->rt_pref_src) { if (!(dst->rt_pref_src = nl_addr_clone(src->rt_pref_src))) return -NLE_NOMEM; + } - /* Will be inc'ed again while adding the nexthops of the source */ - dst->rt_nr_nh = 0; - - nl_init_list_head(&dst->rt_nexthops); nl_list_for_each_entry(nh, &src->rt_nexthops, rtnh_list) { new = rtnl_route_nh_clone(nh); if (!new) @@ -142,7 +177,8 @@ static void route_dump_line(struct nl_object *a, struct nl_dump_params *p) nl_dump(p, "cache "); if (!(r->ce_mask & ROUTE_ATTR_DST) || - nl_addr_get_len(r->rt_dst) == 0) + (nl_addr_get_prefixlen(r->rt_dst) == 0 && + nl_addr_get_len(r->rt_dst) > 0 && nl_addr_iszero(r->rt_dst))) nl_dump(p, "default "); else nl_dump(p, "%s ", nl_addr2str(r->rt_dst, buf, sizeof(buf))); @@ -206,8 +242,8 @@ static void route_dump_line(struct nl_object *a, struct nl_dump_params *p) static void route_dump_details(struct nl_object *a, struct nl_dump_params *p) { + _nl_auto_nl_cache struct nl_cache *link_cache = NULL; struct rtnl_route *r = (struct rtnl_route *) a; - struct nl_cache *link_cache; char buf[256]; int i; @@ -243,6 +279,11 @@ static void route_dump_details(struct nl_object *a, struct nl_dump_params *p) if (r->ce_mask & ROUTE_ATTR_SRC) nl_dump(p, "src %s ", nl_addr2str(r->rt_src, buf, sizeof(buf))); + if (r->ce_mask & ROUTE_ATTR_TTL_PROPAGATE) { + nl_dump(p, " ttl-propagate %s", + r->rt_ttl_propagate ? "enabled" : "disabled"); + } + nl_dump(p, "\n"); if (r->ce_mask & ROUTE_ATTR_MULTIPATH) { @@ -259,7 +300,7 @@ static void route_dump_details(struct nl_object *a, struct nl_dump_params *p) if ((r->ce_mask & ROUTE_ATTR_CACHEINFO) && r->rt_cacheinfo.rtci_error) { nl_dump_line(p, " cacheinfo error %d (%s)\n", r->rt_cacheinfo.rtci_error, - strerror_r(-r->rt_cacheinfo.rtci_error, buf, sizeof(buf))); + nl_strerror_l(-r->rt_cacheinfo.rtci_error)); } if (r->ce_mask & ROUTE_ATTR_METRICS) { @@ -272,9 +313,6 @@ static void route_dump_details(struct nl_object *a, struct nl_dump_params *p) r->rt_metrics[i]); nl_dump(p, "]\n"); } - - if (link_cache) - nl_cache_put(link_cache); } static void route_dump_stats(struct nl_object *obj, struct nl_dump_params *p) @@ -300,13 +338,13 @@ static void route_keygen(struct nl_object *obj, uint32_t *hashkey, struct rtnl_route *route = (struct rtnl_route *) obj; unsigned int rkey_sz; struct nl_addr *addr = NULL; - struct route_hash_key { + _nl_auto_free struct route_hash_key { uint8_t rt_family; uint8_t rt_tos; uint32_t rt_table; uint32_t rt_prio; char rt_addr[0]; - } __attribute__((packed)) *rkey; + } _nl_packed *rkey = NULL; #ifdef NL_DEBUG char buf[INET6_ADDRSTRLEN+5]; #endif @@ -338,33 +376,46 @@ static void route_keygen(struct nl_object *obj, uint32_t *hashkey, rkey->rt_table, nl_addr2str(addr, buf, sizeof(buf)), rkey_sz, *hashkey); - free(rkey); - return; } -static int route_compare(struct nl_object *_a, struct nl_object *_b, - uint32_t attrs, int flags) +static uint32_t route_id_attrs_get(struct nl_object *obj) +{ + struct rtnl_route *route = (struct rtnl_route *)obj; + struct nl_object_ops *ops = obj->ce_ops; + uint32_t rv = ops->oo_id_attrs; + + /* MPLS address family does not allow RTA_PRIORITY to be set */ + if (route->rt_family == AF_MPLS) + rv &= ~ROUTE_ATTR_PRIO; + + return rv; +} + +static uint64_t route_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) { struct rtnl_route *a = (struct rtnl_route *) _a; struct rtnl_route *b = (struct rtnl_route *) _b; struct rtnl_nexthop *nh_a, *nh_b; - int i, diff = 0, found; - -#define ROUTE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ROUTE_ATTR_##ATTR, a, b, EXPR) - - diff |= ROUTE_DIFF(FAMILY, a->rt_family != b->rt_family); - diff |= ROUTE_DIFF(TOS, a->rt_tos != b->rt_tos); - diff |= ROUTE_DIFF(TABLE, a->rt_table != b->rt_table); - diff |= ROUTE_DIFF(PROTOCOL, a->rt_protocol != b->rt_protocol); - diff |= ROUTE_DIFF(SCOPE, a->rt_scope != b->rt_scope); - diff |= ROUTE_DIFF(TYPE, a->rt_type != b->rt_type); - diff |= ROUTE_DIFF(PRIO, a->rt_prio != b->rt_prio); - diff |= ROUTE_DIFF(DST, nl_addr_cmp(a->rt_dst, b->rt_dst)); - diff |= ROUTE_DIFF(SRC, nl_addr_cmp(a->rt_src, b->rt_src)); - diff |= ROUTE_DIFF(IIF, a->rt_iif != b->rt_iif); - diff |= ROUTE_DIFF(PREF_SRC, nl_addr_cmp(a->rt_pref_src, - b->rt_pref_src)); + int i, found; + uint64_t diff = 0; + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(ROUTE_ATTR_FAMILY, a->rt_family != b->rt_family); + diff |= _DIFF(ROUTE_ATTR_TOS, a->rt_tos != b->rt_tos); + diff |= _DIFF(ROUTE_ATTR_TABLE, a->rt_table != b->rt_table); + diff |= _DIFF(ROUTE_ATTR_PROTOCOL, a->rt_protocol != b->rt_protocol); + diff |= _DIFF(ROUTE_ATTR_SCOPE, a->rt_scope != b->rt_scope); + diff |= _DIFF(ROUTE_ATTR_TYPE, a->rt_type != b->rt_type); + diff |= _DIFF(ROUTE_ATTR_PRIO, a->rt_prio != b->rt_prio); + diff |= _DIFF(ROUTE_ATTR_DST, nl_addr_cmp(a->rt_dst, b->rt_dst)); + diff |= _DIFF(ROUTE_ATTR_SRC, nl_addr_cmp(a->rt_src, b->rt_src)); + diff |= _DIFF(ROUTE_ATTR_IIF, a->rt_iif != b->rt_iif); + diff |= _DIFF(ROUTE_ATTR_PREF_SRC, + nl_addr_cmp(a->rt_pref_src, b->rt_pref_src)); + diff |= _DIFF(ROUTE_ATTR_TTL_PROPAGATE, + a->rt_ttl_propagate != b->rt_ttl_propagate); if (flags & LOOSE_COMPARISON) { nl_list_for_each_entry(nh_b, &b->rt_nexthops, rtnh_list) { @@ -386,10 +437,10 @@ static int route_compare(struct nl_object *_a, struct nl_object *_b, if (a->rt_metrics_mask & (1 << i) && (!(b->rt_metrics_mask & (1 << i)) || a->rt_metrics[i] != b->rt_metrics[i])) - diff |= ROUTE_DIFF(METRICS, 1); + diff |= _DIFF(ROUTE_ATTR_METRICS, 1); } - diff |= ROUTE_DIFF(FLAGS, + diff |= _DIFF(ROUTE_ATTR_FLAGS, (a->rt_flags ^ b->rt_flags) & b->rt_flag_mask); } else { if (a->rt_nr_nh != b->rt_nr_nh) @@ -427,23 +478,22 @@ static int route_compare(struct nl_object *_a, struct nl_object *_b, for (i = 0; i < RTAX_MAX - 1; i++) { if ((a->rt_metrics_mask & (1 << i)) ^ (b->rt_metrics_mask & (1 << i))) - diff |= ROUTE_DIFF(METRICS, 1); + diff |= _DIFF(ROUTE_ATTR_METRICS, 1); else - diff |= ROUTE_DIFF(METRICS, + diff |= _DIFF(ROUTE_ATTR_METRICS, a->rt_metrics[i] != b->rt_metrics[i]); } - diff |= ROUTE_DIFF(FLAGS, a->rt_flags != b->rt_flags); + diff |= _DIFF(ROUTE_ATTR_FLAGS, a->rt_flags != b->rt_flags); } out: return diff; nh_mismatch: - diff |= ROUTE_DIFF(MULTIPATH, 1); + diff |= _DIFF(ROUTE_ATTR_MULTIPATH, 1); goto out; - -#undef ROUTE_DIFF +#undef _DIFF } static int route_update(struct nl_object *old_obj, struct nl_object *new_obj) @@ -486,6 +536,16 @@ static int route_update(struct nl_object *old_obj, struct nl_object *new_obj) switch(action) { case RTM_NEWROUTE : { struct rtnl_nexthop *cloned_nh; + struct rtnl_nexthop *old_nh; + + /* + * Do not add the nexthop to old route if it was already added before + */ + nl_list_for_each_entry(old_nh, &old_route->rt_nexthops, rtnh_list) { + if (!rtnl_route_nh_compare(old_nh, new_nh, ~0, 0)) { + return 0; + } + } /* * Add the nexthop to old route @@ -544,24 +604,25 @@ static int route_update(struct nl_object *old_obj, struct nl_object *new_obj) } static const struct trans_tbl route_attrs[] = { - __ADD(ROUTE_ATTR_FAMILY, family) - __ADD(ROUTE_ATTR_TOS, tos) - __ADD(ROUTE_ATTR_TABLE, table) - __ADD(ROUTE_ATTR_PROTOCOL, protocol) - __ADD(ROUTE_ATTR_SCOPE, scope) - __ADD(ROUTE_ATTR_TYPE, type) - __ADD(ROUTE_ATTR_FLAGS, flags) - __ADD(ROUTE_ATTR_DST, dst) - __ADD(ROUTE_ATTR_SRC, src) - __ADD(ROUTE_ATTR_IIF, iif) - __ADD(ROUTE_ATTR_OIF, oif) - __ADD(ROUTE_ATTR_GATEWAY, gateway) - __ADD(ROUTE_ATTR_PRIO, prio) - __ADD(ROUTE_ATTR_PREF_SRC, pref_src) - __ADD(ROUTE_ATTR_METRICS, metrics) - __ADD(ROUTE_ATTR_MULTIPATH, multipath) - __ADD(ROUTE_ATTR_REALMS, realms) - __ADD(ROUTE_ATTR_CACHEINFO, cacheinfo) + __ADD(ROUTE_ATTR_FAMILY, family), + __ADD(ROUTE_ATTR_TOS, tos), + __ADD(ROUTE_ATTR_TABLE, table), + __ADD(ROUTE_ATTR_PROTOCOL, protocol), + __ADD(ROUTE_ATTR_SCOPE, scope), + __ADD(ROUTE_ATTR_TYPE, type), + __ADD(ROUTE_ATTR_FLAGS, flags), + __ADD(ROUTE_ATTR_DST, dst), + __ADD(ROUTE_ATTR_SRC, src), + __ADD(ROUTE_ATTR_IIF, iif), + __ADD(ROUTE_ATTR_OIF, oif), + __ADD(ROUTE_ATTR_GATEWAY, gateway), + __ADD(ROUTE_ATTR_PRIO, prio), + __ADD(ROUTE_ATTR_PREF_SRC, pref_src), + __ADD(ROUTE_ATTR_METRICS, metrics), + __ADD(ROUTE_ATTR_MULTIPATH, multipath), + __ADD(ROUTE_ATTR_REALMS, realms), + __ADD(ROUTE_ATTR_CACHEINFO, cacheinfo), + __ADD(ROUTE_ATTR_TTL_PROPAGATE, ttl_propagate), }; static char *route_attrs2str(int attrs, char *buf, size_t len) @@ -654,13 +715,17 @@ uint32_t rtnl_route_get_priority(struct rtnl_route *route) int rtnl_route_set_family(struct rtnl_route *route, uint8_t family) { - if (family != AF_INET && family != AF_INET6 && family != AF_DECnet) - return -NLE_AF_NOSUPPORT; - - route->rt_family = family; - route->ce_mask |= ROUTE_ATTR_FAMILY; + switch(family) { + case AF_INET: + case AF_INET6: + case AF_DECnet: + case AF_MPLS: + route->rt_family = family; + route->ce_mask |= ROUTE_ATTR_FAMILY; + return 0; + } - return 0; + return -NLE_AF_NOSUPPORT; } uint8_t rtnl_route_get_family(struct rtnl_route *route) @@ -681,7 +746,7 @@ int rtnl_route_set_dst(struct rtnl_route *route, struct nl_addr *addr) nl_addr_get(addr); route->rt_dst = addr; - + route->ce_mask |= (ROUTE_ATTR_DST | ROUTE_ATTR_FAMILY); return 0; @@ -867,10 +932,10 @@ void rtnl_route_foreach_nexthop(struct rtnl_route *r, void *arg) { struct rtnl_nexthop *nh; - + if (r->ce_mask & ROUTE_ATTR_MULTIPATH) { nl_list_for_each_entry(nh, &r->rt_nexthops, rtnh_list) { - cb(nh, arg); + cb(nh, arg); } } } @@ -879,15 +944,30 @@ struct rtnl_nexthop *rtnl_route_nexthop_n(struct rtnl_route *r, int n) { struct rtnl_nexthop *nh; uint32_t i; - + if (r->ce_mask & ROUTE_ATTR_MULTIPATH && r->rt_nr_nh > n) { i = 0; nl_list_for_each_entry(nh, &r->rt_nexthops, rtnh_list) { - if (i == n) return nh; + if (i == n) return nh; i++; } } - return NULL; + return NULL; +} + +void rtnl_route_set_ttl_propagate(struct rtnl_route *route, uint8_t ttl_prop) +{ + route->rt_ttl_propagate = ttl_prop; + route->ce_mask |= ROUTE_ATTR_TTL_PROPAGATE; +} + +int rtnl_route_get_ttl_propagate(struct rtnl_route *route) +{ + if (!route) + return -NLE_INVAL; + if (!(route->ce_mask & ROUTE_ATTR_TTL_PROPAGATE)) + return -NLE_MISSING_ATTR; + return route->rt_ttl_propagate; } /** @} */ @@ -915,6 +995,9 @@ int rtnl_route_guess_scope(struct rtnl_route *route) if (route->rt_type == RTN_LOCAL) return RT_SCOPE_HOST; + if (route->rt_family == AF_MPLS) + return RT_SCOPE_UNIVERSE; + if (!nl_list_empty(&route->rt_nexthops)) { struct rtnl_nexthop *nh; @@ -933,6 +1016,31 @@ int rtnl_route_guess_scope(struct rtnl_route *route) /** @} */ +static struct nl_addr *rtnl_route_parse_via(struct nlattr *nla) +{ + int alen = nla_len(nla) - offsetof(struct rtvia, rtvia_addr); + struct rtvia *via = nla_data(nla); + + return nl_addr_build(via->rtvia_family, via->rtvia_addr, alen); +} + +static int rtnl_route_put_via(struct nl_msg *msg, struct nl_addr *addr) +{ + unsigned int alen = nl_addr_get_len(addr); + struct nlattr *nla; + struct rtvia *via; + + nla = nla_reserve(msg, RTA_VIA, alen + sizeof(*via)); + if (!nla) + return -EMSGSIZE; + + via = nla_data(nla); + via->rtvia_family = nl_addr_get_family(addr); + memcpy(via->rtvia_addr, nl_addr_get_binary_addr(addr), alen); + + return 0; +} + static struct nla_policy route_policy[RTA_MAX+1] = { [RTA_IIF] = { .type = NLA_U32 }, [RTA_OIF] = { .type = NLA_U32 }, @@ -941,16 +1049,20 @@ static struct nla_policy route_policy[RTA_MAX+1] = { [RTA_CACHEINFO] = { .minlen = sizeof(struct rta_cacheinfo) }, [RTA_METRICS] = { .type = NLA_NESTED }, [RTA_MULTIPATH] = { .type = NLA_NESTED }, + [RTA_TTL_PROPAGATE] = { .type = NLA_U8 }, + [RTA_ENCAP] = { .type = NLA_NESTED }, + [RTA_ENCAP_TYPE] = { .type = NLA_U16 }, }; static int parse_multipath(struct rtnl_route *route, struct nlattr *attr) { - struct rtnl_nexthop *nh = NULL; struct rtnexthop *rtnh = nla_data(attr); size_t tlen = nla_len(attr); int err; while (tlen >= sizeof(*rtnh) && tlen >= rtnh->rtnh_len) { + _nl_auto_rtnl_nexthop struct rtnl_nexthop *nh = NULL; + nh = rtnl_route_nh_alloc(); if (!nh) return -NLE_NOMEM; @@ -967,63 +1079,88 @@ static int parse_multipath(struct rtnl_route *route, struct nlattr *attr) rtnh->rtnh_len - sizeof(*rtnh), route_policy); if (err < 0) - goto errout; + return err; if (ntb[RTA_GATEWAY]) { - struct nl_addr *addr; + _nl_auto_nl_addr struct nl_addr *addr = NULL; addr = nl_addr_alloc_attr(ntb[RTA_GATEWAY], route->rt_family); - if (!addr) { - err = -NLE_NOMEM; - goto errout; - } + if (!addr) + return -NLE_NOMEM; rtnl_route_nh_set_gateway(nh, addr); - nl_addr_put(addr); } if (ntb[RTA_FLOW]) { uint32_t realms; - + realms = nla_get_u32(ntb[RTA_FLOW]); rtnl_route_nh_set_realms(nh, realms); } + + if (ntb[RTA_NEWDST]) { + _nl_auto_nl_addr struct nl_addr *addr = NULL; + + addr = nl_addr_alloc_attr(ntb[RTA_NEWDST], + route->rt_family); + if (!addr) + return -NLE_NOMEM; + + err = rtnl_route_nh_set_newdst(nh, addr); + if (err < 0) + return err; + } + + if (ntb[RTA_VIA]) { + _nl_auto_nl_addr struct nl_addr *addr = NULL; + + addr = rtnl_route_parse_via(ntb[RTA_VIA]); + if (!addr) + return -NLE_NOMEM; + + err = rtnl_route_nh_set_via(nh, addr); + if (err < 0) + return err; + } + + if (ntb[RTA_ENCAP] && ntb[RTA_ENCAP_TYPE]) { + err = nh_encap_parse_msg(ntb[RTA_ENCAP], + ntb[RTA_ENCAP_TYPE], + nh); + if (err < 0) + return err; + } } - rtnl_route_add_nexthop(route, nh); + rtnl_route_add_nexthop(route, _nl_steal_pointer(&nh)); tlen -= RTNH_ALIGN(rtnh->rtnh_len); rtnh = RTNH_NEXT(rtnh); } - err = 0; -errout: - if (err && nh) - rtnl_route_nh_free(nh); - - return err; + return 0; } int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) { - struct rtmsg *rtm; - struct rtnl_route *route; + _nl_auto_rtnl_route struct rtnl_route *route = NULL; + _nl_auto_rtnl_nexthop struct rtnl_nexthop *old_nh = NULL; + _nl_auto_nl_addr struct nl_addr *src = NULL; + _nl_auto_nl_addr struct nl_addr *dst = NULL; struct nlattr *tb[RTA_MAX + 1]; - struct nl_addr *src = NULL, *dst = NULL, *addr; - struct rtnl_nexthop *old_nh = NULL; - int err, family; + struct rtmsg *rtm; + int family; + int err; route = rtnl_route_alloc(); - if (!route) { - err = -NLE_NOMEM; - goto errout; - } + if (!route) + return -NLE_NOMEM; route->ce_msgtype = nlh->nlmsg_type; err = nlmsg_parse(nlh, sizeof(struct rtmsg), tb, RTA_MAX, route_policy); if (err < 0) - goto errout; + return err; rtm = nlmsg_data(nlh); route->rt_family = family = rtm->rtm_family; @@ -1038,35 +1175,52 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) route->ce_mask |= ROUTE_ATTR_FAMILY | ROUTE_ATTR_TOS | ROUTE_ATTR_TABLE | ROUTE_ATTR_TYPE | ROUTE_ATTR_SCOPE | ROUTE_ATTR_PROTOCOL | - ROUTE_ATTR_FLAGS | ROUTE_ATTR_PRIO; + ROUTE_ATTR_FLAGS; + + /* right now MPLS does not allow rt_prio to be set, so don't + * assume it is unless it comes from an attribute + */ + if (family != AF_MPLS) + route->ce_mask |= ROUTE_ATTR_PRIO; if (tb[RTA_DST]) { if (!(dst = nl_addr_alloc_attr(tb[RTA_DST], family))) - goto errout_nomem; + return -NLE_NOMEM; } else { - if (!(dst = nl_addr_alloc(0))) - goto errout_nomem; - nl_addr_set_family(dst, rtm->rtm_family); + int len; + + switch (family) { + case AF_INET: + len = 4; + break; + + case AF_INET6: + len = 16; + break; + default: + len = 0; + break; + } + + if (!(dst = nl_addr_build(family, NULL, len))) + return -NLE_NOMEM; } nl_addr_set_prefixlen(dst, rtm->rtm_dst_len); err = rtnl_route_set_dst(route, dst); if (err < 0) - goto errout; - - nl_addr_put(dst); + return err; if (tb[RTA_SRC]) { if (!(src = nl_addr_alloc_attr(tb[RTA_SRC], family))) - goto errout_nomem; + return -NLE_NOMEM; } else if (rtm->rtm_src_len) if (!(src = nl_addr_alloc(0))) - goto errout_nomem; + return -NLE_NOMEM; if (src) { nl_addr_set_prefixlen(src, rtm->rtm_src_len); rtnl_route_set_src(route, src); - nl_addr_put(src); } if (tb[RTA_TABLE]) @@ -1079,10 +1233,11 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) rtnl_route_set_priority(route, nla_get_u32(tb[RTA_PRIORITY])); if (tb[RTA_PREFSRC]) { + _nl_auto_nl_addr struct nl_addr *addr = NULL; + if (!(addr = nl_addr_alloc_attr(tb[RTA_PREFSRC], family))) - goto errout_nomem; + return -NLE_NOMEM; rtnl_route_set_pref_src(route, addr); - nl_addr_put(addr); } if (tb[RTA_METRICS]) { @@ -1091,20 +1246,23 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) err = nla_parse_nested(mtb, RTAX_MAX, tb[RTA_METRICS], NULL); if (err < 0) - goto errout; + return err; for (i = 1; i <= RTAX_MAX; i++) { if (mtb[i] && nla_len(mtb[i]) >= sizeof(uint32_t)) { uint32_t m = nla_get_u32(mtb[i]); - if (rtnl_route_set_metric(route, i, m) < 0) - goto errout; + + err = rtnl_route_set_metric(route, i, m); + if (err < 0) + return err; } } } - if (tb[RTA_MULTIPATH]) + if (tb[RTA_MULTIPATH]) { if ((err = parse_multipath(route, tb[RTA_MULTIPATH])) < 0) - goto errout; + return err; + } if (tb[RTA_CACHEINFO]) { nla_memcpy(&route->rt_cacheinfo, tb[RTA_CACHEINFO], @@ -1114,36 +1272,84 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) if (tb[RTA_OIF]) { if (!old_nh && !(old_nh = rtnl_route_nh_alloc())) - goto errout; + return -NLE_NOMEM; rtnl_route_nh_set_ifindex(old_nh, nla_get_u32(tb[RTA_OIF])); } if (tb[RTA_GATEWAY]) { + _nl_auto_nl_addr struct nl_addr *addr = NULL; + if (!old_nh && !(old_nh = rtnl_route_nh_alloc())) - goto errout; + return -NLE_NOMEM; if (!(addr = nl_addr_alloc_attr(tb[RTA_GATEWAY], family))) - goto errout_nomem; + return -NLE_NOMEM; rtnl_route_nh_set_gateway(old_nh, addr); - nl_addr_put(addr); } if (tb[RTA_FLOW]) { if (!old_nh && !(old_nh = rtnl_route_nh_alloc())) - goto errout; + return -NLE_NOMEM; rtnl_route_nh_set_realms(old_nh, nla_get_u32(tb[RTA_FLOW])); } + if (tb[RTA_NEWDST]) { + _nl_auto_nl_addr struct nl_addr *addr = NULL; + + if (!old_nh && !(old_nh = rtnl_route_nh_alloc())) + return -NLE_NOMEM; + + addr = nl_addr_alloc_attr(tb[RTA_NEWDST], route->rt_family); + if (!addr) + return -NLE_NOMEM; + + err = rtnl_route_nh_set_newdst(old_nh, addr); + if (err < 0) + return err; + } + + if (tb[RTA_VIA]) { + int alen = nla_len(tb[RTA_VIA]) - offsetof(struct rtvia, rtvia_addr); + _nl_auto_nl_addr struct nl_addr *addr = NULL; + struct rtvia *via = nla_data(tb[RTA_VIA]); + + if (!old_nh && !(old_nh = rtnl_route_nh_alloc())) + return -NLE_NOMEM; + + addr = nl_addr_build(via->rtvia_family, via->rtvia_addr, alen); + if (!addr) + return -NLE_NOMEM; + + err = rtnl_route_nh_set_via(old_nh, addr); + if (err < 0) + return err; + } + + if (tb[RTA_TTL_PROPAGATE]) { + rtnl_route_set_ttl_propagate(route, + nla_get_u8(tb[RTA_TTL_PROPAGATE])); + } + + if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE]) { + if (!old_nh && !(old_nh = rtnl_route_nh_alloc())) + return -NLE_NOMEM; + + err = nh_encap_parse_msg(tb[RTA_ENCAP], + tb[RTA_ENCAP_TYPE], old_nh); + if (err < 0) + return err; + } + if (old_nh) { rtnl_route_nh_set_flags(old_nh, rtm->rtm_flags & 0xff); if (route->rt_nr_nh == 0) { /* If no nexthops have been provided via RTA_MULTIPATH * we add it as regular nexthop to maintain backwards * compatibility */ - rtnl_route_add_nexthop(route, old_nh); + rtnl_route_add_nexthop(route, _nl_steal_pointer(&old_nh)); } else { /* Kernel supports new style nexthop configuration, * verify that it is a duplicate and discard nexthop. */ @@ -1157,24 +1363,13 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) if (rtnl_route_nh_compare(old_nh, first, old_nh->ce_mask, 0)) { - err = -NLE_INVAL; - goto errout; + return -NLE_INVAL; } - - rtnl_route_nh_free(old_nh); } } - *result = route; + *result = _nl_steal_pointer(&route); return 0; - -errout: - rtnl_route_put(route); - return err; - -errout_nomem: - err = -NLE_NOMEM; - goto errout; } int rtnl_route_build_msg(struct nl_msg *msg, struct rtnl_route *route) @@ -1198,7 +1393,7 @@ int rtnl_route_build_msg(struct nl_msg *msg, struct rtnl_route *route) if (route->rt_src) rtmsg.rtm_src_len = nl_addr_get_prefixlen(route->rt_src); - if (rtmsg.rtm_scope == RT_SCOPE_NOWHERE) + if (!(route->ce_mask & ROUTE_ATTR_SCOPE)) rtmsg.rtm_scope = rtnl_route_guess_scope(route); if (rtnl_route_get_nnexthops(route) == 1) { @@ -1211,12 +1406,17 @@ int rtnl_route_build_msg(struct nl_msg *msg, struct rtnl_route *route) goto nla_put_failure; /* Additional table attribute replacing the 8bit in the header, was - * required to allow more than 256 tables. */ - NLA_PUT_U32(msg, RTA_TABLE, route->rt_table); + * required to allow more than 256 tables. MPLS does not allow the + * table attribute to be set + */ + if (route->rt_family != AF_MPLS) + NLA_PUT_U32(msg, RTA_TABLE, route->rt_table); if (nl_addr_get_len(route->rt_dst)) NLA_PUT_ADDR(msg, RTA_DST, route->rt_dst); - NLA_PUT_U32(msg, RTA_PRIORITY, route->rt_prio); + + if (route->ce_mask & ROUTE_ATTR_PRIO) + NLA_PUT_U32(msg, RTA_PRIORITY, route->rt_prio); if (route->ce_mask & ROUTE_ATTR_SRC) NLA_PUT_ADDR(msg, RTA_SRC, route->rt_src); @@ -1227,6 +1427,9 @@ int rtnl_route_build_msg(struct nl_msg *msg, struct rtnl_route *route) if (route->ce_mask & ROUTE_ATTR_IIF) NLA_PUT_U32(msg, RTA_IIF, route->rt_iif); + if (route->ce_mask & ROUTE_ATTR_TTL_PROPAGATE) + NLA_PUT_U8(msg, RTA_TTL_PROPAGATE, route->rt_ttl_propagate); + if (route->rt_nmetrics > 0) { uint32_t val; @@ -1252,6 +1455,13 @@ int rtnl_route_build_msg(struct nl_msg *msg, struct rtnl_route *route) NLA_PUT_U32(msg, RTA_OIF, nh->rtnh_ifindex); if (nh->rtnh_realms) NLA_PUT_U32(msg, RTA_FLOW, nh->rtnh_realms); + if (nh->rtnh_newdst) + NLA_PUT_ADDR(msg, RTA_NEWDST, nh->rtnh_newdst); + if (nh->rtnh_via && rtnl_route_put_via(msg, nh->rtnh_via) < 0) + goto nla_put_failure; + if (nh->rtnh_encap && + nh_encap_build_msg(msg, nh->rtnh_encap) < 0) + goto nla_put_failure; } else if (rtnl_route_get_nnexthops(route) > 1) { struct nlattr *multipath; struct rtnl_nexthop *nh; @@ -1274,11 +1484,22 @@ int rtnl_route_build_msg(struct nl_msg *msg, struct rtnl_route *route) NLA_PUT_ADDR(msg, RTA_GATEWAY, nh->rtnh_gateway); + if (nh->rtnh_newdst) + NLA_PUT_ADDR(msg, RTA_NEWDST, nh->rtnh_newdst); + + if (nh->rtnh_via && + rtnl_route_put_via(msg, nh->rtnh_via) < 0) + goto nla_put_failure; + if (nh->rtnh_realms) NLA_PUT_U32(msg, RTA_FLOW, nh->rtnh_realms); - rtnh->rtnh_len = nlmsg_tail(msg->nm_nlh) - - (void *) rtnh; + if (nh->rtnh_encap && + nh_encap_build_msg(msg, nh->rtnh_encap) < 0) + goto nla_put_failure; + + rtnh->rtnh_len = (char *) nlmsg_tail(msg->nm_nlh) - + (char *) rtnh; } nla_nest_end(msg, multipath); @@ -1309,6 +1530,7 @@ struct nl_object_ops route_obj_ops = { .oo_id_attrs = (ROUTE_ATTR_FAMILY | ROUTE_ATTR_TOS | ROUTE_ATTR_TABLE | ROUTE_ATTR_DST | ROUTE_ATTR_PRIO), + .oo_id_attrs_get = route_id_attrs_get, }; /** @endcond */ diff --git a/lib/route/route_utils.c b/lib/route/route_utils.c index a5b3966..04e52b4 100644 --- a/lib/route/route_utils.c +++ b/lib/route/route_utils.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/route_utils.c Routing Utilities - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2006 Thomas Graf */ @@ -37,12 +31,15 @@ * @{ */ -#include +#include "nl-default.h" + #include #include #include #include - + +#include "nl-priv-dynamic-core/nl-core.h" + /** * @name Routing Table Identifier Translations * @{ @@ -55,16 +52,16 @@ static int add_routing_table_name(long id, const char *name) return __trans_list_add(id, name, &table_names); } -static void __init init_routing_table_names(void) +static void _nl_init init_routing_table_names(void) { add_routing_table_name(RT_TABLE_UNSPEC, "unspec"); add_routing_table_name(RT_TABLE_COMPAT, "compat"); add_routing_table_name(RT_TABLE_DEFAULT, "default"); add_routing_table_name(RT_TABLE_MAIN, "main"); add_routing_table_name(RT_TABLE_LOCAL, "local"); -}; +} -static void __exit release_routing_table_names(void) +static void _nl_exit release_routing_table_names(void) { __trans_list_clear(&table_names); } @@ -101,16 +98,16 @@ static int add_proto_name(long id, const char *name) return __trans_list_add(id, name, &proto_names); } -static void __init init_proto_names(void) +static void _nl_init init_proto_names(void) { add_proto_name(RTPROT_UNSPEC, "unspec"); add_proto_name(RTPROT_REDIRECT, "redirect"); add_proto_name(RTPROT_KERNEL, "kernel"); add_proto_name(RTPROT_BOOT, "boot"); add_proto_name(RTPROT_STATIC, "static"); -}; +} -static void __exit release_proto_names(void) +static void _nl_exit release_proto_names(void) { __trans_list_clear(&proto_names); } @@ -140,19 +137,19 @@ int rtnl_route_str2proto(const char *name) */ static const struct trans_tbl route_metrices[] = { - __ADD(RTAX_UNSPEC, unspec) - __ADD(RTAX_LOCK, lock) - __ADD(RTAX_MTU, mtu) - __ADD(RTAX_WINDOW, window) - __ADD(RTAX_RTT, rtt) - __ADD(RTAX_RTTVAR, rttvar) - __ADD(RTAX_SSTHRESH, ssthresh) - __ADD(RTAX_CWND, cwnd) - __ADD(RTAX_ADVMSS, advmss) - __ADD(RTAX_REORDERING, reordering) - __ADD(RTAX_HOPLIMIT, hoplimit) - __ADD(RTAX_INITCWND, initcwnd) - __ADD(RTAX_FEATURES, features) + __ADD(RTAX_UNSPEC, unspec), + __ADD(RTAX_LOCK, lock), + __ADD(RTAX_MTU, mtu), + __ADD(RTAX_WINDOW, window), + __ADD(RTAX_RTT, rtt), + __ADD(RTAX_RTTVAR, rttvar), + __ADD(RTAX_SSTHRESH, ssthresh), + __ADD(RTAX_CWND, cwnd), + __ADD(RTAX_ADVMSS, advmss), + __ADD(RTAX_REORDERING, reordering), + __ADD(RTAX_HOPLIMIT, hoplimit), + __ADD(RTAX_INITCWND, initcwnd), + __ADD(RTAX_FEATURES, features), }; char *rtnl_route_metric2str(int metric, char *buf, size_t size) diff --git a/lib/route/rtnl.c b/lib/route/rtnl.c index 82397e9..142c4c4 100644 --- a/lib/route/rtnl.c +++ b/lib/route/rtnl.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/rtnl.c Routing Netlink - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -14,11 +8,14 @@ * @{ */ -#include +#include "nl-default.h" + #include #include #include +#include "nl-priv-dynamic-core/nl-core.h" + /** * @name Sending * @{ @@ -34,15 +31,20 @@ * Fills out a routing netlink request message and sends it out * using nl_send_simple(). * - * @return 0 on success or a negative error code. + * @return 0 on success or a negative error code. Due to a bug in older + * version of the library, this function returned the number of bytes sent. + * Treat any non-negative number as success. */ int nl_rtgen_request(struct nl_sock *sk, int type, int family, int flags) { + int err; struct rtgenmsg gmsg = { .rtgen_family = family, }; - return nl_send_simple(sk, type, flags, &gmsg, sizeof(gmsg)); + err = nl_send_simple(sk, type, flags, &gmsg, sizeof(gmsg)); + + return err >= 0 ? 0 : err; } /** @} */ @@ -53,18 +55,18 @@ int nl_rtgen_request(struct nl_sock *sk, int type, int family, int flags) */ static const struct trans_tbl rtntypes[] = { - __ADD(RTN_UNSPEC,unspec) - __ADD(RTN_UNICAST,unicast) - __ADD(RTN_LOCAL,local) - __ADD(RTN_BROADCAST,broadcast) - __ADD(RTN_ANYCAST,anycast) - __ADD(RTN_MULTICAST,multicast) - __ADD(RTN_BLACKHOLE,blackhole) - __ADD(RTN_UNREACHABLE,unreachable) - __ADD(RTN_PROHIBIT,prohibit) - __ADD(RTN_THROW,throw) - __ADD(RTN_NAT,nat) - __ADD(RTN_XRESOLVE,xresolve) + __ADD(RTN_UNSPEC,unspec), + __ADD(RTN_UNICAST,unicast), + __ADD(RTN_LOCAL,local), + __ADD(RTN_BROADCAST,broadcast), + __ADD(RTN_ANYCAST,anycast), + __ADD(RTN_MULTICAST,multicast), + __ADD(RTN_BLACKHOLE,blackhole), + __ADD(RTN_UNREACHABLE,unreachable), + __ADD(RTN_PROHIBIT,prohibit), + __ADD(RTN_THROW,throw), + __ADD(RTN_NAT,nat), + __ADD(RTN_XRESOLVE,xresolve), }; char *nl_rtntype2str(int type, char *buf, size_t size) @@ -85,11 +87,11 @@ int nl_str2rtntype(const char *name) */ static const struct trans_tbl scopes[] = { - __ADD(255,nowhere) - __ADD(254,host) - __ADD(253,link) - __ADD(200,site) - __ADD(0,global) + __ADD(255,nowhere), + __ADD(254,host), + __ADD(253,link), + __ADD(200,site), + __ADD(0,global), }; char *rtnl_scope2str(int scope, char *buf, size_t size) diff --git a/lib/route/rule.c b/lib/route/rule.c index b2161a2..6e7c084 100644 --- a/lib/route/rule.c +++ b/lib/route/rule.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/rule.c Routing Rules - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2010 Thomas Graf */ @@ -16,28 +10,63 @@ * @{ */ -#include +#include "nl-default.h" + +#include + #include #include #include #include -#include + +#include "nl-route.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" /** @cond SKIP */ -#define RULE_ATTR_FAMILY 0x0001 -#define RULE_ATTR_TABLE 0x0002 -#define RULE_ATTR_ACTION 0x0004 -#define RULE_ATTR_FLAGS 0x0008 -#define RULE_ATTR_IIFNAME 0x0010 -#define RULE_ATTR_OIFNAME 0x0020 -#define RULE_ATTR_PRIO 0x0040 -#define RULE_ATTR_MARK 0x0080 -#define RULE_ATTR_MASK 0x0100 -#define RULE_ATTR_GOTO 0x0200 -#define RULE_ATTR_SRC 0x0400 -#define RULE_ATTR_DST 0x0800 -#define RULE_ATTR_DSFIELD 0x1000 -#define RULE_ATTR_FLOW 0x2000 +struct rtnl_rule { + NLHDR_COMMON + uint8_t r_family; + uint8_t r_action; + uint8_t r_dsfield; /* ipv4 only */ + uint8_t r_l3mdev; + uint8_t r_protocol; /* protocol that installed rule */ + uint8_t r_ip_proto; /* IP/IPv6 protocol */ + uint32_t r_table; + uint32_t r_flags; + uint32_t r_prio; + uint32_t r_mark; + uint32_t r_mask; + uint32_t r_goto; + uint32_t r_flow; /* ipv4 only */ + struct nl_addr *r_src; + struct nl_addr *r_dst; + char r_iifname[IFNAMSIZ]; + char r_oifname[IFNAMSIZ]; + + struct fib_rule_port_range r_sport; + struct fib_rule_port_range r_dport; +}; + +#define RULE_ATTR_FAMILY 0x000001 +#define RULE_ATTR_TABLE 0x000002 +#define RULE_ATTR_ACTION 0x000004 +#define RULE_ATTR_FLAGS 0x000008 +#define RULE_ATTR_IIFNAME 0x000010 +#define RULE_ATTR_OIFNAME 0x000020 +#define RULE_ATTR_PRIO 0x000040 +#define RULE_ATTR_MARK 0x000080 +#define RULE_ATTR_MASK 0x000100 +#define RULE_ATTR_GOTO 0x000200 +#define RULE_ATTR_SRC 0x000400 +#define RULE_ATTR_DST 0x000800 +#define RULE_ATTR_DSFIELD 0x001000 +#define RULE_ATTR_FLOW 0x002000 +#define RULE_ATTR_L3MDEV 0x004000 +#define RULE_ATTR_PROTOCOL 0x008000 +#define RULE_ATTR_IP_PROTO 0x010000 +#define RULE_ATTR_SPORT 0x020000 +#define RULE_ATTR_DPORT 0x040000 static struct nl_cache_ops rtnl_rule_ops; static struct nl_object_ops rule_obj_ops; @@ -59,6 +88,9 @@ static int rule_clone(struct nl_object *_dst, struct nl_object *_src) struct rtnl_rule *dst = nl_object_priv(_dst); struct rtnl_rule *src = nl_object_priv(_src); + dst->r_src = NULL; + dst->r_dst = NULL; + if (src->r_src) if (!(dst->r_src = nl_addr_clone(src->r_src))) return -NLE_NOMEM; @@ -79,6 +111,13 @@ static struct nla_policy rule_policy[FRA_MAX+1] = { [FRA_FWMASK] = { .type = NLA_U32 }, [FRA_GOTO] = { .type = NLA_U32 }, [FRA_FLOW] = { .type = NLA_U32 }, + [FRA_L3MDEV] = { .type = NLA_U8 }, + [FRA_PROTOCOL] = { .type = NLA_U8 }, + [FRA_IP_PROTO] = { .type = NLA_U8 }, + [FRA_SPORT_RANGE] = { .minlen = sizeof(struct fib_rule_port_range), + .maxlen = sizeof(struct fib_rule_port_range) }, + [FRA_DPORT_RANGE] = { .minlen = sizeof(struct fib_rule_port_range), + .maxlen = sizeof(struct fib_rule_port_range) }, }; static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, @@ -107,8 +146,9 @@ static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, rule->r_action = frh->action; rule->r_flags = frh->flags; - rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_TABLE | RULE_ATTR_ACTION | - RULE_ATTR_FLAGS); + rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_ACTION | RULE_ATTR_FLAGS); + if (rule->r_table) + rule->ce_mask |= RULE_ATTR_TABLE; /* ipv4 only */ if (frh->tos) { @@ -118,7 +158,8 @@ static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, if (tb[FRA_TABLE]) { rule->r_table = nla_get_u32(tb[FRA_TABLE]); - rule->ce_mask |= RULE_ATTR_TABLE; + if (rule->r_table) + rule->ce_mask |= RULE_ATTR_TABLE; } if (tb[FRA_IIFNAME]) { @@ -172,6 +213,37 @@ static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, rule->ce_mask |= RULE_ATTR_FLOW; } + if (tb[FRA_L3MDEV]) { + rule->r_l3mdev = nla_get_u8(tb[FRA_L3MDEV]); + rule->ce_mask |= RULE_ATTR_L3MDEV; + } + + if (tb[FRA_PROTOCOL]) { + rule->r_protocol = nla_get_u8(tb[FRA_PROTOCOL]); + rule->ce_mask |= RULE_ATTR_PROTOCOL; + } + + if (tb[FRA_IP_PROTO]) { + rule->r_ip_proto = nla_get_u8(tb[FRA_IP_PROTO]); + rule->ce_mask |= RULE_ATTR_IP_PROTO; + } + + if (tb[FRA_SPORT_RANGE]) { + struct fib_rule_port_range *pr; + + pr = nla_data(tb[FRA_SPORT_RANGE]); + rule->r_sport = *pr; + rule->ce_mask |= RULE_ATTR_SPORT; + } + + if (tb[FRA_DPORT_RANGE]) { + struct fib_rule_port_range *pr; + + pr = nla_data(tb[FRA_DPORT_RANGE]); + rule->r_dport = *pr; + rule->ce_mask |= RULE_ATTR_DPORT; + } + err = pp->pp_cb((struct nl_object *) rule, pp); errout: rtnl_rule_put(rule); @@ -219,6 +291,33 @@ static void rule_dump_line(struct nl_object *o, struct nl_dump_params *p) nl_dump(p, "lookup %s ", rtnl_route_table2str(r->r_table, buf, sizeof(buf))); + if (r->ce_mask & RULE_ATTR_L3MDEV) + nl_dump(p, "lookup [l3mdev-table] "); + + if (r->ce_mask & RULE_ATTR_IP_PROTO) + nl_dump(p, "ipproto %s ", + nl_ip_proto2str(r->r_ip_proto, buf, sizeof(buf))); + + if (r->ce_mask & RULE_ATTR_SPORT) { + if (r->r_sport.start == r->r_sport.end) + nl_dump(p, "sport %u ", r->r_sport.start); + else + nl_dump(p, "sport %u-%u ", + r->r_sport.start, r->r_sport.end); + } + + if (r->ce_mask & RULE_ATTR_DPORT) { + if (r->r_dport.start == r->r_dport.end) + nl_dump(p, "dport %u ", r->r_dport.start); + else + nl_dump(p, "dport %u-%u ", + r->r_dport.start, r->r_dport.end); + } + + if (r->ce_mask & RULE_ATTR_PROTOCOL) + nl_dump(p, "protocol %s ", + rtnl_route_proto2str(r->r_protocol, buf, sizeof(buf))); + if (r->ce_mask & RULE_ATTR_FLOW) nl_dump(p, "flow %s ", rtnl_realms2str(r->r_flow, buf, sizeof(buf))); @@ -243,50 +342,46 @@ static void rule_dump_stats(struct nl_object *obj, struct nl_dump_params *p) rule_dump_details(obj, p); } -#define RULE_ATTR_FLAGS 0x0008 - -static int rule_compare(struct nl_object *_a, struct nl_object *_b, - uint32_t attrs, int flags) +static uint64_t rule_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) { struct rtnl_rule *a = (struct rtnl_rule *) _a; struct rtnl_rule *b = (struct rtnl_rule *) _b; - int diff = 0; - -#define RULE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, RULE_ATTR_##ATTR, a, b, EXPR) - - diff |= RULE_DIFF(FAMILY, a->r_family != b->r_family); - diff |= RULE_DIFF(TABLE, a->r_table != b->r_table); - diff |= RULE_DIFF(ACTION, a->r_action != b->r_action); - diff |= RULE_DIFF(IIFNAME, strcmp(a->r_iifname, b->r_iifname)); - diff |= RULE_DIFF(OIFNAME, strcmp(a->r_oifname, b->r_oifname)); - diff |= RULE_DIFF(PRIO, a->r_prio != b->r_prio); - diff |= RULE_DIFF(MARK, a->r_mark != b->r_mark); - diff |= RULE_DIFF(MASK, a->r_mask != b->r_mask); - diff |= RULE_DIFF(GOTO, a->r_goto != b->r_goto); - diff |= RULE_DIFF(SRC, nl_addr_cmp(a->r_src, b->r_src)); - diff |= RULE_DIFF(DST, nl_addr_cmp(a->r_dst, b->r_dst)); - diff |= RULE_DIFF(DSFIELD, a->r_dsfield != b->r_dsfield); - diff |= RULE_DIFF(FLOW, a->r_flow != b->r_flow); - -#undef RULE_DIFF + uint64_t diff = 0; + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(RULE_ATTR_FAMILY, a->r_family != b->r_family); + diff |= _DIFF(RULE_ATTR_TABLE, a->r_table != b->r_table); + diff |= _DIFF(RULE_ATTR_ACTION, a->r_action != b->r_action); + diff |= _DIFF(RULE_ATTR_IIFNAME, strcmp(a->r_iifname, b->r_iifname)); + diff |= _DIFF(RULE_ATTR_OIFNAME, strcmp(a->r_oifname, b->r_oifname)); + diff |= _DIFF(RULE_ATTR_PRIO, a->r_prio != b->r_prio); + diff |= _DIFF(RULE_ATTR_MARK, a->r_mark != b->r_mark); + diff |= _DIFF(RULE_ATTR_MASK, a->r_mask != b->r_mask); + diff |= _DIFF(RULE_ATTR_GOTO, a->r_goto != b->r_goto); + diff |= _DIFF(RULE_ATTR_SRC, nl_addr_cmp(a->r_src, b->r_src)); + diff |= _DIFF(RULE_ATTR_DST, nl_addr_cmp(a->r_dst, b->r_dst)); + diff |= _DIFF(RULE_ATTR_DSFIELD, a->r_dsfield != b->r_dsfield); + diff |= _DIFF(RULE_ATTR_FLOW, a->r_flow != b->r_flow); +#undef _DIFF return diff; } static const struct trans_tbl rule_attrs[] = { - __ADD(RULE_ATTR_FAMILY, family) - __ADD(RULE_ATTR_TABLE, table) - __ADD(RULE_ATTR_ACTION, action) - __ADD(RULE_ATTR_IIFNAME, iifname) - __ADD(RULE_ATTR_OIFNAME, oifname) - __ADD(RULE_ATTR_PRIO, prio) - __ADD(RULE_ATTR_MARK, mark) - __ADD(RULE_ATTR_MASK, mask) - __ADD(RULE_ATTR_GOTO, goto) - __ADD(RULE_ATTR_SRC, src) - __ADD(RULE_ATTR_DST, dst) - __ADD(RULE_ATTR_DSFIELD, dsfield) - __ADD(RULE_ATTR_FLOW, flow) + __ADD(RULE_ATTR_FAMILY, family), + __ADD(RULE_ATTR_TABLE, table), + __ADD(RULE_ATTR_ACTION, action), + __ADD(RULE_ATTR_IIFNAME, iifname), + __ADD(RULE_ATTR_OIFNAME, oifname), + __ADD(RULE_ATTR_PRIO, prio), + __ADD(RULE_ATTR_MARK, mark), + __ADD(RULE_ATTR_MASK, mask), + __ADD(RULE_ATTR_GOTO, goto), + __ADD(RULE_ATTR_SRC, src), + __ADD(RULE_ATTR_DST, dst), + __ADD(RULE_ATTR_DSFIELD, dsfield), + __ADD(RULE_ATTR_FLOW, flow), }; static char *rule_attrs2str(int attrs, char *buf, size_t len) @@ -414,6 +509,22 @@ static int build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags, if (tmpl->ce_mask & RULE_ATTR_FLOW) NLA_PUT_U32(msg, FRA_FLOW, tmpl->r_flow); + if (tmpl->ce_mask & RULE_ATTR_L3MDEV) + NLA_PUT_U8(msg, FRA_L3MDEV, tmpl->r_l3mdev); + + if (tmpl->ce_mask & RULE_ATTR_IP_PROTO) + NLA_PUT_U8(msg, FRA_IP_PROTO, tmpl->r_ip_proto); + + if (tmpl->ce_mask & RULE_ATTR_SPORT) + NLA_PUT(msg, FRA_SPORT_RANGE, sizeof(tmpl->r_sport), + &tmpl->r_sport); + + if (tmpl->ce_mask & RULE_ATTR_DPORT) + NLA_PUT(msg, FRA_DPORT_RANGE, sizeof(tmpl->r_dport), + &tmpl->r_dport); + + if (tmpl->ce_mask & RULE_ATTR_PROTOCOL) + NLA_PUT_U8(msg, FRA_PROTOCOL, tmpl->r_protocol); *result = msg; return 0; @@ -454,7 +565,7 @@ int rtnl_rule_build_add_request(struct rtnl_rule *tmpl, int flags, * sends the request to the kernel and waits for the next ACK to be * received and thus blocks until the request has been fullfilled. * - * @return 0 on sucess or a negative error if an error occured. + * @return 0 on success or a negative error if an error occured. */ int rtnl_rule_add(struct nl_sock *sk, struct rtnl_rule *tmpl, int flags) { @@ -509,7 +620,7 @@ int rtnl_rule_build_delete_request(struct rtnl_rule *rule, int flags, * sends the request to the kernel and waits for the next ACK to be * received and thus blocks until the request has been fullfilled. * - * @return 0 on sucess or a negative error if an error occured. + * @return 0 on success or a negative error if an error occured. */ int rtnl_rule_delete(struct nl_sock *sk, struct rtnl_rule *rule, int flags) { @@ -690,6 +801,152 @@ uint8_t rtnl_rule_get_action(struct rtnl_rule *rule) return rule->r_action; } +/** + * Set l3mdev value of the rule (FRA_L3MDEV) + * @arg rule rule + * @arg value value to set + * + * Set the l3mdev value to value. Currently supported values + * are only 1 (set it) and -1 (unset it). All other values + * are reserved. + */ +void rtnl_rule_set_l3mdev(struct rtnl_rule *rule, int value) +{ + if (value >= 0) { + rule->r_l3mdev = (uint8_t) value; + rule->ce_mask |= RULE_ATTR_L3MDEV; + } else { + rule->r_l3mdev = 0; + rule->ce_mask &= ~((uint32_t) RULE_ATTR_L3MDEV); + } +} + +/** + * Get l3mdev value of the rule (FRA_L3MDEV) + * @arg rule rule + * + * @return a negative error code, including -NLE_MISSING_ATTR + * if the property is unset. Otherwise returns a non-negative + * value. As FRA_L3MDEV is a boolean, the only expected + * value at the moment is 1. + */ +int rtnl_rule_get_l3mdev(struct rtnl_rule *rule) +{ + if (!rule) + return -NLE_INVAL; + if (!(rule->ce_mask & RULE_ATTR_L3MDEV)) + return -NLE_MISSING_ATTR; + return rule->r_l3mdev; +} + +int rtnl_rule_set_protocol(struct rtnl_rule *rule, uint8_t protocol) +{ + if (protocol) { + rule->r_protocol = protocol; + rule->ce_mask |= RULE_ATTR_PROTOCOL; + } else { + rule->r_protocol = 0; + rule->ce_mask &= ~((uint32_t) RULE_ATTR_PROTOCOL); + } + return 0; +} + +int rtnl_rule_get_protocol(struct rtnl_rule *rule, uint8_t *protocol) +{ + if (!(rule->ce_mask & RULE_ATTR_PROTOCOL)) + return -NLE_INVAL; + + *protocol = rule->r_protocol; + return 0; +} + +int rtnl_rule_set_ipproto(struct rtnl_rule *rule, uint8_t ip_proto) +{ + if (ip_proto) { + rule->r_ip_proto = ip_proto; + rule->ce_mask |= RULE_ATTR_IP_PROTO; + } else { + rule->r_ip_proto = 0; + rule->ce_mask &= ~((uint32_t) RULE_ATTR_IP_PROTO); + } + return 0; +} + +int rtnl_rule_get_ipproto(struct rtnl_rule *rule, uint8_t *ip_proto) +{ + if (!(rule->ce_mask & RULE_ATTR_IP_PROTO)) + return -NLE_INVAL; + + *ip_proto = rule->r_ip_proto; + return 0; +} + +static int __rtnl_rule_set_port(struct fib_rule_port_range *prange, + uint16_t start, uint16_t end, + uint64_t attr, uint64_t *mask) +{ + if ((start && end < start) || (end && !start)) + return -NLE_INVAL; + + if (start) { + prange->start = start; + prange->end = end; + *mask |= attr; + } else { + prange->start = 0; + prange->end = 0; + *mask &= ~attr; + + } + return 0; +} + +int rtnl_rule_set_sport(struct rtnl_rule *rule, uint16_t sport) +{ + return __rtnl_rule_set_port(&rule->r_sport, sport, sport, + RULE_ATTR_SPORT, &rule->ce_mask); +} + +int rtnl_rule_set_sport_range(struct rtnl_rule *rule, uint16_t start, + uint16_t end) +{ + return __rtnl_rule_set_port(&rule->r_sport, start, end, + RULE_ATTR_SPORT, &rule->ce_mask); +} + +int rtnl_rule_get_sport(struct rtnl_rule *rule, uint16_t *start, uint16_t *end) +{ + if (!(rule->ce_mask & RULE_ATTR_SPORT)) + return -NLE_INVAL; + + *start = rule->r_sport.start; + *end = rule->r_sport.end; + return 0; +} + +int rtnl_rule_set_dport(struct rtnl_rule *rule, uint16_t dport) +{ + return __rtnl_rule_set_port(&rule->r_dport, dport, dport, + RULE_ATTR_DPORT, &rule->ce_mask); +} + +int rtnl_rule_set_dport_range(struct rtnl_rule *rule, uint16_t start, + uint16_t end) +{ + return __rtnl_rule_set_port(&rule->r_dport, start, end, + RULE_ATTR_DPORT, &rule->ce_mask); +} + +int rtnl_rule_get_dport(struct rtnl_rule *rule, uint16_t *start, uint16_t *end) +{ + if (!(rule->ce_mask & RULE_ATTR_DPORT)) + return -NLE_INVAL; + + *start = rule->r_dport.start; + *end = rule->r_dport.end; + return 0; +} + void rtnl_rule_set_realms(struct rtnl_rule *rule, uint32_t realms) { rule->r_flow = realms; @@ -729,6 +986,12 @@ static struct nl_object_ops rule_obj_ops = { .oo_id_attrs = ~0, }; +static struct nl_af_group rule_groups[] = { + { AF_INET, RTNLGRP_IPV4_RULE }, + { AF_INET6, RTNLGRP_IPV6_RULE }, + { END_OF_GROUP_LIST }, +}; + static struct nl_cache_ops rtnl_rule_ops = { .co_name = "route/rule", .co_hdrsize = sizeof(struct fib_rule_hdr), @@ -742,14 +1005,15 @@ static struct nl_cache_ops rtnl_rule_ops = { .co_request_update = rule_request_update, .co_msg_parser = rule_msg_parser, .co_obj_ops = &rule_obj_ops, + .co_groups = rule_groups, }; -static void __init rule_init(void) +static void _nl_init rule_init(void) { nl_cache_mngt_register(&rtnl_rule_ops); } -static void __exit rule_exit(void) +static void _nl_exit rule_exit(void) { nl_cache_mngt_unregister(&rtnl_rule_ops); } diff --git a/lib/route/tc-api.h b/lib/route/tc-api.h new file mode 100644 index 0000000..43c4a28 --- /dev/null +++ b/lib/route/tc-api.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2011-2013 Thomas Graf + */ + +#ifndef NETLINK_TC_API_H_ +#define NETLINK_TC_API_H_ + +#include +#include +#include + +#include "nl-route.h" +#include "nl-priv-dynamic-route/nl-priv-dynamic-route.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" + +/*****************************************************************************/ + +#define TCA_ATTR_HANDLE 0x0001 +#define TCA_ATTR_PARENT 0x0002 +#define TCA_ATTR_IFINDEX 0x0004 +#define TCA_ATTR_KIND 0x0008 +#define TCA_ATTR_FAMILY 0x0010 +#define TCA_ATTR_INFO 0x0020 +#define TCA_ATTR_OPTS 0x0040 +#define TCA_ATTR_STATS 0x0080 +#define TCA_ATTR_XSTATS 0x0100 +#define TCA_ATTR_LINK 0x0200 +#define TCA_ATTR_MTU 0x0400 +#define TCA_ATTR_MPU 0x0800 +#define TCA_ATTR_OVERHEAD 0x1000 +#define TCA_ATTR_LINKTYPE 0x2000 +#define TCA_ATTR_CHAIN 0x4000 +#define TCA_ATTR_MAX TCA_ATTR_CHAIN + +extern int tca_parse(struct nlattr **, int, struct rtnl_tc *, + const struct nla_policy *); + +#define RTNL_TC_RTABLE_SIZE 256 + +static inline void *tca_xstats(struct rtnl_tc *tca) +{ + return tca->tc_xstats->d_data; +} + +extern struct nl_af_group tc_groups[]; + +/*****************************************************************************/ + +struct rtnl_tc_type_ops +{ + enum rtnl_tc_type tt_type; + + char *tt_dump_prefix; + + /** + * Dump callbacks + */ + void (*tt_dump[NL_DUMP_MAX+1])(struct rtnl_tc *, + struct nl_dump_params *); +}; + +void *rtnl_tc_data_peek(struct rtnl_tc *tc); + +/*****************************************************************************/ + +/* WARNING: the following symbols are wrongly exported in libnl-route-3 + * library. They are private API, but leaked. */ +extern int rtnl_tc_msg_parse(struct nlmsghdr *, + struct rtnl_tc *); +extern int rtnl_tc_msg_build(struct rtnl_tc *, int, + int, struct nl_msg **); + +extern void rtnl_tc_free_data(struct nl_object *); +extern int rtnl_tc_clone(struct nl_object *, + struct nl_object *); +extern void rtnl_tc_dump_line(struct nl_object *, + struct nl_dump_params *); +extern void rtnl_tc_dump_details(struct nl_object *, + struct nl_dump_params *); +extern void rtnl_tc_dump_stats(struct nl_object *, + struct nl_dump_params *); +extern uint64_t rtnl_tc_compare(struct nl_object *, + struct nl_object *, + uint64_t, int); + +extern void * rtnl_tc_data(struct rtnl_tc *); +extern void * rtnl_tc_data_check(struct rtnl_tc *, + struct rtnl_tc_ops *, int *); + +extern int rtnl_tc_register(struct rtnl_tc_ops *); +extern void rtnl_tc_unregister(struct rtnl_tc_ops *); + +extern void rtnl_tc_type_register(struct rtnl_tc_type_ops *); +extern void rtnl_tc_type_unregister(struct rtnl_tc_type_ops *); + + +extern int rtnl_tc_build_rate_table(struct rtnl_tc *tc, struct rtnl_ratespec *, + uint32_t *); + +/*****************************************************************************/ + +#endif diff --git a/lib/route/tc.c b/lib/route/tc.c index 29954fd..a2fd567 100644 --- a/lib/route/tc.c +++ b/lib/route/tc.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/route/tc.c Traffic Control - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2011 Thomas Graf */ @@ -15,14 +9,20 @@ * @{ */ -#include -#include +#include "nl-default.h" + +#include +#include + +#include + #include #include #include #include #include -#include + +#include "tc-api.h" /** @cond SKIP */ @@ -32,12 +32,13 @@ static struct rtnl_tc_type_ops *tc_type_ops[__RTNL_TC_TYPE_MAX]; static struct nla_policy tc_policy[TCA_MAX+1] = { [TCA_KIND] = { .type = NLA_STRING, .maxlen = TCKINDSIZ }, + [TCA_CHAIN] = { .type = NLA_U32 }, [TCA_STATS] = { .minlen = sizeof(struct tc_stats) }, [TCA_STATS2] = { .type = NLA_NESTED }, }; int tca_parse(struct nlattr **tb, int maxattr, struct rtnl_tc *g, - struct nla_policy *policy) + const struct nla_policy *policy) { if (g->ce_mask & TCA_ATTR_OPTS) @@ -79,6 +80,9 @@ int rtnl_tc_msg_parse(struct nlmsghdr *n, struct rtnl_tc *tc) nla_strlcpy(kind, tb[TCA_KIND], sizeof(kind)); rtnl_tc_set_kind(tc, kind); + if (tb[TCA_CHAIN]) + rtnl_tc_set_chain(tc, nla_get_u32(tb[TCA_CHAIN])); + tm = nlmsg_data(n); tc->tc_family = tm->tcm_family; tc->tc_ifindex = tm->tcm_ifindex; @@ -105,11 +109,11 @@ int rtnl_tc_msg_parse(struct nlmsghdr *n, struct rtnl_tc *tc) return err; if (tbs[TCA_STATS_BASIC]) { - struct gnet_stats_basic *bs; + struct gnet_stats_basic bs; - bs = nla_data(tbs[TCA_STATS_BASIC]); - tc->tc_stats[RTNL_TC_BYTES] = bs->bytes; - tc->tc_stats[RTNL_TC_PACKETS] = bs->packets; + memcpy(&bs, nla_data(tbs[TCA_STATS_BASIC]), sizeof(bs)); + tc->tc_stats[RTNL_TC_BYTES] = bs.bytes; + tc->tc_stats[RTNL_TC_PACKETS] = bs.packets; } if (tbs[TCA_STATS_RATE_EST]) { @@ -137,20 +141,22 @@ int rtnl_tc_msg_parse(struct nlmsghdr *n, struct rtnl_tc *tc) tc->tc_xstats = nl_data_alloc_attr(tbs[TCA_STATS_APP]); if (tc->tc_xstats == NULL) return -NLE_NOMEM; + tc->ce_mask |= TCA_ATTR_XSTATS; } else goto compat_xstats; } else { if (tb[TCA_STATS]) { - struct tc_stats *st = nla_data(tb[TCA_STATS]); - - tc->tc_stats[RTNL_TC_BYTES] = st->bytes; - tc->tc_stats[RTNL_TC_PACKETS] = st->packets; - tc->tc_stats[RTNL_TC_RATE_BPS] = st->bps; - tc->tc_stats[RTNL_TC_RATE_PPS] = st->pps; - tc->tc_stats[RTNL_TC_QLEN] = st->qlen; - tc->tc_stats[RTNL_TC_BACKLOG] = st->backlog; - tc->tc_stats[RTNL_TC_DROPS] = st->drops; - tc->tc_stats[RTNL_TC_OVERLIMITS]= st->overlimits; + struct tc_stats st; + + memcpy(&st, nla_data(tb[TCA_STATS]), sizeof(st)); + tc->tc_stats[RTNL_TC_BYTES] = st.bytes; + tc->tc_stats[RTNL_TC_PACKETS] = st.packets; + tc->tc_stats[RTNL_TC_RATE_BPS] = st.bps; + tc->tc_stats[RTNL_TC_RATE_PPS] = st.pps; + tc->tc_stats[RTNL_TC_QLEN] = st.qlen; + tc->tc_stats[RTNL_TC_BACKLOG] = st.backlog; + tc->tc_stats[RTNL_TC_DROPS] = st.drops; + tc->tc_stats[RTNL_TC_OVERLIMITS]= st.overlimits; tc->ce_mask |= TCA_ATTR_STATS; } @@ -201,46 +207,55 @@ int rtnl_tc_msg_build(struct rtnl_tc *tc, int type, int flags, .tcm_handle = tc->tc_handle, .tcm_parent = tc->tc_parent, }; - int err = -NLE_MSGSIZE; + int err; msg = nlmsg_alloc_simple(type, flags); if (!msg) return -NLE_NOMEM; - if (nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO) < 0) - goto nla_put_failure; + if (nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO) < 0) { + err = -NLE_MSGSIZE; + goto out_err; + } if (tc->ce_mask & TCA_ATTR_KIND) - NLA_PUT_STRING(msg, TCA_KIND, tc->tc_kind); + NLA_PUT_STRING(msg, TCA_KIND, tc->tc_kind); + + if (tc->ce_mask & TCA_ATTR_CHAIN) + NLA_PUT_U32(msg, TCA_CHAIN, tc->tc_chain); ops = rtnl_tc_get_ops(tc); - if (ops && ops->to_msg_fill) { + if (ops && (ops->to_msg_fill || ops->to_msg_fill_raw)) { struct nlattr *opts; void *data = rtnl_tc_data(tc); - if (!(opts = nla_nest_start(msg, TCA_OPTIONS))) - goto nla_put_failure; - - if ((err = ops->to_msg_fill(tc, data, msg)) < 0) - goto nla_put_failure; - - nla_nest_end(msg, opts); + if (ops->to_msg_fill) { + if (!(opts = nla_nest_start(msg, TCA_OPTIONS))) { + err = -NLE_NOMEM; + goto out_err; + } + + if ((err = ops->to_msg_fill(tc, data, msg)) < 0) + goto out_err; + + if (strcmp("cgroup", tc->tc_kind)) + nla_nest_end(msg, opts); + else + nla_nest_end_keep_empty(msg, opts); + } else if ((err = ops->to_msg_fill_raw(tc, data, msg)) < 0) + goto out_err; } *result = msg; return 0; nla_put_failure: + err = -NLE_NOMEM; +out_err: nlmsg_free(msg); return err; } -void tca_set_kind(struct rtnl_tc *t, const char *kind) -{ - strncpy(t->tc_kind, kind, sizeof(t->tc_kind) - 1); - t->ce_mask |= TCA_ATTR_KIND; -} - /** @endcond */ @@ -297,6 +312,8 @@ void rtnl_tc_set_link(struct rtnl_tc *tc, struct rtnl_link *link) if (!link) return; + if (!link->l_index) + BUG(); nl_object_get(OBJ_CAST(link)); tc->tc_link = link; @@ -513,7 +530,12 @@ int rtnl_tc_set_kind(struct rtnl_tc *tc, const char *kind) if (tc->ce_mask & TCA_ATTR_KIND) return -NLE_EXIST; - strncpy(tc->tc_kind, kind, sizeof(tc->tc_kind) - 1); + if ( !kind + || strlen (kind) >= sizeof (tc->tc_kind)) + return -NLE_INVAL; + + _nl_strncpy_assert(tc->tc_kind, kind, sizeof(tc->tc_kind)); + tc->ce_mask |= TCA_ATTR_KIND; /* Force allocation of data */ @@ -545,12 +567,40 @@ char *rtnl_tc_get_kind(struct rtnl_tc *tc) */ uint64_t rtnl_tc_get_stat(struct rtnl_tc *tc, enum rtnl_tc_stat id) { - if (id < 0 || id > RTNL_TC_STATS_MAX) + if ((unsigned int) id > RTNL_TC_STATS_MAX) return 0; return tc->tc_stats[id]; } +/** + * Set the chain index of a traffic control object + * @arg tc traffic control object + * @arg chain chain index of traffic control object + * + */ +void rtnl_tc_set_chain(struct rtnl_tc *tc, uint32_t chain) +{ + tc->tc_chain = chain; + tc->ce_mask |= TCA_ATTR_CHAIN; +} + +/** + * Return chain index of traffic control object + * @arg tc traffic control object + * @arg out_value output argument. + * + * @return 0 of the output value was successfully returned, or a negative + * error code on failure. + */ +int rtnl_tc_get_chain(struct rtnl_tc *tc, uint32_t *out_value) +{ + if (!(tc->ce_mask & TCA_ATTR_CHAIN)) + return -NLE_MISSING_ATTR; + *out_value = tc->tc_chain; + return 0; +} + /** @} */ /** @@ -558,6 +608,28 @@ uint64_t rtnl_tc_get_stat(struct rtnl_tc *tc, enum rtnl_tc_stat id) * @{ */ +static const struct trans_tbl tc_stats[] = { + __ADD(RTNL_TC_PACKETS, packets), + __ADD(RTNL_TC_BYTES, bytes), + __ADD(RTNL_TC_RATE_BPS, rate_bps), + __ADD(RTNL_TC_RATE_PPS, rate_pps), + __ADD(RTNL_TC_QLEN, qlen), + __ADD(RTNL_TC_BACKLOG, backlog), + __ADD(RTNL_TC_DROPS, drops), + __ADD(RTNL_TC_REQUEUES, requeues), + __ADD(RTNL_TC_OVERLIMITS, overlimits), +}; + +char *rtnl_tc_stat2str(enum rtnl_tc_stat st, char *buf, size_t len) +{ + return __type2str(st, buf, len, tc_stats, ARRAY_SIZE(tc_stats)); +} + +int rtnl_tc_str2stat(const char *name) +{ + return __str2type(name, tc_stats, ARRAY_SIZE(tc_stats)); +} + /** * Calculate time required to transmit buffer at a specific rate * @arg bufsize Size of buffer to be transmited in bytes. @@ -574,11 +646,7 @@ uint64_t rtnl_tc_get_stat(struct rtnl_tc *tc, enum rtnl_tc_stat id) */ int rtnl_tc_calc_txtime(int bufsize, int rate) { - double tx_time_secs; - - tx_time_secs = (double) bufsize / (double) rate; - - return tx_time_secs * 1000000.; + return ((double) bufsize / (double) rate) * 1000000.0; } /** @@ -597,24 +665,20 @@ int rtnl_tc_calc_txtime(int bufsize, int rate) */ int rtnl_tc_calc_bufsize(int txtime, int rate) { - double bufsize; - - bufsize = (double) txtime * (double) rate; - - return bufsize / 1000000.; + return ((double) txtime * (double) rate) / 1000000.0; } /** * Calculate the binary logarithm for a specific cell size * @arg cell_size Size of cell, must be a power of two. - * @return Binary logirhtm of cell size or a negative error code. + * @return Binary logarithm of cell size or a negative error code. */ int rtnl_tc_calc_cell_log(int cell_size) { int i; for (i = 0; i < 32; i++) - if ((1 << i) == cell_size) + if ((((uint32_t)1u) << i) == cell_size) return i; return -NLE_INVAL; @@ -710,7 +774,7 @@ int rtnl_tc_build_rate_table(struct rtnl_tc *tc, struct rtnl_ratespec *spec, for (i = 0; i < RTNL_TC_RTABLE_SIZE; i++) { size = adjust_size((i + 1) << cell_log, spec->rs_mpu, linktype); - dst[i] = nl_us2ticks(rtnl_tc_calc_txtime(size, spec->rs_rate)); + dst[i] = nl_us2ticks(rtnl_tc_calc_txtime64(size, spec->rs_rate64)); } spec->rs_cell_align = -1; @@ -749,39 +813,51 @@ int rtnl_tc_clone(struct nl_object *dstobj, struct nl_object *srcobj) struct rtnl_tc *src = TC_CAST(srcobj); struct rtnl_tc_ops *ops; + dst->tc_opts = NULL; + dst->tc_xstats = NULL; + dst->tc_subdata = NULL; + dst->tc_link = NULL; + dst->tc_ops = NULL; + if (src->tc_link) { nl_object_get(OBJ_CAST(src->tc_link)); dst->tc_link = src->tc_link; } + dst->ce_mask &= ~(TCA_ATTR_OPTS | + TCA_ATTR_XSTATS); + if (src->tc_opts) { dst->tc_opts = nl_data_clone(src->tc_opts); if (!dst->tc_opts) return -NLE_NOMEM; + dst->ce_mask |= TCA_ATTR_OPTS; } - + if (src->tc_xstats) { dst->tc_xstats = nl_data_clone(src->tc_xstats); if (!dst->tc_xstats) return -NLE_NOMEM; + dst->ce_mask |= TCA_ATTR_XSTATS; } if (src->tc_subdata) { if (!(dst->tc_subdata = nl_data_clone(src->tc_subdata))) { return -NLE_NOMEM; } - } - - ops = rtnl_tc_get_ops(src); - if (ops && ops->to_clone) { - void *a = rtnl_tc_data(dst), *b = rtnl_tc_data(src); - - if (!a) - return 0; - else if (!b) - return -NLE_NOMEM; - return ops->to_clone(a, b); + /* Warning: if the data contains pointer, then at this point, dst->tc_subdata + * will alias those pointers. + * + * ops->to_clone() MUST fix that. + * + * If the type is actually "struct rtnl_act", then to_clone() must also + * fix dangling "a_next" pointer. */ + + ops = rtnl_tc_get_ops(src); + if (ops && ops->to_clone) { + return ops->to_clone(rtnl_tc_data(dst), rtnl_tc_data(src)); + } } return 0; @@ -867,56 +943,45 @@ void rtnl_tc_dump_details(struct nl_object *obj, struct nl_dump_params *p) void rtnl_tc_dump_stats(struct nl_object *obj, struct nl_dump_params *p) { struct rtnl_tc *tc = TC_CAST(obj); - char *unit, fmt[64]; + char *unit; float res; rtnl_tc_dump_details(OBJ_CAST(tc), p); - strcpy(fmt, " %7.2f %s %10u %10u %10u %10u %10u\n"); - - nl_dump_line(p, - " Stats: bytes packets drops overlimits" \ - " qlen backlog\n"); + nl_dump_line(p, + " stats: %-14s %-10s %-10s %-10s %-10s %-10s\n", + "bytes", "packets", "drops", "overlimits", "qlen", "backlog"); res = nl_cancel_down_bytes(tc->tc_stats[RTNL_TC_BYTES], &unit); - if (*unit == 'B') - fmt[11] = '9'; - nl_dump_line(p, fmt, res, unit, - tc->tc_stats[RTNL_TC_PACKETS], - tc->tc_stats[RTNL_TC_DROPS], - tc->tc_stats[RTNL_TC_OVERLIMITS], - tc->tc_stats[RTNL_TC_QLEN], - tc->tc_stats[RTNL_TC_BACKLOG]); + nl_dump_line( + p, + " %10.2f %3s %10llu %-10llu %-10llu %-10llu %-10llu\n", + res, unit, (long long unsigned)tc->tc_stats[RTNL_TC_PACKETS], + (long long unsigned)tc->tc_stats[RTNL_TC_DROPS], + (long long unsigned)tc->tc_stats[RTNL_TC_OVERLIMITS], + (long long unsigned)tc->tc_stats[RTNL_TC_QLEN], + (long long unsigned)tc->tc_stats[RTNL_TC_BACKLOG]); res = nl_cancel_down_bytes(tc->tc_stats[RTNL_TC_RATE_BPS], &unit); - strcpy(fmt, " %7.2f %s/s%9u pps"); - - if (*unit == 'B') - fmt[11] = '9'; - - nl_dump_line(p, fmt, res, unit, tc->tc_stats[RTNL_TC_RATE_PPS]); - - tc_dump(tc, NL_DUMP_LINE, p); - nl_dump(p, "\n"); + nl_dump_line(p, " %10.2f %3s/s %10llu/s\n", res, unit, + (long long unsigned)tc->tc_stats[RTNL_TC_RATE_PPS]); } -int rtnl_tc_compare(struct nl_object *aobj, struct nl_object *bobj, - uint32_t attrs, int flags) +uint64_t rtnl_tc_compare(struct nl_object *aobj, struct nl_object *bobj, + uint64_t attrs, int flags) { struct rtnl_tc *a = TC_CAST(aobj); struct rtnl_tc *b = TC_CAST(bobj); - int diff = 0; - -#define TC_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, TCA_ATTR_##ATTR, a, b, EXPR) - - diff |= TC_DIFF(HANDLE, a->tc_handle != b->tc_handle); - diff |= TC_DIFF(PARENT, a->tc_parent != b->tc_parent); - diff |= TC_DIFF(IFINDEX, a->tc_ifindex != b->tc_ifindex); - diff |= TC_DIFF(KIND, strcmp(a->tc_kind, b->tc_kind)); + uint64_t diff = 0; -#undef TC_DIFF +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(TCA_ATTR_HANDLE, a->tc_handle != b->tc_handle); + diff |= _DIFF(TCA_ATTR_PARENT, a->tc_parent != b->tc_parent); + diff |= _DIFF(TCA_ATTR_IFINDEX, a->tc_ifindex != b->tc_ifindex); + diff |= _DIFF(TCA_ATTR_KIND, strcmp(a->tc_kind, b->tc_kind)); +#undef _DIFF return diff; } @@ -957,7 +1022,7 @@ int rtnl_tc_register(struct rtnl_tc_ops *ops) /* * Initialiation hack, make sure list is initialized when * the first tc module registers. Putting this in a - * separate __init would required correct ordering of init + * separate _nl_init would required correct ordering of init * functions */ if (!init) { @@ -990,6 +1055,19 @@ void rtnl_tc_unregister(struct rtnl_tc_ops *ops) } /** + * Returns the private data of the traffic control object. + * Contrary to rtnl_tc_data(), this returns NULL if the data is + * not yet allocated + * @arg tc traffic control object + * + * @return pointer to the private data or NULL if not allocated. + */ +void *rtnl_tc_data_peek(struct rtnl_tc *tc) +{ + return tc->tc_subdata ? nl_data_get(tc->tc_subdata) : NULL; +} + +/** * Return pointer to private data of traffic control object * @arg tc traffic control object * @@ -1004,9 +1082,6 @@ void *rtnl_tc_data(struct rtnl_tc *tc) size_t size; if (!tc->tc_ops) { - if (!tc->tc_kind) - BUG(); - if (!rtnl_tc_get_ops(tc)) return NULL; } @@ -1025,6 +1100,7 @@ void *rtnl_tc_data(struct rtnl_tc *tc) * Check traffic control object type and return private data section * @arg tc traffic control object * @arg ops expected traffic control object operations + * @arg err the place where saves the error code if fails * * Checks whether the traffic control object matches the type * specified with the traffic control object operations. If the @@ -1035,8 +1111,10 @@ void *rtnl_tc_data(struct rtnl_tc *tc) * * @return Pointer to private tc data or NULL if type mismatches. */ -void *rtnl_tc_data_check(struct rtnl_tc *tc, struct rtnl_tc_ops *ops) +void *rtnl_tc_data_check(struct rtnl_tc *tc, struct rtnl_tc_ops *ops, int *err) { + void *ret; + if (tc->tc_ops != ops) { char buf[64]; @@ -1045,12 +1123,26 @@ void *rtnl_tc_data_check(struct rtnl_tc *tc, struct rtnl_tc_ops *ops) tc, ops->to_kind, tc->tc_ops->to_kind); APPBUG(buf); + if (err) + *err = -NLE_OPNOTSUPP; return NULL; } - return rtnl_tc_data(tc); + ret = rtnl_tc_data(tc); + if (ret == NULL) { + if (err) + *err = -NLE_NOMEM; + } + + return ret; } +struct nl_af_group tc_groups[] = { + { AF_UNSPEC, RTNLGRP_TC }, + { END_OF_GROUP_LIST }, +}; + + void rtnl_tc_type_register(struct rtnl_tc_type_ops *ops) { if (ops->tt_type > RTNL_TC_TYPE_MAX) diff --git a/lib/socket.c b/lib/socket.c index 1ca7783..9b42f67 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/socket.c Netlink Socket - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -27,18 +21,28 @@ * ~~~~ */ -#include "defs.h" +#include "nl-default.h" + +#include +#include -#include #include #include #include #include #include +#include "nl-core.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-aux-core/nl-core.h" + +#ifndef SOL_NETLINK +#define SOL_NETLINK 270 +#endif + static int default_cb = NL_CB_DEFAULT; -static void __init init_default_cb(void) +static void _nl_init init_default_cb(void) { char *nlcb; @@ -56,21 +60,63 @@ static void __init init_default_cb(void) } } +static uint32_t _badrandom_from_time(void) +{ + uint32_t result; + uint64_t v64; + time_t t; + + t = time(NULL); + v64 = (uint64_t)t; + result = (uint32_t)v64; + + /* XOR with the upper bits. Otherwise, coverity warns about only + * considering 32 bit from time_t. Use the inverse, so that for the + * most part the bits don't change. */ + result ^= (~(v64 >> 32)); + + return result; +} + static uint32_t used_ports_map[32]; static NL_RW_LOCK(port_map_lock); static uint32_t generate_local_port(void) { - int i, n; + int i, j, m; + uint16_t n; + static uint16_t idx_state = 0; uint32_t pid = getpid() & 0x3FFFFF; nl_write_lock(&port_map_lock); - for (i = 0; i < 32; i++) { + if (idx_state == 0) { + uint32_t t = _badrandom_from_time(); + + /* from time to time (on average each 2^15 calls), the idx_state will + * be zero again. No problem, just "seed" anew with time(). */ + idx_state = t ^ (t >> 16) ^ 0x3047; + } else + idx_state = idx_state + 20011; /* add prime number */ + + i = idx_state >> 5; + n = idx_state; + for (j = 0; j < 32; j++) { + /* walk the index somewhat randomized, with always leaving the block + * #0 as last. The reason is that libnl-1 will start at block #0, + * so just leave the first 32 ports preferably for libnl-1 owned sockets + * (this is relevant only if the applications ends up using both versions + * of the library and doesn't hurt otherwise). */ + if (j == 31) + i = 0; + else + i = (((i-1) + 7) % 31) + 1; + if (used_ports_map[i] == 0xFFFFFFFF) continue; - for (n = 0; n < 32; n++) { + for (m = 0; m < 32; m++) { + n = (n + 13u) % 32u; if (1UL & (used_ports_map[i] >> n)) continue; @@ -82,30 +128,69 @@ static uint32_t generate_local_port(void) nl_write_unlock(&port_map_lock); - return pid + (n << 22); + /* ensure we don't return zero. */ + pid = pid + (n << 22); + return pid ? pid : 1024; } } nl_write_unlock(&port_map_lock); - - /* Out of sockets in our own PID namespace, what to do? FIXME */ - return UINT_MAX; + return 0; } static void release_local_port(uint32_t port) { int nr; + uint32_t mask; + + BUG_ON(port == 0); - if (port == UINT_MAX) - return; - nr = port >> 22; + mask = 1UL << (nr % 32); + nr /= 32; nl_write_lock(&port_map_lock); - used_ports_map[nr / 32] &= ~(1 << (nr % 32)); + BUG_ON((used_ports_map[nr] & mask) != mask); + used_ports_map[nr] &= ~mask; nl_write_unlock(&port_map_lock); } +/** \cond skip */ +void _nl_socket_used_ports_release_all(const uint32_t *used_ports) +{ + int i; + + for (i = 0; i < 32; i++) { + if (used_ports[i] != 0) { + nl_write_lock(&port_map_lock); + for (; i < 32; i++) { + BUG_ON((used_ports_map[i] & used_ports[i]) != used_ports[i]); + used_ports_map[i] &= ~(used_ports[i]); + } + nl_write_unlock(&port_map_lock); + return; + } + } +} + +void _nl_socket_used_ports_set(uint32_t *used_ports, uint32_t port) +{ + int nr; + int32_t mask; + + nr = port >> 22; + mask = 1UL << (nr % 32); + nr /= 32; + + /* + BUG_ON(port == 0 || (getpid() & 0x3FFFFF) != (port & 0x3FFFFF)); + BUG_ON(used_ports[nr] & mask); + */ + + used_ports[nr] |= mask; +} +/** \endcond */ + /** * @name Allocation * @{ @@ -123,12 +208,11 @@ static struct nl_sock *__alloc_socket(struct nl_cb *cb) sk->s_cb = nl_cb_get(cb); sk->s_local.nl_family = AF_NETLINK; sk->s_peer.nl_family = AF_NETLINK; - sk->s_seq_expect = sk->s_seq_next = time(0); - sk->s_local.nl_pid = generate_local_port(); - if (sk->s_local.nl_pid == UINT_MAX) { - nl_socket_free(sk); - return NULL; - } + sk->s_seq_next = _badrandom_from_time(); + sk->s_seq_expect = sk->s_seq_next; + + /* the port is 0 (unspecified), meaning NL_OWN_PORT */ + sk->s_flags = NL_OWN_PORT; return sk; } @@ -141,18 +225,18 @@ static struct nl_sock *__alloc_socket(struct nl_cb *cb) struct nl_sock *nl_socket_alloc(void) { struct nl_cb *cb; - struct nl_sock *sk; + struct nl_sock *sk; cb = nl_cb_alloc(default_cb); if (!cb) return NULL; - /* will increment cb reference count on success */ + /* will increment cb reference count on success */ sk = __alloc_socket(cb); - nl_cb_put(cb); + nl_cb_put(cb); - return sk; + return sk; } /** @@ -264,6 +348,34 @@ void nl_socket_enable_auto_ack(struct nl_sock *sk) /** @} */ +/** \cond skip */ +int _nl_socket_is_local_port_unspecified(struct nl_sock *sk) +{ + return (sk->s_local.nl_pid == 0); +} + +uint32_t _nl_socket_set_local_port_no_release(struct nl_sock *sk, int generate_other) +{ + uint32_t port; + + /* reset the port to generate_local_port(), but do not release + * the previously generated port. */ + + if (generate_other) + port = generate_local_port(); + else + port = 0; + sk->s_local.nl_pid = port; + if (port == 0) { + /* failed to find an unsed port. Restore the socket to have an + * unspecified port. */ + sk->s_flags |= NL_OWN_PORT; + } else + sk->s_flags &= ~NL_OWN_PORT; + return port; +} +/** \endcond */ + /** * @name Source Idenficiation * @{ @@ -271,6 +383,28 @@ void nl_socket_enable_auto_ack(struct nl_sock *sk) uint32_t nl_socket_get_local_port(const struct nl_sock *sk) { + if (sk->s_local.nl_pid == 0) { + struct nl_sock *sk_mutable = (struct nl_sock *) sk; + + /* modify the const argument sk. This is justified, because + * nobody ever saw the local_port from externally. So, we + * initilize it on first use. + * + * Note that this also means that you cannot call this function + * from multiple threads without synchronization. But nl_sock + * is not automatically threadsafe anyway, so the user is not + * allowed to do that. + */ + sk_mutable->s_local.nl_pid = generate_local_port(); + if (sk_mutable->s_local.nl_pid == 0) { + /* could not generate a local port. Assign UINT32_MAX to preserve + * backward compatibility. A user who cares can clear that anyway + * with nl_socket_set_local_port(). */ + sk_mutable->s_local.nl_pid = UINT32_MAX; + sk_mutable->s_flags |= NL_OWN_PORT; + } else + sk_mutable->s_flags &= ~NL_OWN_PORT; + } return sk->s_local.nl_pid; } @@ -279,27 +413,18 @@ uint32_t nl_socket_get_local_port(const struct nl_sock *sk) * @arg sk Netlink socket. * @arg port Local port identifier * - * Assigns a local port identifier to the socket. If port is 0 - * a unique port identifier will be generated automatically. + * Assigns a local port identifier to the socket. + * + * If port is 0, the port is reset to 'unspecified' as it is after newly + * calling nl_socket_alloc(). + * Unspecified means, that the port will be generated automatically later + * on first use (either on nl_socket_get_local_port() or nl_connect()). */ void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port) { - if (port == 0) { - port = generate_local_port(); - /* - * Release local port after generation of a new one to be - * able to change local port using nl_socket_set_local_port(, 0) - */ - if (!(sk->s_flags & NL_OWN_PORT)) - release_local_port(sk->s_local.nl_pid); - else - sk->s_flags &= ~NL_OWN_PORT; - } else { - if (!(sk->s_flags & NL_OWN_PORT)) - release_local_port(sk->s_local.nl_pid); - sk->s_flags |= NL_OWN_PORT; - } - + if (!(sk->s_flags & NL_OWN_PORT)) + release_local_port(sk->s_local.nl_pid); + sk->s_flags |= NL_OWN_PORT; sk->s_local.nl_pid = port; } @@ -324,7 +449,7 @@ void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port) * bitmask definitions for nl_join_groups() are likely to still * be present for backward compatibility reasons. * - * @return 0 on sucess or a negative error code. + * @return 0 on success or a negative error code. */ int nl_socket_add_memberships(struct nl_sock *sk, int group, ...) { @@ -346,6 +471,8 @@ int nl_socket_add_memberships(struct nl_sock *sk, int group, ...) &group, sizeof(group)); if (err < 0) { va_end(ap); + NL_DBG(4, "nl_socket_add_memberships(%p): setsockopt() failed with %d (%s)\n", + sk, errno, nl_strerror_l(errno)); return -nl_syserr2nlerr(errno); } @@ -394,6 +521,8 @@ int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...) &group, sizeof(group)); if (err < 0) { va_end(ap); + NL_DBG(4, "nl_socket_drop_memberships(%p): setsockopt() failed with %d (%s)\n", + sk, errno, nl_strerror_l(errno)); return -nl_syserr2nlerr(errno); } @@ -477,6 +606,114 @@ int nl_socket_get_fd(const struct nl_sock *sk) } /** + * Set the socket file descriptor externally which initializes the + * socket similar to nl_connect(). + * + * @arg sk Netlink socket (required) + * @arg protocol The socket protocol (optional). Linux 2.6.32 supports + * the socket option SO_PROTOCOL. In this case, you can set + * protocol to a negative value and let it autodetect. + * If you set it to a non-negative value, the detected protocol + * must match the one provided. + * To support older kernels, you must specify the protocol. + * @arg fd Socket file descriptor to use (required) + * + * Set the socket file descriptor. @fd must be valid and bind'ed. + * + * This is an alternative to nl_connect(). nl_connect() creates, binds and + * sets the socket. With this function you can set the socket to an externally + * created file descriptor. + * + * @see nl_connect() + * + * @return 0 on success or a negative error code. On error, @fd is not closed but + * possibly unusable. + * + * @retval -NLE_BAD_SOCK Netlink socket is already connected + * @retval -NLE_INVAL Socket is of unexpected type + */ +int nl_socket_set_fd(struct nl_sock *sk, int protocol, int fd) +{ + int err = 0; + socklen_t addrlen; + struct sockaddr_nl local = { 0 }; + int so_type = -1, so_protocol = -1; + + if (sk->s_fd != -1) + return -NLE_BAD_SOCK; + if (fd < 0) + return -NLE_INVAL; + + addrlen = sizeof(local); + err = getsockname(fd, (struct sockaddr *) &local, + &addrlen); + if (err < 0) { + NL_DBG(4, "nl_socket_set_fd(%p,%d): getsockname() failed with %d (%s)\n", + sk, fd, errno, nl_strerror_l(errno)); + return -nl_syserr2nlerr(errno); + } + if (addrlen != sizeof(local)) + return -NLE_INVAL; + if (local.nl_family != AF_NETLINK) { + NL_DBG(4, "nl_socket_set_fd(%p,%d): getsockname() returned family %d instead of %d (AF_NETLINK)\n", + sk, fd, local.nl_family, AF_NETLINK); + return -NLE_INVAL; + } + + addrlen = sizeof(so_type); + err = getsockopt(fd, SOL_SOCKET, SO_TYPE, &so_type, &addrlen); + if (err < 0) { + NL_DBG(4, "nl_socket_set_fd(%p,%d): getsockopt() for SO_TYPE failed with %d (%s)\n", + sk, fd, errno, nl_strerror_l(errno)); + return -nl_syserr2nlerr(errno); + } + if (addrlen != sizeof(so_type)) + return -NLE_INVAL; + if (so_type != SOCK_RAW) { + NL_DBG(4, "nl_socket_set_fd(%p,%d): getsockopt() returned SO_TYPE %d instead of %d (SOCK_RAW)\n", + sk, fd, so_type, SOCK_RAW); + return -NLE_INVAL; + } + +#if SO_PROTOCOL + addrlen = sizeof(so_protocol); + err = getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &so_protocol, &addrlen); + if (err < 0) { + if (errno == ENOPROTOOPT) + goto no_so_protocol; + NL_DBG(4, "nl_socket_set_fd(%p,%d): getsockopt() for SO_PROTOCOL failed with %d (%s)\n", + sk, fd, errno, nl_strerror_l(errno)); + return -nl_syserr2nlerr(errno); + } + if (addrlen != sizeof(so_protocol)) + return -NLE_INVAL; + if (protocol >= 0 && protocol != so_protocol) { + NL_DBG(4, "nl_socket_set_fd(%p,%d): getsockopt() for SO_PROTOCOL returned %d instead of %d\n", + sk, fd, so_protocol, protocol); + return -NLE_INVAL; + } + + if (0) +#endif + { +no_so_protocol: + if (protocol < 0) { + NL_DBG(4, "nl_socket_set_fd(%p,%d): unknown protocol and unable to detect it via SO_PROTOCOL socket option\n", + sk, fd); + return -NLE_INVAL; + } + so_protocol = protocol; + } + + nl_socket_set_local_port (sk, local.nl_pid); + sk->s_local = local; + sk->s_fd = fd; + sk->s_proto = so_protocol; + + return 0; +} + +/** * Set file descriptor of socket to non-blocking state * @arg sk Netlink socket. * @@ -487,8 +724,11 @@ int nl_socket_set_nonblocking(const struct nl_sock *sk) if (sk->s_fd == -1) return -NLE_BAD_SOCK; - if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0) + if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0) { + NL_DBG(4, "nl_socket_set_nonblocking(%p): fcntl() failed with %d (%s)\n", + sk, errno, nl_strerror_l(errno)); return -nl_syserr2nlerr(errno); + } return 0; } @@ -496,18 +736,23 @@ int nl_socket_set_nonblocking(const struct nl_sock *sk) /** * Enable use of MSG_PEEK when reading from socket * @arg sk Netlink socket. + * + * See also NL_CAPABILITY_NL_RECVMSGS_PEEK_BY_DEFAULT capability */ void nl_socket_enable_msg_peek(struct nl_sock *sk) { - sk->s_flags |= NL_MSG_PEEK; + sk->s_flags |= (NL_MSG_PEEK | NL_MSG_PEEK_EXPLICIT); } /** * Disable use of MSG_PEEK when reading from socket * @arg sk Netlink socket. + * + * See also NL_CAPABILITY_NL_RECVMSGS_PEEK_BY_DEFAULT capability */ void nl_socket_disable_msg_peek(struct nl_sock *sk) { + sk->s_flags |= NL_MSG_PEEK_EXPLICIT; sk->s_flags &= ~NL_MSG_PEEK; } @@ -525,8 +770,8 @@ struct nl_cb *nl_socket_get_cb(const struct nl_sock *sk) void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb) { - if (cb == NULL) - BUG(); + if (cb == NULL) + BUG(); nl_cb_put(sk->s_cb); sk->s_cb = nl_cb_get(cb); @@ -582,7 +827,7 @@ int nl_socket_modify_err_cb(struct nl_sock *sk, enum nl_cb_kind kind, * good default value. * * @note It is not required to call this function prior to nl_connect(). - * @return 0 on sucess or a negative error code. + * @return 0 on success or a negative error code. */ int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf) { @@ -596,18 +841,22 @@ int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf) if (sk->s_fd == -1) return -NLE_BAD_SOCK; - + err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF, &txbuf, sizeof(txbuf)); - if (err < 0) + if (err < 0) { + NL_DBG(4, "nl_socket_set_buffer_size(%p): setsockopt() failed with %d (%s)\n", + sk, errno, nl_strerror_l(errno)); return -nl_syserr2nlerr(errno); + } err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF, &rxbuf, sizeof(rxbuf)); - if (err < 0) + if (err < 0) { + NL_DBG(4, "nl_socket_set_buffer_size(%p): setsockopt() failed with %d (%s)\n", + sk, errno, nl_strerror_l(errno)); return -nl_syserr2nlerr(errno); - - sk->s_flags |= NL_SOCK_BUFSIZE_SET; + } return 0; } @@ -622,6 +871,19 @@ int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf) * socket will be able to receive. It is generally recommneded to specify * a buffer size no less than the size of a memory page. * + * Setting the @bufsize to zero means to use a default of 4 times getpagesize(). + * + * When MSG_PEEK is enabled, the buffer size is used for the initial choice + * of the buffer while peeking. It still makes sense to choose an optimal value + * to avoid realloc(). + * + * When MSG_PEEK is disabled, the buffer size is important because a too small + * size will lead to failure of receiving the message via nl_recvmsgs(). + * + * By default, MSG_PEEK is enabled unless the user calls either nl_socket_disable_msg_peek()/ + * nl_socket_enable_msg_peek() or sets the message buffer size to a positive value. + * See capability NL_CAPABILITY_NL_RECVMSGS_PEEK_BY_DEFAULT for that. + * * @return 0 on success or a negative error code. */ int nl_socket_set_msg_buf_size(struct nl_sock *sk, size_t bufsize) @@ -658,8 +920,11 @@ int nl_socket_set_passcred(struct nl_sock *sk, int state) err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED, &state, sizeof(state)); - if (err < 0) + if (err < 0) { + NL_DBG(4, "nl_socket_set_passcred(%p): setsockopt() failed with %d (%s)\n", + sk, errno, nl_strerror_l(errno)); return -nl_syserr2nlerr(errno); + } if (state) sk->s_flags |= NL_SOCK_PASSCRED; @@ -685,8 +950,11 @@ int nl_socket_recv_pktinfo(struct nl_sock *sk, int state) err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_PKTINFO, &state, sizeof(state)); - if (err < 0) + if (err < 0) { + NL_DBG(4, "nl_socket_recv_pktinfo(%p): setsockopt() failed with %d (%s)\n", + sk, errno, nl_strerror_l(errno)); return -nl_syserr2nlerr(errno); + } return 0; } diff --git a/lib/utils.c b/lib/utils.c index 4457b1f..4f5fd1a 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/utils.c Utility Functions - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -24,11 +18,20 @@ * ~~~~ */ -#include +#include "nl-default.h" + +#include + +#include +#include + #include #include -#include -#include /* exit() */ + +#include "nl-core.h" +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-aux-core/nl-core.h" /** * Global variable indicating the desired level of debugging output. @@ -54,10 +57,10 @@ struct nl_dump_params nl_debug_dp = { .dp_type = NL_DUMP_DETAILS, }; -static void __init nl_debug_init(void) +static void _nl_init nl_debug_init(void) { char *nldbg, *end; - + if ((nldbg = getenv("NLDBG"))) { long level = strtol(nldbg, &end, 0); if (nldbg != end) @@ -73,7 +76,7 @@ int __nl_read_num_str_file(const char *path, int (*cb)(long, const char *)) FILE *fd; char buf[128]; - fd = fopen(path, "r"); + fd = fopen(path, "re"); if (fd == NULL) return -nl_syserr2nlerr(errno); @@ -118,6 +121,89 @@ int __nl_read_num_str_file(const char *path, int (*cb)(long, const char *)) return 0; } + +struct trans_list { + int i; + char *a; + struct nl_list_head list; +}; + +int nl_getprotobyname(const char *name) +{ + const struct protoent *result; + +#if HAVE_DECL_GETPROTOBYNAME_R + struct protoent result_buf; + char buf[2048]; + int r; + + r = getprotobyname_r(name, &result_buf, buf, sizeof(buf), + (struct protoent **)&result); + if (r != 0 || result != &result_buf) + result = NULL; +#else + result = getprotobyname(name); +#endif + + if (!result) + return -1; + + if (result->p_proto < 0 || result->p_proto > UINT8_MAX) + return -1; + return (uint8_t)result->p_proto; +} + +bool nl_getprotobynumber(int proto, char *out_name, size_t name_len) +{ + const struct protoent *result; + +#if HAVE_DECL_GETPROTOBYNUMBER_R + struct protoent result_buf; + char buf[2048]; + int r; + + r = getprotobynumber_r(proto, &result_buf, buf, sizeof(buf), + (struct protoent **)&result); + if (r != 0 || result != &result_buf) + result = NULL; +#else + result = getprotobynumber(proto); +#endif + + if (!result) + return false; + + if (strlen(result->p_name) >= name_len) + return false; + strcpy(out_name, result->p_name); + return true; +} + +const char *nl_strerror_l(int err) +{ + const char *buf; +#ifdef HAVE_STRERROR_L + int errno_save = errno; + locale_t loc = newlocale(LC_MESSAGES_MASK, "", (locale_t)0); + + if (loc == (locale_t)0) { + if (errno == ENOENT) + loc = newlocale(LC_MESSAGES_MASK, + "POSIX", (locale_t)0); + } + if (loc != (locale_t)0) { + buf = strerror_l(err, loc); + freelocale(loc); + } else { + buf = "newlocale() failed"; + } + + errno = errno_save; +#else + buf = strerror(err); +#endif + return buf; +} /** @endcond */ /** @@ -202,11 +288,11 @@ int nl_rate2str(unsigned long long rate, int type, char *buf, size_t len) case NL_BYTE_RATE: frac = nl_cancel_down_bytes(rate, &unit); break; - + case NL_BIT_RATE: frac = nl_cancel_down_bits(rate, &unit); break; - + default: BUG(); } @@ -328,6 +414,11 @@ char *nl_size2str(const size_t size, char *buf, const size_t len) { size_t i; + if (size == 0) { + snprintf(buf, len, "0B"); + return buf; + } + for (i = 0; i < ARRAY_SIZE(size_units); i++) { if (size >= size_units[i].limit) { snprintf(buf, len, "%.2g%s", @@ -370,7 +461,7 @@ long nl_prob2int(const char *str) if (*p && strcmp(p, "%") != 0) return -NLE_INVAL; - return rint(d * NL_PROB_MAX); + return (long) (((d * NL_PROB_MAX) + 0.5)); } /** @} */ @@ -398,14 +489,25 @@ static double ticks_per_usec = 1.0f; * Supports the environment variables: * PROC_NET_PSCHED - may point to psched file in /proc * PROC_ROOT - may point to /proc fs */ -static void __init get_psched_settings(void) +static void get_psched_settings(void) { char name[FILENAME_MAX]; FILE *fd; int got_hz = 0; + static volatile int initialized = 0; + const char *ev; + NL_LOCK(mutex); - if (getenv("HZ")) { - long hz = strtol(getenv("HZ"), NULL, 0); + if (initialized == 1) + return; + + nl_lock(&mutex); + + if (initialized == 1) + return; + + if ((ev = getenv("HZ"))) { + long hz = strtol(ev, NULL, 0); if (LONG_MIN != hz && LONG_MAX != hz) { user_hz = hz; @@ -418,31 +520,30 @@ static void __init get_psched_settings(void) psched_hz = user_hz; - if (getenv("TICKS_PER_USEC")) { - double t = strtod(getenv("TICKS_PER_USEC"), NULL); + if ((ev = getenv("TICKS_PER_USEC"))) { + double t = strtod(ev, NULL); ticks_per_usec = t; } else { - if (getenv("PROC_NET_PSCHED")) - snprintf(name, sizeof(name), "%s", getenv("PROC_NET_PSCHED")); - else if (getenv("PROC_ROOT")) - snprintf(name, sizeof(name), "%s/net/psched", - getenv("PROC_ROOT")); + if ((ev = getenv("PROC_NET_PSCHED"))) + snprintf(name, sizeof(name), "%s", ev); + else if ((ev = getenv("PROC_ROOT"))) + snprintf(name, sizeof(name), "%s/net/psched", ev); else - strncpy(name, "/proc/net/psched", sizeof(name) - 1); - - if ((fd = fopen(name, "r"))) { + _nl_strncpy_assert(name, "/proc/net/psched", sizeof(name)); + + if ((fd = fopen(name, "re"))) { unsigned int ns_per_usec, ns_per_tick, nom, denom; if (fscanf(fd, "%08x %08x %08x %08x", &ns_per_usec, &ns_per_tick, &nom, &denom) != 4) { - NL_DBG(1, "Fatal error: can not read psched settings from \"%s\". " \ - "Try to set TICKS_PER_USEC, PROC_NET_PSCHED or PROC_ROOT " \ - "environment variables\n", name); - exit(1); - } + NL_DBG(1, "Fatal error: can not read psched settings from \"%s\". " \ + "Try to set TICKS_PER_USEC, PROC_NET_PSCHED or PROC_ROOT " \ + "environment variables\n", name); + exit(1); + } - ticks_per_usec = (double) ns_per_usec / + ticks_per_usec = (double) ns_per_usec / (double) ns_per_tick; if (nom == 1000000) @@ -451,6 +552,9 @@ static void __init get_psched_settings(void) fclose(fd); } } + initialized = 1; + + nl_unlock(&mutex); } @@ -459,6 +563,7 @@ static void __init get_psched_settings(void) */ int nl_get_user_hz(void) { + get_psched_settings(); return user_hz; } @@ -467,6 +572,7 @@ int nl_get_user_hz(void) */ int nl_get_psched_hz(void) { + get_psched_settings(); return psched_hz; } @@ -477,6 +583,7 @@ int nl_get_psched_hz(void) */ uint32_t nl_us2ticks(uint32_t us) { + get_psched_settings(); return us * ticks_per_usec; } @@ -488,6 +595,7 @@ uint32_t nl_us2ticks(uint32_t us) */ uint32_t nl_ticks2us(uint32_t ticks) { + get_psched_settings(); return ticks / ticks_per_usec; } @@ -546,6 +654,11 @@ char * nl_msec2str(uint64_t msec, char *buf, size_t len) static const char *units[5] = {"d", "h", "m", "s", "msec"}; char * const buf_orig = buf; + if (msec == 0) { + snprintf(buf, len, "0msec"); + return buf_orig; + } + #define _SPLIT(idx, unit) if ((split[idx] = msec / unit)) msec %= unit _SPLIT(0, 86400000); /* days */ _SPLIT(1, 3600000); /* hours */ @@ -575,24 +688,26 @@ char * nl_msec2str(uint64_t msec, char *buf, size_t len) */ static const struct trans_tbl nlfamilies[] = { - __ADD(NETLINK_ROUTE,route) - __ADD(NETLINK_USERSOCK,usersock) - __ADD(NETLINK_FIREWALL,firewall) - __ADD(NETLINK_INET_DIAG,inetdiag) - __ADD(NETLINK_NFLOG,nflog) - __ADD(NETLINK_XFRM,xfrm) - __ADD(NETLINK_SELINUX,selinux) - __ADD(NETLINK_ISCSI,iscsi) - __ADD(NETLINK_AUDIT,audit) - __ADD(NETLINK_FIB_LOOKUP,fib_lookup) - __ADD(NETLINK_CONNECTOR,connector) - __ADD(NETLINK_NETFILTER,netfilter) - __ADD(NETLINK_IP6_FW,ip6_fw) - __ADD(NETLINK_DNRTMSG,dnrtmsg) - __ADD(NETLINK_KOBJECT_UEVENT,kobject_uevent) - __ADD(NETLINK_GENERIC,generic) - __ADD(NETLINK_SCSITRANSPORT,scsitransport) - __ADD(NETLINK_ECRYPTFS,ecryptfs) + __ADD(NETLINK_ROUTE,route), + __ADD(NETLINK_USERSOCK,usersock), + __ADD(NETLINK_FIREWALL,firewall), + __ADD(NETLINK_INET_DIAG,inetdiag), + __ADD(NETLINK_NFLOG,nflog), + __ADD(NETLINK_XFRM,xfrm), + __ADD(NETLINK_SELINUX,selinux), + __ADD(NETLINK_ISCSI,iscsi), + __ADD(NETLINK_AUDIT,audit), + __ADD(NETLINK_FIB_LOOKUP,fib_lookup), + __ADD(NETLINK_CONNECTOR,connector), + __ADD(NETLINK_NETFILTER,netfilter), + __ADD(NETLINK_IP6_FW,ip6_fw), + __ADD(NETLINK_DNRTMSG,dnrtmsg), + __ADD(NETLINK_KOBJECT_UEVENT,kobject_uevent), + __ADD(NETLINK_GENERIC,generic), + __ADD(NETLINK_SCSITRANSPORT,scsitransport), + __ADD(NETLINK_ECRYPTFS,ecryptfs), + __ADD(NETLINK_RDMA,rdma), + __ADD(NETLINK_CRYPTO,crypto), }; char * nl_nlfamily2str(int family, char *buf, size_t size) @@ -617,86 +732,83 @@ int nl_str2nlfamily(const char *name) static const struct trans_tbl llprotos[] = { {0, "generic"}, - __ADD(ARPHRD_ETHER,ether) - __ADD(ARPHRD_EETHER,eether) - __ADD(ARPHRD_AX25,ax25) - __ADD(ARPHRD_PRONET,pronet) - __ADD(ARPHRD_CHAOS,chaos) - __ADD(ARPHRD_IEEE802,ieee802) - __ADD(ARPHRD_ARCNET,arcnet) - __ADD(ARPHRD_APPLETLK,atalk) - __ADD(ARPHRD_DLCI,dlci) - __ADD(ARPHRD_ATM,atm) - __ADD(ARPHRD_METRICOM,metricom) - __ADD(ARPHRD_IEEE1394,ieee1394) -#ifdef ARPHRD_EUI64 - __ADD(ARPHRD_EUI64,eui64) -#endif - __ADD(ARPHRD_INFINIBAND,infiniband) - __ADD(ARPHRD_SLIP,slip) - __ADD(ARPHRD_CSLIP,cslip) - __ADD(ARPHRD_SLIP6,slip6) - __ADD(ARPHRD_CSLIP6,cslip6) - __ADD(ARPHRD_RSRVD,rsrvd) - __ADD(ARPHRD_ADAPT,adapt) - __ADD(ARPHRD_ROSE,rose) - __ADD(ARPHRD_X25,x25) -#ifdef ARPHRD_HWX25 - __ADD(ARPHRD_HWX25,hwx25) -#endif - __ADD(ARPHRD_CAN,can) - __ADD(ARPHRD_PPP,ppp) - __ADD(ARPHRD_HDLC,hdlc) - __ADD(ARPHRD_LAPB,lapb) - __ADD(ARPHRD_DDCMP,ddcmp) - __ADD(ARPHRD_RAWHDLC,rawhdlc) - __ADD(ARPHRD_TUNNEL,ipip) - __ADD(ARPHRD_TUNNEL6,tunnel6) - __ADD(ARPHRD_FRAD,frad) - __ADD(ARPHRD_SKIP,skip) - __ADD(ARPHRD_LOOPBACK,loopback) - __ADD(ARPHRD_LOCALTLK,localtlk) - __ADD(ARPHRD_FDDI,fddi) - __ADD(ARPHRD_BIF,bif) - __ADD(ARPHRD_SIT,sit) - __ADD(ARPHRD_IPDDP,ip/ddp) - __ADD(ARPHRD_IPGRE,gre) - __ADD(ARPHRD_PIMREG,pimreg) - __ADD(ARPHRD_HIPPI,hippi) - __ADD(ARPHRD_ASH,ash) - __ADD(ARPHRD_ECONET,econet) - __ADD(ARPHRD_IRDA,irda) - __ADD(ARPHRD_FCPP,fcpp) - __ADD(ARPHRD_FCAL,fcal) - __ADD(ARPHRD_FCPL,fcpl) - __ADD(ARPHRD_FCFABRIC,fcfb_0) - __ADD(ARPHRD_FCFABRIC+1,fcfb_1) - __ADD(ARPHRD_FCFABRIC+2,fcfb_2) - __ADD(ARPHRD_FCFABRIC+3,fcfb_3) - __ADD(ARPHRD_FCFABRIC+4,fcfb_4) - __ADD(ARPHRD_FCFABRIC+5,fcfb_5) - __ADD(ARPHRD_FCFABRIC+6,fcfb_6) - __ADD(ARPHRD_FCFABRIC+7,fcfb_7) - __ADD(ARPHRD_FCFABRIC+8,fcfb_8) - __ADD(ARPHRD_FCFABRIC+9,fcfb_9) - __ADD(ARPHRD_FCFABRIC+10,fcfb_10) - __ADD(ARPHRD_FCFABRIC+11,fcfb_11) - __ADD(ARPHRD_FCFABRIC+12,fcfb_12) - __ADD(ARPHRD_IEEE802_TR,tr) - __ADD(ARPHRD_IEEE80211,ieee802.11) - __ADD(ARPHRD_PHONET,phonet) -#ifdef ARPHRD_CAIF - __ADD(ARPHRD_CAIF, caif) -#endif -#ifdef ARPHRD_IEEE80211_PRISM - __ADD(ARPHRD_IEEE80211_PRISM, ieee802.11_prism) -#endif -#ifdef ARPHRD_VOID - __ADD(ARPHRD_VOID,void) -#endif -#ifdef ARPHRD_NONE - __ADD(ARPHRD_NONE,nohdr) -#endif + __ADD(ARPHRD_NETROM,netrom), + __ADD(ARPHRD_ETHER,ether), + __ADD(ARPHRD_EETHER,eether), + __ADD(ARPHRD_AX25,ax25), + __ADD(ARPHRD_PRONET,pronet), + __ADD(ARPHRD_CHAOS,chaos), + __ADD(ARPHRD_IEEE802,ieee802), + __ADD(ARPHRD_ARCNET,arcnet), + __ADD(ARPHRD_APPLETLK,atalk), + __ADD(ARPHRD_DLCI,dlci), + __ADD(ARPHRD_ATM,atm), + __ADD(ARPHRD_METRICOM,metricom), + __ADD(ARPHRD_IEEE1394,ieee1394), + __ADD(ARPHRD_EUI64,eui64), + __ADD(ARPHRD_INFINIBAND,infiniband), + __ADD(ARPHRD_SLIP,slip), + __ADD(ARPHRD_CSLIP,cslip), + __ADD(ARPHRD_SLIP6,slip6), + __ADD(ARPHRD_CSLIP6,cslip6), + __ADD(ARPHRD_RSRVD,rsrvd), + __ADD(ARPHRD_ADAPT,adapt), + __ADD(ARPHRD_ROSE,rose), + __ADD(ARPHRD_X25,x25), + __ADD(ARPHRD_HWX25,hwx25), + __ADD(ARPHRD_CAN,can), + __ADD(ARPHRD_PPP,ppp), + __ADD(ARPHRD_CISCO,cisco), + __ADD(ARPHRD_HDLC,hdlc), + __ADD(ARPHRD_LAPB,lapb), + __ADD(ARPHRD_DDCMP,ddcmp), + __ADD(ARPHRD_RAWHDLC,rawhdlc), + __ADD(ARPHRD_TUNNEL,ipip), + __ADD(ARPHRD_TUNNEL6,tunnel6), + __ADD(ARPHRD_FRAD,frad), + __ADD(ARPHRD_SKIP,skip), + __ADD(ARPHRD_LOOPBACK,loopback), + __ADD(ARPHRD_LOCALTLK,localtlk), + __ADD(ARPHRD_FDDI,fddi), + __ADD(ARPHRD_BIF,bif), + __ADD(ARPHRD_SIT,sit), + __ADD(ARPHRD_IPDDP,ip/ddp), + __ADD(ARPHRD_IPGRE,gre), + __ADD(ARPHRD_PIMREG,pimreg), + __ADD(ARPHRD_HIPPI,hippi), + __ADD(ARPHRD_ASH,ash), + __ADD(ARPHRD_ECONET,econet), + __ADD(ARPHRD_IRDA,irda), + __ADD(ARPHRD_FCPP,fcpp), + __ADD(ARPHRD_FCAL,fcal), + __ADD(ARPHRD_FCPL,fcpl), + __ADD(ARPHRD_FCFABRIC,fcfb_0), + __ADD(ARPHRD_FCFABRIC+1,fcfb_1), + __ADD(ARPHRD_FCFABRIC+2,fcfb_2), + __ADD(ARPHRD_FCFABRIC+3,fcfb_3), + __ADD(ARPHRD_FCFABRIC+4,fcfb_4), + __ADD(ARPHRD_FCFABRIC+5,fcfb_5), + __ADD(ARPHRD_FCFABRIC+6,fcfb_6), + __ADD(ARPHRD_FCFABRIC+7,fcfb_7), + __ADD(ARPHRD_FCFABRIC+8,fcfb_8), + __ADD(ARPHRD_FCFABRIC+9,fcfb_9), + __ADD(ARPHRD_FCFABRIC+10,fcfb_10), + __ADD(ARPHRD_FCFABRIC+11,fcfb_11), + __ADD(ARPHRD_FCFABRIC+12,fcfb_12), + __ADD(ARPHRD_IEEE802_TR,tr), + __ADD(ARPHRD_IEEE80211,ieee802.11), + __ADD(ARPHRD_IEEE80211_PRISM,ieee802.11_prism), + __ADD(ARPHRD_IEEE80211_RADIOTAP,ieee802.11_radiotap), + __ADD(ARPHRD_IEEE802154,ieee802.15.4), + __ADD(ARPHRD_IEEE802154_MONITOR,ieee802.15.4_monitor), + __ADD(ARPHRD_PHONET,phonet), + __ADD(ARPHRD_PHONET_PIPE,phonet_pipe), + __ADD(ARPHRD_CAIF,caif), + __ADD(ARPHRD_IP6GRE,ip6gre), + __ADD(ARPHRD_NETLINK,netlink), + __ADD(ARPHRD_6LOWPAN,6lowpan), + __ADD(ARPHRD_VOID,void), + __ADD(ARPHRD_NONE,nohdr), }; char * nl_llproto2str(int llproto, char *buf, size_t len) @@ -718,75 +830,75 @@ int nl_str2llproto(const char *name) */ static const struct trans_tbl ether_protos[] = { - __ADD(ETH_P_LOOP,loop) - __ADD(ETH_P_PUP,pup) - __ADD(ETH_P_PUPAT,pupat) - __ADD(ETH_P_IP,ip) - __ADD(ETH_P_X25,x25) - __ADD(ETH_P_ARP,arp) - __ADD(ETH_P_BPQ,bpq) - __ADD(ETH_P_IEEEPUP,ieeepup) - __ADD(ETH_P_IEEEPUPAT,ieeepupat) - __ADD(ETH_P_DEC,dec) - __ADD(ETH_P_DNA_DL,dna_dl) - __ADD(ETH_P_DNA_RC,dna_rc) - __ADD(ETH_P_DNA_RT,dna_rt) - __ADD(ETH_P_LAT,lat) - __ADD(ETH_P_DIAG,diag) - __ADD(ETH_P_CUST,cust) - __ADD(ETH_P_SCA,sca) - __ADD(ETH_P_TEB,teb) - __ADD(ETH_P_RARP,rarp) - __ADD(ETH_P_ATALK,atalk) - __ADD(ETH_P_AARP,aarp) + __ADD(ETH_P_LOOP,loop), + __ADD(ETH_P_PUP,pup), + __ADD(ETH_P_PUPAT,pupat), + __ADD(ETH_P_IP,ip), + __ADD(ETH_P_X25,x25), + __ADD(ETH_P_ARP,arp), + __ADD(ETH_P_BPQ,bpq), + __ADD(ETH_P_IEEEPUP,ieeepup), + __ADD(ETH_P_IEEEPUPAT,ieeepupat), + __ADD(ETH_P_DEC,dec), + __ADD(ETH_P_DNA_DL,dna_dl), + __ADD(ETH_P_DNA_RC,dna_rc), + __ADD(ETH_P_DNA_RT,dna_rt), + __ADD(ETH_P_LAT,lat), + __ADD(ETH_P_DIAG,diag), + __ADD(ETH_P_CUST,cust), + __ADD(ETH_P_SCA,sca), + __ADD(ETH_P_TEB,teb), + __ADD(ETH_P_RARP,rarp), + __ADD(ETH_P_ATALK,atalk), + __ADD(ETH_P_AARP,aarp), #ifdef ETH_P_8021Q - __ADD(ETH_P_8021Q,802.1q) + __ADD(ETH_P_8021Q,802.1q), #endif - __ADD(ETH_P_IPX,ipx) - __ADD(ETH_P_IPV6,ipv6) - __ADD(ETH_P_PAUSE,pause) - __ADD(ETH_P_SLOW,slow) + __ADD(ETH_P_IPX,ipx), + __ADD(ETH_P_IPV6,ipv6), + __ADD(ETH_P_PAUSE,pause), + __ADD(ETH_P_SLOW,slow), #ifdef ETH_P_WCCP - __ADD(ETH_P_WCCP,wccp) + __ADD(ETH_P_WCCP,wccp), #endif - __ADD(ETH_P_PPP_DISC,ppp_disc) - __ADD(ETH_P_PPP_SES,ppp_ses) - __ADD(ETH_P_MPLS_UC,mpls_uc) - __ADD(ETH_P_MPLS_MC,mpls_mc) - __ADD(ETH_P_ATMMPOA,atmmpoa) - __ADD(ETH_P_LINK_CTL,link_ctl) - __ADD(ETH_P_ATMFATE,atmfate) - __ADD(ETH_P_PAE,pae) - __ADD(ETH_P_AOE,aoe) - __ADD(ETH_P_TIPC,tipc) - __ADD(ETH_P_1588,ieee1588) - __ADD(ETH_P_FCOE,fcoe) - __ADD(ETH_P_FIP,fip) - __ADD(ETH_P_EDSA,edsa) - __ADD(ETH_P_EDP2,edp2) - __ADD(ETH_P_802_3,802.3) - __ADD(ETH_P_AX25,ax25) - __ADD(ETH_P_ALL,all) - __ADD(ETH_P_802_2,802.2) - __ADD(ETH_P_SNAP,snap) - __ADD(ETH_P_DDCMP,ddcmp) - __ADD(ETH_P_WAN_PPP,wan_ppp) - __ADD(ETH_P_PPP_MP,ppp_mp) - __ADD(ETH_P_LOCALTALK,localtalk) - __ADD(ETH_P_CAN,can) - __ADD(ETH_P_PPPTALK,ppptalk) - __ADD(ETH_P_TR_802_2,tr_802.2) - __ADD(ETH_P_MOBITEX,mobitex) - __ADD(ETH_P_CONTROL,control) - __ADD(ETH_P_IRDA,irda) - __ADD(ETH_P_ECONET,econet) - __ADD(ETH_P_HDLC,hdlc) - __ADD(ETH_P_ARCNET,arcnet) - __ADD(ETH_P_DSA,dsa) - __ADD(ETH_P_TRAILER,trailer) - __ADD(ETH_P_PHONET,phonet) - __ADD(ETH_P_IEEE802154,ieee802154) - __ADD(ETH_P_CAIF,caif) + __ADD(ETH_P_PPP_DISC,ppp_disc), + __ADD(ETH_P_PPP_SES,ppp_ses), + __ADD(ETH_P_MPLS_UC,mpls_uc), + __ADD(ETH_P_MPLS_MC,mpls_mc), + __ADD(ETH_P_ATMMPOA,atmmpoa), + __ADD(ETH_P_LINK_CTL,link_ctl), + __ADD(ETH_P_ATMFATE,atmfate), + __ADD(ETH_P_PAE,pae), + __ADD(ETH_P_AOE,aoe), + __ADD(ETH_P_TIPC,tipc), + __ADD(ETH_P_1588,ieee1588), + __ADD(ETH_P_FCOE,fcoe), + __ADD(ETH_P_FIP,fip), + __ADD(ETH_P_EDSA,edsa), + __ADD(ETH_P_EDP2,edp2), + __ADD(ETH_P_802_3,802.3), + __ADD(ETH_P_AX25,ax25), + __ADD(ETH_P_ALL,all), + __ADD(ETH_P_802_2,802.2), + __ADD(ETH_P_SNAP,snap), + __ADD(ETH_P_DDCMP,ddcmp), + __ADD(ETH_P_WAN_PPP,wan_ppp), + __ADD(ETH_P_PPP_MP,ppp_mp), + __ADD(ETH_P_LOCALTALK,localtalk), + __ADD(ETH_P_CAN,can), + __ADD(ETH_P_PPPTALK,ppptalk), + __ADD(ETH_P_TR_802_2,tr_802.2), + __ADD(ETH_P_MOBITEX,mobitex), + __ADD(ETH_P_CONTROL,control), + __ADD(ETH_P_IRDA,irda), + __ADD(ETH_P_ECONET,econet), + __ADD(ETH_P_HDLC,hdlc), + __ADD(ETH_P_ARCNET,arcnet), + __ADD(ETH_P_DSA,dsa), + __ADD(ETH_P_TRAILER,trailer), + __ADD(ETH_P_PHONET,phonet), + __ADD(ETH_P_IEEE802154,ieee802154), + __ADD(ETH_P_CAIF,caif), }; char *nl_ether_proto2str(int eproto, char *buf, size_t len) @@ -809,12 +921,8 @@ int nl_str2ether_proto(const char *name) char *nl_ip_proto2str(int proto, char *buf, size_t len) { - struct protoent *p = getprotobynumber(proto); - - if (p) { - snprintf(buf, len, "%s", p->p_name); + if (nl_getprotobynumber(proto, buf, len)) return buf; - } snprintf(buf, len, "0x%x", proto); return buf; @@ -822,15 +930,19 @@ char *nl_ip_proto2str(int proto, char *buf, size_t len) int nl_str2ip_proto(const char *name) { - struct protoent *p = getprotobyname(name); unsigned long l; char *end; + int p; + + if (!name) + return -NLE_INVAL; - if (p) - return p->p_proto; + p = nl_getprotobyname(name); + if (p >= 0) + return p; l = strtoul(name, &end, 0); - if (l == ULONG_MAX || *end != '\0') + if (name == end || *end != '\0' || l > (unsigned long)INT_MAX) return -NLE_OBJ_NOTFOUND; return (int) l; @@ -993,7 +1105,7 @@ char *__flags2str(int flags, char *buf, size_t len, int tmp = flags; memset(buf, 0, len); - + for (i = 0; i < tbl_len; i++) { if (tbl[i].i & tmp) { tmp &= ~tbl[i].i; @@ -1057,7 +1169,7 @@ int __str2flags(const char *buf, const struct trans_tbl *tbl, size_t tbl_len) for (;;) { if (*p == ' ') p++; - + t = strchr(p, ','); len = t ? t - p : strlen(p); for (i = 0; i < tbl_len; i++) @@ -1101,6 +1213,108 @@ void dump_from_ops(struct nl_object *obj, struct nl_dump_params *params) obj->ce_ops->oo_dump[type](obj, params); } +/** + * Check for library capabilities + * + * @arg capability capability identifier + * + * Check whether the loaded libnl library supports a certain capability. + * This is useful so that applications can workaround known issues of + * libnl that are fixed in newer library versions, without + * having a hard dependency on the new version. It is also useful, for + * capabilities that cannot easily be detected using autoconf tests. + * The capabilities are integer constants with name NL_CAPABILITY_*. + * + * As this function is intended to detect capabilities at runtime, + * you might not want to depend during compile time on the NL_CAPABILITY_* + * names. Instead you can use their numeric values which are guaranteed not to + * change meaning. + * + * @return non zero if libnl supports a certain capability, 0 otherwise. + **/ +int nl_has_capability (int capability) +{ + static const uint8_t caps[ ( NL_CAPABILITY_MAX + 7 ) / 8 ] = { +#define _NL_ASSERT(expr) ( 0 * sizeof(struct { unsigned int x: ( (!!(expr)) ? 1 : -1 ); }) ) +#define _NL_SETV(i, r, v) \ + ( _NL_ASSERT( (v) == 0 || (i) * 8 + (r) == (v) - 1 ) + \ + ( (v) == 0 ? 0 : (1 << (r)) ) ) +#define _NL_SET(i, v0, v1, v2, v3, v4, v5, v6, v7) \ + [(i)] = ( \ + _NL_SETV((i), 0, (v0)) | _NL_SETV((i), 4, (v4)) | \ + _NL_SETV((i), 1, (v1)) | _NL_SETV((i), 5, (v5)) | \ + _NL_SETV((i), 2, (v2)) | _NL_SETV((i), 6, (v6)) | \ + _NL_SETV((i), 3, (v3)) | _NL_SETV((i), 7, (v7)) ) + _NL_SET(0, + NL_CAPABILITY_ROUTE_BUILD_MSG_SET_SCOPE, + NL_CAPABILITY_ROUTE_LINK_VETH_GET_PEER_OWN_REFERENCE, + NL_CAPABILITY_ROUTE_LINK_CLS_ADD_ACT_OWN_REFERENCE, + NL_CAPABILITY_NL_CONNECT_RETRY_GENERATE_PORT_ON_ADDRINUSE, + NL_CAPABILITY_ROUTE_LINK_GET_KERNEL_FAIL_OPNOTSUPP, + NL_CAPABILITY_ROUTE_ADDR_COMPARE_CACHEINFO, + NL_CAPABILITY_VERSION_3_2_26, + NL_CAPABILITY_NL_RECV_FAIL_TRUNC_NO_PEEK), + _NL_SET(1, + NL_CAPABILITY_LINK_BUILD_CHANGE_REQUEST_SET_CHANGE, + NL_CAPABILITY_RTNL_NEIGH_GET_FILTER_AF_UNSPEC_FIX, + NL_CAPABILITY_VERSION_3_2_27, + NL_CAPABILITY_RTNL_LINK_VLAN_PROTOCOL_SERIALZE, + NL_CAPABILITY_RTNL_LINK_PARSE_GRE_REMOTE, + NL_CAPABILITY_RTNL_LINK_VLAN_INGRESS_MAP_CLEAR, + NL_CAPABILITY_RTNL_LINK_VXLAN_IO_COMPARE, + NL_CAPABILITY_NL_OBJECT_DIFF64), + _NL_SET (2, + NL_CAPABILITY_XFRM_SA_KEY_SIZE, + NL_CAPABILITY_RTNL_ADDR_PEER_FIX, + NL_CAPABILITY_VERSION_3_2_28, + NL_CAPABILITY_RTNL_ADDR_PEER_ID_FIX, + NL_CAPABILITY_NL_ADDR_FILL_SOCKADDR, + NL_CAPABILITY_XFRM_SEC_CTX_LEN, + NL_CAPABILITY_LINK_BUILD_ADD_REQUEST_SET_CHANGE, + NL_CAPABILITY_NL_RECVMSGS_PEEK_BY_DEFAULT), + _NL_SET (3, + NL_CAPABILITY_VERSION_3_2_29, + NL_CAPABILITY_XFRM_SP_SEC_CTX_LEN, + NL_CAPABILITY_VERSION_3_3_0, + NL_CAPABILITY_VERSION_3_4_0, + NL_CAPABILITY_ROUTE_FIX_VLAN_SET_EGRESS_MAP, + NL_CAPABILITY_VERSION_3_5_0, + NL_CAPABILITY_NL_OBJECT_IDENTICAL_PARTIAL, + NL_CAPABILITY_VERSION_3_6_0), + _NL_SET (4, + NL_CAPABILITY_VERSION_3_7_0, + NL_CAPABILITY_VERSION_3_8_0, + NL_CAPABILITY_VERSION_3_9_0, + 0, + 0, + 0, + 0, + 0), + /* IMPORTANT: these capability numbers are intended to be universal and stable + * for libnl3. Don't allocate new numbers on your own that differ from upstream + * libnl3. + * + * Instead register a capability number upstream too. We will take patches + * for that. We especially take patches to register a capability number that is + * only implemented in your fork of libnl3. + * + * If you really don't want that, use capabilities in the range 0x7000 to 0x7FFF. + * (NL_CAPABILITY_IS_USER_RESERVED). Upstream libnl3 will not register conflicting + * capabilities in that range. + * + * Obviously, only backport capability numbers to libnl versions that actually + * implement that capability as well. */ +#undef _NL_SET +#undef _NL_SETV +#undef _NL_ASSERT + }; + + if (capability <= 0 || capability > NL_CAPABILITY_MAX) + return 0; + capability--; + return (caps[capability / 8] & (1 << (capability % 8))) != 0; +} + /** @endcond */ /** @} */ diff --git a/lib/version.c b/lib/version.c index 0dcafa0..da4bd25 100644 --- a/lib/version.c +++ b/lib/version.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * lib/version.c Run-time version information - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2012 Thomas Graf */ @@ -24,6 +18,8 @@ * @{ */ +#include "nl-default.h" + #include const int nl_ver_num = LIBNL_VER_NUM; diff --git a/lib/xfrm/ae.c b/lib/xfrm/ae.c new file mode 100644 index 0000000..9af73a8 --- /dev/null +++ b/lib/xfrm/ae.c @@ -0,0 +1,1027 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @ingroup xfrmnl + * @defgroup ae Attribute Element + * @brief + * + * The AE interface allows a user to retrieve and update various + * Security Association (SA) attributes such as lifetime, replay state etc. + * + * @par AE Flags + * @code + * XFRM_AE_UNSPEC + * XFRM_AE_RTHR=1 + * XFRM_AE_RVAL=2 + * XFRM_AE_LVAL=4 + * XFRM_AE_ETHR=8 + * XFRM_AE_CR=16 + * XFRM_AE_CE=32 + * XFRM_AE_CU=64 + * @endcode + * + * @par AE Identification + * An AE is uniquely identified by the attributes listed below, whenever + * you refer to an existing AE all of the attributes must be set. There is + * no cache support for AE since you can retrieve the AE for any given combination + * of attributes mentioned below, but not all at once since they just characterize + * an SA. + * - destination address (xfrmnl_ae_set_daddr()) + * - SPI (xfrmnl_ae_set_spi) + * - protocol (xfrmnl_ae_set_proto) + * - mark (xfrmnl_ae_set_mark) + * + * @par Changeable Attributes + * \anchor ae_changeable + * - current lifetime (xfrmnl_ae_set_curlifetime()) + * - replay properties (xfrmnl_ae_set_replay_maxage(), xfrmnl_ae_set_replay_maxdiff()) + * - replay state (xfrmnl_ae_set_replay_state(), xfrmnl_ae_set_replay_state_esn)) + * + * @par Required Caches for Dumping + * None + * + * @par TODO + * None + * + * @par 1) Retrieving AE information for a given SA tuple + * @code + * // Create a netlink socket and connect it to XFRM subsystem in + * the kernel to be able to send/receive info from userspace. + * struct nl_sock* sk = nl_socket_alloc (); + * nl_connect (sk, NETLINK_XFRM); + * + * // AEs can then be looked up by the SA tuple, destination address, + * SPI, protocol, mark: + * struct xfrmnl_ae *ae; + * xfrmnl_ae_get_kernel(sk, dst_addr, spi, proto,mark_mask, mark_value, &ae); + * + * // After successful usage, the object must be freed + * xfrmnl_ae_put(ae); + * @endcode + * + * @par 2) Updating AE + * @code + * // Allocate an empty AE handle to be filled out with the attributes + * // of the new AE. + * struct xfrmnl_ae *ae = xfrmnl_ae_alloc(); + * + * // Fill out the attributes of the new AE + * xfrmnl_ae_set_daddr(ae, dst_addr); + * xfrmnl_ae_set_spi(ae, 0xDEADBEEF); + * xfrmnl_ae_set_proto(ae, 50); + * xfrmnl_ae_set_mark(ae, 0x0); + * xfrmnl_ae_set_saddr(ae, src_addr); + * xfrmnl_ae_set_curlifetime(ae, 540, 10, 0xAABB1122, 0x0); + * + * // Build the netlink message and send it to the kernel, the operation will + * // block until the operation has been completed. Alternatively, a netlink message + * // can be built using xfrmnl_ae_build_get_request () API and be sent using + * // nl_send_auto(). Further the result from the kernel can be parsed using + * // xfrmnl_ae_parse() API. + * xfrmnl_ae_set(sk, ae, NLM_F_REPLACE); + * + * // Free the memory + * xfrmnl_ae_put(ae); + * @endcode + * + * @{ + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include + +#include "nl-xfrm.h" +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" +#include "nl-aux-core/nl-core.h" +#include "nl-aux-xfrm/nl-xfrm.h" + +/** @cond SKIP */ + +struct xfrmnl_sa_id { + struct nl_addr* daddr; + uint32_t spi; + uint16_t family; + uint8_t proto; +}; + +struct xfrmnl_ae { + NLHDR_COMMON + + struct xfrmnl_sa_id sa_id; + struct nl_addr* saddr; + uint32_t flags; + uint32_t reqid; + struct xfrmnl_mark mark; + struct xfrmnl_lifetime_cur lifetime_cur; + uint32_t replay_maxage; + uint32_t replay_maxdiff; + struct xfrmnl_replay_state replay_state; + struct xfrmnl_replay_state_esn* replay_state_esn; +}; + +#define XFRM_AE_ATTR_DADDR 0x01 +#define XFRM_AE_ATTR_SPI 0x02 +#define XFRM_AE_ATTR_PROTO 0x04 +#define XFRM_AE_ATTR_SADDR 0x08 +#define XFRM_AE_ATTR_FLAGS 0x10 +#define XFRM_AE_ATTR_REQID 0x20 +#define XFRM_AE_ATTR_MARK 0x40 +#define XFRM_AE_ATTR_LIFETIME 0x80 +#define XFRM_AE_ATTR_REPLAY_MAXAGE 0x100 +#define XFRM_AE_ATTR_REPLAY_MAXDIFF 0x200 +#define XFRM_AE_ATTR_REPLAY_STATE 0x400 +#define XFRM_AE_ATTR_FAMILY 0x800 + +static struct nl_object_ops xfrm_ae_obj_ops; +/** @endcond */ + + +static void xfrm_ae_free_data(struct nl_object *c) +{ + struct xfrmnl_ae* ae = nl_object_priv (c); + + if (ae == NULL) + return; + + nl_addr_put (ae->sa_id.daddr); + nl_addr_put (ae->saddr); + + if (ae->replay_state_esn) + free (ae->replay_state_esn); +} + +static int xfrm_ae_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct xfrmnl_ae* dst = nl_object_priv(_dst); + struct xfrmnl_ae* src = nl_object_priv(_src); + + dst->sa_id.daddr = NULL; + dst->saddr = NULL; + dst->replay_state_esn = NULL; + + if (src->sa_id.daddr) { + if ((dst->sa_id.daddr = nl_addr_clone (src->sa_id.daddr)) == NULL) + return -NLE_NOMEM; + } + + if (src->saddr) { + if ((dst->saddr = nl_addr_clone (src->saddr)) == NULL) + return -NLE_NOMEM; + } + + if (src->replay_state_esn) { + uint32_t len = sizeof (struct xfrmnl_replay_state_esn) + (sizeof (uint32_t) * src->replay_state_esn->bmp_len); + + if ((dst->replay_state_esn = malloc (len)) == NULL) + return -NLE_NOMEM; + memcpy (dst->replay_state_esn, src->replay_state_esn, len); + } + + return 0; +} + +static uint64_t xfrm_ae_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) +{ + struct xfrmnl_ae* a = (struct xfrmnl_ae *) _a; + struct xfrmnl_ae* b = (struct xfrmnl_ae *) _b; + uint64_t diff = 0; + int found = 0; + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(XFRM_AE_ATTR_DADDR, + nl_addr_cmp(a->sa_id.daddr, b->sa_id.daddr)); + diff |= _DIFF(XFRM_AE_ATTR_SPI, a->sa_id.spi != b->sa_id.spi); + diff |= _DIFF(XFRM_AE_ATTR_PROTO, a->sa_id.proto != b->sa_id.proto); + diff |= _DIFF(XFRM_AE_ATTR_SADDR, nl_addr_cmp(a->saddr, b->saddr)); + diff |= _DIFF(XFRM_AE_ATTR_FLAGS, a->flags != b->flags); + diff |= _DIFF(XFRM_AE_ATTR_REQID, a->reqid != b->reqid); + diff |= _DIFF(XFRM_AE_ATTR_MARK, + (a->mark.v & a->mark.m) != (b->mark.v & b->mark.m)); + diff |= _DIFF(XFRM_AE_ATTR_REPLAY_MAXAGE, + a->replay_maxage != b->replay_maxage); + diff |= _DIFF(XFRM_AE_ATTR_REPLAY_MAXDIFF, + a->replay_maxdiff != b->replay_maxdiff); + + /* Compare replay states */ + found = AVAILABLE_MISMATCH (a, b, XFRM_AE_ATTR_REPLAY_STATE); + if (found == 0) // attribute exists in both objects + { + if (((a->replay_state_esn != NULL) && (b->replay_state_esn == NULL)) || + ((a->replay_state_esn == NULL) && (b->replay_state_esn != NULL))) + found |= 1; + + if (found == 0) // same replay type. compare actual values + { + if (a->replay_state_esn) + { + if (a->replay_state_esn->bmp_len != b->replay_state_esn->bmp_len) + diff |= 1; + else + { + uint32_t len = sizeof (struct xfrmnl_replay_state_esn) + (sizeof (uint32_t) * a->replay_state_esn->bmp_len); + diff |= memcmp (a->replay_state_esn, b->replay_state_esn, len); + } + } + else + { + if ((a->replay_state.oseq != b->replay_state.oseq) || + (a->replay_state.seq != b->replay_state.seq) || + (a->replay_state.bitmap != b->replay_state.bitmap)) + diff |= 1; + } + } + } +#undef _DIFF + + return diff; +} + +/** + * @name XFRM AE Attribute Translations + * @{ + */ +static const struct trans_tbl ae_attrs[] = +{ + __ADD(XFRM_AE_ATTR_DADDR, daddr), + __ADD(XFRM_AE_ATTR_SPI, spi), + __ADD(XFRM_AE_ATTR_PROTO, protocol), + __ADD(XFRM_AE_ATTR_SADDR, saddr), + __ADD(XFRM_AE_ATTR_FLAGS, flags), + __ADD(XFRM_AE_ATTR_REQID, reqid), + __ADD(XFRM_AE_ATTR_MARK, mark), + __ADD(XFRM_AE_ATTR_LIFETIME, cur_lifetime), + __ADD(XFRM_AE_ATTR_REPLAY_MAXAGE, replay_maxage), + __ADD(XFRM_AE_ATTR_REPLAY_MAXDIFF, replay_maxdiff), + __ADD(XFRM_AE_ATTR_REPLAY_STATE, replay_state), +}; + +static char* xfrm_ae_attrs2str (int attrs, char *buf, size_t len) +{ + return __flags2str(attrs, buf, len, ae_attrs, ARRAY_SIZE(ae_attrs)); +} +/** @} */ + +/** + * @name XFRM AE Flags Translations + * @{ + */ + +static const struct trans_tbl ae_flags[] = { + __ADD(XFRM_AE_UNSPEC, unspecified), + __ADD(XFRM_AE_RTHR, replay threshold), + __ADD(XFRM_AE_RVAL, replay value), + __ADD(XFRM_AE_LVAL, lifetime value), + __ADD(XFRM_AE_ETHR, expiry time threshold), + __ADD(XFRM_AE_CR, replay update event), + __ADD(XFRM_AE_CE, timer expiry event), + __ADD(XFRM_AE_CU, policy update event), +}; + +char* xfrmnl_ae_flags2str(int flags, char *buf, size_t len) +{ + return __flags2str (flags, buf, len, ae_flags, ARRAY_SIZE(ae_flags)); +} + +int xfrmnl_ae_str2flag(const char *name) +{ + return __str2flags(name, ae_flags, ARRAY_SIZE(ae_flags)); +} +/** @} */ + +static void xfrm_ae_dump_line(struct nl_object *a, struct nl_dump_params *p) +{ + char dst[INET6_ADDRSTRLEN+5], src[INET6_ADDRSTRLEN+5]; + struct xfrmnl_ae* ae = (struct xfrmnl_ae *) a; + char flags[128], buf[128]; + time_t add_time, use_time; + struct tm *add_time_tm, *use_time_tm; + struct tm tm_buf; + + nl_dump_line(p, "src %s dst %s \n", nl_addr2str(ae->saddr, src, sizeof(src)), + nl_addr2str(ae->sa_id.daddr, dst, sizeof(dst))); + + nl_dump_line(p, "\tproto %s spi 0x%x reqid %u ", + nl_ip_proto2str (ae->sa_id.proto, buf, sizeof (buf)), + ae->sa_id.spi, ae->reqid); + + xfrmnl_ae_flags2str(ae->flags, flags, sizeof (flags)); + nl_dump_line(p, "flags %s(0x%x) mark mask/value 0x%x/0x%x \n", flags, + ae->flags, ae->mark.m, ae->mark.v); + + nl_dump_line(p, "\tlifetime current: \n"); + nl_dump_line(p, "\t\tbytes %llu packets %llu \n", + (long long unsigned)ae->lifetime_cur.bytes, + (long long unsigned)ae->lifetime_cur.packets); + if (ae->lifetime_cur.add_time != 0) + { + add_time = ae->lifetime_cur.add_time; + add_time_tm = gmtime_r (&add_time, &tm_buf); + strftime (flags, 128, "%Y-%m-%d %H-%M-%S", add_time_tm); + } + else + { + sprintf (flags, "%s", "-"); + } + + if (ae->lifetime_cur.use_time != 0) + { + use_time = ae->lifetime_cur.use_time; + use_time_tm = gmtime_r (&use_time, &tm_buf); + strftime (buf, 128, "%Y-%m-%d %H-%M-%S", use_time_tm); + } + else + { + sprintf (buf, "%s", "-"); + } + nl_dump_line(p, "\t\tadd_time: %s, use_time: %s\n", flags, buf); + + nl_dump_line(p, "\treplay info: \n"); + nl_dump_line(p, "\t\tmax age %u max diff %u \n", ae->replay_maxage, ae->replay_maxdiff); + + nl_dump_line(p, "\treplay state info: \n"); + if (ae->replay_state_esn) + { + nl_dump_line(p, "\t\toseq %u seq %u oseq_hi %u seq_hi %u replay window: %u \n", + ae->replay_state_esn->oseq, ae->replay_state_esn->seq, + ae->replay_state_esn->oseq_hi, ae->replay_state_esn->seq_hi, + ae->replay_state_esn->replay_window); + } + else + { + nl_dump_line(p, "\t\toseq %u seq %u bitmap: %u \n", ae->replay_state.oseq, + ae->replay_state.seq, ae->replay_state.bitmap); + } + + nl_dump(p, "\n"); +} + +static void xfrm_ae_dump_details(struct nl_object *a, struct nl_dump_params *p) +{ + xfrm_ae_dump_line(a, p); +} + +static void xfrm_ae_dump_stats(struct nl_object *a, struct nl_dump_params *p) +{ + xfrm_ae_dump_details(a, p); +} + + +static int build_xfrm_ae_message(struct xfrmnl_ae *tmpl, int cmd, int flags, + struct nl_msg **result) +{ + struct nl_msg* msg; + struct xfrm_aevent_id ae_id; + + if (!(tmpl->ce_mask & XFRM_AE_ATTR_DADDR) || + !(tmpl->ce_mask & XFRM_AE_ATTR_SPI) || + !(tmpl->ce_mask & XFRM_AE_ATTR_PROTO)) + return -NLE_MISSING_ATTR; + + memset(&ae_id, 0, sizeof(ae_id)); + + memcpy (&ae_id.sa_id.daddr, nl_addr_get_binary_addr (tmpl->sa_id.daddr), sizeof (uint8_t) * nl_addr_get_len (tmpl->sa_id.daddr)); + ae_id.sa_id.spi = htonl(tmpl->sa_id.spi); + ae_id.sa_id.family = tmpl->sa_id.family; + ae_id.sa_id.proto = tmpl->sa_id.proto; + + if (tmpl->ce_mask & XFRM_AE_ATTR_SADDR) + memcpy (&ae_id.saddr, nl_addr_get_binary_addr (tmpl->saddr), sizeof (uint8_t) * nl_addr_get_len (tmpl->saddr)); + + if (tmpl->ce_mask & XFRM_AE_ATTR_FLAGS) + ae_id.flags = tmpl->flags; + + if (tmpl->ce_mask & XFRM_AE_ATTR_REQID) + ae_id.reqid = tmpl->reqid; + + msg = nlmsg_alloc_simple(cmd, flags); + if (!msg) + return -NLE_NOMEM; + + if (nlmsg_append(msg, &ae_id, sizeof(ae_id), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if (tmpl->ce_mask & XFRM_AE_ATTR_MARK) + NLA_PUT (msg, XFRMA_MARK, sizeof (struct xfrmnl_mark), &tmpl->mark); + + if (tmpl->ce_mask & XFRM_AE_ATTR_LIFETIME) + NLA_PUT (msg, XFRMA_LTIME_VAL, sizeof (struct xfrmnl_lifetime_cur), &tmpl->lifetime_cur); + + if (tmpl->ce_mask & XFRM_AE_ATTR_REPLAY_MAXAGE) + NLA_PUT_U32 (msg, XFRMA_ETIMER_THRESH, tmpl->replay_maxage); + + if (tmpl->ce_mask & XFRM_AE_ATTR_REPLAY_MAXDIFF) + NLA_PUT_U32 (msg, XFRMA_REPLAY_THRESH, tmpl->replay_maxdiff); + + if (tmpl->ce_mask & XFRM_AE_ATTR_REPLAY_STATE) { + if (tmpl->replay_state_esn) { + uint32_t len = sizeof (struct xfrm_replay_state_esn) + (sizeof (uint32_t) * tmpl->replay_state_esn->bmp_len); + NLA_PUT (msg, XFRMA_REPLAY_ESN_VAL, len, tmpl->replay_state_esn); + } + else { + NLA_PUT (msg, XFRMA_REPLAY_VAL, sizeof (struct xfrmnl_replay_state), &tmpl->replay_state); + } + } + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +/** + * @name XFRM AE Update + * @{ + */ + +int xfrmnl_ae_set(struct nl_sock* sk, struct xfrmnl_ae* ae, int flags) +{ + int err; + struct nl_msg *msg; + + if ((err = build_xfrm_ae_message(ae, XFRM_MSG_NEWAE, flags|NLM_F_REPLACE, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return nl_wait_for_ack(sk); +} + +/** @} */ + +/** + * @name XFRM AE Object Allocation/Freeage + * @{ + */ + +struct xfrmnl_ae* xfrmnl_ae_alloc(void) +{ + return (struct xfrmnl_ae*) nl_object_alloc(&xfrm_ae_obj_ops); +} + +void xfrmnl_ae_put(struct xfrmnl_ae* ae) +{ + nl_object_put((struct nl_object *) ae); +} + +/** @} */ + +static struct nla_policy xfrm_ae_policy[XFRMA_MAX+1] = { + [XFRMA_LTIME_VAL] = { .minlen = sizeof(struct xfrm_lifetime_cur) }, + [XFRMA_REPLAY_VAL] = { .minlen = sizeof(struct xfrm_replay_state) }, + [XFRMA_REPLAY_THRESH] = { .type = NLA_U32 }, + [XFRMA_ETIMER_THRESH] = { .type = NLA_U32 }, + [XFRMA_SRCADDR] = { .minlen = sizeof(xfrm_address_t) }, + [XFRMA_MARK] = { .minlen = sizeof(struct xfrm_mark) }, + [XFRMA_REPLAY_ESN_VAL] = { .minlen = sizeof(struct xfrm_replay_state_esn) }, +}; + +int xfrmnl_ae_parse(struct nlmsghdr *n, struct xfrmnl_ae **result) +{ + _nl_auto_xfrmnl_ae struct xfrmnl_ae *ae = NULL; + struct nlattr *tb[XFRMA_MAX + 1]; + struct xfrm_aevent_id* ae_id; + int err; + + ae = xfrmnl_ae_alloc(); + if (!ae) + return -NLE_NOMEM; + + ae->ce_msgtype = n->nlmsg_type; + ae_id = nlmsg_data(n); + + err = nlmsg_parse(n, sizeof(struct xfrm_aevent_id), tb, XFRMA_MAX, xfrm_ae_policy); + if (err < 0) + return err; + + if (!(ae->sa_id.daddr = + _nl_addr_build(ae_id->sa_id.family, &ae_id->sa_id.daddr))) + return -NLE_NOMEM; + ae->sa_id.family= ae_id->sa_id.family; + ae->sa_id.spi = ntohl(ae_id->sa_id.spi); + ae->sa_id.proto = ae_id->sa_id.proto; + if (!(ae->saddr = _nl_addr_build(ae_id->sa_id.family, &ae_id->saddr))) + return -NLE_NOMEM; + ae->reqid = ae_id->reqid; + ae->flags = ae_id->flags; + ae->ce_mask |= (XFRM_AE_ATTR_DADDR | XFRM_AE_ATTR_FAMILY | XFRM_AE_ATTR_SPI | + XFRM_AE_ATTR_PROTO | XFRM_AE_ATTR_SADDR | XFRM_AE_ATTR_REQID | + XFRM_AE_ATTR_FLAGS); + + if (tb[XFRMA_MARK]) { + struct xfrm_mark* m = nla_data(tb[XFRMA_MARK]); + ae->mark.m = m->m; + ae->mark.v = m->v; + ae->ce_mask |= XFRM_AE_ATTR_MARK; + } + + if (tb[XFRMA_LTIME_VAL]) { + struct xfrm_lifetime_cur* cur = nla_data(tb[XFRMA_LTIME_VAL]); + + ae->lifetime_cur.bytes = cur->bytes; + ae->lifetime_cur.packets = cur->packets; + ae->lifetime_cur.add_time = cur->add_time; + ae->lifetime_cur.use_time = cur->use_time; + ae->ce_mask |= XFRM_AE_ATTR_LIFETIME; + } + + if (tb[XFRM_AE_ETHR]) { + ae->replay_maxage = *(uint32_t*)nla_data(tb[XFRM_AE_ETHR]); + ae->ce_mask |= XFRM_AE_ATTR_REPLAY_MAXAGE; + } + + if (tb[XFRM_AE_RTHR]) { + ae->replay_maxdiff = *(uint32_t*)nla_data(tb[XFRM_AE_RTHR]); + ae->ce_mask |= XFRM_AE_ATTR_REPLAY_MAXDIFF; + } + + if (tb[XFRMA_REPLAY_ESN_VAL]) { + struct xfrm_replay_state_esn* esn = nla_data (tb[XFRMA_REPLAY_ESN_VAL]); + uint32_t len = sizeof (struct xfrmnl_replay_state_esn) + (sizeof (uint32_t) * esn->bmp_len); + + if ((ae->replay_state_esn = calloc (1, len)) == NULL) + return -NLE_NOMEM; + ae->replay_state_esn->oseq = esn->oseq; + ae->replay_state_esn->seq = esn->seq; + ae->replay_state_esn->oseq_hi = esn->oseq_hi; + ae->replay_state_esn->seq_hi = esn->seq_hi; + ae->replay_state_esn->replay_window = esn->replay_window; + ae->replay_state_esn->bmp_len = esn->bmp_len; + memcpy (ae->replay_state_esn->bmp, esn->bmp, sizeof (uint32_t) * esn->bmp_len); + ae->ce_mask |= XFRM_AE_ATTR_REPLAY_STATE; + } + else + { + struct xfrm_replay_state* replay_state = nla_data (tb[XFRMA_REPLAY_VAL]); + ae->replay_state.oseq = replay_state->oseq; + ae->replay_state.seq = replay_state->seq; + ae->replay_state.bitmap = replay_state->bitmap; + ae->ce_mask |= XFRM_AE_ATTR_REPLAY_STATE; + + ae->replay_state_esn = NULL; + } + + *result = _nl_steal_pointer(&ae); + return 0; +} + +static int xfrm_ae_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *n, struct nl_parser_param *pp) +{ + struct xfrmnl_ae* ae; + int err; + + if ((err = xfrmnl_ae_parse(n, &ae)) < 0) + return err; + + err = pp->pp_cb((struct nl_object *) ae, pp); + + xfrmnl_ae_put(ae); + return err; +} + +/** + * @name XFRM AE Get + * @{ + */ + +int xfrmnl_ae_build_get_request(struct nl_addr* daddr, unsigned int spi, unsigned int protocol, + unsigned int mark_mask, unsigned int mark_value, struct nl_msg **result) +{ + struct nl_msg *msg; + struct xfrm_aevent_id ae_id; + struct xfrmnl_mark mark; + + if (!daddr || !spi) + { + fprintf(stderr, "APPLICATION BUG: %s:%d:%s: A valid destination address, spi must be specified\n", + __FILE__, __LINE__, __func__); + assert(0); + return -NLE_MISSING_ATTR; + } + + memset(&ae_id, 0, sizeof(ae_id)); + memcpy (&ae_id.sa_id.daddr, nl_addr_get_binary_addr (daddr), sizeof (uint8_t) * nl_addr_get_len (daddr)); + ae_id.sa_id.spi = htonl(spi); + ae_id.sa_id.family = nl_addr_get_family (daddr); + ae_id.sa_id.proto = protocol; + + if (!(msg = nlmsg_alloc_simple(XFRM_MSG_GETAE, 0))) + return -NLE_NOMEM; + + if (nlmsg_append(msg, &ae_id, sizeof(ae_id), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + mark.m = mark_mask; + mark.v = mark_value; + NLA_PUT (msg, XFRMA_MARK, sizeof (struct xfrmnl_mark), &mark); + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +int xfrmnl_ae_get_kernel(struct nl_sock* sock, struct nl_addr* daddr, unsigned int spi, unsigned int protocol, + unsigned int mark_mask, unsigned int mark_value, struct xfrmnl_ae** result) +{ + struct nl_msg *msg = NULL; + struct nl_object *obj; + int err; + + if ((err = xfrmnl_ae_build_get_request(daddr, spi, protocol, mark_mask, mark_value, &msg)) < 0) + return err; + + err = nl_send_auto(sock, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + if ((err = nl_pickup(sock, &xfrm_ae_msg_parser, &obj)) < 0) + return err; + + /* We have used xfrm_ae_msg_parser(), object is definitely a xfrm ae */ + *result = (struct xfrmnl_ae *) obj; + + /* If an object has been returned, we also need to wait for the ACK */ + if (err == 0 && obj) + nl_wait_for_ack(sock); + + return 0; +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ + +static inline int __assign_addr(struct xfrmnl_ae* ae, struct nl_addr **pos, + struct nl_addr *new, int flag, int nocheck) +{ + if (!nocheck) { + if (ae->ce_mask & XFRM_AE_ATTR_FAMILY) { + if (nl_addr_get_family (new) != ae->sa_id.family) + return -NLE_AF_MISMATCH; + } else { + ae->sa_id.family = nl_addr_get_family (new); + ae->ce_mask |= XFRM_AE_ATTR_FAMILY; + } + } + + if (*pos) + nl_addr_put(*pos); + + nl_addr_get(new); + *pos = new; + + ae->ce_mask |= flag; + + return 0; +} + + +struct nl_addr* xfrmnl_ae_get_daddr (struct xfrmnl_ae* ae) +{ + if (ae->ce_mask & XFRM_AE_ATTR_DADDR) + return ae->sa_id.daddr; + else + return NULL; +} + +int xfrmnl_ae_set_daddr (struct xfrmnl_ae* ae, struct nl_addr* addr) +{ + return __assign_addr(ae, &ae->sa_id.daddr, addr, XFRM_AE_ATTR_DADDR, 0); +} + +int xfrmnl_ae_get_spi (struct xfrmnl_ae* ae) +{ + if (ae->ce_mask & XFRM_AE_ATTR_SPI) + return ae->sa_id.spi; + else + return -1; +} + +int xfrmnl_ae_set_spi (struct xfrmnl_ae* ae, unsigned int spi) +{ + ae->sa_id.spi = spi; + ae->ce_mask |= XFRM_AE_ATTR_SPI; + + return 0; +} + +int xfrmnl_ae_get_family (struct xfrmnl_ae* ae) +{ + if (ae->ce_mask & XFRM_AE_ATTR_FAMILY) + return ae->sa_id.family; + else + return -1; +} + +int xfrmnl_ae_set_family (struct xfrmnl_ae* ae, unsigned int family) +{ + ae->sa_id.family = family; + ae->ce_mask |= XFRM_AE_ATTR_FAMILY; + + return 0; +} + +int xfrmnl_ae_get_proto (struct xfrmnl_ae* ae) +{ + if (ae->ce_mask & XFRM_AE_ATTR_PROTO) + return ae->sa_id.proto; + else + return -1; +} + +int xfrmnl_ae_set_proto (struct xfrmnl_ae* ae, unsigned int protocol) +{ + ae->sa_id.proto = protocol; + ae->ce_mask |= XFRM_AE_ATTR_PROTO; + + return 0; +} + +struct nl_addr* xfrmnl_ae_get_saddr (struct xfrmnl_ae* ae) +{ + if (ae->ce_mask & XFRM_AE_ATTR_SADDR) + return ae->saddr; + else + return NULL; +} + +int xfrmnl_ae_set_saddr (struct xfrmnl_ae* ae, struct nl_addr* addr) +{ + return __assign_addr(ae, &ae->saddr, addr, XFRM_AE_ATTR_SADDR, 1); +} + +int xfrmnl_ae_get_flags (struct xfrmnl_ae* ae) +{ + if (ae->ce_mask & XFRM_AE_ATTR_FLAGS) + return ae->flags; + else + return -1; +} + +int xfrmnl_ae_set_flags (struct xfrmnl_ae* ae, unsigned int flags) +{ + ae->flags = flags; + ae->ce_mask |= XFRM_AE_ATTR_FLAGS; + + return 0; +} + +int xfrmnl_ae_get_reqid (struct xfrmnl_ae* ae) +{ + if (ae->ce_mask & XFRM_AE_ATTR_REQID) + return ae->reqid; + else + return -1; +} + +int xfrmnl_ae_set_reqid (struct xfrmnl_ae* ae, unsigned int reqid) +{ + ae->reqid = reqid; + ae->ce_mask |= XFRM_AE_ATTR_REQID; + + return 0; +} + +int xfrmnl_ae_get_mark (struct xfrmnl_ae* ae, unsigned int* mark_mask, unsigned int* mark_value) +{ + if (mark_mask == NULL || mark_value == NULL) + return -1; + + if (ae->ce_mask & XFRM_AE_ATTR_MARK) + { + *mark_mask = ae->mark.m; + *mark_value = ae->mark.v; + + return 0; + } + else + return -1; +} + +int xfrmnl_ae_set_mark (struct xfrmnl_ae* ae, unsigned int value, unsigned int mask) +{ + ae->mark.v = value; + ae->mark.m = mask; + ae->ce_mask |= XFRM_AE_ATTR_MARK; + + return 0; +} + +int xfrmnl_ae_get_curlifetime (struct xfrmnl_ae* ae, unsigned long long int* curr_bytes, + unsigned long long int* curr_packets, unsigned long long int* curr_add_time, + unsigned long long int* curr_use_time) +{ + if (curr_bytes == NULL || curr_packets == NULL || curr_add_time == NULL || curr_use_time == NULL) + return -1; + + if (ae->ce_mask & XFRM_AE_ATTR_LIFETIME) + { + *curr_bytes = ae->lifetime_cur.bytes; + *curr_packets = ae->lifetime_cur.packets; + *curr_add_time = ae->lifetime_cur.add_time; + *curr_use_time = ae->lifetime_cur.use_time; + + return 0; + } + else + return -1; +} + +int xfrmnl_ae_set_curlifetime (struct xfrmnl_ae* ae, unsigned long long int curr_bytes, + unsigned long long int curr_packets, unsigned long long int curr_add_time, + unsigned long long int curr_use_time) +{ + ae->lifetime_cur.bytes = curr_bytes; + ae->lifetime_cur.packets = curr_packets; + ae->lifetime_cur.add_time = curr_add_time; + ae->lifetime_cur.use_time = curr_use_time; + ae->ce_mask |= XFRM_AE_ATTR_LIFETIME; + + return 0; +} + +int xfrmnl_ae_get_replay_maxage (struct xfrmnl_ae* ae) +{ + if (ae->ce_mask & XFRM_AE_ATTR_REPLAY_MAXAGE) + return ae->replay_maxage; + else + return -1; +} + +int xfrmnl_ae_set_replay_maxage (struct xfrmnl_ae* ae, unsigned int replay_maxage) +{ + ae->replay_maxage = replay_maxage; + ae->ce_mask |= XFRM_AE_ATTR_REPLAY_MAXAGE; + + return 0; +} + +int xfrmnl_ae_get_replay_maxdiff (struct xfrmnl_ae* ae) +{ + if (ae->ce_mask & XFRM_AE_ATTR_REPLAY_MAXDIFF) + return ae->replay_maxdiff; + else + return -1; +} + +int xfrmnl_ae_set_replay_maxdiff (struct xfrmnl_ae* ae, unsigned int replay_maxdiff) +{ + ae->replay_maxdiff = replay_maxdiff; + ae->ce_mask |= XFRM_AE_ATTR_REPLAY_MAXDIFF; + + return 0; +} + +int xfrmnl_ae_get_replay_state (struct xfrmnl_ae* ae, unsigned int* oseq, unsigned int* seq, unsigned int* bmp) +{ + if (ae->ce_mask & XFRM_AE_ATTR_REPLAY_STATE) + { + if (ae->replay_state_esn == NULL) + { + *oseq = ae->replay_state.oseq; + *seq = ae->replay_state.seq; + *bmp = ae->replay_state.bitmap; + + return 0; + } + else + { + return -1; + } + } + else + return -1; +} + +int xfrmnl_ae_set_replay_state (struct xfrmnl_ae* ae, unsigned int oseq, unsigned int seq, unsigned int bitmap) +{ + ae->replay_state.oseq = oseq; + ae->replay_state.seq = seq; + ae->replay_state.bitmap = bitmap; + ae->ce_mask |= XFRM_AE_ATTR_REPLAY_STATE; + + return 0; +} + +int xfrmnl_ae_get_replay_state_esn(struct xfrmnl_ae* ae, unsigned int* oseq, unsigned int* seq, unsigned int* oseq_hi, + unsigned int* seq_hi, unsigned int* replay_window, unsigned int* bmp_len, unsigned int* bmp) +{ + if (ae->ce_mask & XFRM_AE_ATTR_REPLAY_STATE) + { + if (ae->replay_state_esn) + { + *oseq = ae->replay_state_esn->oseq; + *seq = ae->replay_state_esn->seq; + *oseq_hi= ae->replay_state_esn->oseq_hi; + *seq_hi = ae->replay_state_esn->seq_hi; + *replay_window = ae->replay_state_esn->replay_window; + *bmp_len = ae->replay_state_esn->bmp_len; // In number of 32 bit words + memcpy (bmp, ae->replay_state_esn->bmp, ae->replay_state_esn->bmp_len * sizeof (uint32_t)); + + return 0; + } + else + { + return -1; + } + } + else + return -1; +} + +int xfrmnl_ae_set_replay_state_esn(struct xfrmnl_ae* ae, unsigned int oseq, unsigned int seq, + unsigned int oseq_hi, unsigned int seq_hi, unsigned int replay_window, + unsigned int bmp_len, unsigned int* bmp) +{ + /* Free the old replay ESN state and allocate new one */ + if (ae->replay_state_esn) + free (ae->replay_state_esn); + + if ((ae->replay_state_esn = calloc (1, sizeof (struct xfrmnl_replay_state_esn) + sizeof (uint32_t) * bmp_len)) == NULL) + return -1; + + ae->replay_state_esn->oseq = oseq; + ae->replay_state_esn->seq = seq; + ae->replay_state_esn->oseq_hi = oseq_hi; + ae->replay_state_esn->seq_hi = seq_hi; + ae->replay_state_esn->replay_window = replay_window; + ae->replay_state_esn->bmp_len = bmp_len; // In number of 32 bit words + memcpy (ae->replay_state_esn->bmp, bmp, bmp_len * sizeof (uint32_t)); + ae->ce_mask |= XFRM_AE_ATTR_REPLAY_STATE; + + return 0; +} + +/** @} */ + +static struct nl_object_ops xfrm_ae_obj_ops = { + .oo_name = "xfrm/ae", + .oo_size = sizeof(struct xfrmnl_ae), + .oo_free_data = xfrm_ae_free_data, + .oo_clone = xfrm_ae_clone, + .oo_dump = { + [NL_DUMP_LINE] = xfrm_ae_dump_line, + [NL_DUMP_DETAILS] = xfrm_ae_dump_details, + [NL_DUMP_STATS] = xfrm_ae_dump_stats, + }, + .oo_compare = xfrm_ae_compare, + .oo_attrs2str = xfrm_ae_attrs2str, + .oo_id_attrs = (XFRM_AE_ATTR_DADDR | XFRM_AE_ATTR_SPI | XFRM_AE_ATTR_PROTO), +}; + +/** @} */ + diff --git a/lib/xfrm/lifetime.c b/lib/xfrm/lifetime.c new file mode 100644 index 0000000..17c9883 --- /dev/null +++ b/lib/xfrm/lifetime.c @@ -0,0 +1,278 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * @ingroup xfrmnl + * @defgroup XFRM Lifetime Configuration Object + * + * Abstract data type representing XFRM SA lifetime properties + * + * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ + */ + +#include "nl-default.h" + +#include + +#include "nl-xfrm.h" + +static void ltime_cfg_destroy(struct xfrmnl_ltime_cfg* ltime) +{ + if (!ltime) + return; + + if (ltime->refcnt != 1) + { + fprintf(stderr, "BUG: %s:%d\n", __FILE__, __LINE__); + assert(0); + } + + free(ltime); +} + +/** + * @name Creating Selector + * @{ + */ + +/** + * Allocate new lifetime config object. + * @return Newly allocated lifetime config object or NULL + */ +struct xfrmnl_ltime_cfg* xfrmnl_ltime_cfg_alloc() +{ + struct xfrmnl_ltime_cfg* ltime; + + ltime = calloc(1, sizeof(struct xfrmnl_ltime_cfg)); + if (!ltime) + return NULL; + + ltime->refcnt = 1; + + return ltime; +} + +/** + * Clone existing lifetime config object. + * @arg ltime Selector object. + * @return Newly allocated lifetime config object being a duplicate of the + * specified lifetime config object or NULL if a failure occured. + */ +struct xfrmnl_ltime_cfg* xfrmnl_ltime_cfg_clone(struct xfrmnl_ltime_cfg* ltime) +{ + struct xfrmnl_ltime_cfg* new; + + new = xfrmnl_ltime_cfg_alloc(); + if (new) + memcpy ((void*)new, (void*)ltime, sizeof (struct xfrmnl_ltime_cfg)); + + return new; +} + +/** @} */ + +/** + * @name Managing Usage References + * @{ + */ + +struct xfrmnl_ltime_cfg* xfrmnl_ltime_cfg_get(struct xfrmnl_ltime_cfg* ltime) +{ + ltime->refcnt++; + + return ltime; +} + +void xfrmnl_ltime_cfg_put(struct xfrmnl_ltime_cfg* ltime) +{ + if (!ltime) + return; + + if (ltime->refcnt == 1) + ltime_cfg_destroy(ltime); + else + ltime->refcnt--; +} + +/** + * Check whether an lifetime config object is shared. + * @arg addr Selector object. + * @return Non-zero if the lifetime config object is shared, otherwise 0. + */ +int xfrmnl_ltime_cfg_shared(struct xfrmnl_ltime_cfg* ltime) +{ + return ltime->refcnt > 1; +} + +/** @} */ + +/** + * @name Miscellaneous + * @{ + */ + +/** + * Compares two lifetime config objects. + * @arg a A lifetime config object. + * @arg b Another lifetime config object. + * + * @return Non zero if difference is found, 0 otherwise if both + * the objects are identical. + */ +int xfrmnl_ltime_cfg_cmp(struct xfrmnl_ltime_cfg* a, struct xfrmnl_ltime_cfg* b) +{ + /* Check for any differences */ + if ((a->soft_byte_limit != b->soft_byte_limit) || + (a->soft_packet_limit != b->soft_packet_limit) || + (a->hard_byte_limit != b->hard_byte_limit) || + (a->hard_packet_limit != b->hard_packet_limit) || + (a->soft_add_expires_seconds != b->soft_add_expires_seconds) || + (a->hard_add_expires_seconds != b->hard_add_expires_seconds) || + (a->soft_use_expires_seconds != b->soft_use_expires_seconds) || + (a->hard_use_expires_seconds != b->hard_use_expires_seconds)) + return 1; + + /* The objects are identical */ + return 0; +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ +unsigned long long xfrmnl_ltime_cfg_get_soft_bytelimit (struct xfrmnl_ltime_cfg* ltime) +{ + return ltime->soft_byte_limit; +} + +int xfrmnl_ltime_cfg_set_soft_bytelimit (struct xfrmnl_ltime_cfg* ltime, unsigned long long soft_byte_limit) +{ + ltime->soft_byte_limit = soft_byte_limit; + + return 0; +} + +unsigned long long xfrmnl_ltime_cfg_get_hard_bytelimit (struct xfrmnl_ltime_cfg* ltime) +{ + return ltime->hard_byte_limit; +} + +int xfrmnl_ltime_cfg_set_hard_bytelimit (struct xfrmnl_ltime_cfg* ltime, unsigned long long hard_byte_limit) +{ + ltime->hard_byte_limit = hard_byte_limit; + + return 0; +} + +unsigned long long xfrmnl_ltime_cfg_get_soft_packetlimit (struct xfrmnl_ltime_cfg* ltime) +{ + return ltime->soft_packet_limit; +} + +int xfrmnl_ltime_cfg_set_soft_packetlimit (struct xfrmnl_ltime_cfg* ltime, unsigned long long soft_packet_limit) +{ + ltime->soft_packet_limit = soft_packet_limit; + + return 0; +} + +unsigned long long xfrmnl_ltime_cfg_get_hard_packetlimit (struct xfrmnl_ltime_cfg* ltime) +{ + return ltime->hard_packet_limit; +} + +int xfrmnl_ltime_cfg_set_hard_packetlimit (struct xfrmnl_ltime_cfg* ltime, unsigned long long hard_packet_limit) +{ + ltime->hard_packet_limit = hard_packet_limit; + + return 0; +} + +unsigned long long xfrmnl_ltime_cfg_get_soft_addexpires (struct xfrmnl_ltime_cfg* ltime) +{ + return ltime->soft_add_expires_seconds; +} + +int xfrmnl_ltime_cfg_set_soft_addexpires (struct xfrmnl_ltime_cfg* ltime, unsigned long long soft_add_expires_seconds) +{ + ltime->soft_add_expires_seconds = soft_add_expires_seconds; + + return 0; +} + +unsigned long long xfrmnl_ltime_cfg_get_hard_addexpires (struct xfrmnl_ltime_cfg* ltime) +{ + return ltime->hard_add_expires_seconds; +} + +int xfrmnl_ltime_cfg_set_hard_addexpires (struct xfrmnl_ltime_cfg* ltime, unsigned long long hard_add_expires_seconds) +{ + ltime->hard_add_expires_seconds = hard_add_expires_seconds; + + return 0; +} + +unsigned long long xfrmnl_ltime_cfg_get_soft_useexpires (struct xfrmnl_ltime_cfg* ltime) +{ + return ltime->soft_use_expires_seconds; +} + +int xfrmnl_ltime_cfg_set_soft_useexpires (struct xfrmnl_ltime_cfg* ltime, unsigned long long soft_use_expires_seconds) +{ + ltime->soft_use_expires_seconds = soft_use_expires_seconds; + + return 0; +} + +unsigned long long xfrmnl_ltime_cfg_get_hard_useexpires (struct xfrmnl_ltime_cfg* ltime) +{ + return ltime->hard_use_expires_seconds; +} + +int xfrmnl_ltime_cfg_set_hard_useexpires (struct xfrmnl_ltime_cfg* ltime, unsigned long long hard_use_expires_seconds) +{ + ltime->hard_use_expires_seconds = hard_use_expires_seconds; + + return 0; +} + +/** @} */ diff --git a/lib/xfrm/nl-xfrm.h b/lib/xfrm/nl-xfrm.h new file mode 100644 index 0000000..0469c63 --- /dev/null +++ b/lib/xfrm/nl-xfrm.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2003-2013 Thomas Graf + * Copyright (c) 2013 Sassano Systems LLC + */ + +#ifndef __LIB_XFRM_NL_XFRM_H__ +#define __LIB_XFRM_NL_XFRM_H__ + +/* Lifetime configuration, used for both policy rules (SPD) and SAs. */ +struct xfrmnl_ltime_cfg { + uint32_t refcnt; + uint64_t soft_byte_limit; + uint64_t hard_byte_limit; + uint64_t soft_packet_limit; + uint64_t hard_packet_limit; + uint64_t soft_add_expires_seconds; + uint64_t hard_add_expires_seconds; + uint64_t soft_use_expires_seconds; + uint64_t hard_use_expires_seconds; +}; + +/* Current lifetime, used for both policy rules (SPD) and SAs. */ +struct xfrmnl_lifetime_cur { + uint64_t bytes; + uint64_t packets; + uint64_t add_time; + uint64_t use_time; +}; + +struct xfrmnl_replay_state { + uint32_t oseq; + uint32_t seq; + uint32_t bitmap; +}; + +struct xfrmnl_replay_state_esn { + uint32_t bmp_len; + uint32_t oseq; + uint32_t seq; + uint32_t oseq_hi; + uint32_t seq_hi; + uint32_t replay_window; + uint32_t bmp[0]; +}; + +struct xfrmnl_mark { + uint32_t v; /* value */ + uint32_t m; /* mask */ +}; + +struct xfrmnl_id { + struct nl_addr *daddr; + uint32_t spi; + uint8_t proto; +}; + +struct xfrmnl_user_sec_ctx { + uint16_t len; + uint16_t exttype; + uint8_t ctx_alg; + uint8_t ctx_doi; + uint16_t ctx_len; + char ctx[0]; +}; + +struct xfrmnl_user_tmpl { + struct xfrmnl_id id; + uint16_t family; + struct nl_addr *saddr; + uint32_t reqid; + uint8_t mode; + uint8_t share; + uint8_t optional; + uint32_t aalgos; + uint32_t ealgos; + uint32_t calgos; + struct nl_list_head utmpl_list; +}; + +#endif /* __LIB_XFRM_NL_XFRM_H__ */ diff --git a/lib/xfrm/sa.c b/lib/xfrm/sa.c new file mode 100644 index 0000000..0c89c71 --- /dev/null +++ b/lib/xfrm/sa.c @@ -0,0 +1,2385 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @ingroup xfrmnl + * @defgroup sa Security Association + * @brief + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "nl-xfrm.h" +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" +#include "nl-aux-core/nl-core.h" +#include "nl-aux-xfrm/nl-xfrm.h" + +/** @cond SKIP */ + +struct xfrmnl_stats { + uint32_t replay_window; + uint32_t replay; + uint32_t integrity_failed; +}; + +struct xfrmnl_algo_aead { + char alg_name[64]; + uint32_t alg_key_len; /* in bits */ + uint32_t alg_icv_len; /* in bits */ + char alg_key[0]; +}; + +struct xfrmnl_algo_auth { + char alg_name[64]; + uint32_t alg_key_len; /* in bits */ + uint32_t alg_trunc_len; /* in bits */ + char alg_key[0]; +}; + +struct xfrmnl_algo { + char alg_name[64]; + uint32_t alg_key_len; /* in bits */ + char alg_key[0]; +}; + +struct xfrmnl_encap_tmpl { + uint16_t encap_type; + uint16_t encap_sport; + uint16_t encap_dport; + struct nl_addr* encap_oa; +}; + +struct xfrmnl_user_offload { + int ifindex; + uint8_t flags; +}; + +struct xfrmnl_sa { + NLHDR_COMMON + + struct xfrmnl_sel* sel; + struct xfrmnl_id id; + struct nl_addr* saddr; + struct xfrmnl_ltime_cfg* lft; + struct xfrmnl_lifetime_cur curlft; + struct xfrmnl_stats stats; + uint32_t seq; + uint32_t reqid; + uint16_t family; + uint8_t mode; /* XFRM_MODE_xxx */ + uint8_t replay_window; + uint8_t flags; + struct xfrmnl_algo_aead* aead; + struct xfrmnl_algo_auth* auth; + struct xfrmnl_algo* crypt; + struct xfrmnl_algo* comp; + struct xfrmnl_encap_tmpl* encap; + uint32_t tfcpad; + struct nl_addr* coaddr; + struct xfrmnl_mark mark; + struct xfrmnl_user_sec_ctx* sec_ctx; + uint32_t replay_maxage; + uint32_t replay_maxdiff; + struct xfrmnl_replay_state replay_state; + struct xfrmnl_replay_state_esn* replay_state_esn; + uint8_t hard; + struct xfrmnl_user_offload* user_offload; +}; + +#define XFRM_SA_ATTR_SEL 0x01 +#define XFRM_SA_ATTR_DADDR 0x02 +#define XFRM_SA_ATTR_SPI 0x04 +#define XFRM_SA_ATTR_PROTO 0x08 +#define XFRM_SA_ATTR_SADDR 0x10 +#define XFRM_SA_ATTR_LTIME_CFG 0x20 +#define XFRM_SA_ATTR_LTIME_CUR 0x40 +#define XFRM_SA_ATTR_STATS 0x80 +#define XFRM_SA_ATTR_SEQ 0x100 +#define XFRM_SA_ATTR_REQID 0x200 +#define XFRM_SA_ATTR_FAMILY 0x400 +#define XFRM_SA_ATTR_MODE 0x800 +#define XFRM_SA_ATTR_REPLAY_WIN 0x1000 +#define XFRM_SA_ATTR_FLAGS 0x2000 +#define XFRM_SA_ATTR_ALG_AEAD 0x4000 +#define XFRM_SA_ATTR_ALG_AUTH 0x8000 +#define XFRM_SA_ATTR_ALG_CRYPT 0x10000 +#define XFRM_SA_ATTR_ALG_COMP 0x20000 +#define XFRM_SA_ATTR_ENCAP 0x40000 +#define XFRM_SA_ATTR_TFCPAD 0x80000 +#define XFRM_SA_ATTR_COADDR 0x100000 +#define XFRM_SA_ATTR_MARK 0x200000 +#define XFRM_SA_ATTR_SECCTX 0x400000 +#define XFRM_SA_ATTR_REPLAY_MAXAGE 0x800000 +#define XFRM_SA_ATTR_REPLAY_MAXDIFF 0x1000000 +#define XFRM_SA_ATTR_REPLAY_STATE 0x2000000 +#define XFRM_SA_ATTR_EXPIRE 0x4000000 +#define XFRM_SA_ATTR_OFFLOAD_DEV 0x8000000 + +static struct nl_cache_ops xfrmnl_sa_ops; +static struct nl_object_ops xfrm_sa_obj_ops; +/** @endcond */ + +static void xfrm_sa_alloc_data(struct nl_object *c) +{ + struct xfrmnl_sa* sa = nl_object_priv (c); + + if ((sa->sel = xfrmnl_sel_alloc ()) == NULL) + return; + + if ((sa->lft = xfrmnl_ltime_cfg_alloc ()) == NULL) + return; +} + +static void xfrm_sa_free_data(struct nl_object *c) +{ + struct xfrmnl_sa* sa = nl_object_priv (c); + + if (sa == NULL) + return; + + xfrmnl_sel_put (sa->sel); + xfrmnl_ltime_cfg_put (sa->lft); + nl_addr_put (sa->id.daddr); + nl_addr_put (sa->saddr); + + if (sa->aead) + free (sa->aead); + if (sa->auth) + free (sa->auth); + if (sa->crypt) + free (sa->crypt); + if (sa->comp) + free (sa->comp); + if (sa->encap) { + if (sa->encap->encap_oa) + nl_addr_put(sa->encap->encap_oa); + free(sa->encap); + } + if (sa->coaddr) + nl_addr_put (sa->coaddr); + if (sa->sec_ctx) + free (sa->sec_ctx); + if (sa->replay_state_esn) + free (sa->replay_state_esn); + if (sa->user_offload) + free(sa->user_offload); +} + +static int xfrm_sa_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct xfrmnl_sa* dst = nl_object_priv(_dst); + struct xfrmnl_sa* src = nl_object_priv(_src); + uint32_t len = 0; + + dst->sel = NULL; + dst->id.daddr = NULL; + dst->saddr = NULL; + dst->lft = NULL; + dst->aead = NULL; + dst->auth = NULL; + dst->crypt = NULL; + dst->comp = NULL; + dst->encap = NULL; + dst->coaddr = NULL; + dst->sec_ctx = NULL; + dst->replay_state_esn = NULL; + dst->user_offload = NULL; + + if (src->sel) + if ((dst->sel = xfrmnl_sel_clone (src->sel)) == NULL) + return -NLE_NOMEM; + + if (src->lft) + if ((dst->lft = xfrmnl_ltime_cfg_clone (src->lft)) == NULL) + return -NLE_NOMEM; + + if (src->id.daddr) + if ((dst->id.daddr = nl_addr_clone (src->id.daddr)) == NULL) + return -NLE_NOMEM; + + if (src->saddr) + if ((dst->saddr = nl_addr_clone (src->saddr)) == NULL) + return -NLE_NOMEM; + + if (src->aead) { + len = sizeof (struct xfrmnl_algo_aead) + ((src->aead->alg_key_len + 7) / 8); + if ((dst->aead = calloc (1, len)) == NULL) + return -NLE_NOMEM; + memcpy ((void *)dst->aead, (void *)src->aead, len); + } + + if (src->auth) { + len = sizeof (struct xfrmnl_algo_auth) + ((src->auth->alg_key_len + 7) / 8); + if ((dst->auth = calloc (1, len)) == NULL) + return -NLE_NOMEM; + memcpy ((void *)dst->auth, (void *)src->auth, len); + } + + if (src->crypt) { + len = sizeof (struct xfrmnl_algo) + ((src->crypt->alg_key_len + 7) / 8); + if ((dst->crypt = calloc (1, len)) == NULL) + return -NLE_NOMEM; + memcpy ((void *)dst->crypt, (void *)src->crypt, len); + } + + if (src->comp) { + len = sizeof (struct xfrmnl_algo) + ((src->comp->alg_key_len + 7) / 8); + if ((dst->comp = calloc (1, len)) == NULL) + return -NLE_NOMEM; + memcpy ((void *)dst->comp, (void *)src->comp, len); + } + + if (src->encap) { + len = sizeof (struct xfrmnl_encap_tmpl); + if ((dst->encap = calloc (1, len)) == NULL) + return -NLE_NOMEM; + memcpy ((void *)dst->encap, (void *)src->encap, len); + } + + if (src->coaddr) + if ((dst->coaddr = nl_addr_clone (src->coaddr)) == NULL) + return -NLE_NOMEM; + + if (src->sec_ctx) { + len = sizeof (*src->sec_ctx) + src->sec_ctx->ctx_len; + if ((dst->sec_ctx = calloc (1, len)) == NULL) + return -NLE_NOMEM; + memcpy ((void *)dst->sec_ctx, (void *)src->sec_ctx, len); + } + + if (src->replay_state_esn) { + len = sizeof (struct xfrmnl_replay_state_esn) + (src->replay_state_esn->bmp_len * sizeof (uint32_t)); + if ((dst->replay_state_esn = calloc (1, len)) == NULL) + return -NLE_NOMEM; + memcpy ((void *)dst->replay_state_esn, (void *)src->replay_state_esn, len); + } + + if (src->user_offload) { + dst->user_offload = _nl_memdup_ptr(src->user_offload); + if (!dst->user_offload) + return -NLE_NOMEM; + } + + return 0; +} + +static uint64_t xfrm_sa_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) +{ + struct xfrmnl_sa* a = (struct xfrmnl_sa *) _a; + struct xfrmnl_sa* b = (struct xfrmnl_sa *) _b; + uint64_t diff = 0; + int found = 0; + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(XFRM_SA_ATTR_SEL, xfrmnl_sel_cmp(a->sel, b->sel)); + diff |= _DIFF(XFRM_SA_ATTR_DADDR, + nl_addr_cmp(a->id.daddr, b->id.daddr)); + diff |= _DIFF(XFRM_SA_ATTR_SPI, a->id.spi != b->id.spi); + diff |= _DIFF(XFRM_SA_ATTR_PROTO, a->id.proto != b->id.proto); + diff |= _DIFF(XFRM_SA_ATTR_SADDR, nl_addr_cmp(a->saddr, b->saddr)); + diff |= _DIFF(XFRM_SA_ATTR_LTIME_CFG, + xfrmnl_ltime_cfg_cmp(a->lft, b->lft)); + diff |= _DIFF(XFRM_SA_ATTR_REQID, a->reqid != b->reqid); + diff |= _DIFF(XFRM_SA_ATTR_FAMILY, a->family != b->family); + diff |= _DIFF(XFRM_SA_ATTR_MODE, a->mode != b->mode); + diff |= _DIFF(XFRM_SA_ATTR_REPLAY_WIN, + a->replay_window != b->replay_window); + diff |= _DIFF(XFRM_SA_ATTR_FLAGS, a->flags != b->flags); + diff |= _DIFF(XFRM_SA_ATTR_ALG_AEAD, + (strcmp(a->aead->alg_name, b->aead->alg_name) || + (a->aead->alg_key_len != b->aead->alg_key_len) || + (a->aead->alg_icv_len != b->aead->alg_icv_len) || + memcmp(a->aead->alg_key, b->aead->alg_key, + ((a->aead->alg_key_len + 7) / 8)))); + diff |= _DIFF(XFRM_SA_ATTR_ALG_AUTH, + (strcmp(a->auth->alg_name, b->auth->alg_name) || + (a->auth->alg_key_len != b->auth->alg_key_len) || + (a->auth->alg_trunc_len != b->auth->alg_trunc_len) || + memcmp(a->auth->alg_key, b->auth->alg_key, + ((a->auth->alg_key_len + 7) / 8)))); + diff |= _DIFF(XFRM_SA_ATTR_ALG_CRYPT, + (strcmp(a->crypt->alg_name, b->crypt->alg_name) || + (a->crypt->alg_key_len != b->crypt->alg_key_len) || + memcmp(a->crypt->alg_key, b->crypt->alg_key, + ((a->crypt->alg_key_len + 7) / 8)))); + diff |= _DIFF(XFRM_SA_ATTR_ALG_COMP, + (strcmp(a->comp->alg_name, b->comp->alg_name) || + (a->comp->alg_key_len != b->comp->alg_key_len) || + memcmp(a->comp->alg_key, b->comp->alg_key, + ((a->comp->alg_key_len + 7) / 8)))); + diff |= _DIFF(XFRM_SA_ATTR_ENCAP, + ((a->encap->encap_type != b->encap->encap_type) || + (a->encap->encap_sport != b->encap->encap_sport) || + (a->encap->encap_dport != b->encap->encap_dport) || + nl_addr_cmp(a->encap->encap_oa, b->encap->encap_oa))); + diff |= _DIFF(XFRM_SA_ATTR_TFCPAD, a->tfcpad != b->tfcpad); + diff |= _DIFF(XFRM_SA_ATTR_COADDR, nl_addr_cmp(a->coaddr, b->coaddr)); + diff |= _DIFF(XFRM_SA_ATTR_MARK, + (a->mark.m != b->mark.m) || (a->mark.v != b->mark.v)); + diff |= _DIFF(XFRM_SA_ATTR_SECCTX, + ((a->sec_ctx->ctx_doi != b->sec_ctx->ctx_doi) || + (a->sec_ctx->ctx_alg != b->sec_ctx->ctx_alg) || + (a->sec_ctx->ctx_len != b->sec_ctx->ctx_len) || + strcmp(a->sec_ctx->ctx, b->sec_ctx->ctx))); + diff |= _DIFF(XFRM_SA_ATTR_REPLAY_MAXAGE, + a->replay_maxage != b->replay_maxage); + diff |= _DIFF(XFRM_SA_ATTR_REPLAY_MAXDIFF, + a->replay_maxdiff != b->replay_maxdiff); + diff |= _DIFF(XFRM_SA_ATTR_EXPIRE, a->hard != b->hard); + + /* Compare replay states */ + found = AVAILABLE_MISMATCH (a, b, XFRM_SA_ATTR_REPLAY_STATE); + if (found == 0) // attribute exists in both objects + { + if (((a->replay_state_esn != NULL) && (b->replay_state_esn == NULL)) || + ((a->replay_state_esn == NULL) && (b->replay_state_esn != NULL))) + found |= 1; + + if (found == 0) // same replay type. compare actual values + { + if (a->replay_state_esn) + { + if (a->replay_state_esn->bmp_len != b->replay_state_esn->bmp_len) + diff |= 1; + else + { + uint32_t len = sizeof (struct xfrmnl_replay_state_esn) + + (a->replay_state_esn->bmp_len * sizeof (uint32_t)); + diff |= memcmp (a->replay_state_esn, b->replay_state_esn, len); + } + } + else + { + if ((a->replay_state.oseq != b->replay_state.oseq) || + (a->replay_state.seq != b->replay_state.seq) || + (a->replay_state.bitmap != b->replay_state.bitmap)) + diff |= 1; + } + } + } +#undef _DIFF + + return diff; +} + +/** + * @name XFRM SA Attribute Translations + * @{ + */ +static const struct trans_tbl sa_attrs[] = { + __ADD(XFRM_SA_ATTR_SEL, selector), + __ADD(XFRM_SA_ATTR_DADDR, daddr), + __ADD(XFRM_SA_ATTR_SPI, spi), + __ADD(XFRM_SA_ATTR_PROTO, proto), + __ADD(XFRM_SA_ATTR_SADDR, saddr), + __ADD(XFRM_SA_ATTR_LTIME_CFG, lifetime_cfg), + __ADD(XFRM_SA_ATTR_LTIME_CUR, lifetime_cur), + __ADD(XFRM_SA_ATTR_STATS, stats), + __ADD(XFRM_SA_ATTR_SEQ, seqnum), + __ADD(XFRM_SA_ATTR_REQID, reqid), + __ADD(XFRM_SA_ATTR_FAMILY, family), + __ADD(XFRM_SA_ATTR_MODE, mode), + __ADD(XFRM_SA_ATTR_REPLAY_WIN, replay_window), + __ADD(XFRM_SA_ATTR_FLAGS, flags), + __ADD(XFRM_SA_ATTR_ALG_AEAD, alg_aead), + __ADD(XFRM_SA_ATTR_ALG_AUTH, alg_auth), + __ADD(XFRM_SA_ATTR_ALG_CRYPT, alg_crypto), + __ADD(XFRM_SA_ATTR_ALG_COMP, alg_comp), + __ADD(XFRM_SA_ATTR_ENCAP, encap), + __ADD(XFRM_SA_ATTR_TFCPAD, tfcpad), + __ADD(XFRM_SA_ATTR_COADDR, coaddr), + __ADD(XFRM_SA_ATTR_MARK, mark), + __ADD(XFRM_SA_ATTR_SECCTX, sec_ctx), + __ADD(XFRM_SA_ATTR_REPLAY_MAXAGE, replay_maxage), + __ADD(XFRM_SA_ATTR_REPLAY_MAXDIFF, replay_maxdiff), + __ADD(XFRM_SA_ATTR_REPLAY_STATE, replay_state), + __ADD(XFRM_SA_ATTR_EXPIRE, expire), + __ADD(XFRM_SA_ATTR_OFFLOAD_DEV, user_offload), +}; + +static char* xfrm_sa_attrs2str(int attrs, char *buf, size_t len) +{ + return __flags2str (attrs, buf, len, sa_attrs, ARRAY_SIZE(sa_attrs)); +} +/** @} */ + +/** + * @name XFRM SA Flags Translations + * @{ + */ +static const struct trans_tbl sa_flags[] = { + __ADD(XFRM_STATE_NOECN, no ecn), + __ADD(XFRM_STATE_DECAP_DSCP, decap dscp), + __ADD(XFRM_STATE_NOPMTUDISC, no pmtu discovery), + __ADD(XFRM_STATE_WILDRECV, wild receive), + __ADD(XFRM_STATE_ICMP, icmp), + __ADD(XFRM_STATE_AF_UNSPEC, unspecified), + __ADD(XFRM_STATE_ALIGN4, align4), + __ADD(XFRM_STATE_ESN, esn), +}; + +char* xfrmnl_sa_flags2str(int flags, char *buf, size_t len) +{ + return __flags2str (flags, buf, len, sa_flags, ARRAY_SIZE(sa_flags)); +} + +int xfrmnl_sa_str2flag(const char *name) +{ + return __str2flags (name, sa_flags, ARRAY_SIZE(sa_flags)); +} +/** @} */ + +/** + * @name XFRM SA Mode Translations + * @{ + */ +static const struct trans_tbl sa_modes[] = { + __ADD(XFRM_MODE_TRANSPORT, transport), + __ADD(XFRM_MODE_TUNNEL, tunnel), + __ADD(XFRM_MODE_ROUTEOPTIMIZATION, route optimization), + __ADD(XFRM_MODE_IN_TRIGGER, in trigger), + __ADD(XFRM_MODE_BEET, beet), +}; + +char* xfrmnl_sa_mode2str(int mode, char *buf, size_t len) +{ + return __type2str (mode, buf, len, sa_modes, ARRAY_SIZE(sa_modes)); +} + +int xfrmnl_sa_str2mode(const char *name) +{ + return __str2type (name, sa_modes, ARRAY_SIZE(sa_modes)); +} +/** @} */ + + +static void xfrm_sa_dump_line(struct nl_object *a, struct nl_dump_params *p) +{ + char dst[INET6_ADDRSTRLEN+5], src[INET6_ADDRSTRLEN+5]; + struct xfrmnl_sa* sa = (struct xfrmnl_sa *) a; + char flags[128], mode[128]; + time_t add_time, use_time; + struct tm *add_time_tm, *use_time_tm; + struct tm tm_buf; + + nl_dump_line(p, "src %s dst %s family: %s\n", nl_addr2str(sa->saddr, src, sizeof(src)), + nl_addr2str(sa->id.daddr, dst, sizeof(dst)), + nl_af2str (sa->family, flags, sizeof (flags))); + + nl_dump_line(p, "\tproto %s spi 0x%x reqid %u\n", + nl_ip_proto2str (sa->id.proto, flags, sizeof(flags)), + sa->id.spi, sa->reqid); + + xfrmnl_sa_flags2str(sa->flags, flags, sizeof (flags)); + xfrmnl_sa_mode2str(sa->mode, mode, sizeof (mode)); + nl_dump_line(p, "\tmode: %s flags: %s (0x%x) seq: %u replay window: %u\n", + mode, flags, sa->flags, sa->seq, sa->replay_window); + + nl_dump_line(p, "\tlifetime configuration: \n"); + if (sa->lft->soft_byte_limit == XFRM_INF) + sprintf (flags, "INF"); + else + sprintf (flags, "%" PRIu64, sa->lft->soft_byte_limit); + if (sa->lft->soft_packet_limit == XFRM_INF) + sprintf (mode, "INF"); + else + sprintf (mode, "%" PRIu64, sa->lft->soft_packet_limit); + nl_dump_line(p, "\t\tsoft limit: %s (bytes), %s (packets)\n", flags, mode); + if (sa->lft->hard_byte_limit == XFRM_INF) + sprintf (flags, "INF"); + else + sprintf (flags, "%" PRIu64, sa->lft->hard_byte_limit); + if (sa->lft->hard_packet_limit == XFRM_INF) + sprintf (mode, "INF"); + else + sprintf (mode, "%" PRIu64, sa->lft->hard_packet_limit); + nl_dump_line(p, "\t\thard limit: %s (bytes), %s (packets)\n", flags, + mode); + nl_dump_line( + p, + "\t\tsoft add_time: %llu (seconds), soft use_time: %llu (seconds) \n", + (long long unsigned)sa->lft->soft_add_expires_seconds, + (long long unsigned)sa->lft->soft_use_expires_seconds); + nl_dump_line( + p, + "\t\thard add_time: %llu (seconds), hard use_time: %llu (seconds) \n", + (long long unsigned)sa->lft->hard_add_expires_seconds, + (long long unsigned)sa->lft->hard_use_expires_seconds); + + nl_dump_line(p, "\tlifetime current: \n"); + nl_dump_line(p, "\t\t%llu bytes, %llu packets\n", + (long long unsigned)sa->curlft.bytes, + (long long unsigned)sa->curlft.packets); + if (sa->curlft.add_time != 0) + { + add_time = sa->curlft.add_time; + add_time_tm = gmtime_r (&add_time, &tm_buf); + strftime (flags, 128, "%Y-%m-%d %H-%M-%S", add_time_tm); + } + else + { + sprintf (flags, "%s", "-"); + } + + if (sa->curlft.use_time != 0) + { + use_time = sa->curlft.use_time; + use_time_tm = gmtime_r (&use_time, &tm_buf); + strftime (mode, 128, "%Y-%m-%d %H-%M-%S", use_time_tm); + } + else + { + sprintf (mode, "%s", "-"); + } + nl_dump_line(p, "\t\tadd_time: %s, use_time: %s\n", flags, mode); + + if (sa->aead) + { + nl_dump_line(p, "\tAEAD Algo: \n"); + nl_dump_line(p, "\t\tName: %s Key len(bits): %u ICV Len(bits): %u\n", + sa->aead->alg_name, sa->aead->alg_key_len, sa->aead->alg_icv_len); + } + + if (sa->auth) + { + nl_dump_line(p, "\tAuth Algo: \n"); + nl_dump_line(p, "\t\tName: %s Key len(bits): %u Trunc len(bits): %u\n", + sa->auth->alg_name, sa->auth->alg_key_len, sa->auth->alg_trunc_len); + } + + if (sa->crypt) + { + nl_dump_line(p, "\tEncryption Algo: \n"); + nl_dump_line(p, "\t\tName: %s Key len(bits): %u\n", + sa->crypt->alg_name, sa->crypt->alg_key_len); + } + + if (sa->comp) + { + nl_dump_line(p, "\tCompression Algo: \n"); + nl_dump_line(p, "\t\tName: %s Key len(bits): %u\n", + sa->comp->alg_name, sa->comp->alg_key_len); + } + + if (sa->encap) + { + nl_dump_line(p, "\tEncapsulation template: \n"); + nl_dump_line(p, "\t\tType: %d Src port: %d Dst port: %d Encap addr: %s\n", + sa->encap->encap_type, sa->encap->encap_sport, sa->encap->encap_dport, + nl_addr2str (sa->encap->encap_oa, dst, sizeof (dst))); + } + + if (sa->ce_mask & XFRM_SA_ATTR_TFCPAD) + nl_dump_line(p, "\tTFC Pad: %u\n", sa->tfcpad); + + if (sa->ce_mask & XFRM_SA_ATTR_COADDR) + nl_dump_line(p, "\tCO Address: %s\n", nl_addr2str (sa->coaddr, dst, sizeof (dst))); + + if (sa->ce_mask & XFRM_SA_ATTR_MARK) + nl_dump_line(p, "\tMark mask: 0x%x Mark value: 0x%x\n", sa->mark.m, sa->mark.v); + + if (sa->ce_mask & XFRM_SA_ATTR_SECCTX) + nl_dump_line(p, "\tDOI: %d Algo: %d Len: %u ctx: %s\n", sa->sec_ctx->ctx_doi, + sa->sec_ctx->ctx_alg, sa->sec_ctx->ctx_len, sa->sec_ctx->ctx); + + nl_dump_line(p, "\treplay info: \n"); + nl_dump_line(p, "\t\tmax age %u max diff %u \n", sa->replay_maxage, sa->replay_maxdiff); + + if (sa->ce_mask & XFRM_SA_ATTR_REPLAY_STATE) + { + nl_dump_line(p, "\treplay state info: \n"); + if (sa->replay_state_esn) + { + nl_dump_line(p, "\t\toseq %u seq %u oseq_hi %u seq_hi %u replay window: %u \n", + sa->replay_state_esn->oseq, sa->replay_state_esn->seq, + sa->replay_state_esn->oseq_hi, sa->replay_state_esn->seq_hi, + sa->replay_state_esn->replay_window); + } + else + { + nl_dump_line(p, "\t\toseq %u seq %u bitmap: %u \n", sa->replay_state.oseq, + sa->replay_state.seq, sa->replay_state.bitmap); + } + } + + nl_dump_line(p, "\tselector info: \n"); + xfrmnl_sel_dump (sa->sel, p); + + nl_dump_line(p, "\tHard: %d\n", sa->hard); + + nl_dump(p, "\n"); +} + +static void xfrm_sa_dump_stats(struct nl_object *a, struct nl_dump_params *p) +{ + struct xfrmnl_sa* sa = (struct xfrmnl_sa*)a; + + nl_dump_line(p, "\tstats: \n"); + nl_dump_line(p, "\t\treplay window: %u replay: %u integrity failed: %u \n", + sa->stats.replay_window, sa->stats.replay, sa->stats.integrity_failed); + + return; +} + +static void xfrm_sa_dump_details(struct nl_object *a, struct nl_dump_params *p) +{ + xfrm_sa_dump_line(a, p); + xfrm_sa_dump_stats (a, p); +} + +/** + * @name XFRM SA Object Allocation/Freeage + * @{ + */ + +struct xfrmnl_sa* xfrmnl_sa_alloc(void) +{ + return (struct xfrmnl_sa*) nl_object_alloc(&xfrm_sa_obj_ops); +} + +void xfrmnl_sa_put(struct xfrmnl_sa* sa) +{ + nl_object_put((struct nl_object *) sa); +} + +/** @} */ + +/** + * @name SA Cache Managament + * @{ + */ + +/** + * Build a SA cache including all SAs currently configured in the kernel. + * @arg sock Netlink socket. + * @arg result Pointer to store resulting cache. + * + * Allocates a new SA cache, initializes it properly and updates it + * to include all SAs currently configured in the kernel. + * + * @return 0 on success or a negative error code. + */ +int xfrmnl_sa_alloc_cache(struct nl_sock *sock, struct nl_cache **result) +{ + return nl_cache_alloc_and_fill(&xfrmnl_sa_ops, sock, result); +} + +/** + * Look up a SA by destination address, SPI, protocol + * @arg cache SA cache + * @arg daddr destination address of the SA + * @arg spi SPI + * @arg proto protocol + * @return sa handle or NULL if no match was found. + */ +struct xfrmnl_sa* xfrmnl_sa_get(struct nl_cache* cache, struct nl_addr* daddr, + unsigned int spi, unsigned int proto) +{ + struct xfrmnl_sa *sa; + + //nl_list_for_each_entry(sa, &cache->c_items, ce_list) { + for (sa = (struct xfrmnl_sa*)nl_cache_get_first (cache); + sa != NULL; + sa = (struct xfrmnl_sa*)nl_cache_get_next ((struct nl_object*)sa)) + { + if (sa->id.proto == proto && + sa->id.spi == spi && + !nl_addr_cmp(sa->id.daddr, daddr)) + { + nl_object_get((struct nl_object *) sa); + return sa; + } + + } + + return NULL; +} + + +/** @} */ + + +static struct nla_policy xfrm_sa_policy[XFRMA_MAX+1] = { + [XFRMA_SA] = { .minlen = sizeof(struct xfrm_usersa_info)}, + [XFRMA_ALG_AUTH_TRUNC] = { .minlen = sizeof(struct xfrm_algo_auth)}, + [XFRMA_ALG_AEAD] = { .minlen = sizeof(struct xfrm_algo_aead) }, + [XFRMA_ALG_AUTH] = { .minlen = sizeof(struct xfrm_algo) }, + [XFRMA_ALG_CRYPT] = { .minlen = sizeof(struct xfrm_algo) }, + [XFRMA_ALG_COMP] = { .minlen = sizeof(struct xfrm_algo) }, + [XFRMA_ENCAP] = { .minlen = sizeof(struct xfrm_encap_tmpl) }, + [XFRMA_TMPL] = { .minlen = sizeof(struct xfrm_user_tmpl) }, + [XFRMA_SEC_CTX] = { .minlen = sizeof(struct xfrm_sec_ctx) }, + [XFRMA_LTIME_VAL] = { .minlen = sizeof(struct xfrm_lifetime_cur) }, + [XFRMA_REPLAY_VAL] = { .minlen = sizeof(struct xfrm_replay_state) }, + [XFRMA_OFFLOAD_DEV] = { .minlen = sizeof(struct xfrm_user_offload) }, + [XFRMA_REPLAY_THRESH] = { .type = NLA_U32 }, + [XFRMA_ETIMER_THRESH] = { .type = NLA_U32 }, + [XFRMA_SRCADDR] = { .minlen = sizeof(xfrm_address_t) }, + [XFRMA_COADDR] = { .minlen = sizeof(xfrm_address_t) }, + [XFRMA_MARK] = { .minlen = sizeof(struct xfrm_mark) }, + [XFRMA_TFCPAD] = { .type = NLA_U32 }, + [XFRMA_REPLAY_ESN_VAL] = { .minlen = sizeof(struct xfrm_replay_state_esn) }, +}; + +static int xfrm_sa_request_update(struct nl_cache *c, struct nl_sock *h) +{ + return nl_send_simple (h, XFRM_MSG_GETSA, NLM_F_DUMP, NULL, 0); +} + +int xfrmnl_sa_parse(struct nlmsghdr *n, struct xfrmnl_sa **result) +{ + _nl_auto_nl_addr struct nl_addr *addr1 = NULL; + _nl_auto_nl_addr struct nl_addr *addr2 = NULL; + _nl_auto_xfrmnl_sa struct xfrmnl_sa *sa = NULL; + struct nlattr *tb[XFRMA_MAX + 1]; + struct xfrm_usersa_info* sa_info; + struct xfrm_user_expire* ue; + int len, err; + + sa = xfrmnl_sa_alloc(); + if (!sa) + return -NLE_NOMEM; + + sa->ce_msgtype = n->nlmsg_type; + if (n->nlmsg_type == XFRM_MSG_EXPIRE) + { + ue = nlmsg_data(n); + sa_info = &ue->state; + sa->hard = ue->hard; + sa->ce_mask |= XFRM_SA_ATTR_EXPIRE; + } + else if (n->nlmsg_type == XFRM_MSG_DELSA) + { + sa_info = (struct xfrm_usersa_info*)((char *)nlmsg_data(n) + sizeof (struct xfrm_usersa_id) + NLA_HDRLEN); + } + else + { + sa_info = nlmsg_data(n); + } + + err = nlmsg_parse(n, sizeof(struct xfrm_usersa_info), tb, XFRMA_MAX, xfrm_sa_policy); + if (err < 0) + return err; + + if (!(addr1 = _nl_addr_build(sa_info->sel.family, &sa_info->sel.daddr))) + return -NLE_NOMEM; + nl_addr_set_prefixlen (addr1, sa_info->sel.prefixlen_d); + xfrmnl_sel_set_daddr (sa->sel, addr1); + xfrmnl_sel_set_prefixlen_d (sa->sel, sa_info->sel.prefixlen_d); + + if (!(addr2 = _nl_addr_build(sa_info->sel.family, &sa_info->sel.saddr))) + return -NLE_NOMEM; + nl_addr_set_prefixlen (addr2, sa_info->sel.prefixlen_s); + xfrmnl_sel_set_saddr (sa->sel, addr2); + xfrmnl_sel_set_prefixlen_s (sa->sel, sa_info->sel.prefixlen_s); + + xfrmnl_sel_set_dport (sa->sel, ntohs(sa_info->sel.dport)); + xfrmnl_sel_set_dportmask (sa->sel, ntohs(sa_info->sel.dport_mask)); + xfrmnl_sel_set_sport (sa->sel, ntohs(sa_info->sel.sport)); + xfrmnl_sel_set_sportmask (sa->sel, ntohs(sa_info->sel.sport_mask)); + xfrmnl_sel_set_family (sa->sel, sa_info->sel.family); + xfrmnl_sel_set_proto (sa->sel, sa_info->sel.proto); + xfrmnl_sel_set_ifindex (sa->sel, sa_info->sel.ifindex); + xfrmnl_sel_set_userid (sa->sel, sa_info->sel.user); + sa->ce_mask |= XFRM_SA_ATTR_SEL; + + if (!(sa->id.daddr = _nl_addr_build(sa_info->family, &sa_info->id.daddr))) + return -NLE_NOMEM; + sa->id.spi = ntohl(sa_info->id.spi); + sa->id.proto = sa_info->id.proto; + sa->ce_mask |= (XFRM_SA_ATTR_DADDR | XFRM_SA_ATTR_SPI | XFRM_SA_ATTR_PROTO); + + if (!(sa->saddr = _nl_addr_build(sa_info->family, &sa_info->saddr))) + return -NLE_NOMEM; + sa->ce_mask |= XFRM_SA_ATTR_SADDR; + + sa->lft->soft_byte_limit = sa_info->lft.soft_byte_limit; + sa->lft->hard_byte_limit = sa_info->lft.hard_byte_limit; + sa->lft->soft_packet_limit = sa_info->lft.soft_packet_limit; + sa->lft->hard_packet_limit = sa_info->lft.hard_packet_limit; + sa->lft->soft_add_expires_seconds = sa_info->lft.soft_add_expires_seconds; + sa->lft->hard_add_expires_seconds = sa_info->lft.hard_add_expires_seconds; + sa->lft->soft_use_expires_seconds = sa_info->lft.soft_use_expires_seconds; + sa->lft->hard_use_expires_seconds = sa_info->lft.hard_use_expires_seconds; + sa->ce_mask |= XFRM_SA_ATTR_LTIME_CFG; + + sa->curlft.bytes = sa_info->curlft.bytes; + sa->curlft.packets = sa_info->curlft.packets; + sa->curlft.add_time = sa_info->curlft.add_time; + sa->curlft.use_time = sa_info->curlft.use_time; + sa->ce_mask |= XFRM_SA_ATTR_LTIME_CUR; + + sa->stats.replay_window = sa_info->stats.replay_window; + sa->stats.replay = sa_info->stats.replay; + sa->stats.integrity_failed = sa_info->stats.integrity_failed; + sa->ce_mask |= XFRM_SA_ATTR_STATS; + + sa->seq = sa_info->seq; + sa->reqid = sa_info->reqid; + sa->family = sa_info->family; + sa->mode = sa_info->mode; + sa->replay_window = sa_info->replay_window; + sa->flags = sa_info->flags; + sa->ce_mask |= (XFRM_SA_ATTR_SEQ | XFRM_SA_ATTR_REQID | + XFRM_SA_ATTR_FAMILY | XFRM_SA_ATTR_MODE | + XFRM_SA_ATTR_REPLAY_WIN | XFRM_SA_ATTR_FLAGS); + + if (tb[XFRMA_ALG_AEAD]) { + struct xfrm_algo_aead* aead = nla_data(tb[XFRMA_ALG_AEAD]); + + len = sizeof (struct xfrmnl_algo_aead) + ((aead->alg_key_len + 7) / 8); + if ((sa->aead = calloc (1, len)) == NULL) + return -NLE_NOMEM; + memcpy ((void *)sa->aead, (void *)aead, len); + sa->ce_mask |= XFRM_SA_ATTR_ALG_AEAD; + } + + if (tb[XFRMA_ALG_AUTH_TRUNC]) { + struct xfrm_algo_auth* auth = nla_data(tb[XFRMA_ALG_AUTH_TRUNC]); + + len = sizeof (struct xfrmnl_algo_auth) + ((auth->alg_key_len + 7) / 8); + if ((sa->auth = calloc (1, len)) == NULL) + return -NLE_NOMEM; + memcpy ((void *)sa->auth, (void *)auth, len); + sa->ce_mask |= XFRM_SA_ATTR_ALG_AUTH; + } + + if (tb[XFRMA_ALG_AUTH] && !sa->auth) { + struct xfrm_algo* auth = nla_data(tb[XFRMA_ALG_AUTH]); + + len = sizeof (struct xfrmnl_algo_auth) + ((auth->alg_key_len + 7) / 8); + if ((sa->auth = calloc (1, len)) == NULL) + return -NLE_NOMEM; + strcpy(sa->auth->alg_name, auth->alg_name); + memcpy(sa->auth->alg_key, auth->alg_key, (auth->alg_key_len + 7) / 8); + sa->auth->alg_key_len = auth->alg_key_len; + sa->ce_mask |= XFRM_SA_ATTR_ALG_AUTH; + } + + if (tb[XFRMA_ALG_CRYPT]) { + struct xfrm_algo* crypt = nla_data(tb[XFRMA_ALG_CRYPT]); + + len = sizeof (struct xfrmnl_algo) + ((crypt->alg_key_len + 7) / 8); + if ((sa->crypt = calloc (1, len)) == NULL) + return -NLE_NOMEM; + memcpy ((void *)sa->crypt, (void *)crypt, len); + sa->ce_mask |= XFRM_SA_ATTR_ALG_CRYPT; + } + + if (tb[XFRMA_ALG_COMP]) { + struct xfrm_algo* comp = nla_data(tb[XFRMA_ALG_COMP]); + + len = sizeof (struct xfrmnl_algo) + ((comp->alg_key_len + 7) / 8); + if ((sa->comp = calloc (1, len)) == NULL) + return -NLE_NOMEM; + memcpy ((void *)sa->comp, (void *)comp, len); + sa->ce_mask |= XFRM_SA_ATTR_ALG_COMP; + } + + if (tb[XFRMA_ENCAP]) { + struct xfrm_encap_tmpl* encap = nla_data(tb[XFRMA_ENCAP]); + + len = sizeof (struct xfrmnl_encap_tmpl); + if ((sa->encap = calloc (1, len)) == NULL) + return -NLE_NOMEM; + sa->encap->encap_type = encap->encap_type; + sa->encap->encap_sport = ntohs(encap->encap_sport); + sa->encap->encap_dport = ntohs(encap->encap_dport); + if (!(sa->encap->encap_oa = _nl_addr_build(sa_info->family, + &encap->encap_oa))) + return -NLE_NOMEM; + sa->ce_mask |= XFRM_SA_ATTR_ENCAP; + } + + if (tb[XFRMA_TFCPAD]) { + sa->tfcpad = *(uint32_t*)nla_data(tb[XFRMA_TFCPAD]); + sa->ce_mask |= XFRM_SA_ATTR_TFCPAD; + } + + if (tb[XFRMA_COADDR]) { + if (!(sa->coaddr = _nl_addr_build( + sa_info->family, nla_data(tb[XFRMA_COADDR])))) + return -NLE_NOMEM; + sa->ce_mask |= XFRM_SA_ATTR_COADDR; + } + + if (tb[XFRMA_MARK]) { + struct xfrm_mark* m = nla_data(tb[XFRMA_MARK]); + + sa->mark.m = m->m; + sa->mark.v = m->v; + sa->ce_mask |= XFRM_SA_ATTR_MARK; + } + + if (tb[XFRMA_SEC_CTX]) { + struct xfrm_user_sec_ctx* sec_ctx = nla_data(tb[XFRMA_SEC_CTX]); + + len = sizeof (struct xfrmnl_user_sec_ctx) + sec_ctx->ctx_len; + if ((sa->sec_ctx = calloc (1, len)) == NULL) + return -NLE_NOMEM; + memcpy (sa->sec_ctx, sec_ctx, len); + sa->ce_mask |= XFRM_SA_ATTR_SECCTX; + } + + if (tb[XFRMA_ETIMER_THRESH]) { + sa->replay_maxage = *(uint32_t*)nla_data(tb[XFRMA_ETIMER_THRESH]); + sa->ce_mask |= XFRM_SA_ATTR_REPLAY_MAXAGE; + } + + if (tb[XFRMA_REPLAY_THRESH]) { + sa->replay_maxdiff = *(uint32_t*)nla_data(tb[XFRMA_REPLAY_THRESH]); + sa->ce_mask |= XFRM_SA_ATTR_REPLAY_MAXDIFF; + } + + if (tb[XFRMA_REPLAY_ESN_VAL]) { + struct xfrm_replay_state_esn* esn = nla_data (tb[XFRMA_REPLAY_ESN_VAL]); + + len = sizeof (struct xfrmnl_replay_state_esn) + (sizeof (uint32_t) * esn->bmp_len); + if ((sa->replay_state_esn = calloc (1, len)) == NULL) + return -NLE_NOMEM; + memcpy ((void *)sa->replay_state_esn, (void *)esn, len); + sa->ce_mask |= XFRM_SA_ATTR_REPLAY_STATE; + } + else if (tb[XFRMA_REPLAY_VAL]) + { + struct xfrm_replay_state* replay_state = nla_data (tb[XFRMA_REPLAY_VAL]); + sa->replay_state.oseq = replay_state->oseq; + sa->replay_state.seq = replay_state->seq; + sa->replay_state.bitmap = replay_state->bitmap; + sa->ce_mask |= XFRM_SA_ATTR_REPLAY_STATE; + sa->replay_state_esn = NULL; + } + + if (tb[XFRMA_OFFLOAD_DEV]) { + struct xfrm_user_offload *offload; + + len = sizeof(struct xfrmnl_user_offload); + if ((sa->user_offload = calloc(1, len)) == NULL) + return -NLE_NOMEM; + offload = nla_data(tb[XFRMA_OFFLOAD_DEV]); + sa->user_offload->ifindex = offload->ifindex; + sa->user_offload->flags = offload->flags; + sa->ce_mask |= XFRM_SA_ATTR_OFFLOAD_DEV; + } + + *result = _nl_steal_pointer(&sa); + return 0; +} + +static int xfrm_sa_update_cache (struct nl_cache *cache, struct nl_object *obj, + change_func_t change_cb, change_func_v2_t change_cb_v2, + void *data) +{ + struct nl_object* old_sa; + struct xfrmnl_sa* sa = (struct xfrmnl_sa*)obj; + + if (nl_object_get_msgtype (obj) == XFRM_MSG_EXPIRE) + { + /* On hard expiry, the SA gets deleted too from the kernel state without any + * further delete event. On Expire message, we are only updating the cache with + * the SA object's new state. In absence of the explicit delete event, the cache will + * be out of sync with the kernel state. To get around this, expiry messages cache + * operations are handled here (installed with NL_ACT_UNSPEC action) instead of + * in Libnl Cache module. */ + + /* Do we already have this object in the cache? */ + old_sa = nl_cache_search(cache, obj); + if (old_sa) + { + /* Found corresponding SA object in cache. Delete it */ + nl_cache_remove (old_sa); + } + + /* Handle the expiry event now */ + if (sa->hard == 0) + { + /* Soft expiry event: Save the new object to the + * cache and notify application of the expiry event. */ + nl_cache_move (cache, obj); + + if (old_sa == NULL) + { + /* Application CB present, no previous instance of SA object present. + * Notify application CB as a NEW event */ + if (change_cb_v2) + change_cb_v2(cache, NULL, obj, 0, NL_ACT_NEW, data); + else if (change_cb) + change_cb(cache, obj, NL_ACT_NEW, data); + } + else if (old_sa) + { + uint64_t diff = 0; + if (change_cb || change_cb_v2) + diff = nl_object_diff64(old_sa, obj); + + /* Application CB present, a previous instance of SA object present. + * Notify application CB as a CHANGE1 event */ + if (diff) { + if (change_cb_v2) { + change_cb_v2(cache, old_sa, obj, diff, NL_ACT_CHANGE, data); + } else if (change_cb) + change_cb(cache, obj, NL_ACT_CHANGE, data); + } + nl_object_put (old_sa); + } + } + else + { + /* Hard expiry event: Delete the object from the + * cache and notify application of the expiry event. */ + if (change_cb_v2) + change_cb_v2(cache, obj, NULL, 0, NL_ACT_DEL, data); + else if (change_cb) + change_cb (cache, obj, NL_ACT_DEL, data); + nl_object_put (old_sa); + } + + /* Done handling expire message */ + return 0; + } + else + { + /* All other messages other than Expire, let the standard Libnl cache + * module handle it. */ + if (change_cb_v2) + return nl_cache_include_v2(cache, obj, change_cb_v2, data); + else + return nl_cache_include (cache, obj, change_cb, data); + } +} + +static int xfrm_sa_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *n, struct nl_parser_param *pp) +{ + struct xfrmnl_sa* sa; + int err; + + if ((err = xfrmnl_sa_parse(n, &sa)) < 0) + return err; + + err = pp->pp_cb((struct nl_object *) sa, pp); + + xfrmnl_sa_put(sa); + return err; +} + +/** + * @name XFRM SA Get + * @{ + */ + +int xfrmnl_sa_build_get_request(struct nl_addr* daddr, unsigned int spi, unsigned int protocol, unsigned int mark_v, unsigned int mark_m, struct nl_msg **result) +{ + struct nl_msg *msg; + struct xfrm_usersa_id sa_id; + struct xfrm_mark mark; + + if (!daddr || !spi) + { + fprintf(stderr, "APPLICATION BUG: %s:%d:%s: A valid destination address, spi must be specified\n", + __FILE__, __LINE__, __func__); + assert(0); + return -NLE_MISSING_ATTR; + } + + memset(&sa_id, 0, sizeof(sa_id)); + memcpy (&sa_id.daddr, nl_addr_get_binary_addr (daddr), sizeof (uint8_t) * nl_addr_get_len (daddr)); + sa_id.family = nl_addr_get_family (daddr); + sa_id.spi = htonl(spi); + sa_id.proto = protocol; + + if (!(msg = nlmsg_alloc_simple(XFRM_MSG_GETSA, 0))) + return -NLE_NOMEM; + + if (nlmsg_append(msg, &sa_id, sizeof(sa_id), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if ((mark_m & mark_v) != 0) + { + memset(&mark, 0, sizeof(struct xfrm_mark)); + mark.m = mark_m; + mark.v = mark_v; + + NLA_PUT (msg, XFRMA_MARK, sizeof (struct xfrm_mark), &mark); + } + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +int xfrmnl_sa_get_kernel(struct nl_sock* sock, struct nl_addr* daddr, unsigned int spi, unsigned int protocol, unsigned int mark_v, unsigned int mark_m, struct xfrmnl_sa** result) +{ + struct nl_msg *msg = NULL; + struct nl_object *obj; + int err; + + if ((err = xfrmnl_sa_build_get_request(daddr, spi, protocol, mark_m, mark_v, &msg)) < 0) + return err; + + err = nl_send_auto(sock, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + if ((err = nl_pickup(sock, &xfrm_sa_msg_parser, &obj)) < 0) + return err; + + /* We have used xfrm_sa_msg_parser(), object is definitely a xfrm sa */ + *result = (struct xfrmnl_sa *) obj; + + /* If an object has been returned, we also need to wait for the ACK */ + if (err == 0 && obj) + nl_wait_for_ack(sock); + + return 0; +} + +/** @} */ + +static int build_xfrm_sa_message(struct xfrmnl_sa *tmpl, int cmd, int flags, struct nl_msg **result) +{ + struct nl_msg* msg; + struct xfrm_usersa_info sa_info; + uint32_t len; + struct nl_addr* addr; + + if (!(tmpl->ce_mask & XFRM_SA_ATTR_DADDR) || + !(tmpl->ce_mask & XFRM_SA_ATTR_SPI) || + !(tmpl->ce_mask & XFRM_SA_ATTR_PROTO)) + return -NLE_MISSING_ATTR; + + memset ((void*)&sa_info, 0, sizeof (sa_info)); + if (tmpl->ce_mask & XFRM_SA_ATTR_SEL) + { + addr = xfrmnl_sel_get_daddr (tmpl->sel); + memcpy ((void*)&sa_info.sel.daddr, (void*)nl_addr_get_binary_addr (addr), sizeof (uint8_t) * nl_addr_get_len (addr)); + addr = xfrmnl_sel_get_saddr (tmpl->sel); + memcpy ((void*)&sa_info.sel.saddr, (void*)nl_addr_get_binary_addr (addr), sizeof (uint8_t) * nl_addr_get_len (addr)); + sa_info.sel.dport = htons (xfrmnl_sel_get_dport (tmpl->sel)); + sa_info.sel.dport_mask = htons (xfrmnl_sel_get_dportmask (tmpl->sel)); + sa_info.sel.sport = htons (xfrmnl_sel_get_sport (tmpl->sel)); + sa_info.sel.sport_mask = htons (xfrmnl_sel_get_sportmask (tmpl->sel)); + sa_info.sel.family = xfrmnl_sel_get_family (tmpl->sel); + sa_info.sel.prefixlen_d = xfrmnl_sel_get_prefixlen_d (tmpl->sel); + sa_info.sel.prefixlen_s = xfrmnl_sel_get_prefixlen_s (tmpl->sel); + sa_info.sel.proto = xfrmnl_sel_get_proto (tmpl->sel); + sa_info.sel.ifindex = xfrmnl_sel_get_ifindex (tmpl->sel); + sa_info.sel.user = xfrmnl_sel_get_userid (tmpl->sel); + } + + memcpy (&sa_info.id.daddr, nl_addr_get_binary_addr (tmpl->id.daddr), sizeof (uint8_t) * nl_addr_get_len (tmpl->id.daddr)); + sa_info.id.spi = htonl(tmpl->id.spi); + sa_info.id.proto = tmpl->id.proto; + + if (tmpl->ce_mask & XFRM_SA_ATTR_SADDR) + memcpy (&sa_info.saddr, nl_addr_get_binary_addr (tmpl->saddr), sizeof (uint8_t) * nl_addr_get_len (tmpl->saddr)); + + if (tmpl->ce_mask & XFRM_SA_ATTR_LTIME_CFG) + { + sa_info.lft.soft_byte_limit = xfrmnl_ltime_cfg_get_soft_bytelimit (tmpl->lft); + sa_info.lft.hard_byte_limit = xfrmnl_ltime_cfg_get_hard_bytelimit (tmpl->lft); + sa_info.lft.soft_packet_limit = xfrmnl_ltime_cfg_get_soft_packetlimit (tmpl->lft); + sa_info.lft.hard_packet_limit = xfrmnl_ltime_cfg_get_hard_packetlimit (tmpl->lft); + sa_info.lft.soft_add_expires_seconds = xfrmnl_ltime_cfg_get_soft_addexpires (tmpl->lft); + sa_info.lft.hard_add_expires_seconds = xfrmnl_ltime_cfg_get_hard_addexpires (tmpl->lft); + sa_info.lft.soft_use_expires_seconds = xfrmnl_ltime_cfg_get_soft_useexpires (tmpl->lft); + sa_info.lft.hard_use_expires_seconds = xfrmnl_ltime_cfg_get_hard_useexpires (tmpl->lft); + } + + //Skip current lifetime: cur lifetime can be updated only via AE + //Skip stats: stats cant be updated + //Skip seq: seq cant be updated + + if (tmpl->ce_mask & XFRM_SA_ATTR_REQID) + sa_info.reqid = tmpl->reqid; + + if (tmpl->ce_mask & XFRM_SA_ATTR_FAMILY) + sa_info.family = tmpl->family; + + if (tmpl->ce_mask & XFRM_SA_ATTR_MODE) + sa_info.mode = tmpl->mode; + + if (tmpl->ce_mask & XFRM_SA_ATTR_REPLAY_WIN) + sa_info.replay_window = tmpl->replay_window; + + if (tmpl->ce_mask & XFRM_SA_ATTR_FLAGS) + sa_info.flags = tmpl->flags; + + msg = nlmsg_alloc_simple(cmd, flags); + if (!msg) + return -NLE_NOMEM; + + if (nlmsg_append(msg, &sa_info, sizeof(sa_info), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if (tmpl->ce_mask & XFRM_SA_ATTR_ALG_AEAD) { + len = sizeof (struct xfrm_algo_aead) + ((tmpl->aead->alg_key_len + 7) / 8); + NLA_PUT (msg, XFRMA_ALG_AEAD, len, tmpl->aead); + } + + if (tmpl->ce_mask & XFRM_SA_ATTR_ALG_AUTH) { + /* kernel prefers XFRMA_ALG_AUTH_TRUNC over XFRMA_ALG_AUTH, so only + * one of the attributes needs to be present */ + if (tmpl->auth->alg_trunc_len) { + len = sizeof (struct xfrm_algo_auth) + ((tmpl->auth->alg_key_len + 7) / 8); + NLA_PUT (msg, XFRMA_ALG_AUTH_TRUNC, len, tmpl->auth); + } else { + struct xfrm_algo *auth; + + len = sizeof (struct xfrm_algo) + ((tmpl->auth->alg_key_len + 7) / 8); + auth = malloc(len); + if (!auth) { + nlmsg_free(msg); + return -NLE_NOMEM; + } + + _nl_strncpy_assert(auth->alg_name, tmpl->auth->alg_name, sizeof(auth->alg_name)); + auth->alg_key_len = tmpl->auth->alg_key_len; + memcpy(auth->alg_key, tmpl->auth->alg_key, (tmpl->auth->alg_key_len + 7) / 8); + if (nla_put(msg, XFRMA_ALG_AUTH, len, auth) < 0) { + free(auth); + goto nla_put_failure; + } + free(auth); + } + } + + if (tmpl->ce_mask & XFRM_SA_ATTR_ALG_CRYPT) { + len = sizeof (struct xfrm_algo) + ((tmpl->crypt->alg_key_len + 7) / 8); + NLA_PUT (msg, XFRMA_ALG_CRYPT, len, tmpl->crypt); + } + + if (tmpl->ce_mask & XFRM_SA_ATTR_ALG_COMP) { + len = sizeof (struct xfrm_algo) + ((tmpl->comp->alg_key_len + 7) / 8); + NLA_PUT (msg, XFRMA_ALG_COMP, len, tmpl->comp); + } + + if (tmpl->ce_mask & XFRM_SA_ATTR_ENCAP) { + struct xfrm_encap_tmpl* encap_tmpl; + struct nlattr* encap_attr; + + len = sizeof (struct xfrm_encap_tmpl); + encap_attr = nla_reserve(msg, XFRMA_ENCAP, len); + if (!encap_attr) + goto nla_put_failure; + encap_tmpl = nla_data (encap_attr); + encap_tmpl->encap_type = tmpl->encap->encap_type; + encap_tmpl->encap_sport = htons (tmpl->encap->encap_sport); + encap_tmpl->encap_dport = htons (tmpl->encap->encap_dport); + memcpy (&encap_tmpl->encap_oa, nl_addr_get_binary_addr (tmpl->encap->encap_oa), sizeof (uint8_t) * nl_addr_get_len (tmpl->encap->encap_oa)); + } + + if (tmpl->ce_mask & XFRM_SA_ATTR_TFCPAD) { + NLA_PUT_U32 (msg, XFRMA_TFCPAD, tmpl->tfcpad); + } + + if (tmpl->ce_mask & XFRM_SA_ATTR_COADDR) { + NLA_PUT (msg, XFRMA_COADDR, sizeof (xfrm_address_t), tmpl->coaddr); + } + + if (tmpl->ce_mask & XFRM_SA_ATTR_MARK) { + NLA_PUT (msg, XFRMA_MARK, sizeof (struct xfrm_mark), &tmpl->mark); + } + + if (tmpl->ce_mask & XFRM_SA_ATTR_SECCTX) { + len = sizeof (struct xfrm_sec_ctx) + tmpl->sec_ctx->ctx_len; + NLA_PUT (msg, XFRMA_SEC_CTX, len, tmpl->sec_ctx); + } + + if (tmpl->ce_mask & XFRM_SA_ATTR_REPLAY_MAXAGE) { + NLA_PUT_U32 (msg, XFRMA_ETIMER_THRESH, tmpl->replay_maxage); + } + + if (tmpl->ce_mask & XFRM_SA_ATTR_REPLAY_MAXDIFF) { + NLA_PUT_U32 (msg, XFRMA_REPLAY_THRESH, tmpl->replay_maxdiff); + } + + if (tmpl->ce_mask & XFRM_SA_ATTR_REPLAY_STATE) { + if (tmpl->replay_state_esn) { + len = sizeof (struct xfrm_replay_state_esn) + (sizeof (uint32_t) * tmpl->replay_state_esn->bmp_len); + NLA_PUT (msg, XFRMA_REPLAY_ESN_VAL, len, tmpl->replay_state_esn); + } + else { + NLA_PUT (msg, XFRMA_REPLAY_VAL, sizeof (struct xfrm_replay_state), &tmpl->replay_state); + } + } + + if (tmpl->ce_mask & XFRM_SA_ATTR_OFFLOAD_DEV) { + struct xfrm_user_offload *offload; + struct nlattr *attr; + + len = sizeof(struct xfrm_user_offload); + attr = nla_reserve(msg, XFRMA_OFFLOAD_DEV, len); + + if (!attr) + goto nla_put_failure; + + offload = nla_data(attr); + offload->ifindex = tmpl->user_offload->ifindex; + offload->flags = tmpl->user_offload->flags; + } + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +/** + * @name XFRM SA Add + * @{ + */ + +int xfrmnl_sa_build_add_request(struct xfrmnl_sa* tmpl, int flags, struct nl_msg **result) +{ + return build_xfrm_sa_message (tmpl, XFRM_MSG_NEWSA, flags, result); +} + +int xfrmnl_sa_add(struct nl_sock* sk, struct xfrmnl_sa* tmpl, int flags) +{ + int err; + struct nl_msg *msg; + + if ((err = xfrmnl_sa_build_add_request(tmpl, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return nl_wait_for_ack(sk); +} + +/** + * @name XFRM SA Update + * @{ + */ + +int xfrmnl_sa_build_update_request(struct xfrmnl_sa* tmpl, int flags, struct nl_msg **result) +{ + return build_xfrm_sa_message (tmpl, XFRM_MSG_UPDSA, flags, result); +} + +int xfrmnl_sa_update(struct nl_sock* sk, struct xfrmnl_sa* tmpl, int flags) +{ + int err; + struct nl_msg *msg; + + if ((err = xfrmnl_sa_build_update_request(tmpl, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return nl_wait_for_ack(sk); +} + +/** @} */ + +static int build_xfrm_sa_delete_message(struct xfrmnl_sa *tmpl, int cmd, int flags, struct nl_msg **result) +{ + struct nl_msg* msg; + struct xfrm_usersa_id sa_id; + + if (!(tmpl->ce_mask & XFRM_SA_ATTR_DADDR) || + !(tmpl->ce_mask & XFRM_SA_ATTR_SPI) || + !(tmpl->ce_mask & XFRM_SA_ATTR_PROTO)) + return -NLE_MISSING_ATTR; + + memset(&sa_id, 0, sizeof(struct xfrm_usersa_id)); + memcpy (&sa_id.daddr, nl_addr_get_binary_addr (tmpl->id.daddr), + sizeof (uint8_t) * nl_addr_get_len (tmpl->id.daddr)); + sa_id.family = nl_addr_get_family (tmpl->id.daddr); + sa_id.spi = htonl(tmpl->id.spi); + sa_id.proto = tmpl->id.proto; + + msg = nlmsg_alloc_simple(cmd, flags); + if (!msg) + return -NLE_NOMEM; + + if (nlmsg_append(msg, &sa_id, sizeof(sa_id), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if (tmpl->ce_mask & XFRM_SA_ATTR_MARK) { + NLA_PUT (msg, XFRMA_MARK, sizeof (struct xfrm_mark), &tmpl->mark); + } + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +/** + * @name XFRM SA Delete + * @{ + */ + +int xfrmnl_sa_build_delete_request(struct xfrmnl_sa* tmpl, int flags, struct nl_msg **result) +{ + return build_xfrm_sa_delete_message (tmpl, XFRM_MSG_DELSA, flags, result); +} + +int xfrmnl_sa_delete(struct nl_sock* sk, struct xfrmnl_sa* tmpl, int flags) +{ + int err; + struct nl_msg *msg; + + if ((err = xfrmnl_sa_build_delete_request(tmpl, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return nl_wait_for_ack(sk); +} + +/** @} */ + + +/** + * @name Attributes + * @{ + */ + +struct xfrmnl_sel* xfrmnl_sa_get_sel (struct xfrmnl_sa* sa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_SEL) + return sa->sel; + else + return NULL; +} + +int xfrmnl_sa_set_sel (struct xfrmnl_sa* sa, struct xfrmnl_sel* sel) +{ + /* Release any previously held selector object from the SA */ + if (sa->sel) + xfrmnl_sel_put (sa->sel); + + /* Increment ref count on new selector and save it in the SA */ + xfrmnl_sel_get (sel); + sa->sel = sel; + sa->ce_mask |= XFRM_SA_ATTR_SEL; + + return 0; +} + +static inline int __assign_addr(struct xfrmnl_sa* sa, struct nl_addr **pos, + struct nl_addr *new, int flag, int nocheck) +{ + if (!nocheck) + { + if (sa->ce_mask & XFRM_SA_ATTR_FAMILY) + { + if (nl_addr_get_family (new) != sa->family) + return -NLE_AF_MISMATCH; + } + } + + if (*pos) + nl_addr_put(*pos); + + nl_addr_get(new); + *pos = new; + + sa->ce_mask |= flag; + + return 0; +} + + +struct nl_addr* xfrmnl_sa_get_daddr (struct xfrmnl_sa* sa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_DADDR) + return sa->id.daddr; + else + return NULL; +} + +int xfrmnl_sa_set_daddr (struct xfrmnl_sa* sa, struct nl_addr* addr) +{ + return __assign_addr(sa, &sa->id.daddr, addr, XFRM_SA_ATTR_DADDR, 0); +} + +int xfrmnl_sa_get_spi (struct xfrmnl_sa* sa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_SPI) + return sa->id.spi; + else + return -1; +} + +int xfrmnl_sa_set_spi (struct xfrmnl_sa* sa, unsigned int spi) +{ + sa->id.spi = spi; + sa->ce_mask |= XFRM_SA_ATTR_SPI; + + return 0; +} + +int xfrmnl_sa_get_proto (struct xfrmnl_sa* sa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_PROTO) + return sa->id.proto; + else + return -1; +} + +int xfrmnl_sa_set_proto (struct xfrmnl_sa* sa, unsigned int protocol) +{ + sa->id.proto = protocol; + sa->ce_mask |= XFRM_SA_ATTR_PROTO; + + return 0; +} + +struct nl_addr* xfrmnl_sa_get_saddr (struct xfrmnl_sa* sa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_SADDR) + return sa->saddr; + else + return NULL; +} + +int xfrmnl_sa_set_saddr (struct xfrmnl_sa* sa, struct nl_addr* addr) +{ + return __assign_addr(sa, &sa->saddr, addr, XFRM_SA_ATTR_SADDR, 1); +} + +struct xfrmnl_ltime_cfg* xfrmnl_sa_get_lifetime_cfg (struct xfrmnl_sa* sa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_LTIME_CFG) + return sa->lft; + else + return NULL; +} + +int xfrmnl_sa_set_lifetime_cfg (struct xfrmnl_sa* sa, struct xfrmnl_ltime_cfg* ltime) +{ + /* Release any previously held lifetime cfg object from the SA */ + if (sa->lft) + xfrmnl_ltime_cfg_put (sa->lft); + + /* Increment ref count on new lifetime object and save it in the SA */ + xfrmnl_ltime_cfg_get (ltime); + sa->lft = ltime; + sa->ce_mask |= XFRM_SA_ATTR_LTIME_CFG; + + return 0; +} + +int xfrmnl_sa_get_curlifetime (struct xfrmnl_sa* sa, unsigned long long int* curr_bytes, + unsigned long long int* curr_packets, unsigned long long int* curr_add_time, unsigned long long int* curr_use_time) +{ + if (sa == NULL || curr_bytes == NULL || curr_packets == NULL || curr_add_time == NULL || curr_use_time == NULL) + return -1; + + if (sa->ce_mask & XFRM_SA_ATTR_LTIME_CUR) + { + *curr_bytes = sa->curlft.bytes; + *curr_packets = sa->curlft.packets; + *curr_add_time = sa->curlft.add_time; + *curr_use_time = sa->curlft.use_time; + } + else + return -1; + + return 0; +} + +int xfrmnl_sa_get_stats (struct xfrmnl_sa* sa, unsigned long long int* replay_window, + unsigned long long int* replay, unsigned long long int* integrity_failed) +{ + if (sa == NULL || replay_window == NULL || replay == NULL || integrity_failed == NULL) + return -1; + + if (sa->ce_mask & XFRM_SA_ATTR_STATS) + { + *replay_window = sa->stats.replay_window; + *replay = sa->stats.replay; + *integrity_failed = sa->stats.integrity_failed; + } + else + return -1; + + return 0; +} + +int xfrmnl_sa_get_seq (struct xfrmnl_sa* sa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_SEQ) + return sa->seq; + else + return -1; +} + +int xfrmnl_sa_get_reqid (struct xfrmnl_sa* sa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_REQID) + return sa->reqid; + else + return -1; +} + +int xfrmnl_sa_set_reqid (struct xfrmnl_sa* sa, unsigned int reqid) +{ + sa->reqid = reqid; + sa->ce_mask |= XFRM_SA_ATTR_REQID; + + return 0; +} + +int xfrmnl_sa_get_family (struct xfrmnl_sa* sa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_FAMILY) + return sa->family; + else + return -1; +} + +int xfrmnl_sa_set_family (struct xfrmnl_sa* sa, unsigned int family) +{ + sa->family = family; + sa->ce_mask |= XFRM_SA_ATTR_FAMILY; + + return 0; +} + +int xfrmnl_sa_get_mode (struct xfrmnl_sa* sa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_MODE) + return sa->mode; + else + return -1; +} + +int xfrmnl_sa_set_mode (struct xfrmnl_sa* sa, unsigned int mode) +{ + sa->mode = mode; + sa->ce_mask |= XFRM_SA_ATTR_MODE; + + return 0; +} + +int xfrmnl_sa_get_replay_window (struct xfrmnl_sa* sa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_REPLAY_WIN) + return sa->replay_window; + else + return -1; +} + +int xfrmnl_sa_set_replay_window (struct xfrmnl_sa* sa, unsigned int replay_window) +{ + sa->replay_window = replay_window; + sa->ce_mask |= XFRM_SA_ATTR_REPLAY_WIN; + + return 0; +} + +int xfrmnl_sa_get_flags (struct xfrmnl_sa* sa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_FLAGS) + return sa->flags; + else + return -1; +} + +int xfrmnl_sa_set_flags (struct xfrmnl_sa* sa, unsigned int flags) +{ + sa->flags = flags; + sa->ce_mask |= XFRM_SA_ATTR_FLAGS; + + return 0; +} + +/** + * Get the aead-params + * @arg sa the xfrmnl_sa object + * @arg alg_name an optional output buffer for the algorithm name. Must be at least 64 bytes. + * @arg key_len an optional output value for the key length in bits. + * @arg icv_len an optional output value for the alt-icv-len. + * @arg key an optional buffer large enough for the key. It must contain at least + * ((@key_len + 7) / 8) bytes. + * + * Warning: you must ensure that @key is large enough. If you don't know the key_len before-hand, + * call xfrmnl_sa_get_aead_params() without @key argument to query only the required buffer size. + * This modified API is available in all versions of libnl3 that support the capability + * @def NL_CAPABILITY_XFRM_SA_KEY_SIZE (@see nl_has_capability for further information). + * + * @return 0 on success or a negative error code. + */ +int xfrmnl_sa_get_aead_params (struct xfrmnl_sa* sa, char* alg_name, unsigned int* key_len, unsigned int* icv_len, char* key) +{ + if (sa->ce_mask & XFRM_SA_ATTR_ALG_AEAD) + { + if (alg_name) + strcpy (alg_name, sa->aead->alg_name); + if (key_len) + *key_len = sa->aead->alg_key_len; + if (icv_len) + *icv_len = sa->aead->alg_icv_len; + if (key) + memcpy (key, sa->aead->alg_key, ((sa->aead->alg_key_len + 7)/8)); + } + else + return -1; + + return 0; +} + +int xfrmnl_sa_set_aead_params (struct xfrmnl_sa* sa, const char* alg_name, unsigned int key_len, unsigned int icv_len, const char* key) +{ + _nl_auto_free struct xfrmnl_algo_aead *b = NULL; + size_t keysize = sizeof (uint8_t) * ((key_len + 7)/8); + uint32_t newlen = sizeof (struct xfrmnl_algo_aead) + keysize; + + /* Free up the old key and allocate memory to hold new key */ + if (strlen (alg_name) >= sizeof (sa->aead->alg_name)) + return -1; + if (!(b = calloc (1, newlen))) + return -1; + + strcpy (b->alg_name, alg_name); + b->alg_key_len = key_len; + b->alg_icv_len = icv_len; + memcpy (b->alg_key, key, keysize); + + free (sa->aead); + sa->aead = _nl_steal_pointer (&b); + sa->ce_mask |= XFRM_SA_ATTR_ALG_AEAD; + return 0; +} + +/** + * Get the auth-params + * @arg sa the xfrmnl_sa object + * @arg alg_name an optional output buffer for the algorithm name. Must be at least 64 bytes. + * @arg key_len an optional output value for the key length in bits. + * @arg trunc_len an optional output value for the alg-trunc-len. + * @arg key an optional buffer large enough for the key. It must contain at least + * ((@key_len + 7) / 8) bytes. + * + * Warning: you must ensure that @key is large enough. If you don't know the key_len before-hand, + * call xfrmnl_sa_get_auth_params() without @key argument to query only the required buffer size. + * This modified API is available in all versions of libnl3 that support the capability + * @def NL_CAPABILITY_XFRM_SA_KEY_SIZE (@see nl_has_capability for further information). + * + * @return 0 on success or a negative error code. + */ +int xfrmnl_sa_get_auth_params (struct xfrmnl_sa* sa, char* alg_name, unsigned int* key_len, unsigned int* trunc_len, char* key) +{ + if (!(sa->ce_mask & XFRM_SA_ATTR_ALG_AUTH)) + return -NLE_MISSING_ATTR; + + if (alg_name) + strcpy(alg_name, sa->auth->alg_name); + if (key_len) + *key_len = sa->auth->alg_key_len; + if (trunc_len) + *trunc_len = sa->auth->alg_trunc_len; + if (key) + memcpy(key, sa->auth->alg_key, (sa->auth->alg_key_len + 7) / 8); + return 0; +} + +int xfrmnl_sa_set_auth_params (struct xfrmnl_sa* sa, const char* alg_name, unsigned int key_len, unsigned int trunc_len, const char* key) +{ + _nl_auto_free struct xfrmnl_algo_auth *b = NULL; + size_t keysize = sizeof (uint8_t) * ((key_len + 7)/8); + uint32_t newlen = sizeof (struct xfrmnl_algo_auth) + keysize; + + if (strlen (alg_name) >= sizeof (sa->auth->alg_name)) + return -1; + if (!(b = calloc (1, newlen))) + return -1; + + strcpy (b->alg_name, alg_name); + b->alg_key_len = key_len; + b->alg_trunc_len = trunc_len; + memcpy (b->alg_key, key, keysize); + + free (sa->auth); + sa->auth = _nl_steal_pointer (&b); + sa->ce_mask |= XFRM_SA_ATTR_ALG_AUTH; + return 0; +} + +/** + * Get the crypto-params + * @arg sa the xfrmnl_sa object + * @arg alg_name an optional output buffer for the algorithm name. Must be at least 64 bytes. + * @arg key_len an optional output value for the key length in bits. + * @arg key an optional buffer large enough for the key. It must contain at least + * ((@key_len + 7) / 8) bytes. + * + * Warning: you must ensure that @key is large enough. If you don't know the key_len before-hand, + * call xfrmnl_sa_get_crypto_params() without @key argument to query only the required buffer size. + * This modified API is available in all versions of libnl3 that support the capability + * @def NL_CAPABILITY_XFRM_SA_KEY_SIZE (@see nl_has_capability for further information). + * + * @return 0 on success or a negative error code. + */ +int xfrmnl_sa_get_crypto_params (struct xfrmnl_sa* sa, char* alg_name, unsigned int* key_len, char* key) +{ + if (sa->ce_mask & XFRM_SA_ATTR_ALG_CRYPT) + { + if (alg_name) + strcpy (alg_name, sa->crypt->alg_name); + if (key_len) + *key_len = sa->crypt->alg_key_len; + if (key) + memcpy (key, sa->crypt->alg_key, ((sa->crypt->alg_key_len + 7)/8)); + } + else + return -1; + + return 0; +} + +int xfrmnl_sa_set_crypto_params (struct xfrmnl_sa* sa, const char* alg_name, unsigned int key_len, const char* key) +{ + _nl_auto_free struct xfrmnl_algo *b = NULL; + size_t keysize = sizeof (uint8_t) * ((key_len + 7)/8); + uint32_t newlen = sizeof (struct xfrmnl_algo) + keysize; + + if (strlen (alg_name) >= sizeof (sa->crypt->alg_name)) + return -1; + if (!(b = calloc (1, newlen))) + return -1; + + strcpy (b->alg_name, alg_name); + b->alg_key_len = key_len; + memcpy (b->alg_key, key, keysize); + + free(sa->crypt); + sa->crypt = _nl_steal_pointer(&b); + sa->ce_mask |= XFRM_SA_ATTR_ALG_CRYPT; + return 0; +} + +/** + * Get the comp-params + * @arg sa the xfrmnl_sa object + * @arg alg_name an optional output buffer for the algorithm name. Must be at least 64 bytes. + * @arg key_len an optional output value for the key length in bits. + * @arg key an optional buffer large enough for the key. It must contain at least + * ((@key_len + 7) / 8) bytes. + * + * Warning: you must ensure that @key is large enough. If you don't know the key_len before-hand, + * call xfrmnl_sa_get_comp_params() without @key argument to query only the required buffer size. + * This modified API is available in all versions of libnl3 that support the capability + * @def NL_CAPABILITY_XFRM_SA_KEY_SIZE (@see nl_has_capability for further information). + * + * @return 0 on success or a negative error code. + */ +int xfrmnl_sa_get_comp_params (struct xfrmnl_sa* sa, char* alg_name, unsigned int* key_len, char* key) +{ + if (sa->ce_mask & XFRM_SA_ATTR_ALG_COMP) + { + if (alg_name) + strcpy (alg_name, sa->comp->alg_name); + if (key_len) + *key_len = sa->comp->alg_key_len; + if (key) + memcpy (key, sa->comp->alg_key, ((sa->comp->alg_key_len + 7)/8)); + } + else + return -1; + + return 0; +} + +int xfrmnl_sa_set_comp_params (struct xfrmnl_sa* sa, const char* alg_name, unsigned int key_len, const char* key) +{ + _nl_auto_free struct xfrmnl_algo *b = NULL; + size_t keysize = sizeof (uint8_t) * ((key_len + 7)/8); + uint32_t newlen = sizeof (struct xfrmnl_algo) + keysize; + + if (strlen (alg_name) >= sizeof (sa->comp->alg_name)) + return -1; + if (!(b = calloc (1, newlen))) + return -1; + + strcpy (b->alg_name, alg_name); + b->alg_key_len = key_len; + memcpy (b->alg_key, key, keysize); + + free(sa->comp); + sa->comp = _nl_steal_pointer(&b); + sa->ce_mask |= XFRM_SA_ATTR_ALG_COMP; + return 0; +} + +int xfrmnl_sa_get_encap_tmpl (struct xfrmnl_sa* sa, unsigned int* encap_type, unsigned int* encap_sport, unsigned int* encap_dport, struct nl_addr** encap_oa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_ENCAP) + { + *encap_type = sa->encap->encap_type; + *encap_sport = sa->encap->encap_sport; + *encap_dport = sa->encap->encap_dport; + *encap_oa = nl_addr_clone (sa->encap->encap_oa); + } + else + return -1; + + return 0; +} + +int xfrmnl_sa_set_encap_tmpl (struct xfrmnl_sa* sa, unsigned int encap_type, unsigned int encap_sport, unsigned int encap_dport, struct nl_addr* encap_oa) +{ + if (sa->encap) { + /* Free up the old encap OA */ + if (sa->encap->encap_oa) + nl_addr_put(sa->encap->encap_oa); + memset(sa->encap, 0, sizeof (*sa->encap)); + } else if ((sa->encap = calloc(1, sizeof(*sa->encap))) == NULL) + return -1; + + /* Save the new info */ + sa->encap->encap_type = encap_type; + sa->encap->encap_sport = encap_sport; + sa->encap->encap_dport = encap_dport; + nl_addr_get (encap_oa); + sa->encap->encap_oa = encap_oa; + + sa->ce_mask |= XFRM_SA_ATTR_ENCAP; + + return 0; +} + +int xfrmnl_sa_get_tfcpad (struct xfrmnl_sa* sa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_TFCPAD) + return sa->tfcpad; + else + return -1; +} + +int xfrmnl_sa_set_tfcpad (struct xfrmnl_sa* sa, unsigned int tfcpad) +{ + sa->tfcpad = tfcpad; + sa->ce_mask |= XFRM_SA_ATTR_TFCPAD; + + return 0; +} + +struct nl_addr* xfrmnl_sa_get_coaddr (struct xfrmnl_sa* sa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_COADDR) + return sa->coaddr; + else + return NULL; +} + +int xfrmnl_sa_set_coaddr (struct xfrmnl_sa* sa, struct nl_addr* coaddr) +{ + /* Free up the old coaddr */ + if (sa->coaddr) + nl_addr_put (sa->coaddr); + + /* Save the new info */ + nl_addr_get (coaddr); + sa->coaddr = coaddr; + + sa->ce_mask |= XFRM_SA_ATTR_COADDR; + + return 0; +} + +int xfrmnl_sa_get_mark (struct xfrmnl_sa* sa, unsigned int* mark_mask, unsigned int* mark_value) +{ + if (mark_mask == NULL || mark_value == NULL) + return -1; + + if (sa->ce_mask & XFRM_SA_ATTR_MARK) + { + *mark_mask = sa->mark.m; + *mark_value = sa->mark.v; + + return 0; + } + else + return -1; +} + +int xfrmnl_sa_set_mark (struct xfrmnl_sa* sa, unsigned int value, unsigned int mask) +{ + sa->mark.v = value; + sa->mark.m = mask; + sa->ce_mask |= XFRM_SA_ATTR_MARK; + + return 0; +} + +/** + * Get the security context. + * + * @arg sa The xfrmnl_sa object. + * @arg doi An optional output value for the security context domain of interpretation. + * @arg alg An optional output value for the security context algorithm. + * @arg len An optional output value for the security context length, including the + * terminating null byte ('\0'). + * @arg sid Unused parameter. + * @arg ctx_str An optional buffer large enough for the security context string. It must + * contain at least @len bytes. + * + * Warning: you must ensure that @ctx_str is large enough. If you don't know the length before-hand, + * call xfrmnl_sa_get_sec_ctx() without @ctx_str argument to query only the required buffer size. + * This modified API is available in all versions of libnl3 that support the capability + * @def NL_CAPABILITY_XFRM_SEC_CTX_LEN (@see nl_has_capability for further information). + * + * @return 0 on success or a negative error code. + */ +int xfrmnl_sa_get_sec_ctx (struct xfrmnl_sa* sa, unsigned int* doi, unsigned int* alg, + unsigned int* len, unsigned int* sid, char* ctx_str) +{ + if (sa->ce_mask & XFRM_SA_ATTR_SECCTX) + { + if (doi) + *doi = sa->sec_ctx->ctx_doi; + if (alg) + *alg = sa->sec_ctx->ctx_alg; + if (len) + *len = sa->sec_ctx->ctx_len; + if (ctx_str) + memcpy (ctx_str, sa->sec_ctx->ctx, sa->sec_ctx->ctx_len); + } + else + return -1; + + return 0; +} + +/** + * Set the security context. + * + * @arg sa The xfrmnl_sa object. + * @arg doi Parameter for the security context domain of interpretation. + * @arg alg Parameter for the security context algorithm. + * @arg len Parameter for the length of the security context string containing + * the terminating null byte ('\0'). + * @arg sid Unused parameter. + * @arg ctx_str Buffer containing the security context string. + * + * @return 0 on success or a negative error code. + */ +int xfrmnl_sa_set_sec_ctx (struct xfrmnl_sa* sa, unsigned int doi, unsigned int alg, unsigned int len, + unsigned int sid, const char* ctx_str) +{ + _nl_auto_free struct xfrmnl_user_sec_ctx *b = NULL; + + if (!(b = calloc(1, sizeof (struct xfrmnl_user_sec_ctx) + 1 + len))) + return -1; + + b->len = sizeof(struct xfrmnl_user_sec_ctx) + len; + b->exttype = XFRMA_SEC_CTX; + b->ctx_alg = alg; + b->ctx_doi = doi; + b->ctx_len = len; + memcpy (b->ctx, ctx_str, len); + b->ctx[len] = '\0'; + + free(sa->sec_ctx); + sa->sec_ctx = _nl_steal_pointer(&b); + sa->ce_mask |= XFRM_SA_ATTR_SECCTX; + return 0; +} + + +int xfrmnl_sa_get_replay_maxage (struct xfrmnl_sa* sa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_REPLAY_MAXAGE) + return sa->replay_maxage; + else + return -1; +} + +int xfrmnl_sa_set_replay_maxage (struct xfrmnl_sa* sa, unsigned int replay_maxage) +{ + sa->replay_maxage = replay_maxage; + sa->ce_mask |= XFRM_SA_ATTR_REPLAY_MAXAGE; + + return 0; +} + +int xfrmnl_sa_get_replay_maxdiff (struct xfrmnl_sa* sa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_REPLAY_MAXDIFF) + return sa->replay_maxdiff; + else + return -1; +} + +int xfrmnl_sa_set_replay_maxdiff (struct xfrmnl_sa* sa, unsigned int replay_maxdiff) +{ + sa->replay_maxdiff = replay_maxdiff; + sa->ce_mask |= XFRM_SA_ATTR_REPLAY_MAXDIFF; + + return 0; +} + +int xfrmnl_sa_get_replay_state (struct xfrmnl_sa* sa, unsigned int* oseq, unsigned int* seq, unsigned int* bmp) +{ + if (sa->ce_mask & XFRM_SA_ATTR_REPLAY_STATE) + { + if (sa->replay_state_esn == NULL) + { + *oseq = sa->replay_state.oseq; + *seq = sa->replay_state.seq; + *bmp = sa->replay_state.bitmap; + + return 0; + } + else + { + return -1; + } + } + else + return -1; +} + +int xfrmnl_sa_set_replay_state (struct xfrmnl_sa* sa, unsigned int oseq, unsigned int seq, unsigned int bitmap) +{ + sa->replay_state.oseq = oseq; + sa->replay_state.seq = seq; + sa->replay_state.bitmap = bitmap; + sa->ce_mask |= XFRM_SA_ATTR_REPLAY_STATE; + + return 0; +} + +int xfrmnl_sa_get_replay_state_esn (struct xfrmnl_sa* sa, unsigned int* oseq, unsigned int* seq, unsigned int* oseq_hi, + unsigned int* seq_hi, unsigned int* replay_window, unsigned int* bmp_len, unsigned int* bmp) +{ + if (sa->ce_mask & XFRM_SA_ATTR_REPLAY_STATE) + { + if (sa->replay_state_esn) + { + *oseq = sa->replay_state_esn->oseq; + *seq = sa->replay_state_esn->seq; + *oseq_hi= sa->replay_state_esn->oseq_hi; + *seq_hi = sa->replay_state_esn->seq_hi; + *replay_window = sa->replay_state_esn->replay_window; + *bmp_len = sa->replay_state_esn->bmp_len; // In number of 32 bit words + memcpy (bmp, sa->replay_state_esn->bmp, sa->replay_state_esn->bmp_len * sizeof (uint32_t)); + + return 0; + } + else + { + return -1; + } + } + else + return -1; +} + +int xfrmnl_sa_set_replay_state_esn (struct xfrmnl_sa* sa, unsigned int oseq, unsigned int seq, + unsigned int oseq_hi, unsigned int seq_hi, unsigned int replay_window, + unsigned int bmp_len, unsigned int* bmp) +{ + _nl_auto_free struct xfrmnl_replay_state_esn *b = NULL; + + if (!(b = calloc (1, sizeof (struct xfrmnl_replay_state_esn) + (sizeof (uint32_t) * bmp_len)))) + return -1; + + b->oseq = oseq; + b->seq = seq; + b->oseq_hi = oseq_hi; + b->seq_hi = seq_hi; + b->replay_window = replay_window; + b->bmp_len = bmp_len; // In number of 32 bit words + memcpy (b->bmp, bmp, bmp_len * sizeof (uint32_t)); + + free(sa->replay_state_esn); + sa->replay_state_esn = _nl_steal_pointer(&b); + sa->ce_mask |= XFRM_SA_ATTR_REPLAY_STATE; + return 0; +} + + +/** + * Get interface id and flags from xfrm_user_offload. + * + * @arg sa The xfrmnl_sa object. + * @arg ifindex An optional output value for the offload interface index. + * @arg flags An optional output value for the offload flags. + * + * @return 0 on success or a negative error code. + */ +int xfrmnl_sa_get_user_offload(struct xfrmnl_sa *sa, int *ifindex, uint8_t *flags) +{ + int ret = -1; + + if (sa->ce_mask & XFRM_SA_ATTR_OFFLOAD_DEV && sa->user_offload) { + if (ifindex) + *ifindex = sa->user_offload->ifindex; + if (flags) + *flags = sa->user_offload->flags; + ret = 0; + } + + return ret; +} + + +/** + * Set interface id and flags for xfrm_user_offload. + * + * @arg sa The xfrmnl_sa object. + * @arg ifindex Id of the offload interface. + * @arg flags Offload flags for the state. + * + * @return 0 on success or a negative error code. + */ +int xfrmnl_sa_set_user_offload(struct xfrmnl_sa *sa, int ifindex, uint8_t flags) +{ + _nl_auto_free struct xfrmnl_user_offload *b = NULL; + + if (!(b = calloc(1, sizeof(*b)))) + return -1; + + b->ifindex = ifindex; + b->flags = flags; + + free(sa->user_offload); + sa->user_offload = _nl_steal_pointer(&b); + sa->ce_mask |= XFRM_SA_ATTR_OFFLOAD_DEV; + + return 0; +} + +int xfrmnl_sa_is_hardexpiry_reached (struct xfrmnl_sa* sa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_EXPIRE) + return (sa->hard > 0 ? 1: 0); + else + return 0; +} + +int xfrmnl_sa_is_expiry_reached (struct xfrmnl_sa* sa) +{ + if (sa->ce_mask & XFRM_SA_ATTR_EXPIRE) + return 1; + else + return 0; +} + +/** @} */ + +static struct nl_object_ops xfrm_sa_obj_ops = { + .oo_name = "xfrm/sa", + .oo_size = sizeof(struct xfrmnl_sa), + .oo_constructor = xfrm_sa_alloc_data, + .oo_free_data = xfrm_sa_free_data, + .oo_clone = xfrm_sa_clone, + .oo_dump = { + [NL_DUMP_LINE] = xfrm_sa_dump_line, + [NL_DUMP_DETAILS] = xfrm_sa_dump_details, + [NL_DUMP_STATS] = xfrm_sa_dump_stats, + }, + .oo_compare = xfrm_sa_compare, + .oo_attrs2str = xfrm_sa_attrs2str, + .oo_id_attrs = (XFRM_SA_ATTR_DADDR | XFRM_SA_ATTR_SPI | XFRM_SA_ATTR_PROTO), +}; + +static struct nl_af_group xfrm_sa_groups[] = { + { AF_UNSPEC, XFRMNLGRP_SA }, + { AF_UNSPEC, XFRMNLGRP_EXPIRE }, + { END_OF_GROUP_LIST }, +}; + +static struct nl_cache_ops xfrmnl_sa_ops = { + .co_name = "xfrm/sa", + .co_hdrsize = sizeof(struct xfrm_usersa_info), + .co_msgtypes = { + { XFRM_MSG_NEWSA, NL_ACT_NEW, "new" }, + { XFRM_MSG_DELSA, NL_ACT_DEL, "del" }, + { XFRM_MSG_GETSA, NL_ACT_GET, "get" }, + { XFRM_MSG_EXPIRE, NL_ACT_UNSPEC, "expire"}, + { XFRM_MSG_UPDSA, NL_ACT_NEW, "update"}, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_XFRM, + .co_groups = xfrm_sa_groups, + .co_request_update = xfrm_sa_request_update, + .co_msg_parser = xfrm_sa_msg_parser, + .co_obj_ops = &xfrm_sa_obj_ops, + .co_include_event = &xfrm_sa_update_cache +}; + +/** + * @name XFRM SA Cache Managament + * @{ + */ + +static void __attribute__ ((constructor)) xfrm_sa_init(void) +{ + nl_cache_mngt_register(&xfrmnl_sa_ops); +} + +static void __attribute__ ((destructor)) xfrm_sa_exit(void) +{ + nl_cache_mngt_unregister(&xfrmnl_sa_ops); +} + +/** @} */ diff --git a/lib/xfrm/selector.c b/lib/xfrm/selector.c new file mode 100644 index 0000000..4f14b7b --- /dev/null +++ b/lib/xfrm/selector.c @@ -0,0 +1,371 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * @ingroup xfrmnl + * @defgroup XFRM Address Selector + * + * Abstract data type representing XFRM SA/SP selector properties + * + * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ + */ + +#include "nl-default.h" + +#include + +/* Selector, used as selector both on policy rules (SPD) and SAs. */ +struct xfrmnl_sel { + uint32_t refcnt; + struct nl_addr* daddr; + struct nl_addr* saddr; + uint16_t dport; + uint16_t dport_mask; + uint16_t sport; + uint16_t sport_mask; + uint16_t family; + uint8_t prefixlen_d; + uint8_t prefixlen_s; + uint8_t proto; + int32_t ifindex; + uint32_t user; +}; + +static void sel_destroy(struct xfrmnl_sel* sel) +{ + if (!sel) + return; + + if (sel->refcnt != 1) + { + fprintf(stderr, "BUG: %s:%d\n", __FILE__, __LINE__); + assert(0); + } + + nl_addr_put (sel->daddr); + nl_addr_put (sel->saddr); + free(sel); +} + +/** + * @name Creating Selector + * @{ + */ + +/** + * Allocate new selector object. + * @return Newly allocated selector object or NULL + */ +struct xfrmnl_sel* xfrmnl_sel_alloc() +{ + struct xfrmnl_sel* sel; + + sel = calloc(1, sizeof(struct xfrmnl_sel)); + if (!sel) + return NULL; + + sel->refcnt = 1; + + return sel; +} + +/** + * Clone existing selector object. + * @arg sel Selector object. + * @return Newly allocated selector object being a duplicate of the + * specified selector object or NULL if a failure occured. + */ +struct xfrmnl_sel* xfrmnl_sel_clone(struct xfrmnl_sel* sel) +{ + struct xfrmnl_sel* new; + + new = xfrmnl_sel_alloc(); + if (!new) + return NULL; + + memcpy(new, sel, sizeof(struct xfrmnl_sel)); + new->daddr = nl_addr_clone(sel->daddr); + new->saddr = nl_addr_clone(sel->saddr); + + return new; +} + +/** @} */ + +/** + * @name Managing Usage References + * @{ + */ + +struct xfrmnl_sel* xfrmnl_sel_get(struct xfrmnl_sel* sel) +{ + sel->refcnt++; + + return sel; +} + +void xfrmnl_sel_put(struct xfrmnl_sel* sel) +{ + if (!sel) + return; + + if (sel->refcnt == 1) + sel_destroy(sel); + else + sel->refcnt--; +} + +/** + * Check whether an selector object is shared. + * @arg addr Selector object. + * @return Non-zero if the selector object is shared, otherwise 0. + */ +int xfrmnl_sel_shared(struct xfrmnl_sel* sel) +{ + return sel->refcnt > 1; +} + +/** @} */ + +/** + * @name Miscellaneous + * @{ + */ + +/** + * Compares two selector objects. + * @arg a A selector object. + * @arg b Another selector object. + * + * @return Non zero if difference is found, 0 otherwise if both + * the objects are identical. + */ +int xfrmnl_sel_cmp(struct xfrmnl_sel* a, struct xfrmnl_sel* b) +{ + /* Check for any differences */ + if ((nl_addr_cmp_prefix (a->daddr, b->daddr) != 0) || + (nl_addr_cmp_prefix (a->saddr, b->saddr) != 0) || + ((a->sport & a->sport_mask) != (b->sport & b->sport_mask)) || + ((a->dport & a->dport_mask) != (b->dport & b->dport_mask)) || + (a->family != b->family) || + (a->proto && (a->proto != b->proto)) || + (a->ifindex && a->ifindex != b->ifindex) || + (a->user != b->user)) + return 1; + + /* The objects are identical */ + return 0; +} + +void xfrmnl_sel_dump(struct xfrmnl_sel* sel, struct nl_dump_params *p) +{ + char dst[INET6_ADDRSTRLEN+5], src[INET6_ADDRSTRLEN+5]; + char buf [128]; + + nl_dump_line(p, "\t\tsrc %s dst %s family: %s\n", nl_addr2str(sel->saddr, src, sizeof(src)), + nl_addr2str (sel->daddr, dst, sizeof (dst)), nl_af2str (sel->family, buf, 128)); + nl_dump_line (p, "\t\tsrc port/mask: %d/%d dst port/mask: %d/%d\n", + sel->dport, sel->dport_mask, sel->sport, sel->sport_mask); + nl_dump_line (p, "\t\tprotocol: %s ifindex: %u user: %u\n", + nl_ip_proto2str (sel->proto, buf, sizeof(buf)), sel->ifindex, sel->user); + + return; +} + + +/** @} */ + +/** + * @name Attributes + * @{ + */ +struct nl_addr* xfrmnl_sel_get_daddr (struct xfrmnl_sel* sel) +{ + return sel->daddr; +} + +int xfrmnl_sel_set_daddr (struct xfrmnl_sel* sel, struct nl_addr* addr) +{ + /* Increment reference counter on this to keep this address + * object around while selector in use */ + nl_addr_get(addr); + + sel->daddr = addr; + + return 0; +} + +struct nl_addr* xfrmnl_sel_get_saddr (struct xfrmnl_sel* sel) +{ + return sel->saddr; +} + +int xfrmnl_sel_set_saddr (struct xfrmnl_sel* sel, struct nl_addr* addr) +{ + /* Increment reference counter on this to keep this address + * object around while selector in use */ + nl_addr_get(addr); + + sel->saddr = addr; + + return 0; +} + +int xfrmnl_sel_get_dport (struct xfrmnl_sel* sel) +{ + return sel->dport; +} + +int xfrmnl_sel_set_dport (struct xfrmnl_sel* sel, unsigned int dport) +{ + sel->dport = dport; + + return 0; +} + +int xfrmnl_sel_get_dportmask (struct xfrmnl_sel* sel) +{ + return sel->dport_mask; +} + +int xfrmnl_sel_set_dportmask (struct xfrmnl_sel* sel, unsigned int dport_mask) +{ + sel->dport_mask = dport_mask; + + return 0; +} + +int xfrmnl_sel_get_sport (struct xfrmnl_sel* sel) +{ + return sel->sport; +} + +int xfrmnl_sel_set_sport (struct xfrmnl_sel* sel, unsigned int sport) +{ + sel->sport = sport; + + return 0; +} + +int xfrmnl_sel_get_sportmask (struct xfrmnl_sel* sel) +{ + return sel->sport_mask; +} + +int xfrmnl_sel_set_sportmask (struct xfrmnl_sel* sel, unsigned int sport_mask) +{ + sel->sport_mask = sport_mask; + + return 0; +} + +int xfrmnl_sel_get_family(struct xfrmnl_sel *sel) +{ + return sel->family; +} + +int xfrmnl_sel_set_family(struct xfrmnl_sel *sel, unsigned int family) +{ + sel->family = family; + + return 0; +} + +int xfrmnl_sel_get_prefixlen_d (struct xfrmnl_sel* sel) +{ + return sel->prefixlen_d; +} + +int xfrmnl_sel_set_prefixlen_d (struct xfrmnl_sel* sel, unsigned int prefixlen) +{ + sel->prefixlen_d = prefixlen; + + return 0; +} + +int xfrmnl_sel_get_prefixlen_s (struct xfrmnl_sel* sel) +{ + return sel->prefixlen_s; +} + +int xfrmnl_sel_set_prefixlen_s (struct xfrmnl_sel* sel, unsigned int prefixlen) +{ + sel->prefixlen_s = prefixlen; + + return 0; +} + +int xfrmnl_sel_get_proto (struct xfrmnl_sel* sel) +{ + return sel->proto; +} + +int xfrmnl_sel_set_proto (struct xfrmnl_sel* sel, unsigned int protocol) +{ + sel->proto = protocol; + + return 0; +} + +int xfrmnl_sel_get_ifindex (struct xfrmnl_sel* sel) +{ + return sel->ifindex; +} + +int xfrmnl_sel_set_ifindex (struct xfrmnl_sel* sel, unsigned int ifindex) +{ + sel->ifindex = ifindex; + + return 0; +} + +int xfrmnl_sel_get_userid (struct xfrmnl_sel* sel) +{ + return sel->user; +} + +int xfrmnl_sel_set_userid (struct xfrmnl_sel* sel, unsigned int userid) +{ + sel->user = userid; + return 0; +} + + +/** @} */ diff --git a/lib/xfrm/sp.c b/lib/xfrm/sp.c new file mode 100644 index 0000000..a996455 --- /dev/null +++ b/lib/xfrm/sp.c @@ -0,0 +1,1462 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @ingroup xfrmnl + * @defgroup sp Security Policy + * @brief + */ + +#include "nl-default.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "nl-xfrm.h" +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-priv-dynamic-core/nl-core.h" +#include "nl-priv-dynamic-core/cache-api.h" +#include "nl-aux-core/nl-core.h" +#include "nl-aux-xfrm/nl-xfrm.h" + +struct xfrmnl_userpolicy_type { + uint8_t type; + uint16_t reserved1; + uint16_t reserved2; +}; + +struct xfrmnl_sp { + NLHDR_COMMON + + struct xfrmnl_sel* sel; + struct xfrmnl_ltime_cfg* lft; + struct xfrmnl_lifetime_cur curlft; + uint32_t priority; + uint32_t index; + uint8_t dir; + uint8_t action; + uint8_t flags; + uint8_t share; + struct xfrmnl_user_sec_ctx* sec_ctx; + struct xfrmnl_userpolicy_type uptype; + uint32_t nr_user_tmpl; + struct nl_list_head usertmpl_list; + struct xfrmnl_mark mark; +}; + +/** @cond SKIP */ +#define XFRM_SP_ATTR_SEL 0x01 +#define XFRM_SP_ATTR_LTIME_CFG 0x02 +#define XFRM_SP_ATTR_LTIME_CUR 0x04 +#define XFRM_SP_ATTR_PRIO 0x08 +#define XFRM_SP_ATTR_INDEX 0x10 +#define XFRM_SP_ATTR_DIR 0x20 +#define XFRM_SP_ATTR_ACTION 0x40 +#define XFRM_SP_ATTR_FLAGS 0x80 +#define XFRM_SP_ATTR_SHARE 0x100 +#define XFRM_SP_ATTR_POLTYPE 0x200 +#define XFRM_SP_ATTR_SECCTX 0x400 +#define XFRM_SP_ATTR_TMPL 0x800 +#define XFRM_SP_ATTR_MARK 0x1000 + +static struct nl_cache_ops xfrmnl_sp_ops; +static struct nl_object_ops xfrm_sp_obj_ops; +/** @endcond */ + +static void xfrm_sp_alloc_data(struct nl_object *c) +{ + struct xfrmnl_sp* sp = nl_object_priv (c); + + if ((sp->sel = xfrmnl_sel_alloc ()) == NULL) + return; + + if ((sp->lft = xfrmnl_ltime_cfg_alloc ()) == NULL) + return; + + nl_init_list_head(&sp->usertmpl_list); + + return; +} + +static void xfrm_sp_free_data(struct nl_object *c) +{ + struct xfrmnl_sp* sp = nl_object_priv (c); + struct xfrmnl_user_tmpl *utmpl, *tmp; + + if (sp == NULL) + return; + + xfrmnl_sel_put (sp->sel); + xfrmnl_ltime_cfg_put (sp->lft); + + if (sp->sec_ctx) { + free(sp->sec_ctx); + } + + nl_list_for_each_entry_safe(utmpl, tmp, &sp->usertmpl_list, utmpl_list) { + xfrmnl_sp_remove_usertemplate (sp, utmpl); + xfrmnl_user_tmpl_free (utmpl); + } +} + +static int xfrm_sp_clone(struct nl_object *_dst, struct nl_object *_src) +{ + struct xfrmnl_sp* dst = nl_object_priv(_dst); + struct xfrmnl_sp* src = nl_object_priv(_src); + struct xfrmnl_user_tmpl *utmpl; + struct xfrmnl_user_tmpl *new; + + dst->sel = NULL; + dst->lft = NULL; + dst->sec_ctx = NULL; + nl_init_list_head(&dst->usertmpl_list); + + if (src->sel) { + if ((dst->sel = xfrmnl_sel_clone (src->sel)) == NULL) + return -NLE_NOMEM; + } + + if (src->lft) { + if ((dst->lft = xfrmnl_ltime_cfg_clone (src->lft)) == NULL) + return -NLE_NOMEM; + } + + if (src->sec_ctx) { + uint32_t len = sizeof (struct xfrmnl_user_sec_ctx) + src->sec_ctx->ctx_len; + + if ((dst->sec_ctx = malloc (len)) == NULL) + return -NLE_NOMEM; + memcpy(dst->sec_ctx, src->sec_ctx, len); + } + + nl_list_for_each_entry(utmpl, &src->usertmpl_list, utmpl_list) { + new = xfrmnl_user_tmpl_clone (utmpl); + if (!new) + return -NLE_NOMEM; + xfrmnl_sp_add_usertemplate(dst, new); + } + + return 0; +} + +static uint64_t xfrm_sp_compare(struct nl_object *_a, struct nl_object *_b, + uint64_t attrs, int flags) +{ + struct xfrmnl_sp* a = (struct xfrmnl_sp *) _a; + struct xfrmnl_sp* b = (struct xfrmnl_sp *) _b; + struct xfrmnl_user_tmpl *tmpl_a, *tmpl_b; + uint64_t diff = 0; + +#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR) + diff |= _DIFF(XFRM_SP_ATTR_SEL, xfrmnl_sel_cmp(a->sel, b->sel)); + diff |= _DIFF(XFRM_SP_ATTR_LTIME_CFG, + xfrmnl_ltime_cfg_cmp(a->lft, b->lft)); + diff |= _DIFF(XFRM_SP_ATTR_PRIO, a->priority != b->priority); + diff |= _DIFF(XFRM_SP_ATTR_INDEX, a->index != b->index); + diff |= _DIFF(XFRM_SP_ATTR_DIR, a->dir != b->dir); + diff |= _DIFF(XFRM_SP_ATTR_ACTION, a->action != b->action); + diff |= _DIFF(XFRM_SP_ATTR_FLAGS, a->flags != b->flags); + diff |= _DIFF(XFRM_SP_ATTR_SHARE, a->share != b->share); + diff |= _DIFF(XFRM_SP_ATTR_SECCTX, + ((a->sec_ctx->len != b->sec_ctx->len) || + (a->sec_ctx->exttype != b->sec_ctx->exttype) || + (a->sec_ctx->ctx_alg != b->sec_ctx->ctx_alg) || + (a->sec_ctx->ctx_doi != b->sec_ctx->ctx_doi) || + (a->sec_ctx->ctx_len != b->sec_ctx->ctx_len) || + strcmp(a->sec_ctx->ctx, b->sec_ctx->ctx))); + diff |= _DIFF(XFRM_SP_ATTR_POLTYPE, (a->uptype.type != b->uptype.type)); + diff |= _DIFF(XFRM_SP_ATTR_TMPL, (a->nr_user_tmpl != b->nr_user_tmpl)); + diff |= _DIFF(XFRM_SP_ATTR_MARK, + (a->mark.m != b->mark.m) || (a->mark.v != b->mark.v)); + + /* Compare the templates */ + nl_list_for_each_entry(tmpl_b, &b->usertmpl_list, utmpl_list) + nl_list_for_each_entry(tmpl_a, &a->usertmpl_list, utmpl_list) + diff |= xfrmnl_user_tmpl_cmp (tmpl_a, tmpl_b); +#undef _DIFF + + return diff; +} + +/** + * @name XFRM SP Attribute Translations + * @{ + */ +static const struct trans_tbl sp_attrs[] = { + __ADD(XFRM_SP_ATTR_SEL, selector), + __ADD(XFRM_SP_ATTR_LTIME_CFG, lifetime_cfg), + __ADD(XFRM_SP_ATTR_LTIME_CUR, lifetime_cur), + __ADD(XFRM_SP_ATTR_PRIO, priority), + __ADD(XFRM_SP_ATTR_INDEX, index), + __ADD(XFRM_SP_ATTR_DIR, direction), + __ADD(XFRM_SP_ATTR_ACTION, action), + __ADD(XFRM_SP_ATTR_FLAGS, flags), + __ADD(XFRM_SP_ATTR_SHARE, share), + __ADD(XFRM_SP_ATTR_POLTYPE, policy_type), + __ADD(XFRM_SP_ATTR_SECCTX, security_context), + __ADD(XFRM_SP_ATTR_TMPL, user_template), + __ADD(XFRM_SP_ATTR_MARK, mark), +}; + +static char* xfrm_sp_attrs2str(int attrs, char *buf, size_t len) +{ + return __flags2str (attrs, buf, len, sp_attrs, ARRAY_SIZE(sp_attrs)); +} +/** @} */ + +/** + * @name XFRM SP Action Translations + * @{ + */ +static const struct trans_tbl sa_actions[] = { + __ADD(XFRM_POLICY_ALLOW, allow), + __ADD(XFRM_POLICY_BLOCK, block), +}; + +char* xfrmnl_sp_action2str(int action, char *buf, size_t len) +{ + return __type2str (action, buf, len, sa_actions, ARRAY_SIZE(sa_actions)); +} + +int xfrmnl_sp_str2action(const char *name) +{ + return __str2type (name, sa_actions, ARRAY_SIZE(sa_actions)); +} +/** @} */ + +/** + * @name XFRM SP Flags Translations + * @{ + */ +static const struct trans_tbl sp_flags[] = { + __ADD(XFRM_POLICY_LOCALOK, allow policy override by user), + __ADD(XFRM_POLICY_ICMP, auto include ICMP in policy), +}; + +char* xfrmnl_sp_flags2str(int flags, char *buf, size_t len) +{ + return __flags2str (flags, buf, len, sp_flags, ARRAY_SIZE(sp_flags)); +} + +int xfrmnl_sp_str2flag(const char *name) +{ + return __str2flags(name, sp_flags, ARRAY_SIZE(sp_flags)); +} +/** @} */ + +/** + * @name XFRM SP Type Translations + * @{ + */ +static const struct trans_tbl sp_types[] = { + __ADD(XFRM_POLICY_TYPE_MAIN, main), + __ADD(XFRM_POLICY_TYPE_SUB, sub), + __ADD(XFRM_POLICY_TYPE_MAX, max), + __ADD(XFRM_POLICY_TYPE_ANY, any), +}; + +char* xfrmnl_sp_type2str(int type, char *buf, size_t len) +{ + return __type2str(type, buf, len, sp_types, ARRAY_SIZE(sp_types)); +} + +int xfrmnl_sp_str2type(const char *name) +{ + return __str2type(name, sp_types, ARRAY_SIZE(sp_types)); +} +/** @} */ + +/** + * @name XFRM SP Direction Translations + * @{ + */ +static const struct trans_tbl sp_dir[] = { + __ADD(XFRM_POLICY_IN, in), + __ADD(XFRM_POLICY_OUT, out), + __ADD(XFRM_POLICY_FWD, fwd), + __ADD(XFRM_POLICY_MASK, mask), +}; + +char* xfrmnl_sp_dir2str(int dir, char *buf, size_t len) +{ + return __type2str (dir, buf, len, sp_dir, ARRAY_SIZE(sp_dir)); +} + +int xfrmnl_sp_str2dir(const char *name) +{ + return __str2type (name, sp_dir, ARRAY_SIZE(sp_dir)); +} + +int xfrmnl_sp_index2dir (unsigned int index) +{ + return index & 0x7; +} +/** @} */ + +/** + * @name XFRM SP Share Translations + * @{ + */ +static const struct trans_tbl sp_share[] = { + __ADD(XFRM_SHARE_ANY, any), + __ADD(XFRM_SHARE_SESSION, session), + __ADD(XFRM_SHARE_USER, user), + __ADD(XFRM_SHARE_UNIQUE, unique), +}; + +char* xfrmnl_sp_share2str(int share, char *buf, size_t len) +{ + return __type2str (share, buf, len, sp_share, ARRAY_SIZE(sp_share)); +} + +int xfrmnl_sp_str2share(const char *name) +{ + return __str2type (name, sp_share, ARRAY_SIZE(sp_share)); +} +/** @} */ + +static void xfrm_sp_dump_line(struct nl_object *a, struct nl_dump_params *p) +{ + struct xfrmnl_sp* sp = (struct xfrmnl_sp *) a; + char dir[32], action[32], share[32], flags[32]; + char dst[INET6_ADDRSTRLEN+5], src[INET6_ADDRSTRLEN+5]; + time_t add_time, use_time; + struct tm *add_time_tm, *use_time_tm; + struct tm tm_buf; + + nl_addr2str(xfrmnl_sel_get_saddr (sp->sel), src, sizeof(src)); + nl_addr2str (xfrmnl_sel_get_daddr (sp->sel), dst, sizeof (dst)); + nl_af2str (xfrmnl_sel_get_family (sp->sel), dir, 32); + nl_dump_line(p, "src %s dst %s family: %s\n", src, dst, dir); + nl_dump_line (p, "src port/mask: %d/%d dst port/mask: %d/%d\n", + xfrmnl_sel_get_dport (sp->sel), xfrmnl_sel_get_dportmask (sp->sel), + xfrmnl_sel_get_sport (sp->sel), xfrmnl_sel_get_sportmask (sp->sel)); + nl_dump_line (p, "protocol: %s ifindex: %u uid: %u\n", + nl_ip_proto2str (xfrmnl_sel_get_proto (sp->sel), dir, sizeof(dir)), + xfrmnl_sel_get_ifindex (sp->sel), + xfrmnl_sel_get_userid (sp->sel)); + + xfrmnl_sp_dir2str (sp->dir, dir, 32); + xfrmnl_sp_action2str (sp->action, action, 32); + xfrmnl_sp_share2str (sp->share, share, 32); + xfrmnl_sp_flags2str (sp->flags, flags, 32); + nl_dump_line(p, "\tdir: %s action: %s index: %u priority: %u share: %s flags: %s(0x%x) \n", + dir, action, sp->index, sp->priority, share, flags, sp->flags); + + nl_dump_line(p, "\tlifetime configuration: \n"); + if (sp->lft->soft_byte_limit == XFRM_INF) + sprintf (dir, "INF"); + else + sprintf (dir, "%" PRIu64, sp->lft->soft_byte_limit); + if (sp->lft->soft_packet_limit == XFRM_INF) + sprintf (action, "INF"); + else + sprintf (action, "%" PRIu64, sp->lft->soft_packet_limit); + if (sp->lft->hard_byte_limit == XFRM_INF) + sprintf (flags, "INF"); + else + sprintf (flags, "%" PRIu64, sp->lft->hard_byte_limit); + if (sp->lft->hard_packet_limit == XFRM_INF) + sprintf (share, "INF"); + else + sprintf (share, "%" PRIu64, sp->lft->hard_packet_limit); + nl_dump_line(p, "\t\tsoft limit: %s (bytes), %s (packets) \n", dir, + action); + nl_dump_line(p, "\t\thard limit: %s (bytes), %s (packets) \n", flags, + share); + nl_dump_line( + p, + "\t\tsoft add_time: %llu (seconds), soft use_time: %llu (seconds) \n", + (long long unsigned)sp->lft->soft_add_expires_seconds, + (long long unsigned)sp->lft->soft_use_expires_seconds); + nl_dump_line( + p, + "\t\thard add_time: %llu (seconds), hard use_time: %llu (seconds) \n", + (long long unsigned)sp->lft->hard_add_expires_seconds, + (long long unsigned)sp->lft->hard_use_expires_seconds); + + nl_dump_line(p, "\tlifetime current: \n"); + nl_dump_line(p, "\t\t%llu bytes, %llu packets\n", + (long long unsigned)sp->curlft.bytes, + (long long unsigned)sp->curlft.packets); + + if (sp->curlft.add_time != 0) + { + add_time = sp->curlft.add_time; + add_time_tm = gmtime_r (&add_time, &tm_buf); + strftime (dst, INET6_ADDRSTRLEN+5, "%Y-%m-%d %H-%M-%S", add_time_tm); + } + else + { + sprintf (dst, "%s", "-"); + } + + if (sp->curlft.use_time != 0) + { + use_time = sp->curlft.use_time; + use_time_tm = gmtime_r (&use_time, &tm_buf); + strftime (src, INET6_ADDRSTRLEN+5, "%Y-%m-%d %H-%M-%S", use_time_tm); + } + else + { + sprintf (src, "%s", "-"); + } + nl_dump_line(p, "\t\tadd_time: %s, use_time: %s\n", dst, src); + + if (sp->ce_mask & XFRM_SP_ATTR_SECCTX) + { + nl_dump_line(p, "\tUser security context: \n"); + nl_dump_line(p, "\t\tlen: %d exttype: %d Algo: %d DOI: %d ctxlen: %d\n", + sp->sec_ctx->len, sp->sec_ctx->exttype, + sp->sec_ctx->ctx_alg, sp->sec_ctx->ctx_doi, sp->sec_ctx->ctx_len); + nl_dump_line (p, "\t\tctx: %s \n", sp->sec_ctx->ctx); + } + + xfrmnl_sp_type2str (sp->uptype.type, flags, 32); + if (sp->ce_mask & XFRM_SP_ATTR_POLTYPE) + nl_dump_line(p, "\tUser policy type: %s\n", flags); + + if (sp->ce_mask & XFRM_SP_ATTR_TMPL) + { + struct xfrmnl_user_tmpl* utmpl; + + nl_dump_line(p, "\tUser template: \n"); + + nl_list_for_each_entry(utmpl, &sp->usertmpl_list, utmpl_list) + xfrmnl_user_tmpl_dump (utmpl, p); + } + + if (sp->ce_mask & XFRM_SP_ATTR_MARK) + nl_dump_line(p, "\tMark mask: 0x%x Mark value: 0x%x\n", sp->mark.m, sp->mark.v); + + nl_dump(p, "\n"); +} + +static void xfrm_sp_dump_details(struct nl_object *a, struct nl_dump_params *p) +{ + xfrm_sp_dump_line(a, p); +} + +static void xfrm_sp_dump_stats(struct nl_object *a, struct nl_dump_params *p) +{ + xfrm_sp_dump_details(a, p); + + return; +} + +/** + * @name XFRM SP Object Allocation/Freeage + * @{ + */ + +struct xfrmnl_sp* xfrmnl_sp_alloc(void) +{ + return (struct xfrmnl_sp*) nl_object_alloc(&xfrm_sp_obj_ops); +} + +void xfrmnl_sp_put(struct xfrmnl_sp* sp) +{ + nl_object_put((struct nl_object *) sp); +} + +/** @} */ + +/** + * @name SP Cache Managament + * @{ + */ + +/** + * Build a SP cache including all SPs currently configured in the kernel. + * @arg sock Netlink socket. + * @arg result Pointer to store resulting cache. + * + * Allocates a new SP cache, initializes it properly and updates it + * to include all SPs currently configured in the kernel. + * + * @return 0 on success or a negative error code. + */ +int xfrmnl_sp_alloc_cache(struct nl_sock *sock, struct nl_cache **result) +{ + return nl_cache_alloc_and_fill(&xfrmnl_sp_ops, sock, result); +} + +/** + * Look up a SP by policy id and direction + * @arg cache SP cache + * @arg index Policy Id + * @arg dir direction + * @return sp handle or NULL if no match was found. + */ +struct xfrmnl_sp* xfrmnl_sp_get(struct nl_cache* cache, unsigned int index, unsigned int dir) +{ + struct xfrmnl_sp *sp; + + //nl_list_for_each_entry(sp, &cache->c_items, ce_list) { + for (sp = (struct xfrmnl_sp*)nl_cache_get_first (cache); + sp != NULL; + sp = (struct xfrmnl_sp*)nl_cache_get_next ((struct nl_object*)sp)) + { + if (sp->index == index && sp->dir == dir) + { + nl_object_get((struct nl_object *) sp); + return sp; + } + } + + return NULL; +} + + +/** @} */ + + +static struct nla_policy xfrm_sp_policy[XFRMA_MAX+1] = { + [XFRMA_POLICY] = { .minlen = sizeof(struct xfrm_userpolicy_info)}, + [XFRMA_SEC_CTX] = { .minlen = sizeof(struct xfrm_sec_ctx) }, + [XFRMA_TMPL] = { .minlen = sizeof(struct xfrm_user_tmpl) }, + [XFRMA_POLICY_TYPE] = { .minlen = sizeof(struct xfrm_userpolicy_type)}, + [XFRMA_MARK] = { .minlen = sizeof(struct xfrm_mark) }, +}; + +static int xfrm_sp_request_update(struct nl_cache *c, struct nl_sock *h) +{ + return nl_send_simple (h, XFRM_MSG_GETPOLICY, NLM_F_DUMP, NULL, 0); +} + +int xfrmnl_sp_parse(struct nlmsghdr *n, struct xfrmnl_sp **result) +{ + _nl_auto_nl_addr struct nl_addr *addr1 = NULL; + _nl_auto_nl_addr struct nl_addr *addr2 = NULL; + _nl_auto_xfrmnl_sp struct xfrmnl_sp *sp = NULL; + struct nlattr *tb[XFRMA_MAX + 1]; + struct xfrm_userpolicy_info *sp_info; + int len, err; + + sp = xfrmnl_sp_alloc(); + if (!sp) + return -NLE_NOMEM; + + sp->ce_msgtype = n->nlmsg_type; + if (n->nlmsg_type == XFRM_MSG_DELPOLICY) + sp_info = (struct xfrm_userpolicy_info*)((char *)nlmsg_data(n) + sizeof (struct xfrm_userpolicy_id) + NLA_HDRLEN); + else + sp_info = nlmsg_data(n); + + err = nlmsg_parse(n, sizeof(struct xfrm_userpolicy_info), tb, XFRMA_MAX, xfrm_sp_policy); + if (err < 0) + return err; + + if (!(addr1 = _nl_addr_build(sp_info->sel.family, &sp_info->sel.daddr))) + return -NLE_NOMEM; + nl_addr_set_prefixlen (addr1, sp_info->sel.prefixlen_d); + xfrmnl_sel_set_daddr (sp->sel, addr1); + xfrmnl_sel_set_prefixlen_d (sp->sel, sp_info->sel.prefixlen_d); + + if (!(addr2 = _nl_addr_build(sp_info->sel.family, &sp_info->sel.saddr))) + return -NLE_NOMEM; + nl_addr_set_prefixlen (addr2, sp_info->sel.prefixlen_s); + xfrmnl_sel_set_saddr (sp->sel, addr2); + xfrmnl_sel_set_prefixlen_s (sp->sel, sp_info->sel.prefixlen_s); + + xfrmnl_sel_set_dport (sp->sel, ntohs (sp_info->sel.dport)); + xfrmnl_sel_set_dportmask (sp->sel, ntohs (sp_info->sel.dport_mask)); + xfrmnl_sel_set_sport (sp->sel, ntohs (sp_info->sel.sport)); + xfrmnl_sel_set_sportmask (sp->sel, ntohs (sp_info->sel.sport_mask)); + xfrmnl_sel_set_family (sp->sel, sp_info->sel.family); + xfrmnl_sel_set_proto (sp->sel, sp_info->sel.proto); + xfrmnl_sel_set_ifindex (sp->sel, sp_info->sel.ifindex); + xfrmnl_sel_set_userid (sp->sel, sp_info->sel.user); + sp->ce_mask |= XFRM_SP_ATTR_SEL; + + sp->lft->soft_byte_limit = sp_info->lft.soft_byte_limit; + sp->lft->hard_byte_limit = sp_info->lft.hard_byte_limit; + sp->lft->soft_packet_limit = sp_info->lft.soft_packet_limit; + sp->lft->hard_packet_limit = sp_info->lft.hard_packet_limit; + sp->lft->soft_add_expires_seconds = sp_info->lft.soft_add_expires_seconds; + sp->lft->hard_add_expires_seconds = sp_info->lft.hard_add_expires_seconds; + sp->lft->soft_use_expires_seconds = sp_info->lft.soft_use_expires_seconds; + sp->lft->hard_use_expires_seconds = sp_info->lft.hard_use_expires_seconds; + sp->ce_mask |= XFRM_SP_ATTR_LTIME_CFG; + + sp->curlft.bytes = sp_info->curlft.bytes; + sp->curlft.packets = sp_info->curlft.packets; + sp->curlft.add_time = sp_info->curlft.add_time; + sp->curlft.use_time = sp_info->curlft.use_time; + sp->ce_mask |= XFRM_SP_ATTR_LTIME_CUR; + + sp->priority = sp_info->priority; + sp->index = sp_info->index; + sp->dir = sp_info->dir; + sp->action = sp_info->action; + sp->flags = sp_info->flags; + sp->share = sp_info->share; + sp->ce_mask |= (XFRM_SP_ATTR_PRIO | XFRM_SP_ATTR_INDEX | + XFRM_SP_ATTR_DIR | XFRM_SP_ATTR_ACTION | + XFRM_SP_ATTR_FLAGS | XFRM_SP_ATTR_SHARE); + + if (tb[XFRMA_SEC_CTX]) { + struct xfrm_user_sec_ctx* ctx = nla_data(tb[XFRMA_SEC_CTX]); + + len = sizeof (struct xfrmnl_user_sec_ctx) + ctx->ctx_len; + if ((sp->sec_ctx = calloc (1, len)) == NULL) + return -NLE_NOMEM; + memcpy ((void *)sp->sec_ctx, (void *)ctx, len); + sp->ce_mask |= XFRM_SP_ATTR_SECCTX; + } + + if (tb[XFRMA_POLICY_TYPE]) { + struct xfrm_userpolicy_type* up = nla_data(tb[XFRMA_POLICY_TYPE]); + + memcpy ((void *)&sp->uptype, (void *)up, sizeof (struct xfrm_userpolicy_type)); + sp->ce_mask |= XFRM_SP_ATTR_POLTYPE; + } + + if (tb[XFRMA_TMPL]) { + struct xfrm_user_tmpl* tmpl = nla_data(tb[XFRMA_TMPL]); + uint32_t i; + uint32_t num_tmpls = nla_len(tb[XFRMA_TMPL]) / sizeof (*tmpl); + + for (i = 0; (i < num_tmpls) && (tmpl); i ++, tmpl++) + { + _nl_auto_xfrmnl_user_tmpl struct xfrmnl_user_tmpl *sputmpl = NULL; + _nl_auto_nl_addr struct nl_addr *addr1 = NULL; + _nl_auto_nl_addr struct nl_addr *addr2 = NULL; + + if ((sputmpl = xfrmnl_user_tmpl_alloc ()) == NULL) + return -NLE_NOMEM; + + if (!(addr1 = _nl_addr_build(tmpl->family, &tmpl->id.daddr))) + return -NLE_NOMEM; + xfrmnl_user_tmpl_set_daddr (sputmpl, addr1); + xfrmnl_user_tmpl_set_spi (sputmpl, ntohl(tmpl->id.spi)); + xfrmnl_user_tmpl_set_proto (sputmpl, tmpl->id.proto); + xfrmnl_user_tmpl_set_family (sputmpl, tmpl->family); + + if (!(addr2 = _nl_addr_build(tmpl->family, &tmpl->saddr))) + return -NLE_NOMEM; + xfrmnl_user_tmpl_set_saddr (sputmpl, addr2); + + xfrmnl_user_tmpl_set_reqid (sputmpl, tmpl->reqid); + xfrmnl_user_tmpl_set_mode (sputmpl, tmpl->mode); + xfrmnl_user_tmpl_set_share (sputmpl, tmpl->share); + xfrmnl_user_tmpl_set_optional (sputmpl, tmpl->optional); + xfrmnl_user_tmpl_set_aalgos (sputmpl, tmpl->aalgos); + xfrmnl_user_tmpl_set_ealgos (sputmpl, tmpl->ealgos); + xfrmnl_user_tmpl_set_calgos (sputmpl, tmpl->calgos); + xfrmnl_sp_add_usertemplate (sp, _nl_steal_pointer(&sputmpl)); + + sp->ce_mask |= XFRM_SP_ATTR_TMPL; + } + } + + if (tb[XFRMA_MARK]) { + struct xfrm_mark* m = nla_data(tb[XFRMA_MARK]); + sp->mark.m = m->m; + sp->mark.v = m->v; + sp->ce_mask |= XFRM_SP_ATTR_MARK; + } + + *result = _nl_steal_pointer(&sp); + return 0; +} + +static int xfrm_sp_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, + struct nlmsghdr *n, struct nl_parser_param *pp) +{ + struct xfrmnl_sp* sp; + int err; + + if ((err = xfrmnl_sp_parse(n, &sp)) < 0) + { + printf ("received error: %d \n", err); + return err; + } + + err = pp->pp_cb((struct nl_object *) sp, pp); + + xfrmnl_sp_put(sp); + return err; +} + +/** + * @name XFRM SP Get + * @{ + */ + +int xfrmnl_sp_build_get_request(unsigned int index, unsigned int dir, unsigned int mark_v, unsigned int mark_m, struct nl_msg **result) +{ + struct nl_msg *msg; + struct xfrm_userpolicy_id spid; + struct xfrm_mark mark; + + memset(&spid, 0, sizeof(spid)); + spid.index = index; + spid.dir = dir; + + if (!(msg = nlmsg_alloc_simple(XFRM_MSG_GETPOLICY, 0))) + return -NLE_NOMEM; + + if (nlmsg_append(msg, &spid, sizeof(spid), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if ((mark_m & mark_v) != 0) + { + memset(&mark, 0, sizeof(struct xfrm_mark)); + mark.m = mark_m; + mark.v = mark_v; + + NLA_PUT (msg, XFRMA_MARK, sizeof (struct xfrm_mark), &mark); + } + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +int xfrmnl_sp_get_kernel(struct nl_sock* sock, unsigned int index, unsigned int dir, unsigned int mark_v, unsigned int mark_m, struct xfrmnl_sp** result) +{ + struct nl_msg *msg = NULL; + struct nl_object *obj; + int err; + + if ((err = xfrmnl_sp_build_get_request(index, dir, mark_m, mark_v, &msg)) < 0) + return err; + + err = nl_send_auto(sock, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + if ((err = nl_pickup(sock, &xfrm_sp_msg_parser, &obj)) < 0) + return err; + + /* We have used xfrm_sp_msg_parser(), object is definitely a xfrm ae */ + *result = (struct xfrmnl_sp *) obj; + + /* If an object has been returned, we also need to wait for the ACK */ + if (err == 0 && obj) + nl_wait_for_ack(sock); + + return 0; +} + +/** @} */ + +static int build_xfrm_sp_message(struct xfrmnl_sp *tmpl, int cmd, int flags, struct nl_msg **result) +{ + struct nl_msg* msg; + struct xfrm_userpolicy_info sp_info; + uint32_t len; + struct nl_addr* addr; + + if (!(tmpl->ce_mask & XFRM_SP_ATTR_DIR) || + (!(tmpl->ce_mask & XFRM_SP_ATTR_INDEX) && + !(tmpl->ce_mask & XFRM_SP_ATTR_SEL))) + return -NLE_MISSING_ATTR; + + memset ((void*)&sp_info, 0, sizeof (sp_info)); + if (tmpl->ce_mask & XFRM_SP_ATTR_SEL) + { + addr = xfrmnl_sel_get_daddr (tmpl->sel); + memcpy ((void*)&sp_info.sel.daddr, (void*)nl_addr_get_binary_addr (addr), sizeof (uint8_t) * nl_addr_get_len (addr)); + addr = xfrmnl_sel_get_saddr (tmpl->sel); + memcpy ((void*)&sp_info.sel.saddr, (void*)nl_addr_get_binary_addr (addr), sizeof (uint8_t) * nl_addr_get_len (addr)); + sp_info.sel.dport = htons (xfrmnl_sel_get_dport (tmpl->sel)); + sp_info.sel.dport_mask = htons (xfrmnl_sel_get_dportmask (tmpl->sel)); + sp_info.sel.sport = htons (xfrmnl_sel_get_sport (tmpl->sel)); + sp_info.sel.sport_mask = htons (xfrmnl_sel_get_sportmask (tmpl->sel)); + sp_info.sel.family = xfrmnl_sel_get_family (tmpl->sel); + sp_info.sel.prefixlen_d = xfrmnl_sel_get_prefixlen_d (tmpl->sel); + sp_info.sel.prefixlen_s = xfrmnl_sel_get_prefixlen_s (tmpl->sel); + sp_info.sel.proto = xfrmnl_sel_get_proto (tmpl->sel); + sp_info.sel.ifindex = xfrmnl_sel_get_ifindex (tmpl->sel); + sp_info.sel.user = xfrmnl_sel_get_userid (tmpl->sel); + } + + if (tmpl->ce_mask & XFRM_SP_ATTR_LTIME_CFG) + { + sp_info.lft.soft_byte_limit = xfrmnl_ltime_cfg_get_soft_bytelimit (tmpl->lft); + sp_info.lft.hard_byte_limit = xfrmnl_ltime_cfg_get_hard_bytelimit (tmpl->lft); + sp_info.lft.soft_packet_limit = xfrmnl_ltime_cfg_get_soft_packetlimit (tmpl->lft); + sp_info.lft.hard_packet_limit = xfrmnl_ltime_cfg_get_hard_packetlimit (tmpl->lft); + sp_info.lft.soft_add_expires_seconds = xfrmnl_ltime_cfg_get_soft_addexpires (tmpl->lft); + sp_info.lft.hard_add_expires_seconds = xfrmnl_ltime_cfg_get_hard_addexpires (tmpl->lft); + sp_info.lft.soft_use_expires_seconds = xfrmnl_ltime_cfg_get_soft_useexpires (tmpl->lft); + sp_info.lft.hard_use_expires_seconds = xfrmnl_ltime_cfg_get_hard_useexpires (tmpl->lft); + } + + //Skip current lifetime: cur lifetime can be updated only via AE + + if (tmpl->ce_mask & XFRM_SP_ATTR_PRIO) + sp_info.priority = tmpl->priority; + + if (tmpl->ce_mask & XFRM_SP_ATTR_INDEX) + sp_info.index = tmpl->index; + + if (tmpl->ce_mask & XFRM_SP_ATTR_DIR) + sp_info.dir = tmpl->dir; + + if (tmpl->ce_mask & XFRM_SP_ATTR_ACTION) + sp_info.action = tmpl->action; + + if (tmpl->ce_mask & XFRM_SP_ATTR_FLAGS) + sp_info.flags = tmpl->flags; + + if (tmpl->ce_mask & XFRM_SP_ATTR_SHARE) + sp_info.share = tmpl->share; + + msg = nlmsg_alloc_simple(cmd, flags); + if (!msg) + return -NLE_NOMEM; + + if (nlmsg_append(msg, &sp_info, sizeof(sp_info), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if (tmpl->ce_mask & XFRM_SP_ATTR_SECCTX) { + len = (sizeof (struct xfrm_user_sec_ctx)) + tmpl->sec_ctx->ctx_len; + NLA_PUT (msg, XFRMA_SEC_CTX, len, tmpl->sec_ctx); + } + + if (tmpl->ce_mask & XFRM_SP_ATTR_POLTYPE) { + len = sizeof (struct xfrm_userpolicy_type); + NLA_PUT (msg, XFRMA_POLICY_TYPE, len, &tmpl->uptype); + } + + if (tmpl->ce_mask & XFRM_SP_ATTR_TMPL) { + struct nlattr* tmpls; + struct xfrmnl_user_tmpl* utmpl; + struct nl_addr* addr; + + if (!(tmpls = nla_nest_start(msg, XFRMA_TMPL))) + goto nla_put_failure; + + nl_list_for_each_entry(utmpl, &tmpl->usertmpl_list, utmpl_list) { + struct xfrm_user_tmpl* tmpl; + + tmpl = nlmsg_reserve(msg, sizeof(*tmpl), NLMSG_ALIGNTO); + if (!tmpl) + goto nla_put_failure; + addr = xfrmnl_user_tmpl_get_daddr (utmpl); + memcpy ((void *)&tmpl->id.daddr, nl_addr_get_binary_addr (addr), + nl_addr_get_len (addr)); + tmpl->id.spi = htonl(xfrmnl_user_tmpl_get_spi (utmpl)); + tmpl->id.proto = xfrmnl_user_tmpl_get_proto (utmpl); + tmpl->family = xfrmnl_user_tmpl_get_family (utmpl); + addr = xfrmnl_user_tmpl_get_saddr (utmpl); + memcpy ((void *)&tmpl->saddr, nl_addr_get_binary_addr (addr), + nl_addr_get_len (addr)); + tmpl->reqid = xfrmnl_user_tmpl_get_reqid (utmpl); + tmpl->mode = xfrmnl_user_tmpl_get_mode (utmpl); + tmpl->share = xfrmnl_user_tmpl_get_share (utmpl); + tmpl->optional = xfrmnl_user_tmpl_get_optional (utmpl); + tmpl->aalgos = xfrmnl_user_tmpl_get_aalgos (utmpl); + tmpl->ealgos = xfrmnl_user_tmpl_get_ealgos (utmpl); + tmpl->calgos = xfrmnl_user_tmpl_get_calgos (utmpl); + } + nla_nest_end(msg, tmpls); + } + + if (tmpl->ce_mask & XFRM_SP_ATTR_MARK) { + NLA_PUT (msg, XFRMA_MARK, sizeof (struct xfrm_mark), &tmpl->mark); + } + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +/** + * @name XFRM SP Add + * @{ + */ + +int xfrmnl_sp_build_add_request(struct xfrmnl_sp* tmpl, int flags, struct nl_msg **result) +{ + return build_xfrm_sp_message (tmpl, XFRM_MSG_NEWPOLICY, flags, result); +} + +int xfrmnl_sp_add(struct nl_sock* sk, struct xfrmnl_sp* tmpl, int flags) +{ + int err; + struct nl_msg *msg; + + if ((err = xfrmnl_sp_build_add_request(tmpl, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return nl_wait_for_ack(sk); +} + +/** + * @name XFRM SP Update + * @{ + */ + +int xfrmnl_sp_build_update_request(struct xfrmnl_sp* tmpl, int flags, struct nl_msg **result) +{ + return build_xfrm_sp_message (tmpl, XFRM_MSG_UPDPOLICY, flags, result); +} + +int xfrmnl_sp_update(struct nl_sock* sk, struct xfrmnl_sp* tmpl, int flags) +{ + int err; + struct nl_msg *msg; + + if ((err = xfrmnl_sp_build_update_request(tmpl, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return nl_wait_for_ack(sk); +} + +/** @} */ + +/** + * \brief Builds a xfrm_sp_delete_message. Uses either index and direction + * or security-context (not set is a valid value), selector and + * direction for identification. + * Returns error if necessary values aren't set. + * + * \param tmpl The policy template. + * \param cmd The command. Should be XFRM_MSG_DELPOLICY. + * \param flags Additional flags + * \param result Resulting message. + * + * \return 0 if successful, else error value < 0 + */ +static int build_xfrm_sp_delete_message(struct xfrmnl_sp *tmpl, int cmd, int flags, struct nl_msg **result) +{ + struct nl_msg* msg; + struct xfrm_userpolicy_id spid; + struct nl_addr* addr; + uint32_t len; + + if (!(tmpl->ce_mask & XFRM_SP_ATTR_DIR) || + (!(tmpl->ce_mask & XFRM_SP_ATTR_INDEX) && + !(tmpl->ce_mask & XFRM_SP_ATTR_SEL))) + return -NLE_MISSING_ATTR; + + memset(&spid, 0, sizeof(spid)); + spid.dir = tmpl->dir; + if(tmpl->ce_mask & XFRM_SP_ATTR_INDEX) + spid.index = tmpl->index; + + if (tmpl->ce_mask & XFRM_SP_ATTR_SEL) + { + addr = xfrmnl_sel_get_daddr (tmpl->sel); + memcpy ((void*)&spid.sel.daddr, (void*)nl_addr_get_binary_addr (addr), sizeof (uint8_t) * nl_addr_get_len (addr)); + addr = xfrmnl_sel_get_saddr (tmpl->sel); + memcpy ((void*)&spid.sel.saddr, (void*)nl_addr_get_binary_addr (addr), sizeof (uint8_t) * nl_addr_get_len (addr)); + spid.sel.dport = htons (xfrmnl_sel_get_dport (tmpl->sel)); + spid.sel.dport_mask = htons (xfrmnl_sel_get_dportmask (tmpl->sel)); + spid.sel.sport = htons (xfrmnl_sel_get_sport (tmpl->sel)); + spid.sel.sport_mask = htons (xfrmnl_sel_get_sportmask (tmpl->sel)); + spid.sel.family = xfrmnl_sel_get_family (tmpl->sel); + spid.sel.prefixlen_d = xfrmnl_sel_get_prefixlen_d (tmpl->sel); + spid.sel.prefixlen_s = xfrmnl_sel_get_prefixlen_s (tmpl->sel); + spid.sel.proto = xfrmnl_sel_get_proto (tmpl->sel); + spid.sel.ifindex = xfrmnl_sel_get_ifindex (tmpl->sel); + spid.sel.user = xfrmnl_sel_get_userid (tmpl->sel); + } + + msg = nlmsg_alloc_simple(cmd, flags); + if (!msg) + return -NLE_NOMEM; + + if (nlmsg_append(msg, &spid, sizeof(spid), NLMSG_ALIGNTO) < 0) + goto nla_put_failure; + + if (tmpl->ce_mask & XFRM_SP_ATTR_SECCTX) { + len = (sizeof (struct xfrm_user_sec_ctx)) + tmpl->sec_ctx->ctx_len; + NLA_PUT (msg, XFRMA_SEC_CTX, len, tmpl->sec_ctx); + } + + if (tmpl->ce_mask & XFRM_SP_ATTR_MARK) { + len = sizeof (struct xfrm_mark); + NLA_PUT (msg, XFRMA_MARK, len, &tmpl->mark); + } + + *result = msg; + return 0; + +nla_put_failure: + nlmsg_free(msg); + return -NLE_MSGSIZE; +} + +/** + * @name XFRM SA Delete + * @{ + */ + +int xfrmnl_sp_build_delete_request(struct xfrmnl_sp* tmpl, int flags, struct nl_msg **result) +{ + return build_xfrm_sp_delete_message (tmpl, XFRM_MSG_DELPOLICY, flags, result); +} + +int xfrmnl_sp_delete(struct nl_sock* sk, struct xfrmnl_sp* tmpl, int flags) +{ + int err; + struct nl_msg *msg; + + if ((err = xfrmnl_sp_build_delete_request(tmpl, flags, &msg)) < 0) + return err; + + err = nl_send_auto_complete(sk, msg); + nlmsg_free(msg); + if (err < 0) + return err; + + return nl_wait_for_ack(sk); +} + +/** @} */ + + +/** + * @name Attributes + * @{ + */ + +struct xfrmnl_sel* xfrmnl_sp_get_sel (struct xfrmnl_sp* sp) +{ + if (sp->ce_mask & XFRM_SP_ATTR_SEL) + return sp->sel; + else + return NULL; +} + +int xfrmnl_sp_set_sel (struct xfrmnl_sp* sp, struct xfrmnl_sel* sel) +{ + /* Release any previously held selector object from the SP */ + if (sp->sel) + xfrmnl_sel_put (sp->sel); + + /* Increment ref count on new selector and save it in the SP */ + xfrmnl_sel_get (sel); + sp->sel = sel; + sp->ce_mask |= XFRM_SP_ATTR_SEL; + + return 0; +} + +struct xfrmnl_ltime_cfg* xfrmnl_sp_get_lifetime_cfg (struct xfrmnl_sp* sp) +{ + if (sp->ce_mask & XFRM_SP_ATTR_LTIME_CFG) + return sp->lft; + else + return NULL; +} + +int xfrmnl_sp_set_lifetime_cfg (struct xfrmnl_sp* sp, struct xfrmnl_ltime_cfg* ltime) +{ + /* Release any previously held lifetime cfg object from the SP */ + if (sp->lft) + xfrmnl_ltime_cfg_put (sp->lft); + + /* Increment ref count on new lifetime object and save it in the SP */ + xfrmnl_ltime_cfg_get (ltime); + sp->lft = ltime; + sp->ce_mask |= XFRM_SP_ATTR_LTIME_CFG; + + return 0; +} + +int xfrmnl_sp_get_curlifetime (struct xfrmnl_sp* sp, unsigned long long int* curr_bytes, + unsigned long long int* curr_packets, unsigned long long int* curr_add_time, unsigned long long int* curr_use_time) +{ + if (sp == NULL || curr_bytes == NULL || curr_packets == NULL || curr_add_time == NULL || curr_use_time == NULL) + return -1; + + *curr_bytes = sp->curlft.bytes; + *curr_packets = sp->curlft.packets; + *curr_add_time = sp->curlft.add_time; + *curr_use_time = sp->curlft.use_time; + + return 0; +} + +int xfrmnl_sp_get_priority (struct xfrmnl_sp* sp) +{ + if (sp->ce_mask & XFRM_SP_ATTR_PRIO) + return sp->priority; + else + return -1; +} + +int xfrmnl_sp_set_priority (struct xfrmnl_sp* sp, unsigned int prio) +{ + sp->priority = prio; + sp->ce_mask |= XFRM_SP_ATTR_PRIO; + + return 0; +} + +int xfrmnl_sp_get_index (struct xfrmnl_sp* sp) +{ + if (sp->ce_mask & XFRM_SP_ATTR_INDEX) + return sp->index; + else + return -1; +} + +int xfrmnl_sp_set_index (struct xfrmnl_sp* sp, unsigned int index) +{ + sp->index = index; + sp->ce_mask |= XFRM_SP_ATTR_INDEX; + + return 0; +} + +int xfrmnl_sp_get_dir (struct xfrmnl_sp* sp) +{ + if (sp->ce_mask & XFRM_SP_ATTR_DIR) + return sp->dir; + else + return -1; +} + +int xfrmnl_sp_set_dir (struct xfrmnl_sp* sp, unsigned int dir) +{ + sp->dir = dir; + sp->ce_mask |= XFRM_SP_ATTR_DIR; + + return 0; +} + +int xfrmnl_sp_get_action (struct xfrmnl_sp* sp) +{ + if (sp->ce_mask & XFRM_SP_ATTR_ACTION) + return sp->action; + else + return -1; +} + +int xfrmnl_sp_set_action (struct xfrmnl_sp* sp, unsigned int action) +{ + sp->action = action; + sp->ce_mask |= XFRM_SP_ATTR_ACTION; + + return 0; +} + +int xfrmnl_sp_get_flags (struct xfrmnl_sp* sp) +{ + if (sp->ce_mask & XFRM_SP_ATTR_FLAGS) + return sp->flags; + else + return -1; +} + +int xfrmnl_sp_set_flags (struct xfrmnl_sp* sp, unsigned int flags) +{ + sp->flags = flags; + sp->ce_mask |= XFRM_SP_ATTR_FLAGS; + + return 0; +} + +int xfrmnl_sp_get_share (struct xfrmnl_sp* sp) +{ + if (sp->ce_mask & XFRM_SP_ATTR_SHARE) + return sp->share; + else + return -1; +} + +int xfrmnl_sp_set_share (struct xfrmnl_sp* sp, unsigned int share) +{ + sp->share = share; + sp->ce_mask |= XFRM_SP_ATTR_SHARE; + + return 0; +} + +/** + * Get the security context. + * + * @arg sp The xfrmnl_sp object. + * @arg len An optional output value for the ctx_str length including the xfrmnl_sp header. + * @arg exttype An optional output value. + * @arg alg An optional output value for the security context algorithm. + * @arg doi An optional output value for the security context domain of interpretation. + * @arg ctx_len An optional output value for the security context length, including the + * terminating null byte ('\0'). + * @arg ctx_str An optional buffer large enough for the security context string. It must + * contain at least @ctx_len bytes. You are advised to create the ctx_str + * buffer one element larger and ensure NUL termination yourself. + * + * Warning: you must ensure that @ctx_str is large enough. If you don't know the length before-hand, + * call xfrmnl_sp_get_sec_ctx() without @ctx_str argument to query only the required buffer size. + * This modified API is available in all versions of libnl3 that support the capability + * @def NL_CAPABILITY_XFRM_SP_SEC_CTX_LEN (@see nl_has_capability for further information). + * + * @return 0 on success or a negative error code. + */ +int xfrmnl_sp_get_sec_ctx (struct xfrmnl_sp* sp, unsigned int* len, unsigned int* exttype, unsigned int* alg, unsigned int* doi, unsigned int* ctx_len, char* ctx_str) +{ + if (sp->ce_mask & XFRM_SP_ATTR_SECCTX) + { + if (len) + *len = sizeof (struct xfrmnl_user_sec_ctx) + sp->sec_ctx->ctx_len; + if (exttype) + *exttype = sp->sec_ctx->exttype; + if (alg) + *alg = sp->sec_ctx->ctx_alg; + if (doi) + *doi = sp->sec_ctx->ctx_doi; + if (ctx_len) + *ctx_len = sp->sec_ctx->ctx_len; + if (ctx_str) + memcpy ((void *)ctx_str, (void *)sp->sec_ctx->ctx, sp->sec_ctx->ctx_len); + } + else + return -1; + + return 0; +} +/** + * @brief Set security context (ctx_str) for XFRM Polixy. + * + * @param sp XFRM Policy + * @param len !!! depricated unused parameter !!! + * @param exttype netlink message attribute - probably XFRMA_SEC_CTX + * @param alg security context algorithm + * @param doi security context domain interpretation + * @param ctx_len Length of the context string. + * @param ctx_str The context string. + * + * @return 0 if sucessfull, else -1 + */ +int xfrmnl_sp_set_sec_ctx (struct xfrmnl_sp* sp, unsigned int len __attribute__((unused)), unsigned int exttype, unsigned int alg, unsigned int doi, unsigned int ctx_len, char* ctx_str) +{ + /* Free up the old context string and allocate new one */ + if (sp->sec_ctx) + free (sp->sec_ctx); + if ((sp->sec_ctx = calloc (1, sizeof (struct xfrmnl_user_sec_ctx) + 1 + ctx_len)) == NULL) + return -1; + + /* Save the new info */ + sp->sec_ctx->len = sizeof (struct xfrmnl_user_sec_ctx) + ctx_len; + sp->sec_ctx->exttype = exttype; + sp->sec_ctx->ctx_alg = alg; + sp->sec_ctx->ctx_doi = doi; + sp->sec_ctx->ctx_len = ctx_len; + memcpy ((void *)sp->sec_ctx->ctx, (void *)ctx_str, ctx_len); + sp->sec_ctx->ctx[ctx_len] = '\0'; + + sp->ce_mask |= XFRM_SP_ATTR_SECCTX; + + return 0; +} + +int xfrmnl_sp_get_userpolicy_type (struct xfrmnl_sp* sp) +{ + if (sp->ce_mask & XFRM_SP_ATTR_POLTYPE) + return sp->uptype.type; + else + return -1; +} + +int xfrmnl_sp_set_userpolicy_type (struct xfrmnl_sp* sp, unsigned int type) +{ + sp->uptype.type = type; + sp->ce_mask |= XFRM_SP_ATTR_POLTYPE; + + return 0; +} + +void xfrmnl_sp_add_usertemplate(struct xfrmnl_sp *sp, struct xfrmnl_user_tmpl *utmpl) +{ + nl_list_add_tail(&utmpl->utmpl_list, &sp->usertmpl_list); + sp->nr_user_tmpl++; + sp->ce_mask |= XFRM_SP_ATTR_TMPL; +} + +void xfrmnl_sp_remove_usertemplate(struct xfrmnl_sp *sp, struct xfrmnl_user_tmpl *utmpl) +{ + if (sp->ce_mask & XFRM_SP_ATTR_TMPL) { + sp->nr_user_tmpl--; + nl_list_del(&utmpl->utmpl_list); + if (sp->nr_user_tmpl == 0) + sp->ce_mask &= ~XFRM_SP_ATTR_TMPL; + } +} + +struct nl_list_head *xfrmnl_sp_get_usertemplates(struct xfrmnl_sp *sp) +{ + if (sp->ce_mask & XFRM_SP_ATTR_TMPL) + return &sp->usertmpl_list; + + return NULL; +} + +int xfrmnl_sp_get_nusertemplates(struct xfrmnl_sp *sp) +{ + if (sp->ce_mask & XFRM_SP_ATTR_TMPL) + return sp->nr_user_tmpl; + + return 0; +} + +void xfrmnl_sp_foreach_usertemplate(struct xfrmnl_sp *r, + void (*cb)(struct xfrmnl_user_tmpl *, void *), + void *arg) +{ + struct xfrmnl_user_tmpl *utmpl; + + if (r->ce_mask & XFRM_SP_ATTR_TMPL) { + nl_list_for_each_entry(utmpl, &r->usertmpl_list, utmpl_list) { + cb(utmpl, arg); + } + } +} + +struct xfrmnl_user_tmpl *xfrmnl_sp_usertemplate_n(struct xfrmnl_sp *r, int n) +{ + struct xfrmnl_user_tmpl *utmpl; + uint32_t i; + + if (r->ce_mask & XFRM_SP_ATTR_TMPL && r->nr_user_tmpl > n) { + i = 0; + nl_list_for_each_entry(utmpl, &r->usertmpl_list, utmpl_list) { + if (i == n) return utmpl; + i++; + } + } + return NULL; +} + +int xfrmnl_sp_get_mark (struct xfrmnl_sp* sp, unsigned int* mark_mask, unsigned int* mark_value) +{ + if (mark_mask == NULL || mark_value == NULL) + return -1; + + if (sp->ce_mask & XFRM_SP_ATTR_MARK) + { + *mark_mask = sp->mark.m; + *mark_value = sp->mark.v; + + return 0; + } + else + return -1; +} + +int xfrmnl_sp_set_mark (struct xfrmnl_sp* sp, unsigned int value, unsigned int mask) +{ + sp->mark.v = value; + sp->mark.m = mask; + sp->ce_mask |= XFRM_SP_ATTR_MARK; + + return 0; +} + +/** @} */ + +static struct nl_object_ops xfrm_sp_obj_ops = { + .oo_name = "xfrm/sp", + .oo_size = sizeof(struct xfrmnl_sp), + .oo_constructor = xfrm_sp_alloc_data, + .oo_free_data = xfrm_sp_free_data, + .oo_clone = xfrm_sp_clone, + .oo_dump = { + [NL_DUMP_LINE] = xfrm_sp_dump_line, + [NL_DUMP_DETAILS] = xfrm_sp_dump_details, + [NL_DUMP_STATS] = xfrm_sp_dump_stats, + }, + .oo_compare = xfrm_sp_compare, + .oo_attrs2str = xfrm_sp_attrs2str, + .oo_id_attrs = (XFRM_SP_ATTR_SEL | XFRM_SP_ATTR_INDEX | XFRM_SP_ATTR_DIR), +}; + +static struct nl_af_group xfrm_sp_groups[] = { + { AF_UNSPEC, XFRMNLGRP_POLICY }, + { END_OF_GROUP_LIST }, +}; + +static struct nl_cache_ops xfrmnl_sp_ops = { + .co_name = "xfrm/sp", + .co_hdrsize = sizeof(struct xfrm_userpolicy_info), + .co_msgtypes = { + { XFRM_MSG_NEWPOLICY, NL_ACT_NEW, "new" }, + { XFRM_MSG_DELPOLICY, NL_ACT_DEL, "del" }, + { XFRM_MSG_GETPOLICY, NL_ACT_GET, "get" }, + { XFRM_MSG_UPDPOLICY, NL_ACT_NEW, "update" }, + END_OF_MSGTYPES_LIST, + }, + .co_protocol = NETLINK_XFRM, + .co_groups = xfrm_sp_groups, + .co_request_update = xfrm_sp_request_update, + .co_msg_parser = xfrm_sp_msg_parser, + .co_obj_ops = &xfrm_sp_obj_ops, +}; + +/** + * @name XFRM SA Cache Managament + * @{ + */ + +static void __attribute__ ((constructor)) xfrm_sp_init(void) +{ + nl_cache_mngt_register(&xfrmnl_sp_ops); +} + +static void __attribute__ ((destructor)) xfrm_sp_exit(void) +{ + nl_cache_mngt_unregister(&xfrmnl_sp_ops); +} + +/** @} */ diff --git a/lib/xfrm/template.c b/lib/xfrm/template.c new file mode 100644 index 0000000..2a42b28 --- /dev/null +++ b/lib/xfrm/template.c @@ -0,0 +1,345 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * @ingroup xfrmnl + * @defgroup XFRM User Template Object + * + * Abstract data type representing XFRM SA properties + * + * @{ + * + * Header + * ------ + * ~~~~{.c} + * #include + * ~~~~ + */ + +#include "nl-default.h" + +#include + +#include "nl-xfrm.h" +#include "nl-priv-dynamic-core/nl-core.h" + +void xfrmnl_user_tmpl_free(struct xfrmnl_user_tmpl* utmpl) +{ + if (!utmpl) + return; + + nl_addr_put (utmpl->id.daddr); + nl_addr_put (utmpl->saddr); + free(utmpl); +} + +/** + * @name Creating User Template Object + * @{ + */ + +/** + * Allocate new user template object. + * @return Newly allocated user template object or NULL + */ +struct xfrmnl_user_tmpl* xfrmnl_user_tmpl_alloc() +{ + struct xfrmnl_user_tmpl* utmpl; + + utmpl = calloc(1, sizeof(struct xfrmnl_user_tmpl)); + if (!utmpl) + return NULL; + + nl_init_list_head(&utmpl->utmpl_list); + + return utmpl; +} + +/** + * Clone existing user template object. + * @arg utmpl Selector object. + * @return Newly allocated user template object being a duplicate of the + * specified user template object or NULL if a failure occured. + */ +struct xfrmnl_user_tmpl* xfrmnl_user_tmpl_clone(struct xfrmnl_user_tmpl* utmpl) +{ + struct xfrmnl_user_tmpl* new; + + new = xfrmnl_user_tmpl_alloc(); + if (!new) + return NULL; + + memcpy(new, utmpl, sizeof(struct xfrmnl_user_tmpl)); + new->id.daddr = nl_addr_clone (utmpl->id.daddr); + new->saddr = nl_addr_clone (utmpl->saddr); + + return new; +} + +/** @} */ + +/** + * @name XFRM Template Mode Translations + * @{ + */ +static const struct trans_tbl tmpl_modes[] = { + __ADD(XFRM_MODE_TRANSPORT, transport), + __ADD(XFRM_MODE_TUNNEL, tunnel), + __ADD(XFRM_MODE_ROUTEOPTIMIZATION, route optimization), + __ADD(XFRM_MODE_IN_TRIGGER, in trigger), + __ADD(XFRM_MODE_BEET, beet), +}; + +char* xfrmnl_user_tmpl_mode2str(int mode, char *buf, size_t len) +{ + return __type2str (mode, buf, len, tmpl_modes, ARRAY_SIZE(tmpl_modes)); +} + +int xfrmnl_user_tmpl_str2mode(const char *name) +{ + return __str2type (name, tmpl_modes, ARRAY_SIZE(tmpl_modes)); +} +/** @} */ + +/** + * @name Miscellaneous + * @{ + */ + +/** + * Compares two user template objects. + * @arg a A user template object. + * @arg b Another user template object. + * + * @return Non zero if difference is found, 0 otherwise if both + * the objects are identical. + */ +int xfrmnl_user_tmpl_cmp(struct xfrmnl_user_tmpl* a, struct xfrmnl_user_tmpl* b) +{ + /* Check for any differences */ + if ((nl_addr_cmp_prefix (a->id.daddr, b->id.daddr) != 0) || + (a->id.spi != b->id.spi) || + (a->id.proto && (a->id.proto != b->id.proto)) || + (nl_addr_cmp_prefix (a->saddr, b->saddr) != 0) || + (a->family != b->family) || + (a->reqid != b->reqid) || + (a->mode != b->mode) || + (a->share != b->share) || + (a->aalgos != b->aalgos) || + (a->ealgos != b->ealgos) || + (a->calgos != b->calgos)) + return 1; + + /* The objects are identical */ + return 0; +} + +void xfrmnl_user_tmpl_dump(struct xfrmnl_user_tmpl* tmpl, struct nl_dump_params *p) +{ + char dst[INET6_ADDRSTRLEN+5], src[INET6_ADDRSTRLEN+5]; + char buf [128]; + + nl_dump_line(p, "\t\tsrc %s dst %s family: %s \n", + nl_addr2str(tmpl->saddr, src, sizeof(src)), + nl_addr2str (tmpl->id.daddr, dst, sizeof (dst)), + nl_af2str (tmpl->family, buf, 128)); + nl_dump_line (p, "\t\tprotocol: %s spi: 0x%x reqid: %u mode: %s\n", + nl_ip_proto2str (tmpl->id.proto, buf, sizeof(buf)), + tmpl->id.spi, tmpl->reqid, + xfrmnl_user_tmpl_mode2str (tmpl->mode, buf, 128)); + nl_dump_line (p, "\t\tAuth Algo: 0x%x Crypto Algo: 0x%x Compr Algo: 0x%x\n", + tmpl->aalgos, tmpl->ealgos, tmpl->calgos); + + return; +} + +/** @} */ + +/** + * @name Attributes + * @{ + */ +struct nl_addr* xfrmnl_user_tmpl_get_daddr (struct xfrmnl_user_tmpl* utmpl) +{ + return utmpl->id.daddr; +} + +int xfrmnl_user_tmpl_set_daddr (struct xfrmnl_user_tmpl* utmpl, struct nl_addr* addr) +{ + /* Increment reference counter on this to keep this address + * object around while user template in use */ + nl_addr_get(addr); + + utmpl->id.daddr = addr; + + return 0; +} + +int xfrmnl_user_tmpl_get_spi (struct xfrmnl_user_tmpl* utmpl) +{ + return utmpl->id.spi; +} + +int xfrmnl_user_tmpl_set_spi (struct xfrmnl_user_tmpl* utmpl, unsigned int spi) +{ + utmpl->id.spi = spi; + + return 0; +} + +int xfrmnl_user_tmpl_get_proto (struct xfrmnl_user_tmpl* utmpl) +{ + return utmpl->id.proto; +} + +int xfrmnl_user_tmpl_set_proto (struct xfrmnl_user_tmpl* utmpl, unsigned int protocol) +{ + utmpl->id.proto = protocol; + + return 0; +} + +int xfrmnl_user_tmpl_get_family(struct xfrmnl_user_tmpl *utmpl) +{ + return utmpl->family; +} + +int xfrmnl_user_tmpl_set_family(struct xfrmnl_user_tmpl *utmpl, unsigned int family) +{ + utmpl->family = family; + + return 0; +} + +struct nl_addr* xfrmnl_user_tmpl_get_saddr (struct xfrmnl_user_tmpl* utmpl) +{ + return utmpl->saddr; +} + +int xfrmnl_user_tmpl_set_saddr (struct xfrmnl_user_tmpl* utmpl, struct nl_addr* addr) +{ + /* Increment reference counter on this to keep this address + * object around while user template in use */ + nl_addr_get(addr); + + utmpl->saddr = addr; + + return 0; +} + +int xfrmnl_user_tmpl_get_reqid (struct xfrmnl_user_tmpl* utmpl) +{ + return utmpl->reqid; +} + +int xfrmnl_user_tmpl_set_reqid (struct xfrmnl_user_tmpl* utmpl, unsigned int reqid) +{ + utmpl->reqid = reqid; + + return 0; +} + +int xfrmnl_user_tmpl_get_mode (struct xfrmnl_user_tmpl* utmpl) +{ + return utmpl->mode; +} + +int xfrmnl_user_tmpl_set_mode (struct xfrmnl_user_tmpl* utmpl, unsigned int mode) +{ + utmpl->mode = mode; + + return 0; +} + +int xfrmnl_user_tmpl_get_share (struct xfrmnl_user_tmpl* utmpl) +{ + return utmpl->share; +} + +int xfrmnl_user_tmpl_set_share (struct xfrmnl_user_tmpl* utmpl, unsigned int share) +{ + utmpl->share = share; + + return 0; +} + +int xfrmnl_user_tmpl_get_optional (struct xfrmnl_user_tmpl* utmpl) +{ + return utmpl->optional; +} + +int xfrmnl_user_tmpl_set_optional (struct xfrmnl_user_tmpl* utmpl, unsigned int optional) +{ + utmpl->optional = optional; + + return 0; +} + +int xfrmnl_user_tmpl_get_aalgos (struct xfrmnl_user_tmpl* utmpl) +{ + return utmpl->aalgos; +} + +int xfrmnl_user_tmpl_set_aalgos (struct xfrmnl_user_tmpl* utmpl, unsigned int aalgos) +{ + utmpl->aalgos = aalgos; + + return 0; +} + +int xfrmnl_user_tmpl_get_ealgos (struct xfrmnl_user_tmpl* utmpl) +{ + return utmpl->ealgos; +} + +int xfrmnl_user_tmpl_set_ealgos (struct xfrmnl_user_tmpl* utmpl, unsigned int ealgos) +{ + utmpl->ealgos = ealgos; + + return 0; +} + +int xfrmnl_user_tmpl_get_calgos (struct xfrmnl_user_tmpl* utmpl) +{ + return utmpl->calgos; +} + +int xfrmnl_user_tmpl_set_calgos (struct xfrmnl_user_tmpl* utmpl, unsigned int calgos) +{ + utmpl->calgos = calgos; + + return 0; +} + +/** @} */ diff --git a/libnl-3.0.pc.in b/libnl-3.0.pc.in index b87e3dc..ddbc999 100644 --- a/libnl-3.0.pc.in +++ b/libnl-3.0.pc.in @@ -7,4 +7,5 @@ Name: libnl Description: Convenience library for netlink sockets Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lnl-@MAJ_VERSION@ +Libs.private: @LIBS@ Cflags: -I${includedir}/libnl@MAJ_VERSION@ diff --git a/libnl-3.9.0.tar.gz b/libnl-3.9.0.tar.gz deleted file mode 100644 index d23b05fd1cfc902f10a2c2bcd9101922e9673ab4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1074117 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≶bH!9 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

    J&4x}ut$Mw0nX2YrQz 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

    mO{#~+>jMU>OQ3%EW0=a(a? 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 z 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 AK# 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νQWr5K@fFza??C!=;E1fe)jJfg6ss=(rV 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�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 diff --git a/libnl-3.sym b/libnl-3.sym new file mode 100644 index 0000000..bac4fcd --- /dev/null +++ b/libnl-3.sym @@ -0,0 +1,374 @@ +# The linker version script controls which symbols are exported. +# Version tags that correspond to past releases group the symbols +# that were part of that release. Hence, such a version tag is sealed +# and MUST not be extended. +# Any new symbols MUST only be added to the bottom of the file, in +# the version tag for the next upcoming release. +libnl_3 { +global: + # these functions are in private header files and should have never + # been exported. We might hide them later. + nl_cache_parse; + + # these functions are in private header files and should have never + # been exported. They are used by libnl internals + __flags2str; + __list_str2type; + __list_type2str; + __nl_read_num_str_file; + __str2flags; + __str2type; + __trans_list_add; + __trans_list_clear; + __type2str; + + # internal symbols that are in public headers + __nl_cache_mngt_require; + + # variables + nl_debug; + nl_debug_dp; + + nl_addr2str; + nl_addr_alloc; + nl_addr_alloc_attr; + nl_addr_build; + nl_addr_clone; + nl_addr_cmp; + nl_addr_cmp_prefix; + nl_addr_fill_sockaddr; + nl_addr_get; + nl_addr_get_binary_addr; + nl_addr_get_family; + nl_addr_get_len; + nl_addr_get_prefixlen; + nl_addr_guess_family; + nl_addr_info; + nl_addr_iszero; + nl_addr_parse; + nl_addr_put; + nl_addr_resolve; + nl_addr_set_binary_addr; + nl_addr_set_family; + nl_addr_set_prefixlen; + nl_addr_shared; + nl_addr_valid; + nl_af2str; + nl_auto_complete; + nl_cache_add; + nl_cache_alloc; + nl_cache_alloc_and_fill; + nl_cache_alloc_name; + nl_cache_clear; + nl_cache_clone; + nl_cache_dump; + nl_cache_dump_filter; + nl_cache_find; + nl_cache_foreach; + nl_cache_foreach_filter; + nl_cache_free; + nl_cache_get; + nl_cache_get_first; + nl_cache_get_last; + nl_cache_get_next; + nl_cache_get_ops; + nl_cache_get_prev; + nl_cache_include; + nl_cache_is_empty; + nl_cache_mark_all; + nl_cache_mngr_add; + nl_cache_mngr_add_cache; + nl_cache_mngr_alloc; + nl_cache_mngr_data_ready; + nl_cache_mngr_free; + nl_cache_mngr_get_fd; + nl_cache_mngr_info; + nl_cache_mngr_poll; + nl_cache_mngt_provide; + nl_cache_mngt_register; + nl_cache_mngt_require; + nl_cache_mngt_require_safe; + nl_cache_mngt_unprovide; + nl_cache_mngt_unregister; + nl_cache_move; + nl_cache_nitems; + nl_cache_nitems_filter; + nl_cache_ops_associate; + nl_cache_ops_associate_safe; + nl_cache_ops_foreach; + nl_cache_ops_get; + nl_cache_ops_lookup; + nl_cache_ops_lookup_safe; + nl_cache_ops_put; + nl_cache_ops_set_flags; + nl_cache_parse_and_add; + nl_cache_pickup; + nl_cache_put; + nl_cache_refill; + nl_cache_remove; + nl_cache_resync; + nl_cache_search; + nl_cache_set_arg1; + nl_cache_set_arg2; + nl_cache_set_flags; + nl_cache_subset; + nl_cancel_down_bits; + nl_cancel_down_bytes; + nl_cancel_down_us; + nl_cb_active_type; + nl_cb_alloc; + nl_cb_clone; + nl_cb_err; + nl_cb_get; + nl_cb_overwrite_recv; + nl_cb_overwrite_recvmsgs; + nl_cb_overwrite_send; + nl_cb_put; + nl_cb_set; + nl_cb_set_all; + nl_close; + nl_complete_msg; + nl_connect; + nl_data_alloc; + nl_data_alloc_attr; + nl_data_append; + nl_data_clone; + nl_data_cmp; + nl_data_free; + nl_data_get; + nl_data_get_size; + nl_dump; + nl_dump_line; + nl_ether_proto2str; + nl_get_psched_hz; + nl_get_user_hz; + nl_geterror; + nl_has_capability; + nl_hash; + nl_hash_any; + nl_hash_table_add; + nl_hash_table_alloc; + nl_hash_table_del; + nl_hash_table_free; + nl_hash_table_lookup; + nl_ip_proto2str; + nl_join_groups; + nl_llproto2str; + nl_msec2str; + nl_msg_dump; + nl_msg_parse; + nl_msgtype_lookup; + nl_new_line; + nl_nlfamily2str; + nl_nlmsg_flags2str; + nl_nlmsgtype2str; + nl_object_alloc; + nl_object_alloc_name; + nl_object_attr_list; + nl_object_attrs2str; + nl_object_clone; + nl_object_diff; + nl_object_dump; + nl_object_dump_buf; + nl_object_free; + nl_object_get; + nl_object_get_cache; + nl_object_get_id_attrs; + nl_object_get_msgtype; + nl_object_get_ops; + nl_object_get_refcnt; + nl_object_get_type; + nl_object_identical; + nl_object_is_marked; + nl_object_keygen; + nl_object_mark; + nl_object_match_filter; + nl_object_put; + nl_object_shared; + nl_object_unmark; + nl_object_update; + nl_perror; + nl_pickup; + nl_prob2int; + nl_rate2str; + nl_recv; + nl_recvmsgs; + nl_recvmsgs_default; + nl_recvmsgs_report; + nl_send; + nl_send_auto; + nl_send_auto_complete; + nl_send_iovec; + nl_send_simple; + nl_send_sync; + nl_sendmsg; + nl_sendto; + nl_size2int; + nl_size2str; + nl_socket_add_membership; + nl_socket_add_memberships; + nl_socket_alloc; + nl_socket_alloc_cb; + nl_socket_disable_auto_ack; + nl_socket_disable_msg_peek; + nl_socket_disable_seq_check; + nl_socket_drop_membership; + nl_socket_drop_memberships; + nl_socket_enable_auto_ack; + nl_socket_enable_msg_peek; + nl_socket_free; + nl_socket_get_cb; + nl_socket_get_fd; + nl_socket_get_local_port; + nl_socket_get_msg_buf_size; + nl_socket_get_peer_groups; + nl_socket_get_peer_port; + nl_socket_modify_cb; + nl_socket_modify_err_cb; + nl_socket_recv_pktinfo; + nl_socket_set_buffer_size; + nl_socket_set_cb; + nl_socket_set_local_port; + nl_socket_set_msg_buf_size; + nl_socket_set_nonblocking; + nl_socket_set_passcred; + nl_socket_set_peer_groups; + nl_socket_set_peer_port; + nl_socket_use_seq; + nl_str2af; + nl_str2ether_proto; + nl_str2ip_proto; + nl_str2llproto; + nl_str2msec; + nl_str2nlfamily; + nl_str2nlmsgtype; + nl_syserr2nlerr; + nl_ticks2us; + nl_us2ticks; + nl_ver_maj; + nl_ver_mic; + nl_ver_min; + nl_ver_num; + nl_wait_for_ack; + nla_attr_size; + nla_data; + nla_find; + nla_get_flag; + nla_get_msecs; + nla_get_string; + nla_get_u16; + nla_get_u32; + nla_get_u64; + nla_get_u8; + nla_is_nested; + nla_len; + nla_memcmp; + nla_memcpy; + nla_nest_cancel; + nla_nest_end; + nla_nest_start; + nla_next; + nla_ok; + nla_padlen; + nla_parse; + nla_parse_nested; + nla_put; + nla_put_addr; + nla_put_data; + nla_put_flag; + nla_put_msecs; + nla_put_nested; + nla_put_string; + nla_put_u16; + nla_put_u32; + nla_put_u64; + nla_put_u8; + nla_reserve; + nla_strcmp; + nla_strdup; + nla_strlcpy; + nla_total_size; + nla_type; + nla_validate; + nlmsg_alloc; + nlmsg_alloc_simple; + nlmsg_alloc_size; + nlmsg_append; + nlmsg_attrdata; + nlmsg_attrlen; + nlmsg_convert; + nlmsg_data; + nlmsg_datalen; + nlmsg_expand; + nlmsg_find_attr; + nlmsg_free; + nlmsg_get; + nlmsg_get_creds; + nlmsg_get_dst; + nlmsg_get_max_size; + nlmsg_get_proto; + nlmsg_get_src; + nlmsg_hdr; + nlmsg_inherit; + nlmsg_next; + nlmsg_ok; + nlmsg_padlen; + nlmsg_parse; + nlmsg_put; + nlmsg_reserve; + nlmsg_set_creds; + nlmsg_set_default_size; + nlmsg_set_dst; + nlmsg_set_proto; + nlmsg_set_src; + nlmsg_size; + nlmsg_tail; + nlmsg_total_size; + nlmsg_valid_hdr; + nlmsg_validate; + + # The following symbols were added during the development of 3.2.26. + # Keep them in libnl_3 to avoid breaking users. + nl_cache_pickup_checkdup; + nl_pickup_keep_syserr; + +local: + *; +}; + +libnl_3_2_26 { +global: + nl_socket_set_fd; +} libnl_3; + +libnl_3_2_27 { +global: + nla_get_s8; + nla_put_s8; + nla_get_s16; + nla_put_s16; + nla_get_s32; + nla_put_s32; + nla_get_s64; + nla_put_s64; +} libnl_3_2_26; + +libnl_3_2_28 { +global: + nl_object_diff64; +} libnl_3_2_27; + +libnl_3_2_29 { +global: + nl_cache_include_v2; + nl_cache_mngr_add_cache_v2; + nl_strerror_l; +} libnl_3_2_28; + +libnl_3_5 { +global: + nla_nest_end_keep_empty; +} libnl_3_2_29; + +libnl_3_6 { +} libnl_3_5; diff --git a/libnl-cli-3.sym b/libnl-cli-3.sym new file mode 100644 index 0000000..75f03cd --- /dev/null +++ b/libnl-cli-3.sym @@ -0,0 +1,129 @@ +# The linker version script controls which symbols are exported. +# Version tags that correspond to past releases group the symbols +# that were part of that release. Hence, such a version tag is sealed +# and MUST not be extended. +# Any new symbols MUST only be added to the bottom of the file, in +# the version tag for the next upcoming release. +libnl_3 { +global: + nl_cli_addr_alloc; + nl_cli_addr_parse; + nl_cli_addr_parse_broadcast; + nl_cli_addr_parse_dev; + nl_cli_addr_parse_family; + nl_cli_addr_parse_label; + nl_cli_addr_parse_local; + nl_cli_addr_parse_peer; + nl_cli_addr_parse_preferred; + nl_cli_addr_parse_scope; + nl_cli_addr_parse_valid; + nl_cli_alloc_cache; + nl_cli_alloc_socket; + nl_cli_class_alloc; + nl_cli_class_alloc_cache; + nl_cli_cls_alloc; + nl_cli_cls_alloc_cache; + nl_cli_cls_parse_ematch; + nl_cli_cls_parse_proto; + nl_cli_confirm; + nl_cli_connect; + nl_cli_ct_alloc; + nl_cli_ct_alloc_cache; + nl_cli_ct_parse_dst; + nl_cli_ct_parse_dst_port; + nl_cli_ct_parse_family; + nl_cli_ct_parse_id; + nl_cli_ct_parse_mark; + nl_cli_ct_parse_protocol; + nl_cli_ct_parse_src; + nl_cli_ct_parse_src_port; + nl_cli_ct_parse_status; + nl_cli_ct_parse_tcp_state; + nl_cli_ct_parse_timeout; + nl_cli_ct_parse_use; + nl_cli_ct_parse_zone; + nl_cli_exp_alloc; + nl_cli_exp_alloc_cache; + nl_cli_exp_parse_class; + nl_cli_exp_parse_dst; + nl_cli_exp_parse_dst_port; + nl_cli_exp_parse_family; + nl_cli_exp_parse_flags; + nl_cli_exp_parse_fn; + nl_cli_exp_parse_helper_name; + nl_cli_exp_parse_icmp_code; + nl_cli_exp_parse_icmp_id; + nl_cli_exp_parse_icmp_type; + nl_cli_exp_parse_id; + nl_cli_exp_parse_l4protonum; + nl_cli_exp_parse_nat_dir; + nl_cli_exp_parse_src; + nl_cli_exp_parse_src_port; + nl_cli_exp_parse_timeout; + nl_cli_exp_parse_zone; + nl_cli_fatal; + nl_cli_link_alloc; + nl_cli_link_alloc_cache; + nl_cli_link_alloc_cache_family; + nl_cli_link_parse_family; + nl_cli_link_parse_ifalias; + nl_cli_link_parse_ifindex; + nl_cli_link_parse_mtu; + nl_cli_link_parse_name; + nl_cli_link_parse_txqlen; + nl_cli_link_parse_weight; + nl_cli_load_module; + nl_cli_neigh_alloc; + nl_cli_neigh_parse_dev; + nl_cli_neigh_parse_dst; + nl_cli_neigh_parse_family; + nl_cli_neigh_parse_lladdr; + nl_cli_neigh_parse_state; + nl_cli_parse_dumptype; + nl_cli_parse_u32; + nl_cli_print_version; + nl_cli_qdisc_alloc; + nl_cli_route_alloc; + nl_cli_route_alloc_cache; + nl_cli_route_parse_dst; + nl_cli_route_parse_family; + nl_cli_route_parse_iif; + nl_cli_route_parse_metric; + nl_cli_route_parse_nexthop; + nl_cli_route_parse_pref_src; + nl_cli_route_parse_prio; + nl_cli_route_parse_protocol; + nl_cli_route_parse_scope; + nl_cli_route_parse_src; + nl_cli_route_parse_table; + nl_cli_route_parse_type; + nl_cli_rule_alloc; + nl_cli_rule_alloc_cache; + nl_cli_rule_parse_family; + nl_cli_tc_lookup; + nl_cli_tc_parse_dev; + nl_cli_tc_parse_handle; + nl_cli_tc_parse_kind; + nl_cli_tc_parse_linktype; + nl_cli_tc_parse_mpu; + nl_cli_tc_parse_mtu; + nl_cli_tc_parse_overhead; + nl_cli_tc_parse_parent; + nl_cli_tc_register; + nl_cli_tc_unregister; +local: + *; +}; + +libnl_3_2_28 { +global: + nl_cli_alloc_cache_flags; + nl_cli_link_alloc_cache_flags; + nl_cli_link_alloc_cache_family_flags; +} libnl_3; + +libnl_3_8 { +global: + nl_cli_nh_alloc; + nl_cli_nh_alloc_cache; +} libnl_3_2_28; diff --git a/libnl-genl-3.sym b/libnl-genl-3.sym new file mode 100644 index 0000000..1b26127 --- /dev/null +++ b/libnl-genl-3.sym @@ -0,0 +1,57 @@ +# The linker version script controls which symbols are exported. +# Version tags that correspond to past releases group the symbols +# that were part of that release. Hence, such a version tag is sealed +# and MUST not be extended. +# Any new symbols MUST only be added to the bottom of the file, in +# the version tag for the next upcoming release. +libnl_3 { +global: + # these functions are in private header files and should have never + # been exported. We might hide them later. + genl_resolve_id; + + genl_connect; + genl_ctrl_alloc_cache; + genl_ctrl_resolve; + genl_ctrl_resolve_grp; + genl_ctrl_search; + genl_ctrl_search_by_name; + genl_family_add_grp; + genl_family_add_op; + genl_family_alloc; + genl_family_get_hdrsize; + genl_family_get_id; + genl_family_get_maxattr; + genl_family_get_name; + genl_family_get_version; + genl_family_ops; + genl_family_put; + genl_family_set_hdrsize; + genl_family_set_id; + genl_family_set_maxattr; + genl_family_set_name; + genl_family_set_version; + genl_handle_msg; + genl_mngt_resolve; + genl_op2name; + genl_ops_resolve; + genl_register; + genl_register_family; + genl_send_simple; + genl_unregister; + genl_unregister_family; + genlmsg_attrdata; + genlmsg_attrlen; + genlmsg_data; + genlmsg_hdr; + genlmsg_len; + genlmsg_parse; + genlmsg_put; + genlmsg_user_data; + genlmsg_user_datalen; + genlmsg_user_hdr; + genlmsg_valid_hdr; + genlmsg_validate; +local: + *; +}; diff --git a/libnl-idiag-3.0.pc.in b/libnl-idiag-3.0.pc.in new file mode 100644 index 0000000..9ce5100 --- /dev/null +++ b/libnl-idiag-3.0.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libnl-idiag +Description: Netlink Inet Diag Family Library +Version: @PACKAGE_VERSION@ +Requires: libnl-3.0 +Libs: -L${libdir} -lnl-idiag-@MAJ_VERSION@ +Cflags: -I${includedir}/libnl@MAJ_VERSION@ + diff --git a/libnl-idiag-3.sym b/libnl-idiag-3.sym new file mode 100644 index 0000000..3391f19 --- /dev/null +++ b/libnl-idiag-3.sym @@ -0,0 +1,115 @@ +# The linker version script controls which symbols are exported. +# Version tags that correspond to past releases group the symbols +# that were part of that release. Hence, such a version tag is sealed +# and MUST not be extended. +# Any new symbols MUST only be added to the bottom of the file, in +# the version tag for the next upcoming release. +libnl_3 { +global: + # ops structure + idiagnl_meminfo_obj_ops; + idiagnl_msg_obj_ops; + idiagnl_req_obj_ops; + idiagnl_vegasinfo_obj_ops; + + idiagnl_attrs2str; + idiagnl_connect; + idiagnl_exts2str; + idiagnl_meminfo_alloc; + idiagnl_meminfo_get; + idiagnl_meminfo_get_fmem; + idiagnl_meminfo_get_rmem; + idiagnl_meminfo_get_tmem; + idiagnl_meminfo_get_wmem; + idiagnl_meminfo_put; + idiagnl_meminfo_set_fmem; + idiagnl_meminfo_set_rmem; + idiagnl_meminfo_set_tmem; + idiagnl_meminfo_set_wmem; + idiagnl_msg_alloc; + idiagnl_msg_alloc_cache; + idiagnl_msg_get; + idiagnl_msg_get_cong; + idiagnl_msg_get_dport; + idiagnl_msg_get_dst; + idiagnl_msg_get_expires; + idiagnl_msg_get_family; + idiagnl_msg_get_ifindex; + idiagnl_msg_get_inode; + idiagnl_msg_get_meminfo; + idiagnl_msg_get_retrans; + idiagnl_msg_get_rqueue; + idiagnl_msg_get_shutdown; + idiagnl_msg_get_sport; + idiagnl_msg_get_src; + idiagnl_msg_get_state; + idiagnl_msg_get_tclass; + idiagnl_msg_get_tcpinfo; + idiagnl_msg_get_timer; + idiagnl_msg_get_tos; + idiagnl_msg_get_uid; + idiagnl_msg_get_vegasinfo; + idiagnl_msg_get_wqueue; + idiagnl_msg_parse; + idiagnl_msg_put; + idiagnl_msg_set_cong; + idiagnl_msg_set_dport; + idiagnl_msg_set_dst; + idiagnl_msg_set_expires; + idiagnl_msg_set_family; + idiagnl_msg_set_ifindex; + idiagnl_msg_set_inode; + idiagnl_msg_set_meminfo; + idiagnl_msg_set_retrans; + idiagnl_msg_set_rqueue; + idiagnl_msg_set_shutdown; + idiagnl_msg_set_sport; + idiagnl_msg_set_src; + idiagnl_msg_set_state; + idiagnl_msg_set_tclass; + idiagnl_msg_set_tcpinfo; + idiagnl_msg_set_timer; + idiagnl_msg_set_tos; + idiagnl_msg_set_uid; + idiagnl_msg_set_vegasinfo; + idiagnl_msg_set_wqueue; + idiagnl_req_alloc; + idiagnl_req_get; + idiagnl_req_get_dbs; + idiagnl_req_get_dst; + idiagnl_req_get_ext; + idiagnl_req_get_family; + idiagnl_req_get_ifindex; + idiagnl_req_get_src; + idiagnl_req_get_states; + idiagnl_req_parse; + idiagnl_req_put; + idiagnl_req_set_dbs; + idiagnl_req_set_dst; + idiagnl_req_set_ext; + idiagnl_req_set_family; + idiagnl_req_set_ifindex; + idiagnl_req_set_src; + idiagnl_req_set_states; + idiagnl_send_simple; + idiagnl_shutdown2str; + idiagnl_state2str; + idiagnl_str2state; + idiagnl_str2timer; + idiagnl_tcpopts2str; + idiagnl_tcpstate2str; + idiagnl_timer2str; + idiagnl_vegasinfo_alloc; + idiagnl_vegasinfo_get; + idiagnl_vegasinfo_get_enabled; + idiagnl_vegasinfo_get_minrtt; + idiagnl_vegasinfo_get_rtt; + idiagnl_vegasinfo_get_rttcnt; + idiagnl_vegasinfo_put; + idiagnl_vegasinfo_set_enabled; + idiagnl_vegasinfo_set_minrtt; + idiagnl_vegasinfo_set_rtt; + idiagnl_vegasinfo_set_rttcnt; +local: + *; +}; diff --git a/libnl-nf-3.sym b/libnl-nf-3.sym new file mode 100644 index 0000000..7563624 --- /dev/null +++ b/libnl-nf-3.sym @@ -0,0 +1,351 @@ +# The linker version script controls which symbols are exported. +# Version tags that correspond to past releases group the symbols +# that were part of that release. Hence, such a version tag is sealed +# and MUST not be extended. +# Any new symbols MUST only be added to the bottom of the file, in +# the version tag for the next upcoming release. +libnl_3 { +global: + # ops structure + ct_obj_ops; + exp_obj_ops; + log_msg_obj_ops; + log_obj_ops; + queue_msg_obj_ops; + queue_obj_ops; + + nfnl_connect; + nfnl_ct_add; + nfnl_ct_alloc; + nfnl_ct_alloc_cache; + nfnl_ct_build_add_request; + nfnl_ct_build_delete_request; + nfnl_ct_build_query_request; + nfnl_ct_del; + nfnl_ct_dump_request; + nfnl_ct_get; + nfnl_ct_get_bytes; + nfnl_ct_get_dst; + nfnl_ct_get_dst_port; + nfnl_ct_get_family; + nfnl_ct_get_icmp_code; + nfnl_ct_get_icmp_id; + nfnl_ct_get_icmp_type; + nfnl_ct_get_id; + nfnl_ct_get_mark; + nfnl_ct_get_packets; + nfnl_ct_get_proto; + nfnl_ct_get_src; + nfnl_ct_get_src_port; + nfnl_ct_get_status; + nfnl_ct_get_tcp_state; + nfnl_ct_get_timeout; + nfnl_ct_get_timestamp; + nfnl_ct_get_use; + nfnl_ct_get_zone; + nfnl_ct_put; + nfnl_ct_query; + nfnl_ct_set_bytes; + nfnl_ct_set_dst; + nfnl_ct_set_dst_port; + nfnl_ct_set_family; + nfnl_ct_set_icmp_code; + nfnl_ct_set_icmp_id; + nfnl_ct_set_icmp_type; + nfnl_ct_set_id; + nfnl_ct_set_mark; + nfnl_ct_set_packets; + nfnl_ct_set_proto; + nfnl_ct_set_src; + nfnl_ct_set_src_port; + nfnl_ct_set_status; + nfnl_ct_set_tcp_state; + nfnl_ct_set_timeout; + nfnl_ct_set_timestamp; + nfnl_ct_set_use; + nfnl_ct_set_zone; + nfnl_ct_status2str; + nfnl_ct_str2status; + nfnl_ct_str2tcp_state; + nfnl_ct_tcp_state2str; + nfnl_ct_test_bytes; + nfnl_ct_test_dst_port; + nfnl_ct_test_icmp_code; + nfnl_ct_test_icmp_id; + nfnl_ct_test_icmp_type; + nfnl_ct_test_id; + nfnl_ct_test_mark; + nfnl_ct_test_packets; + nfnl_ct_test_proto; + nfnl_ct_test_src_port; + nfnl_ct_test_status; + nfnl_ct_test_tcp_state; + nfnl_ct_test_timeout; + nfnl_ct_test_timestamp; + nfnl_ct_test_use; + nfnl_ct_test_zone; + nfnl_ct_unset_status; + nfnl_exp_add; + nfnl_exp_alloc; + nfnl_exp_alloc_cache; + nfnl_exp_build_add_request; + nfnl_exp_build_delete_request; + nfnl_exp_build_query_request; + nfnl_exp_del; + nfnl_exp_dump_request; + nfnl_exp_flags2str; + nfnl_exp_get; + nfnl_exp_get_class; + nfnl_exp_get_dst; + nfnl_exp_get_dst_port; + nfnl_exp_get_family; + nfnl_exp_get_flags; + nfnl_exp_get_fn; + nfnl_exp_get_helper_name; + nfnl_exp_get_icmp_code; + nfnl_exp_get_icmp_id; + nfnl_exp_get_icmp_type; + nfnl_exp_get_id; + nfnl_exp_get_l4protonum; + nfnl_exp_get_nat_dir; + nfnl_exp_get_src; + nfnl_exp_get_src_port; + nfnl_exp_get_timeout; + nfnl_exp_get_zone; + nfnl_exp_put; + nfnl_exp_query; + nfnl_exp_set_class; + nfnl_exp_set_dst; + nfnl_exp_set_family; + nfnl_exp_set_flags; + nfnl_exp_set_fn; + nfnl_exp_set_helper_name; + nfnl_exp_set_icmp; + nfnl_exp_set_id; + nfnl_exp_set_l4protonum; + nfnl_exp_set_nat_dir; + nfnl_exp_set_ports; + nfnl_exp_set_src; + nfnl_exp_set_timeout; + nfnl_exp_set_zone; + nfnl_exp_str2flags; + nfnl_exp_test_class; + nfnl_exp_test_dst; + nfnl_exp_test_flags; + nfnl_exp_test_fn; + nfnl_exp_test_helper_name; + nfnl_exp_test_icmp; + nfnl_exp_test_id; + nfnl_exp_test_l4protonum; + nfnl_exp_test_nat_dir; + nfnl_exp_test_ports; + nfnl_exp_test_src; + nfnl_exp_test_timeout; + nfnl_exp_test_zone; + nfnl_exp_unset_flags; + nfnl_inet_hook2str; + nfnl_log_alloc; + nfnl_log_build_change_request; + nfnl_log_build_create_request; + nfnl_log_build_delete_request; + nfnl_log_build_pf_bind; + nfnl_log_build_pf_unbind; + nfnl_log_change; + nfnl_log_copy_mode2str; + nfnl_log_create; + nfnl_log_delete; + nfnl_log_flags2str; + nfnl_log_get; + nfnl_log_get_alloc_size; + nfnl_log_get_copy_mode; + nfnl_log_get_copy_range; + nfnl_log_get_flush_timeout; + nfnl_log_get_group; + nfnl_log_get_queue_threshold; + nfnl_log_msg_alloc; + nfnl_log_msg_get; + nfnl_log_msg_get_family; + nfnl_log_msg_get_gid; + nfnl_log_msg_get_hook; + nfnl_log_msg_get_hwaddr; + nfnl_log_msg_get_hwproto; + nfnl_log_msg_get_indev; + nfnl_log_msg_get_mark; + nfnl_log_msg_get_outdev; + nfnl_log_msg_get_payload; + nfnl_log_msg_get_physindev; + nfnl_log_msg_get_physoutdev; + nfnl_log_msg_get_prefix; + nfnl_log_msg_get_seq; + nfnl_log_msg_get_seq_global; + nfnl_log_msg_get_timestamp; + nfnl_log_msg_get_uid; + nfnl_log_msg_put; + nfnl_log_msg_set_family; + nfnl_log_msg_set_gid; + nfnl_log_msg_set_hook; + nfnl_log_msg_set_hwaddr; + nfnl_log_msg_set_hwproto; + nfnl_log_msg_set_indev; + nfnl_log_msg_set_mark; + nfnl_log_msg_set_outdev; + nfnl_log_msg_set_payload; + nfnl_log_msg_set_physindev; + nfnl_log_msg_set_physoutdev; + nfnl_log_msg_set_prefix; + nfnl_log_msg_set_seq; + nfnl_log_msg_set_seq_global; + nfnl_log_msg_set_timestamp; + nfnl_log_msg_set_uid; + nfnl_log_msg_test_gid; + nfnl_log_msg_test_hook; + nfnl_log_msg_test_hwproto; + nfnl_log_msg_test_mark; + nfnl_log_msg_test_seq; + nfnl_log_msg_test_seq_global; + nfnl_log_msg_test_uid; + nfnl_log_pf_bind; + nfnl_log_pf_unbind; + nfnl_log_put; + nfnl_log_set_alloc_size; + nfnl_log_set_copy_mode; + nfnl_log_set_copy_range; + nfnl_log_set_flags; + nfnl_log_set_flush_timeout; + nfnl_log_set_group; + nfnl_log_set_queue_threshold; + nfnl_log_str2copy_mode; + nfnl_log_str2flags; + nfnl_log_test_alloc_size; + nfnl_log_test_copy_mode; + nfnl_log_test_copy_range; + nfnl_log_test_flush_timeout; + nfnl_log_test_group; + nfnl_log_test_queue_threshold; + nfnl_log_unset_flags; + nfnl_queue_alloc; + nfnl_queue_build_change_request; + nfnl_queue_build_create_request; + nfnl_queue_build_delete_request; + nfnl_queue_build_pf_bind; + nfnl_queue_build_pf_unbind; + nfnl_queue_change; + nfnl_queue_copy_mode2str; + nfnl_queue_create; + nfnl_queue_delete; + nfnl_queue_get; + nfnl_queue_get_copy_mode; + nfnl_queue_get_copy_range; + nfnl_queue_get_group; + nfnl_queue_get_maxlen; + nfnl_queue_msg_alloc; + nfnl_queue_msg_build_verdict; + nfnl_queue_msg_build_verdict_batch; + nfnl_queue_msg_get; + nfnl_queue_msg_get_family; + nfnl_queue_msg_get_group; + nfnl_queue_msg_get_hook; + nfnl_queue_msg_get_hwaddr; + nfnl_queue_msg_get_hwproto; + nfnl_queue_msg_get_indev; + nfnl_queue_msg_get_mark; + nfnl_queue_msg_get_outdev; + nfnl_queue_msg_get_packetid; + nfnl_queue_msg_get_payload; + nfnl_queue_msg_get_physindev; + nfnl_queue_msg_get_physoutdev; + nfnl_queue_msg_get_timestamp; + nfnl_queue_msg_get_verdict; + nfnl_queue_msg_put; + nfnl_queue_msg_send_verdict; + nfnl_queue_msg_send_verdict_batch; + nfnl_queue_msg_send_verdict_payload; + nfnl_queue_msg_set_family; + nfnl_queue_msg_set_group; + nfnl_queue_msg_set_hook; + nfnl_queue_msg_set_hwaddr; + nfnl_queue_msg_set_hwproto; + nfnl_queue_msg_set_indev; + nfnl_queue_msg_set_mark; + nfnl_queue_msg_set_outdev; + nfnl_queue_msg_set_packetid; + nfnl_queue_msg_set_payload; + nfnl_queue_msg_set_physindev; + nfnl_queue_msg_set_physoutdev; + nfnl_queue_msg_set_timestamp; + nfnl_queue_msg_set_verdict; + nfnl_queue_msg_test_family; + nfnl_queue_msg_test_group; + nfnl_queue_msg_test_hook; + nfnl_queue_msg_test_hwaddr; + nfnl_queue_msg_test_hwproto; + nfnl_queue_msg_test_indev; + nfnl_queue_msg_test_mark; + nfnl_queue_msg_test_outdev; + nfnl_queue_msg_test_packetid; + nfnl_queue_msg_test_payload; + nfnl_queue_msg_test_physindev; + nfnl_queue_msg_test_physoutdev; + nfnl_queue_msg_test_timestamp; + nfnl_queue_msg_test_verdict; + nfnl_queue_pf_bind; + nfnl_queue_pf_unbind; + nfnl_queue_put; + nfnl_queue_set_copy_mode; + nfnl_queue_set_copy_range; + nfnl_queue_set_group; + nfnl_queue_set_maxlen; + nfnl_queue_socket_alloc; + nfnl_queue_str2copy_mode; + nfnl_queue_test_copy_mode; + nfnl_queue_test_copy_range; + nfnl_queue_test_group; + nfnl_queue_test_maxlen; + nfnl_send_simple; + nfnl_str2inet_hook; + nfnl_str2verdict; + nfnl_verdict2str; + nfnlmsg_alloc_simple; + nfnlmsg_ct_group; + nfnlmsg_ct_parse; + nfnlmsg_exp_group; + nfnlmsg_exp_parse; + nfnlmsg_family; + nfnlmsg_log_msg_parse; + nfnlmsg_put; + nfnlmsg_queue_msg_parse; + nfnlmsg_res_id; + nfnlmsg_subsys; + nfnlmsg_subtype; +local: + *; +}; + +libnl_3_6 { +global: + nfnl_log_msg_get_ct; + nfnl_log_msg_get_ct_info; + nfnl_log_msg_get_hwheader; + nfnl_log_msg_get_hwlen; + nfnl_log_msg_get_hwtype; + nfnl_log_msg_get_vlan_cfi; + nfnl_log_msg_get_vlan_id; + nfnl_log_msg_get_vlan_prio; + nfnl_log_msg_get_vlan_proto; + nfnl_log_msg_get_vlan_tag; + nfnl_log_msg_set_ct; + nfnl_log_msg_set_ct_info; + nfnl_log_msg_set_hwheader; + nfnl_log_msg_set_hwlen; + nfnl_log_msg_set_hwtype; + nfnl_log_msg_set_vlan_proto; + nfnl_log_msg_set_vlan_tag; + nfnl_log_msg_test_ct; + nfnl_log_msg_test_ct_info; + nfnl_log_msg_test_hwheader; + nfnl_log_msg_test_hwlen; + nfnl_log_msg_test_hwtype; + nfnl_log_msg_test_vlan_proto; + nfnl_log_msg_test_vlan_tag; + nfnlmsg_ct_parse_nested; +} libnl_3; diff --git a/libnl-route-3.sym b/libnl-route-3.sym new file mode 100644 index 0000000..fa7af45 --- /dev/null +++ b/libnl-route-3.sym @@ -0,0 +1,1316 @@ +# The linker version script controls which symbols are exported. +# Version tags that correspond to past releases group the symbols +# that were part of that release. Hence, such a version tag is sealed +# and MUST not be extended. +# Any new symbols MUST only be added to the bottom of the file, in +# the version tag for the next upcoming release. +libnl_3 { +global: + # these functions are in private header files and should have never + # been exported. We might hide them later. + rtnl_link_af_alloc; + rtnl_link_af_data; + rtnl_link_af_data_compare; + rtnl_link_af_ops_lookup; + rtnl_link_af_ops_put; + rtnl_link_af_register; + rtnl_link_af_unregister; + rtnl_link_info_ops_lookup; + rtnl_link_info_ops_put; + rtnl_link_register_info; + rtnl_link_unregister_info; + + # these functions are in private header files and should have never + # been exported. + # declared in "lib/route/tc-api.h". + rtnl_tc_build_rate_table; + rtnl_tc_clone; + rtnl_tc_compare; + rtnl_tc_data; + rtnl_tc_data_check; + rtnl_tc_dump_details; + rtnl_tc_dump_line; + rtnl_tc_dump_stats; + rtnl_tc_free_data; + rtnl_tc_msg_build; + rtnl_tc_msg_parse; + rtnl_tc_register; + rtnl_tc_type_register; + rtnl_tc_type_unregister; + rtnl_tc_unregister; + + # these functions are in private header files and should have never + # been exported. They are used by libnl internals. + # declared in "include/nl-priv-dynamic-route/nl-priv-dynamic-route.h". + rtnl_tc_get_ops; + rtnl_tc_lookup_ops; + + # internal symbols that are in public headers + rtln_link_policy; + + # ops structure + route_obj_ops; + + flnl_lookup; + flnl_lookup_build_request; + flnl_request_alloc; + flnl_request_get_addr; + flnl_request_get_fwmark; + flnl_request_get_scope; + flnl_request_get_table; + flnl_request_get_tos; + flnl_request_set_addr; + flnl_request_set_fwmark; + flnl_request_set_scope; + flnl_request_set_table; + flnl_request_set_tos; + flnl_result_alloc; + flnl_result_alloc_cache; + flnl_result_get_error; + flnl_result_get_nexthop_sel; + flnl_result_get_prefixlen; + flnl_result_get_scope; + flnl_result_get_table_id; + flnl_result_get_type; + flnl_result_put; + nl_ovl_strategy2str; + nl_police2str; + nl_rtgen_request; + nl_rtntype2str; + nl_str2ovl_strategy; + nl_str2police; + nl_str2rtntype; + rtnl_act_add; + rtnl_act_alloc; + rtnl_act_append; + rtnl_act_build_add_request; + rtnl_act_build_change_request; + rtnl_act_build_delete_request; + rtnl_act_change; + rtnl_act_delete; + rtnl_act_fill; + rtnl_act_get; + rtnl_act_parse; + rtnl_act_put; + rtnl_act_put_all; + rtnl_act_remove; + rtnl_addr_add; + rtnl_addr_alloc; + rtnl_addr_alloc_cache; + rtnl_addr_build_add_request; + rtnl_addr_build_delete_request; + rtnl_addr_delete; + rtnl_addr_flags2str; + rtnl_addr_get; + rtnl_addr_get_anycast; + rtnl_addr_get_broadcast; + rtnl_addr_get_create_time; + rtnl_addr_get_family; + rtnl_addr_get_flags; + rtnl_addr_get_ifindex; + rtnl_addr_get_label; + rtnl_addr_get_last_update_time; + rtnl_addr_get_link; + rtnl_addr_get_local; + rtnl_addr_get_multicast; + rtnl_addr_get_peer; + rtnl_addr_get_preferred_lifetime; + rtnl_addr_get_prefixlen; + rtnl_addr_get_scope; + rtnl_addr_get_valid_lifetime; + rtnl_addr_put; + rtnl_addr_set_anycast; + rtnl_addr_set_broadcast; + rtnl_addr_set_family; + rtnl_addr_set_flags; + rtnl_addr_set_ifindex; + rtnl_addr_set_label; + rtnl_addr_set_link; + rtnl_addr_set_local; + rtnl_addr_set_multicast; + rtnl_addr_set_peer; + rtnl_addr_set_preferred_lifetime; + rtnl_addr_set_prefixlen; + rtnl_addr_set_scope; + rtnl_addr_set_valid_lifetime; + rtnl_addr_str2flags; + rtnl_addr_unset_flags; + rtnl_basic_add_action; + rtnl_basic_del_action; + rtnl_basic_get_ematch; + rtnl_basic_get_target; + rtnl_basic_set_ematch; + rtnl_basic_set_target; + rtnl_cgroup_get_ematch; + rtnl_cgroup_set_ematch; + rtnl_class_add; + rtnl_class_alloc; + rtnl_class_alloc_cache; + rtnl_class_build_add_request; + rtnl_class_build_delete_request; + rtnl_class_delete; + rtnl_class_dsmark_get_bitmask; + rtnl_class_dsmark_get_value; + rtnl_class_dsmark_set_bitmask; + rtnl_class_dsmark_set_value; + rtnl_class_foreach_child; + rtnl_class_foreach_cls; + rtnl_class_get; + rtnl_class_leaf_qdisc; + rtnl_class_put; + rtnl_classid_generate; + rtnl_cls_add; + rtnl_cls_alloc; + rtnl_cls_alloc_cache; + rtnl_cls_build_add_request; + rtnl_cls_build_change_request; + rtnl_cls_build_delete_request; + rtnl_cls_change; + rtnl_cls_delete; + rtnl_cls_get_prio; + rtnl_cls_get_protocol; + rtnl_cls_put; + rtnl_cls_set_prio; + rtnl_cls_set_protocol; + rtnl_ematch_add_child; + rtnl_ematch_alloc; + rtnl_ematch_cmp_get; + rtnl_ematch_cmp_set; + rtnl_ematch_data; + rtnl_ematch_fill_attr; + rtnl_ematch_free; + rtnl_ematch_get_flags; + rtnl_ematch_lookup_ops; + rtnl_ematch_lookup_ops_by_name; + rtnl_ematch_meta_set_lvalue; + rtnl_ematch_meta_set_operand; + rtnl_ematch_meta_set_rvalue; + rtnl_ematch_nbyte_get_layer; + rtnl_ematch_nbyte_get_len; + rtnl_ematch_nbyte_get_offset; + rtnl_ematch_nbyte_get_pattern; + rtnl_ematch_nbyte_set_offset; + rtnl_ematch_nbyte_set_pattern; + rtnl_ematch_offset2txt; + rtnl_ematch_opnd2txt; + rtnl_ematch_parse_attr; + rtnl_ematch_parse_expr; + rtnl_ematch_register; + rtnl_ematch_set_flags; + rtnl_ematch_set_kind; + rtnl_ematch_set_name; + rtnl_ematch_set_ops; + rtnl_ematch_text_get_algo; + rtnl_ematch_text_get_from_layer; + rtnl_ematch_text_get_from_offset; + rtnl_ematch_text_get_len; + rtnl_ematch_text_get_pattern; + rtnl_ematch_text_get_to_layer; + rtnl_ematch_text_get_to_offset; + rtnl_ematch_text_set_algo; + rtnl_ematch_text_set_from; + rtnl_ematch_text_set_pattern; + rtnl_ematch_text_set_to; + rtnl_ematch_tree_add; + rtnl_ematch_tree_alloc; + rtnl_ematch_tree_dump; + rtnl_ematch_tree_free; + rtnl_ematch_unlink; + rtnl_ematch_unset_flags; + rtnl_fw_set_classid; + rtnl_fw_set_mask; + rtnl_htb_get_cbuffer; + rtnl_htb_get_ceil; + rtnl_htb_get_defcls; + rtnl_htb_get_level; + rtnl_htb_get_prio; + rtnl_htb_get_quantum; + rtnl_htb_get_rate2quantum; + rtnl_htb_get_rate; + rtnl_htb_get_rbuffer; + rtnl_htb_set_cbuffer; + rtnl_htb_set_ceil; + rtnl_htb_set_defcls; + rtnl_htb_set_level; + rtnl_htb_set_prio; + rtnl_htb_set_quantum; + rtnl_htb_set_rate2quantum; + rtnl_htb_set_rate; + rtnl_htb_set_rbuffer; + rtnl_link_add; + rtnl_link_alloc; + rtnl_link_alloc_cache; + rtnl_link_bond_add; + rtnl_link_bond_alloc; + rtnl_link_bond_enslave; + rtnl_link_bond_enslave_ifindex; + rtnl_link_bond_release; + rtnl_link_bond_release_ifindex; + rtnl_link_bridge_add; + rtnl_link_bridge_alloc; + rtnl_link_bridge_flags2str; + rtnl_link_bridge_get_cost; + rtnl_link_bridge_get_flags; + rtnl_link_bridge_get_port_state; + rtnl_link_bridge_get_priority; + rtnl_link_bridge_has_ext_info; + rtnl_link_bridge_set_cost; + rtnl_link_bridge_set_flags; + rtnl_link_bridge_set_port_state; + rtnl_link_bridge_set_priority; + rtnl_link_bridge_str2flags; + rtnl_link_bridge_unset_flags; + rtnl_link_build_add_request; + rtnl_link_build_change_request; + rtnl_link_build_delete_request; + rtnl_link_build_get_request; + rtnl_link_can_berr; + rtnl_link_can_berr_rx; + rtnl_link_can_berr_tx; + rtnl_link_can_ctrlmode2str; + rtnl_link_can_freq; + rtnl_link_can_get_bitrate; + rtnl_link_can_get_bittiming; + rtnl_link_can_get_bt_const; + rtnl_link_can_get_ctrlmode; + rtnl_link_can_get_restart_ms; + rtnl_link_can_get_sample_point; + rtnl_link_can_restart; + rtnl_link_can_set_bitrate; + rtnl_link_can_set_bittiming; + rtnl_link_can_set_ctrlmode; + rtnl_link_can_set_restart_ms; + rtnl_link_can_set_sample_point; + rtnl_link_can_state; + rtnl_link_can_str2ctrlmode; + rtnl_link_can_unset_ctrlmode; + rtnl_link_carrier2str; + rtnl_link_change; + rtnl_link_delete; + rtnl_link_enslave; + rtnl_link_enslave_ifindex; + rtnl_link_fill_info; + rtnl_link_flags2str; + rtnl_link_get; + rtnl_link_get_addr; + rtnl_link_get_arptype; + rtnl_link_get_broadcast; + rtnl_link_get_by_name; + rtnl_link_get_carrier; + rtnl_link_get_family; + rtnl_link_get_flags; + rtnl_link_get_group; + rtnl_link_get_ifalias; + rtnl_link_get_ifindex; + rtnl_link_get_info_type; + rtnl_link_get_kernel; + rtnl_link_get_link; + rtnl_link_get_linkmode; + rtnl_link_get_master; + rtnl_link_get_mtu; + rtnl_link_get_name; + rtnl_link_get_ns_fd; + rtnl_link_get_ns_pid; + rtnl_link_get_num_rx_queues; + rtnl_link_get_num_tx_queues; + rtnl_link_get_num_vf; + rtnl_link_get_operstate; + rtnl_link_get_phys_port_id; + rtnl_link_get_pmtudisc; + rtnl_link_get_promiscuity; + rtnl_link_get_qdisc; + rtnl_link_get_stat; + rtnl_link_get_txqlen; + rtnl_link_get_type; + rtnl_link_get_weight; + rtnl_link_i2name; + rtnl_link_inet_devconf2str; + rtnl_link_inet_get_conf; + rtnl_link_inet_set_conf; + rtnl_link_inet_str2devconf; + rtnl_link_info_parse; + rtnl_link_ip6_tnl_add; + rtnl_link_ip6_tnl_alloc; + rtnl_link_ip6_tnl_get_encaplimit; + rtnl_link_ip6_tnl_get_flags; + rtnl_link_ip6_tnl_get_flowinfo; + rtnl_link_ip6_tnl_get_link; + rtnl_link_ip6_tnl_get_local; + rtnl_link_ip6_tnl_get_proto; + rtnl_link_ip6_tnl_get_remote; + rtnl_link_ip6_tnl_get_tos; + rtnl_link_ip6_tnl_get_ttl; + rtnl_link_ip6_tnl_set_encaplimit; + rtnl_link_ip6_tnl_set_flags; + rtnl_link_ip6_tnl_set_flowinfo; + rtnl_link_ip6_tnl_set_link; + rtnl_link_ip6_tnl_set_local; + rtnl_link_ip6_tnl_set_proto; + rtnl_link_ip6_tnl_set_remote; + rtnl_link_ip6_tnl_set_tos; + rtnl_link_ip6_tnl_set_ttl; + rtnl_link_ipgre_add; + rtnl_link_ipgre_alloc; + rtnl_link_ipgre_get_iflags; + rtnl_link_ipgre_get_ikey; + rtnl_link_ipgre_get_link; + rtnl_link_ipgre_get_local; + rtnl_link_ipgre_get_oflags; + rtnl_link_ipgre_get_okey; + rtnl_link_ipgre_get_remote; + rtnl_link_ipgre_get_tos; + rtnl_link_ipgre_get_ttl; + rtnl_link_ipgre_set_iflags; + rtnl_link_ipgre_set_ikey; + rtnl_link_ipgre_set_link; + rtnl_link_ipgre_set_local; + rtnl_link_ipgre_set_oflags; + rtnl_link_ipgre_set_okey; + rtnl_link_ipgre_set_pmtudisc; + rtnl_link_ipgre_set_remote; + rtnl_link_ipgre_set_tos; + rtnl_link_ipgre_set_ttl; + rtnl_link_ipip_add; + rtnl_link_ipip_alloc; + rtnl_link_ipip_get_link; + rtnl_link_ipip_get_local; + rtnl_link_ipip_get_pmtudisc; + rtnl_link_ipip_get_remote; + rtnl_link_ipip_get_tos; + rtnl_link_ipip_get_ttl; + rtnl_link_ipip_set_link; + rtnl_link_ipip_set_local; + rtnl_link_ipip_set_pmtudisc; + rtnl_link_ipip_set_remote; + rtnl_link_ipip_set_tos; + rtnl_link_ipip_set_ttl; + rtnl_link_ipvti_add; + rtnl_link_ipvti_alloc; + rtnl_link_ipvti_get_ikey; + rtnl_link_ipvti_get_link; + rtnl_link_ipvti_get_local; + rtnl_link_ipvti_get_okey; + rtnl_link_ipvti_get_remote; + rtnl_link_ipvti_set_ikey; + rtnl_link_ipvti_set_link; + rtnl_link_ipvti_set_local; + rtnl_link_ipvti_set_okey; + rtnl_link_ipvti_set_remote; + rtnl_link_is_bridge; + rtnl_link_is_can; + rtnl_link_is_ip6_tnl; + rtnl_link_is_ipgre; + rtnl_link_is_ipip; + rtnl_link_is_ipvti; + rtnl_link_is_macvlan; + rtnl_link_is_sit; + rtnl_link_is_veth; + rtnl_link_is_vlan; + rtnl_link_is_vxlan; + rtnl_link_macvlan_alloc; + rtnl_link_macvlan_flags2str; + rtnl_link_macvlan_get_flags; + rtnl_link_macvlan_get_mode; + rtnl_link_macvlan_mode2str; + rtnl_link_macvlan_set_flags; + rtnl_link_macvlan_set_mode; + rtnl_link_macvlan_str2flags; + rtnl_link_macvlan_str2mode; + rtnl_link_macvlan_unset_flags; + rtnl_link_mode2str; + rtnl_link_name2i; + rtnl_link_operstate2str; + rtnl_link_put; + rtnl_link_release; + rtnl_link_release_ifindex; + rtnl_link_set_addr; + rtnl_link_set_arptype; + rtnl_link_set_broadcast; + rtnl_link_set_carrier; + rtnl_link_set_family; + rtnl_link_set_flags; + rtnl_link_set_group; + rtnl_link_set_ifalias; + rtnl_link_set_ifindex; + rtnl_link_set_info_type; + rtnl_link_set_link; + rtnl_link_set_linkmode; + rtnl_link_set_master; + rtnl_link_set_mtu; + rtnl_link_set_name; + rtnl_link_set_ns_fd; + rtnl_link_set_ns_pid; + rtnl_link_set_num_rx_queues; + rtnl_link_set_num_tx_queues; + rtnl_link_set_operstate; + rtnl_link_set_promiscuity; + rtnl_link_set_qdisc; + rtnl_link_set_stat; + rtnl_link_set_txqlen; + rtnl_link_set_type; + rtnl_link_set_weight; + rtnl_link_sit_add; + rtnl_link_sit_alloc; + rtnl_link_sit_get_flags; + rtnl_link_sit_get_link; + rtnl_link_sit_get_local; + rtnl_link_sit_get_pmtudisc; + rtnl_link_sit_get_proto; + rtnl_link_sit_get_remote; + rtnl_link_sit_get_tos; + rtnl_link_sit_get_ttl; + rtnl_link_sit_set_flags; + rtnl_link_sit_set_link; + rtnl_link_sit_set_local; + rtnl_link_sit_set_pmtudisc; + rtnl_link_sit_set_proto; + rtnl_link_sit_set_remote; + rtnl_link_sit_set_tos; + rtnl_link_sit_set_ttl; + rtnl_link_stat2str; + rtnl_link_str2carrier; + rtnl_link_str2flags; + rtnl_link_str2mode; + rtnl_link_str2operstate; + rtnl_link_str2stat; + rtnl_link_unset_flags; + rtnl_link_veth_add; + rtnl_link_veth_alloc; + rtnl_link_veth_get_peer; + rtnl_link_veth_release; + rtnl_link_vlan_alloc; + rtnl_link_vlan_flags2str; + rtnl_link_vlan_get_egress_map; + rtnl_link_vlan_get_flags; + rtnl_link_vlan_get_id; + rtnl_link_vlan_get_ingress_map; + rtnl_link_vlan_get_protocol; + rtnl_link_vlan_set_egress_map; + rtnl_link_vlan_set_flags; + rtnl_link_vlan_set_id; + rtnl_link_vlan_set_ingress_map; + rtnl_link_vlan_set_protocol; + rtnl_link_vlan_str2flags; + rtnl_link_vlan_unset_flags; + rtnl_link_vxlan_alloc; + rtnl_link_vxlan_disable_l2miss; + rtnl_link_vxlan_disable_l3miss; + rtnl_link_vxlan_disable_learning; + rtnl_link_vxlan_disable_proxy; + rtnl_link_vxlan_disable_rsc; + rtnl_link_vxlan_enable_l2miss; + rtnl_link_vxlan_enable_l3miss; + rtnl_link_vxlan_enable_learning; + rtnl_link_vxlan_enable_proxy; + rtnl_link_vxlan_enable_rsc; + rtnl_link_vxlan_get_ageing; + rtnl_link_vxlan_get_group; + rtnl_link_vxlan_get_id; + rtnl_link_vxlan_get_l2miss; + rtnl_link_vxlan_get_l3miss; + rtnl_link_vxlan_get_learning; + rtnl_link_vxlan_get_limit; + rtnl_link_vxlan_get_link; + rtnl_link_vxlan_get_local; + rtnl_link_vxlan_get_port_range; + rtnl_link_vxlan_get_proxy; + rtnl_link_vxlan_get_rsc; + rtnl_link_vxlan_get_tos; + rtnl_link_vxlan_get_ttl; + rtnl_link_vxlan_set_ageing; + rtnl_link_vxlan_set_group; + rtnl_link_vxlan_set_id; + rtnl_link_vxlan_set_l2miss; + rtnl_link_vxlan_set_l3miss; + rtnl_link_vxlan_set_learning; + rtnl_link_vxlan_set_limit; + rtnl_link_vxlan_set_link; + rtnl_link_vxlan_set_local; + rtnl_link_vxlan_set_port_range; + rtnl_link_vxlan_set_proxy; + rtnl_link_vxlan_set_rsc; + rtnl_link_vxlan_set_tos; + rtnl_link_vxlan_set_ttl; + rtnl_meta_value_alloc_id; + rtnl_meta_value_alloc_int; + rtnl_meta_value_alloc_var; + rtnl_meta_value_put; + rtnl_mirred_get_action; + rtnl_mirred_get_ifindex; + rtnl_mirred_get_policy; + rtnl_mirred_set_action; + rtnl_mirred_set_ifindex; + rtnl_mirred_set_policy; + rtnl_neigh_add; + rtnl_neigh_alloc; + rtnl_neigh_alloc_cache; + rtnl_neigh_build_add_request; + rtnl_neigh_build_delete_request; + rtnl_neigh_delete; + rtnl_neigh_flags2str; + rtnl_neigh_get; + rtnl_neigh_get_dst; + rtnl_neigh_get_family; + rtnl_neigh_get_flags; + rtnl_neigh_get_ifindex; + rtnl_neigh_get_lladdr; + rtnl_neigh_get_state; + rtnl_neigh_get_type; + rtnl_neigh_parse; + rtnl_neigh_put; + rtnl_neigh_set_dst; + rtnl_neigh_set_family; + rtnl_neigh_set_flags; + rtnl_neigh_set_ifindex; + rtnl_neigh_set_lladdr; + rtnl_neigh_set_state; + rtnl_neigh_set_type; + rtnl_neigh_state2str; + rtnl_neigh_str2flag; + rtnl_neigh_str2state; + rtnl_neigh_unset_flags; + rtnl_neigh_unset_state; + rtnl_neightbl_alloc; + rtnl_neightbl_alloc_cache; + rtnl_neightbl_build_change_request; + rtnl_neightbl_change; + rtnl_neightbl_get; + rtnl_neightbl_put; + rtnl_neightbl_set_anycast_delay; + rtnl_neightbl_set_app_probes; + rtnl_neightbl_set_base_reachable_time; + rtnl_neightbl_set_delay_probe_time; + rtnl_neightbl_set_dev; + rtnl_neightbl_set_family; + rtnl_neightbl_set_gc_interval; + rtnl_neightbl_set_gc_stale_time; + rtnl_neightbl_set_gc_tresh1; + rtnl_neightbl_set_gc_tresh2; + rtnl_neightbl_set_gc_tresh3; + rtnl_neightbl_set_locktime; + rtnl_neightbl_set_mcast_probes; + rtnl_neightbl_set_name; + rtnl_neightbl_set_proxy_delay; + rtnl_neightbl_set_proxy_queue_len; + rtnl_neightbl_set_queue_len; + rtnl_neightbl_set_retrans_time; + rtnl_neightbl_set_ucast_probes; + rtnl_netem_get_corruption_correlation; + rtnl_netem_get_corruption_probability; + rtnl_netem_get_delay; + rtnl_netem_get_delay_correlation; + rtnl_netem_get_delay_distribution; + rtnl_netem_get_delay_distribution_size; + rtnl_netem_get_duplicate; + rtnl_netem_get_duplicate_correlation; + rtnl_netem_get_gap; + rtnl_netem_get_jitter; + rtnl_netem_get_limit; + rtnl_netem_get_loss; + rtnl_netem_get_loss_correlation; + rtnl_netem_get_reorder_correlation; + rtnl_netem_get_reorder_probability; + rtnl_netem_set_corruption_correlation; + rtnl_netem_set_corruption_probability; + rtnl_netem_set_delay; + rtnl_netem_set_delay_correlation; + rtnl_netem_set_delay_distribution; + rtnl_netem_set_duplicate; + rtnl_netem_set_duplicate_correlation; + rtnl_netem_set_gap; + rtnl_netem_set_jitter; + rtnl_netem_set_limit; + rtnl_netem_set_loss; + rtnl_netem_set_loss_correlation; + rtnl_netem_set_reorder_correlation; + rtnl_netem_set_reorder_probability; + rtnl_pktloc_add; + rtnl_pktloc_alloc; + rtnl_pktloc_foreach; + rtnl_pktloc_lookup; + rtnl_pktloc_put; + rtnl_prio2str; + rtnl_qdisc_add; + rtnl_qdisc_alloc; + rtnl_qdisc_alloc_cache; + rtnl_qdisc_build_add_request; + rtnl_qdisc_build_change_request; + rtnl_qdisc_build_delete_request; + rtnl_qdisc_build_update_request; + rtnl_qdisc_change; + rtnl_qdisc_delete; + rtnl_qdisc_dsmark_get_default_index; + rtnl_qdisc_dsmark_get_indices; + rtnl_qdisc_dsmark_get_set_tc_index; + rtnl_qdisc_dsmark_set_default_index; + rtnl_qdisc_dsmark_set_indices; + rtnl_qdisc_dsmark_set_set_tc_index; + rtnl_qdisc_fifo_get_limit; + rtnl_qdisc_fifo_set_limit; + rtnl_qdisc_foreach_child; + rtnl_qdisc_foreach_cls; + rtnl_qdisc_fq_codel_get_ecn; + rtnl_qdisc_fq_codel_get_flows; + rtnl_qdisc_fq_codel_get_interval; + rtnl_qdisc_fq_codel_get_limit; + rtnl_qdisc_fq_codel_get_quantum; + rtnl_qdisc_fq_codel_get_target; + rtnl_qdisc_fq_codel_set_ecn; + rtnl_qdisc_fq_codel_set_flows; + rtnl_qdisc_fq_codel_set_interval; + rtnl_qdisc_fq_codel_set_limit; + rtnl_qdisc_fq_codel_set_quantum; + rtnl_qdisc_fq_codel_set_target; + rtnl_qdisc_get; + rtnl_qdisc_get_by_parent; + rtnl_qdisc_plug_buffer; + rtnl_qdisc_plug_release_indefinite; + rtnl_qdisc_plug_release_one; + rtnl_qdisc_plug_set_limit; + rtnl_qdisc_prio_get_bands; + rtnl_qdisc_prio_get_priomap; + rtnl_qdisc_prio_set_bands; + rtnl_qdisc_prio_set_priomap; + rtnl_qdisc_put; + rtnl_qdisc_tbf_get_limit; + rtnl_qdisc_tbf_get_peakrate; + rtnl_qdisc_tbf_get_peakrate_bucket; + rtnl_qdisc_tbf_get_peakrate_cell; + rtnl_qdisc_tbf_get_rate; + rtnl_qdisc_tbf_get_rate_bucket; + rtnl_qdisc_tbf_get_rate_cell; + rtnl_qdisc_tbf_set_limit; + rtnl_qdisc_tbf_set_limit_by_latency; + rtnl_qdisc_tbf_set_peakrate; + rtnl_qdisc_tbf_set_rate; + rtnl_qdisc_update; + rtnl_realms2str; + rtnl_red_get_limit; + rtnl_red_set_limit; + rtnl_route_add; + rtnl_route_add_nexthop; + rtnl_route_alloc; + rtnl_route_alloc_cache; + rtnl_route_build_add_request; + rtnl_route_build_del_request; + rtnl_route_build_msg; + rtnl_route_delete; + rtnl_route_foreach_nexthop; + rtnl_route_get; + rtnl_route_get_dst; + rtnl_route_get_family; + rtnl_route_get_flags; + rtnl_route_get_iif; + rtnl_route_get_metric; + rtnl_route_get_nexthops; + rtnl_route_get_nnexthops; + rtnl_route_get_pref_src; + rtnl_route_get_priority; + rtnl_route_get_protocol; + rtnl_route_get_scope; + rtnl_route_get_src; + rtnl_route_get_table; + rtnl_route_get_tos; + rtnl_route_get_type; + rtnl_route_guess_scope; + rtnl_route_metric2str; + rtnl_route_nexthop_n; + rtnl_route_nh_alloc; + rtnl_route_nh_clone; + rtnl_route_nh_compare; + rtnl_route_nh_dump; + rtnl_route_nh_flags2str; + rtnl_route_nh_free; + rtnl_route_nh_get_flags; + rtnl_route_nh_get_gateway; + rtnl_route_nh_get_ifindex; + rtnl_route_nh_get_realms; + rtnl_route_nh_get_weight; + rtnl_route_nh_set_flags; + rtnl_route_nh_set_gateway; + rtnl_route_nh_set_ifindex; + rtnl_route_nh_set_realms; + rtnl_route_nh_set_weight; + rtnl_route_nh_str2flags; + rtnl_route_nh_unset_flags; + rtnl_route_parse; + rtnl_route_proto2str; + rtnl_route_put; + rtnl_route_read_protocol_names; + rtnl_route_read_table_names; + rtnl_route_remove_nexthop; + rtnl_route_set_dst; + rtnl_route_set_family; + rtnl_route_set_flags; + rtnl_route_set_iif; + rtnl_route_set_metric; + rtnl_route_set_pref_src; + rtnl_route_set_priority; + rtnl_route_set_protocol; + rtnl_route_set_scope; + rtnl_route_set_src; + rtnl_route_set_table; + rtnl_route_set_tos; + rtnl_route_set_type; + rtnl_route_str2metric; + rtnl_route_str2proto; + rtnl_route_str2table; + rtnl_route_table2str; + rtnl_route_unset_flags; + rtnl_route_unset_metric; + rtnl_rule_add; + rtnl_rule_alloc; + rtnl_rule_alloc_cache; + rtnl_rule_build_add_request; + rtnl_rule_build_delete_request; + rtnl_rule_delete; + rtnl_rule_get_action; + rtnl_rule_get_dsfield; + rtnl_rule_get_dst; + rtnl_rule_get_family; + rtnl_rule_get_goto; + rtnl_rule_get_iif; + rtnl_rule_get_mark; + rtnl_rule_get_mask; + rtnl_rule_get_oif; + rtnl_rule_get_prio; + rtnl_rule_get_realms; + rtnl_rule_get_src; + rtnl_rule_get_table; + rtnl_rule_put; + rtnl_rule_set_action; + rtnl_rule_set_dsfield; + rtnl_rule_set_dst; + rtnl_rule_set_family; + rtnl_rule_set_goto; + rtnl_rule_set_iif; + rtnl_rule_set_mark; + rtnl_rule_set_mask; + rtnl_rule_set_oif; + rtnl_rule_set_prio; + rtnl_rule_set_realms; + rtnl_rule_set_src; + rtnl_rule_set_table; + rtnl_scope2str; + rtnl_sfq_get_divisor; + rtnl_sfq_get_limit; + rtnl_sfq_get_perturb; + rtnl_sfq_get_quantum; + rtnl_sfq_set_limit; + rtnl_sfq_set_perturb; + rtnl_sfq_set_quantum; + rtnl_str2prio; + rtnl_str2scope; + rtnl_tc_calc_bufsize; + rtnl_tc_calc_cell_log; + rtnl_tc_calc_txtime; + rtnl_tc_get_handle; + rtnl_tc_get_ifindex; + rtnl_tc_get_kind; + rtnl_tc_get_link; + rtnl_tc_get_linktype; + rtnl_tc_get_mpu; + rtnl_tc_get_mtu; + rtnl_tc_get_overhead; + rtnl_tc_get_parent; + rtnl_tc_get_stat; + rtnl_tc_handle2str; + rtnl_tc_read_classid_file; + rtnl_tc_set_handle; + rtnl_tc_set_ifindex; + rtnl_tc_set_kind; + rtnl_tc_set_link; + rtnl_tc_set_linktype; + rtnl_tc_set_mpu; + rtnl_tc_set_mtu; + rtnl_tc_set_overhead; + rtnl_tc_set_parent; + rtnl_tc_str2handle; + rtnl_u32_add_action; + rtnl_u32_add_key; + rtnl_u32_add_key_in6_addr; + rtnl_u32_add_key_in_addr; + rtnl_u32_add_key_uint16; + rtnl_u32_add_key_uint32; + rtnl_u32_add_key_uint8; + rtnl_u32_del_action; + rtnl_u32_get_key; + rtnl_u32_set_classid; + rtnl_u32_set_cls_terminal; + rtnl_u32_set_divisor; + rtnl_u32_set_flags; + rtnl_u32_set_handle; + rtnl_u32_set_hashmask; + rtnl_u32_set_hashtable; + rtnl_u32_set_link; + + # The following symbols were added during the development of 3.2.26. + # Keep them in libnl_3 to avoid breaking users. + rtnl_class_hfsc_get_fsc; + rtnl_class_hfsc_get_rsc; + rtnl_class_hfsc_get_usc; + rtnl_class_hfsc_set_fsc; + rtnl_class_hfsc_set_rsc; + rtnl_class_hfsc_set_usc; + rtnl_link_inet6_addrgenmode2str; + rtnl_link_inet6_get_addr_gen_mode; + rtnl_link_inet6_get_token; + rtnl_link_inet6_set_addr_gen_mode; + rtnl_link_inet6_set_token; + rtnl_link_inet6_str2addrgenmode; + rtnl_qdisc_hfsc_get_defcls; + rtnl_qdisc_hfsc_set_defcls; + rtnl_u32_add_mark; + rtnl_u32_del_mark; + +local: + *; +}; + +libnl_3_2_26 { +global: + rtnl_neigh_get_vlan; + rtnl_neigh_set_vlan; + rtnl_skbedit_get_action; + rtnl_skbedit_get_mark; + rtnl_skbedit_get_priority; + rtnl_skbedit_get_queue_mapping; + rtnl_skbedit_set_action; + rtnl_skbedit_set_mark; + rtnl_skbedit_set_priority; + rtnl_skbedit_set_queue_mapping; + rtnl_tc_stat2str; + rtnl_tc_str2stat; + rtnl_u32_get_classid; +} libnl_3; + +libnl_3_2_27 { +global: + rtnl_link_get_link_netnsid; + rtnl_link_ipvlan_alloc; + rtnl_link_is_ipvlan; + rtnl_link_ipvlan_mode2str; + rtnl_link_ipvlan_str2mode; + rtnl_link_ipvlan_set_mode; + rtnl_link_ipvlan_get_mode; + rtnl_link_set_link_netnsid; +} libnl_3_2_26; + +libnl_3_2_28 { +global: + rtnl_link_alloc_cache_flags; + rtnl_link_bridge_get_port_vlan; + rtnl_link_bridge_has_vlan; + rtnl_link_bridge_pvid; + rtnl_link_is_macvtap; + rtnl_link_is_vrf; + rtnl_link_ipgretap_add; + rtnl_link_ipgretap_alloc; + rtnl_link_macsec_alloc; + rtnl_link_macsec_set_sci; + rtnl_link_macsec_get_sci; + rtnl_link_macsec_set_port; + rtnl_link_macsec_get_port; + rtnl_link_macsec_set_cipher_suite; + rtnl_link_macsec_get_cipher_suite; + rtnl_link_macsec_set_icv_len; + rtnl_link_macsec_get_icv_len; + rtnl_link_macsec_set_protect; + rtnl_link_macsec_get_protect; + rtnl_link_macsec_set_encrypt; + rtnl_link_macsec_get_encrypt; + rtnl_link_macsec_set_encoding_sa; + rtnl_link_macsec_get_encoding_sa; + rtnl_link_macsec_set_validation_type; + rtnl_link_macsec_get_validation_type; + rtnl_link_macsec_set_replay_protect; + rtnl_link_macsec_get_replay_protect; + rtnl_link_macsec_set_window; + rtnl_link_macsec_get_window; + rtnl_link_macsec_set_send_sci; + rtnl_link_macsec_get_send_sci; + rtnl_link_macsec_set_end_station; + rtnl_link_macsec_get_end_station; + rtnl_link_macsec_set_scb; + rtnl_link_macsec_get_scb; + rtnl_link_macvtap_alloc; + rtnl_link_macvtap_flags2str; + rtnl_link_macvtap_get_flags; + rtnl_link_macvtap_get_mode; + rtnl_link_macvtap_mode2str; + rtnl_link_macvtap_set_flags; + rtnl_link_macvtap_set_mode; + rtnl_link_macvtap_str2flags; + rtnl_link_macvtap_str2mode; + rtnl_link_macvtap_unset_flags; + rtnl_link_sit_get_ip6rd_prefix; + rtnl_link_sit_get_ip6rd_prefixlen; + rtnl_link_sit_get_ip6rd_relay_prefix; + rtnl_link_sit_get_ip6rd_relay_prefixlen; + rtnl_link_sit_set_ip6rd_prefix; + rtnl_link_sit_set_ip6rd_prefixlen; + rtnl_link_sit_set_ip6rd_relay_prefix; + rtnl_link_sit_set_ip6rd_relay_prefixlen; + rtnl_link_vrf_alloc; + rtnl_link_vrf_get_tableid; + rtnl_link_vrf_set_tableid; + rtnl_neigh_alloc_cache_flags; +} libnl_3_2_27; + +libnl_3_2_29 { +global: + rtnl_gact_set_action; + rtnl_gact_get_action; + rtnl_link_bridge_portstate2str; + rtnl_link_bridge_str2portstate; + rtnl_link_bridge_set_self; + rtnl_link_bridge_get_hwmode; + rtnl_link_bridge_set_hwmode; + rtnl_link_bridge_hwmode2str; + rtnl_link_bridge_str2hwmode; + rtnl_link_get_carrier_changes; + rtnl_link_get_gso_max_segs; + rtnl_link_get_gso_max_size; + rtnl_link_get_phys_port_name; + rtnl_link_get_phys_switch_id; + rtnl_link_ipgre_get_pmtudisc; + rtnl_link_is_ipgretap; + rtnl_link_macvlan_add_macaddr; + rtnl_link_macvlan_count_macaddr; + rtnl_link_macvlan_del_macaddr; + rtnl_link_macvlan_get_macaddr; + rtnl_link_macvlan_get_macmode; + rtnl_link_macvlan_macmode2str; + rtnl_link_macvlan_set_macmode; + rtnl_link_macvlan_str2macmode; + rtnl_link_ppp_alloc; + rtnl_link_ppp_set_fd; + rtnl_link_ppp_get_fd; + rtnl_link_vxlan_get_collect_metadata; + rtnl_link_vxlan_get_flags; + rtnl_link_vxlan_get_label; + rtnl_link_vxlan_get_port; + rtnl_link_vxlan_get_remcsum_rx; + rtnl_link_vxlan_get_remcsum_tx; + rtnl_link_vxlan_get_udp_csum; + rtnl_link_vxlan_get_udp_zero_csum6_rx; + rtnl_link_vxlan_get_udp_zero_csum6_tx; + rtnl_link_vxlan_set_collect_metadata; + rtnl_link_vxlan_set_flags; + rtnl_link_vxlan_set_label; + rtnl_link_vxlan_set_port; + rtnl_link_vxlan_set_remcsum_rx; + rtnl_link_vxlan_set_remcsum_tx; + rtnl_link_vxlan_set_udp_csum; + rtnl_link_vxlan_set_udp_zero_csum6_rx; + rtnl_link_vxlan_set_udp_zero_csum6_tx; + rtnl_link_has_vf_list; + rtnl_link_set_vf_list; + rtnl_link_unset_vf_list; + rtnl_link_vf_add; + rtnl_link_vf_alloc; + rtnl_link_vf_free; + rtnl_link_vf_get; + rtnl_link_vf_put; + rtnl_link_vf_get_addr; + rtnl_link_vf_set_addr; + rtnl_link_vf_set_ib_node_guid; + rtnl_link_vf_set_ib_port_guid; + rtnl_link_vf_get_index; + rtnl_link_vf_set_index; + rtnl_link_vf_get_linkstate; + rtnl_link_vf_set_linkstate; + rtnl_link_vf_get_rate; + rtnl_link_vf_set_rate; + rtnl_link_vf_get_rss_query_en; + rtnl_link_vf_set_rss_query_en; + rtnl_link_vf_get_spoofchk; + rtnl_link_vf_set_spoofchk; + rtnl_link_vf_get_stat; + rtnl_link_vf_get_trust; + rtnl_link_vf_set_trust; + rtnl_link_vf_get_vlans; + rtnl_link_vf_set_vlans; + rtnl_link_vf_vlan_alloc; + rtnl_link_vf_vlan_free; + rtnl_link_vf_vlan_put; + rtnl_link_vf_linkstate2str; + rtnl_link_vf_str2linkstate; + rtnl_link_vf_vlanproto2str; + rtnl_link_vf_str2vlanproto; + rtnl_link_vf_str2guid; + rtnl_u32_set_selector; +} libnl_3_2_28; + +libnl_3_4 { +global: + rtnl_act_next; + rtnl_basic_get_action; + rtnl_link_inet6_flags2str; + rtnl_link_inet6_get_flags; + rtnl_link_inet6_set_flags; + rtnl_link_inet6_str2flags; + rtnl_netconf_get_all; + rtnl_netconf_get_by_idx; + rtnl_netconf_get_default; + rtnl_netconf_get_family; + rtnl_netconf_get_forwarding; + rtnl_netconf_get_ifindex; + rtnl_netconf_get_input; + rtnl_netconf_get_mc_forwarding; + rtnl_netconf_get_rp_filter; + rtnl_netconf_put; + rtnl_rule_get_l3mdev; + rtnl_rule_set_l3mdev; + rtnl_u32_get_action; + rtnl_route_nh_set_newdst; + rtnl_route_nh_get_newdst; + rtnl_route_nh_set_via; + rtnl_route_nh_get_via; + rtnl_route_set_ttl_propagate; + rtnl_route_get_ttl_propagate; + rtnl_route_nh_encap_mpls; +} libnl_3_2_29; + +libnl_3_5 { +global: + rtnl_class_get_by_parent; + rtnl_cls_cache_set_tc_params; + rtnl_ematch_tree_clone; + rtnl_htb_get_ceil64; + rtnl_htb_get_rate64; + rtnl_htb_set_ceil64; + rtnl_htb_set_rate64; + rtnl_link_geneve_alloc; + rtnl_link_geneve_get_flags; + rtnl_link_geneve_get_id; + rtnl_link_geneve_get_label; + rtnl_link_geneve_get_port; + rtnl_link_geneve_get_remote; + rtnl_link_geneve_get_tos; + rtnl_link_geneve_get_ttl; + rtnl_link_geneve_get_udp_csum; + rtnl_link_geneve_get_udp_zero_csum6_rx; + rtnl_link_geneve_get_udp_zero_csum6_tx; + rtnl_link_geneve_set_flags; + rtnl_link_geneve_set_id; + rtnl_link_geneve_set_label; + rtnl_link_geneve_set_port; + rtnl_link_geneve_set_remote; + rtnl_link_geneve_set_tos; + rtnl_link_geneve_set_ttl; + rtnl_link_geneve_set_udp_csum; + rtnl_link_geneve_set_udp_zero_csum6_rx; + rtnl_link_geneve_set_udp_zero_csum6_tx; + rtnl_link_get_slave_type; + rtnl_link_is_geneve; + rtnl_link_is_xfrmi; + rtnl_link_set_slave_type; + rtnl_link_xfrmi_alloc; + rtnl_link_xfrmi_get_if_id; + rtnl_link_xfrmi_get_link; + rtnl_link_xfrmi_set_if_id; + rtnl_link_xfrmi_set_link; + rtnl_mall_append_action; + rtnl_mall_del_action; + rtnl_mall_get_classid; + rtnl_mall_get_first_action; + rtnl_mall_get_flags; + rtnl_mall_set_classid; + rtnl_mall_set_flags; + rtnl_neigh_get_by_vlan; + rtnl_neigh_get_master; + rtnl_neigh_set_master; + rtnl_netem_set_delay_distribution_data; + rtnl_qdisc_mqprio_get_hw_offload; + rtnl_qdisc_mqprio_get_max_rate; + rtnl_qdisc_mqprio_get_min_rate; + rtnl_qdisc_mqprio_get_mode; + rtnl_qdisc_mqprio_get_num_tc; + rtnl_qdisc_mqprio_get_priomap; + rtnl_qdisc_mqprio_get_queue; + rtnl_qdisc_mqprio_get_shaper; + rtnl_qdisc_mqprio_hw_offload; + rtnl_qdisc_mqprio_set_max_rate; + rtnl_qdisc_mqprio_set_min_rate; + rtnl_qdisc_mqprio_set_mode; + rtnl_qdisc_mqprio_set_num_tc; + rtnl_qdisc_mqprio_set_priomap; + rtnl_qdisc_mqprio_set_queue; + rtnl_qdisc_mqprio_set_shaper; + rtnl_rule_get_dport; + rtnl_rule_get_ipproto; + rtnl_rule_get_protocol; + rtnl_rule_get_sport; + rtnl_rule_set_dport; + rtnl_rule_set_dport_range; + rtnl_rule_set_ipproto; + rtnl_rule_set_protocol; + rtnl_rule_set_sport; + rtnl_rule_set_sport_range; + rtnl_tc_get_chain; + rtnl_tc_set_chain; + rtnl_vlan_get_action; + rtnl_vlan_get_mode; + rtnl_vlan_get_protocol; + rtnl_vlan_get_vlan_id; + rtnl_vlan_get_vlan_prio; + rtnl_vlan_set_action; + rtnl_vlan_set_mode; + rtnl_vlan_set_protocol; + rtnl_vlan_set_vlan_id; + rtnl_vlan_set_vlan_prio; +} libnl_3_4; + +libnl_3_6 { +global: + rtnl_cls_find_by_handle; + rtnl_cls_find_by_prio; + rtnl_flower_append_action; + rtnl_flower_del_action; + rtnl_flower_get_action; + rtnl_flower_get_dst_mac; + rtnl_flower_get_ip_dscp; + rtnl_flower_get_proto; + rtnl_flower_get_src_mac; + rtnl_flower_get_vlan_id; + rtnl_flower_get_vlan_prio; + rtnl_flower_set_dst_mac; + rtnl_flower_set_flags; + rtnl_flower_set_ip_dscp; + rtnl_flower_set_proto; + rtnl_flower_set_src_mac; + rtnl_flower_set_vlan_ethtype; + rtnl_flower_set_vlan_id; + rtnl_flower_set_vlan_prio; + rtnl_link_can_get_data_bittiming; + rtnl_link_can_get_data_bittiming_const; + rtnl_link_can_set_data_bittiming; + rtnl_link_can_set_data_bittiming_const; + rtnl_link_ip6_tnl_get_fwmark; + rtnl_link_ip6_tnl_set_fwmark; + rtnl_link_ip6gre_add; + rtnl_link_ip6gre_alloc; + rtnl_link_ip6gre_get_encaplimit; + rtnl_link_ip6gre_get_flags; + rtnl_link_ip6gre_get_flowinfo; + rtnl_link_ip6gre_get_fwmark; + rtnl_link_ip6gre_get_iflags; + rtnl_link_ip6gre_get_ikey; + rtnl_link_ip6gre_get_link; + rtnl_link_ip6gre_get_local; + rtnl_link_ip6gre_get_oflags; + rtnl_link_ip6gre_get_okey; + rtnl_link_ip6gre_get_remote; + rtnl_link_ip6gre_get_ttl; + rtnl_link_ip6gre_set_encaplimit; + rtnl_link_ip6gre_set_flags; + rtnl_link_ip6gre_set_flowinfo; + rtnl_link_ip6gre_set_fwmark; + rtnl_link_ip6gre_set_iflags; + rtnl_link_ip6gre_set_ikey; + rtnl_link_ip6gre_set_link; + rtnl_link_ip6gre_set_local; + rtnl_link_ip6gre_set_oflags; + rtnl_link_ip6gre_set_okey; + rtnl_link_ip6gre_set_remote; + rtnl_link_ip6gre_set_ttl; + rtnl_link_ip6vti_add; + rtnl_link_ip6vti_alloc; + rtnl_link_ip6vti_get_fwmark; + rtnl_link_ip6vti_get_ikey; + rtnl_link_ip6vti_get_link; + rtnl_link_ip6vti_get_local; + rtnl_link_ip6vti_get_okey; + rtnl_link_ip6vti_get_remote; + rtnl_link_ip6vti_set_fwmark; + rtnl_link_ip6vti_set_ikey; + rtnl_link_ip6vti_set_link; + rtnl_link_ip6vti_set_local; + rtnl_link_ip6vti_set_okey; + rtnl_link_ip6vti_set_remote; + rtnl_link_ipgre_get_fwmark; + rtnl_link_ipgre_set_fwmark; + rtnl_link_ipip_get_fwmark; + rtnl_link_ipip_set_fwmark; + rtnl_link_ipvti_get_fwmark; + rtnl_link_ipvti_set_fwmark; + rtnl_link_is_ip6gre; + rtnl_link_is_ip6vti; + rtnl_link_macsec_get_offload; + rtnl_link_macsec_set_offload; + rtnl_link_sit_get_fwmark; + rtnl_link_sit_set_fwmark; + rtnl_link_team_add; + rtnl_link_team_alloc; + rtnl_mdb_add_entry; + rtnl_mdb_alloc_cache; + rtnl_mdb_alloc_cache_flags; + rtnl_mdb_entry_get_addr; + rtnl_mdb_entry_get_ifindex; + rtnl_mdb_entry_get_proto; + rtnl_mdb_entry_get_state; + rtnl_mdb_entry_get_vid; + rtnl_mdb_foreach_entry; + rtnl_mdb_get_ifindex; + rtnl_netconf_alloc_cache; + rtnl_netconf_get_ignore_routes_linkdown; + rtnl_netconf_get_proxy_neigh; + rtnl_qdisc_get_by_kind; + rtnl_route_lookup; + rtnl_route_nh_get_encap_mpls_dst; + rtnl_route_nh_get_encap_mpls_ttl; +} libnl_3_5; + +libnl_3_7 { +global: + rtnl_flower_get_ipv4_dst; + rtnl_flower_get_ipv4_src; + rtnl_flower_set_ipv4_dst; + rtnl_flower_set_ipv4_src; + rtnl_nat_get_action; + rtnl_nat_get_flags; + rtnl_nat_get_mask; + rtnl_nat_get_new_addr; + rtnl_nat_get_old_addr; + rtnl_nat_set_action; + rtnl_nat_set_flags; + rtnl_nat_set_mask; + rtnl_nat_set_new_addr; + rtnl_nat_set_old_addr; +} libnl_3_6; + +libnl_3_8 { +global: + rtnl_link_bond_set_activeslave; + rtnl_link_bond_set_mode; + rtnl_link_bridge_get_vlan_filtering; + rtnl_link_bridge_get_vlan_protocol; + rtnl_link_bridge_get_vlan_stats_enabled; + rtnl_link_bridge_set_vlan_filtering; + rtnl_link_bridge_set_vlan_protocol; + rtnl_link_bridge_set_vlan_stats_enabled; + rtnl_link_inet6_get_conf; + rtnl_link_info_ops_get; + rtnl_neigh_get_nhid; + rtnl_neigh_set_nhid; + rtnl_nh_alloc; + rtnl_nh_alloc_cache; + rtnl_nh_get; + rtnl_nh_get_fdb; + rtnl_nh_get_gateway; + rtnl_nh_get_group_entry; + rtnl_nh_get_group_size; + rtnl_nh_get_id; + rtnl_nh_put; + rtnl_nh_set_fdb; + rtnl_nh_set_gateway; +} libnl_3_7; + +libnl_3_9 { +global: + rtnl_link_bond_set_hashing_type; + rtnl_link_bond_set_miimon; + rtnl_link_bond_set_min_links; + rtnl_link_can_get_device_stats; +} libnl_3_8; diff --git a/libnl-xfrm-3.0.pc.in b/libnl-xfrm-3.0.pc.in new file mode 100644 index 0000000..48ffb70 --- /dev/null +++ b/libnl-xfrm-3.0.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libnl-xfrm +Description: Netlink Routing Family Library +Version: @PACKAGE_VERSION@ +Requires: libnl-3.0 +Libs: -L${libdir} -lnl-xfrm-@MAJ_VERSION@ +Cflags: -I${includedir}/libnl@MAJ_VERSION@ diff --git a/libnl-xfrm-3.sym b/libnl-xfrm-3.sym new file mode 100644 index 0000000..ed7c7ad --- /dev/null +++ b/libnl-xfrm-3.sym @@ -0,0 +1,257 @@ +# The linker version script controls which symbols are exported. +# Version tags that correspond to past releases group the symbols +# that were part of that release. Hence, such a version tag is sealed +# and MUST not be extended. +# Any new symbols MUST only be added to the bottom of the file, in +# the version tag for the next upcoming release. +libnl_3 { +global: + xfrmnl_ae_alloc; + xfrmnl_ae_build_get_request; + xfrmnl_ae_flags2str; + xfrmnl_ae_get_curlifetime; + xfrmnl_ae_get_daddr; + xfrmnl_ae_get_family; + xfrmnl_ae_get_flags; + xfrmnl_ae_get_kernel; + xfrmnl_ae_get_mark; + xfrmnl_ae_get_proto; + xfrmnl_ae_get_replay_maxage; + xfrmnl_ae_get_replay_maxdiff; + xfrmnl_ae_get_replay_state; + xfrmnl_ae_get_replay_state_esn; + xfrmnl_ae_get_reqid; + xfrmnl_ae_get_saddr; + xfrmnl_ae_get_spi; + xfrmnl_ae_parse; + xfrmnl_ae_put; + xfrmnl_ae_set; + xfrmnl_ae_set_curlifetime; + xfrmnl_ae_set_daddr; + xfrmnl_ae_set_family; + xfrmnl_ae_set_flags; + xfrmnl_ae_set_mark; + xfrmnl_ae_set_proto; + xfrmnl_ae_set_replay_maxage; + xfrmnl_ae_set_replay_maxdiff; + xfrmnl_ae_set_replay_state; + xfrmnl_ae_set_replay_state_esn; + xfrmnl_ae_set_reqid; + xfrmnl_ae_set_saddr; + xfrmnl_ae_set_spi; + xfrmnl_ae_str2flag; + xfrmnl_ltime_cfg_alloc; + xfrmnl_ltime_cfg_clone; + xfrmnl_ltime_cfg_cmp; + xfrmnl_ltime_cfg_get; + xfrmnl_ltime_cfg_get_hard_addexpires; + xfrmnl_ltime_cfg_get_hard_bytelimit; + xfrmnl_ltime_cfg_get_hard_packetlimit; + xfrmnl_ltime_cfg_get_hard_useexpires; + xfrmnl_ltime_cfg_get_soft_addexpires; + xfrmnl_ltime_cfg_get_soft_bytelimit; + xfrmnl_ltime_cfg_get_soft_packetlimit; + xfrmnl_ltime_cfg_get_soft_useexpires; + xfrmnl_ltime_cfg_put; + xfrmnl_ltime_cfg_set_hard_addexpires; + xfrmnl_ltime_cfg_set_hard_bytelimit; + xfrmnl_ltime_cfg_set_hard_packetlimit; + xfrmnl_ltime_cfg_set_hard_useexpires; + xfrmnl_ltime_cfg_set_soft_addexpires; + xfrmnl_ltime_cfg_set_soft_bytelimit; + xfrmnl_ltime_cfg_set_soft_packetlimit; + xfrmnl_ltime_cfg_set_soft_useexpires; + xfrmnl_ltime_cfg_shared; + xfrmnl_sa_add; + xfrmnl_sa_alloc; + xfrmnl_sa_alloc_cache; + xfrmnl_sa_build_add_request; + xfrmnl_sa_build_delete_request; + xfrmnl_sa_build_get_request; + xfrmnl_sa_build_update_request; + xfrmnl_sa_delete; + xfrmnl_sa_flags2str; + xfrmnl_sa_get; + xfrmnl_sa_get_aead_params; + xfrmnl_sa_get_auth_params; + xfrmnl_sa_get_coaddr; + xfrmnl_sa_get_comp_params; + xfrmnl_sa_get_crypto_params; + xfrmnl_sa_get_curlifetime; + xfrmnl_sa_get_daddr; + xfrmnl_sa_get_encap_tmpl; + xfrmnl_sa_get_family; + xfrmnl_sa_get_flags; + xfrmnl_sa_get_kernel; + xfrmnl_sa_get_lifetime_cfg; + xfrmnl_sa_get_mark; + xfrmnl_sa_get_mode; + xfrmnl_sa_get_proto; + xfrmnl_sa_get_replay_maxage; + xfrmnl_sa_get_replay_maxdiff; + xfrmnl_sa_get_replay_state; + xfrmnl_sa_get_replay_state_esn; + xfrmnl_sa_get_replay_window; + xfrmnl_sa_get_reqid; + xfrmnl_sa_get_saddr; + xfrmnl_sa_get_sec_ctx; + xfrmnl_sa_get_sel; + xfrmnl_sa_get_seq; + xfrmnl_sa_get_spi; + xfrmnl_sa_get_stats; + xfrmnl_sa_get_tfcpad; + xfrmnl_sa_is_expiry_reached; + xfrmnl_sa_is_hardexpiry_reached; + xfrmnl_sa_mode2str; + xfrmnl_sa_parse; + xfrmnl_sa_put; + xfrmnl_sa_set_aead_params; + xfrmnl_sa_set_auth_params; + xfrmnl_sa_set_coaddr; + xfrmnl_sa_set_comp_params; + xfrmnl_sa_set_crypto_params; + xfrmnl_sa_set_daddr; + xfrmnl_sa_set_encap_tmpl; + xfrmnl_sa_set_family; + xfrmnl_sa_set_flags; + xfrmnl_sa_set_lifetime_cfg; + xfrmnl_sa_set_mark; + xfrmnl_sa_set_mode; + xfrmnl_sa_set_proto; + xfrmnl_sa_set_replay_maxage; + xfrmnl_sa_set_replay_maxdiff; + xfrmnl_sa_set_replay_state; + xfrmnl_sa_set_replay_state_esn; + xfrmnl_sa_set_replay_window; + xfrmnl_sa_set_reqid; + xfrmnl_sa_set_saddr; + xfrmnl_sa_set_sec_ctx; + xfrmnl_sa_set_sel; + xfrmnl_sa_set_spi; + xfrmnl_sa_set_tfcpad; + xfrmnl_sa_str2flag; + xfrmnl_sa_str2mode; + xfrmnl_sa_update; + xfrmnl_sel_alloc; + xfrmnl_sel_clone; + xfrmnl_sel_cmp; + xfrmnl_sel_dump; + xfrmnl_sel_get; + xfrmnl_sel_get_daddr; + xfrmnl_sel_get_dport; + xfrmnl_sel_get_dportmask; + xfrmnl_sel_get_family; + xfrmnl_sel_get_ifindex; + xfrmnl_sel_get_prefixlen_d; + xfrmnl_sel_get_prefixlen_s; + xfrmnl_sel_get_proto; + xfrmnl_sel_get_saddr; + xfrmnl_sel_get_sport; + xfrmnl_sel_get_sportmask; + xfrmnl_sel_get_userid; + xfrmnl_sel_put; + xfrmnl_sel_set_daddr; + xfrmnl_sel_set_dport; + xfrmnl_sel_set_dportmask; + xfrmnl_sel_set_family; + xfrmnl_sel_set_ifindex; + xfrmnl_sel_set_prefixlen_d; + xfrmnl_sel_set_prefixlen_s; + xfrmnl_sel_set_proto; + xfrmnl_sel_set_saddr; + xfrmnl_sel_set_sport; + xfrmnl_sel_set_sportmask; + xfrmnl_sel_set_userid; + xfrmnl_sel_shared; + xfrmnl_sp_action2str; + xfrmnl_sp_add; + xfrmnl_sp_add_usertemplate; + xfrmnl_sp_alloc; + xfrmnl_sp_alloc_cache; + xfrmnl_sp_build_add_request; + xfrmnl_sp_build_delete_request; + xfrmnl_sp_build_get_request; + xfrmnl_sp_build_update_request; + xfrmnl_sp_delete; + xfrmnl_sp_dir2str; + xfrmnl_sp_flags2str; + xfrmnl_sp_foreach_usertemplate; + xfrmnl_sp_get; + xfrmnl_sp_get_action; + xfrmnl_sp_get_curlifetime; + xfrmnl_sp_get_dir; + xfrmnl_sp_get_flags; + xfrmnl_sp_get_index; + xfrmnl_sp_get_kernel; + xfrmnl_sp_get_lifetime_cfg; + xfrmnl_sp_get_mark; + xfrmnl_sp_get_nusertemplates; + xfrmnl_sp_get_priority; + xfrmnl_sp_get_sec_ctx; + xfrmnl_sp_get_sel; + xfrmnl_sp_get_share; + xfrmnl_sp_get_userpolicy_type; + xfrmnl_sp_get_usertemplates; + xfrmnl_sp_index2dir; + xfrmnl_sp_parse; + xfrmnl_sp_put; + xfrmnl_sp_remove_usertemplate; + xfrmnl_sp_set_action; + xfrmnl_sp_set_dir; + xfrmnl_sp_set_flags; + xfrmnl_sp_set_index; + xfrmnl_sp_set_lifetime_cfg; + xfrmnl_sp_set_mark; + xfrmnl_sp_set_priority; + xfrmnl_sp_set_sec_ctx; + xfrmnl_sp_set_sel; + xfrmnl_sp_set_share; + xfrmnl_sp_set_userpolicy_type; + xfrmnl_sp_share2str; + xfrmnl_sp_str2action; + xfrmnl_sp_str2dir; + xfrmnl_sp_str2flag; + xfrmnl_sp_str2share; + xfrmnl_sp_str2type; + xfrmnl_sp_type2str; + xfrmnl_sp_update; + xfrmnl_sp_usertemplate_n; + xfrmnl_user_tmpl_alloc; + xfrmnl_user_tmpl_clone; + xfrmnl_user_tmpl_cmp; + xfrmnl_user_tmpl_dump; + xfrmnl_user_tmpl_free; + xfrmnl_user_tmpl_get_aalgos; + xfrmnl_user_tmpl_get_calgos; + xfrmnl_user_tmpl_get_daddr; + xfrmnl_user_tmpl_get_ealgos; + xfrmnl_user_tmpl_get_family; + xfrmnl_user_tmpl_get_mode; + xfrmnl_user_tmpl_get_optional; + xfrmnl_user_tmpl_get_proto; + xfrmnl_user_tmpl_get_reqid; + xfrmnl_user_tmpl_get_saddr; + xfrmnl_user_tmpl_get_share; + xfrmnl_user_tmpl_get_spi; + xfrmnl_user_tmpl_mode2str; + xfrmnl_user_tmpl_set_aalgos; + xfrmnl_user_tmpl_set_calgos; + xfrmnl_user_tmpl_set_daddr; + xfrmnl_user_tmpl_set_ealgos; + xfrmnl_user_tmpl_set_family; + xfrmnl_user_tmpl_set_mode; + xfrmnl_user_tmpl_set_optional; + xfrmnl_user_tmpl_set_proto; + xfrmnl_user_tmpl_set_reqid; + xfrmnl_user_tmpl_set_saddr; + xfrmnl_user_tmpl_set_share; + xfrmnl_user_tmpl_set_spi; + xfrmnl_user_tmpl_str2mode; +local: + *; +}; + +libnl_3_6 { + xfrmnl_sa_get_user_offload; + xfrmnl_sa_set_user_offload; +} libnl_3; diff --git a/m4/libtool.m4 b/m4/libtool.m4 index 56666f0..e3adeda 100644 --- a/m4/libtool.m4 +++ b/m4/libtool.m4 @@ -1,8 +1,7 @@ # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. +# Copyright (C) 1996-2001, 2003-2019, 2021-2022 Free Software +# Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives @@ -10,36 +9,30 @@ # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# Written by Gordon Matzigkeit, 1996 -# -# This file is part of GNU Libtool. -# -# GNU Libtool is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. # -# As a special exception to the GNU General Public License, -# if you distribute this file as part of a program or library that -# is built using GNU Libtool, you may include this file under the -# same distribution terms that you use for the rest of that program. +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. # -# GNU Libtool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, or -# obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# along with this program. If not, see . ]) -# serial 57 LT_INIT +# serial 59 LT_INIT # LT_PREREQ(VERSION) @@ -67,7 +60,7 @@ esac # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], -[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl @@ -91,7 +84,7 @@ dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ltmain" +LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' @@ -111,26 +104,43 @@ dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + # _LT_CC_BASENAME(CC) # ------------------- -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], -[for cc_temp in $1""; do - case $cc_temp in - compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; - distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set -# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} @@ -172,20 +182,22 @@ m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_DECL_FILECMD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ -# See if we are running on zsh, and set the options which allow our +# See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. -if test -n "\${ZSH_VERSION+set}" ; then +if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi ]) -if test -n "${ZSH_VERSION+set}" ; then +if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi @@ -198,7 +210,7 @@ aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then + if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi @@ -209,14 +221,14 @@ esac ofile=libtool can_build_shared=yes -# All known linkers require a `.a' archive for static linking (except MSVC, -# which needs '.lib'). +# All known linkers require a '.a' archive for static linking (except MSVC and +# ICC, which need '.lib'). libext=a -with_gnu_ld="$lt_cv_prog_gnu_ld" +with_gnu_ld=$lt_cv_prog_gnu_ld -old_CC="$CC" -old_CFLAGS="$CFLAGS" +old_CC=$CC +old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc @@ -269,14 +281,14 @@ no_glob_subst='s/\*/\\\*/g' # _LT_PROG_LTMAIN # --------------- -# Note that this code is called both from `configure', and `config.status' +# Note that this code is called both from 'configure', and 'config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, -# `config.status' has no value for ac_aux_dir unless we are using Automake, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) -ltmain="$ac_aux_dir/ltmain.sh" +ltmain=$ac_aux_dir/ltmain.sh ])# _LT_PROG_LTMAIN @@ -286,7 +298,7 @@ ltmain="$ac_aux_dir/ltmain.sh" # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS -# in macros and then make a single call at the end using the `libtool' +# in macros and then make a single call at the end using the 'libtool' # label. @@ -421,8 +433,8 @@ m4_define([_lt_decl_all_varnames], # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ -# Quote a variable value, and forward it to `config.status' so that its -# declaration there will have the same value as in `configure'. VARNAME +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) @@ -446,7 +458,7 @@ m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl -available_tags="_LT_TAGS"dnl +available_tags='_LT_TAGS'dnl ]) @@ -474,7 +486,7 @@ m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables -# suitable for insertion in the LIBTOOL CONFIG section of the `libtool' +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], @@ -500,8 +512,8 @@ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations -# into `config.status', and then the shell code to quote escape them in -# for loops in `config.status'. Finally, any additional code accumulated +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], @@ -547,7 +559,7 @@ for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -560,7 +572,7 @@ for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -576,7 +588,7 @@ _LT_OUTPUT_LIBTOOL_INIT # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the -# `#!' sequence but before initialization text begins. After this +# '#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). @@ -598,7 +610,7 @@ AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF -test $lt_write_fail = 0 && chmod +x $1[]dnl +test 0 = "$lt_write_fail" && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT @@ -621,7 +633,7 @@ exec AS_MESSAGE_LOG_FD>>config.log } >&AS_MESSAGE_LOG_FD lt_cl_help="\ -\`$as_me' creates a local libtool stub from the current configuration, +'$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. @@ -643,7 +655,7 @@ Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." -while test $[#] != 0 +while test 0 != $[#] do case $[1] in --version | --v* | -V ) @@ -656,10 +668,10 @@ do lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] -Try \`$[0] --help' for more information.]) ;; +Try '$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] -Try \`$[0] --help' for more information.]) ;; +Try '$[0] --help' for more information.]) ;; esac shift done @@ -685,7 +697,7 @@ chmod +x "$CONFIG_LT" # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: -test "$silent" = yes && +test yes = "$silent" && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false @@ -705,27 +717,31 @@ m4_defun([_LT_CONFIG], _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ - # See if we are running on zsh, and set the options which allow our + # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then + if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi - cfgfile="${ofile}T" + cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL - -# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Generated automatically by $as_me ($PACKAGE) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. -# + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + _LT_COPYING _LT_LIBTOOL_TAGS +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS @@ -733,13 +749,24 @@ _LT_LIBTOOL_TAG_VARS _LT_EOF + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then +if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi @@ -753,11 +780,9 @@ _LT_EOF # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? - sed '$q' "$ltmain" >> "$cfgfile" \ + $SED '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) - _LT_PROG_REPLACE_SHELLFNS - mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" @@ -775,7 +800,6 @@ _LT_EOF [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' - TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS @@ -974,7 +998,7 @@ m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no - if test -z "${LT_MULTI_MODULE}"; then + if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the @@ -992,7 +1016,7 @@ m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. - elif test -f libconftest.dylib && test $_lt_result -eq 0; then + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD @@ -1010,7 +1034,7 @@ m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], @@ -1020,8 +1044,8 @@ int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD - echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD - $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$AR $AR_FLAGS libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR $AR_FLAGS libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF @@ -1032,7 +1056,7 @@ _LT_EOF _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD - elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD @@ -1042,32 +1066,27 @@ _LT_EOF ]) case $host_os in rhapsody* | darwin1.[[012]]) - _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; - darwin*) # darwin 5.x on - # if running on 10.5 or later, the deployment target defaults - # to the OS version, if on x86, and 10.4, the deployment - # target defaults to 10.4. Don't you love it? - case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in - 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - 10.[[012]]*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; - 10.*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) + case $MACOSX_DEPLOYMENT_TARGET,$host in + 10.[[012]],*|,*powerpc*-darwin[[5-8]]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + *) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac - if test "$lt_cv_apple_cc_single_mod" = "yes"; then + if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi - if test "$lt_cv_ld_exported_symbols_list" = "yes"; then - _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi - if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= @@ -1087,29 +1106,29 @@ m4_defun([_LT_DARWIN_LINKER_FEATURES], _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - if test "$lt_cv_ld_force_load" = "yes"; then - _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined case $cc_basename in - ifort*) _lt_dar_can_shared=yes ;; + ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac - if test "$_lt_dar_can_shared" = "yes"; then + if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all - _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" - _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" - _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" - _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" m4_if([$1], [CXX], -[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then - _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" - _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi ],[]) else @@ -1129,7 +1148,7 @@ m4_defun([_LT_DARWIN_LINKER_FEATURES], # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl -if test "${lt_cv_aix_libpath+set}" = set; then +if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], @@ -1147,7 +1166,7 @@ else _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then - _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) @@ -1167,8 +1186,8 @@ m4_define([_LT_SHELL_INIT], # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start -# of the generated configure script which will find a shell with a builtin -# printf (which we can use as an echo command). +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO @@ -1196,10 +1215,10 @@ fi # Invoke $ECHO with all args, space-separated. func_echo_all () { - $ECHO "$*" + $ECHO "$*" } -case "$ECHO" in +case $ECHO in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; @@ -1223,35 +1242,37 @@ _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], -[AC_MSG_CHECKING([for sysroot]) +[m4_require([_LT_DECL_SED])dnl +AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], -[ --with-sysroot[=DIR] Search for dependent libraries within DIR - (or the compiler's sysroot if not specified).], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= -case ${with_sysroot} in #( +case $with_sysroot in #( yes) - if test "$GCC" = yes; then + if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) - lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) - AC_MSG_RESULT([${with_sysroot}]) + AC_MSG_RESULT([$with_sysroot]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl -[dependent libraries, and in which our libraries should be installed.])]) +[dependent libraries, and where our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- @@ -1259,32 +1280,34 @@ m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes +test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.$ac_objext` in + case `$FILECMD conftest.$ac_objext` in *ELF-32*) - HPUX_IA64_MODE="32" + HPUX_IA64_MODE=32 ;; *ELF-64*) - HPUX_IA64_MODE="64" + HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then - if test "$lt_cv_prog_gnu_ld" = yes; then - case `/usr/bin/file conftest.$ac_objext` in + if test yes = "$lt_cv_prog_gnu_ld"; then + case `$FILECMD conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; @@ -1296,7 +1319,7 @@ ia64-*-hpux*) ;; esac else - case `/usr/bin/file conftest.$ac_objext` in + case `$FILECMD conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; @@ -1312,21 +1335,68 @@ ia64-*-hpux*) rm -rf conftest* ;; -x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `$FILECMD conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `$FILECMD conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `$FILECMD conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.o` in + case `$FILECMD conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) - LD="${LD-ld} -m elf_i386" + case `$FILECMD conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" ;; - ppc64-*linux*|powerpc64-*linux*) + powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) @@ -1345,7 +1415,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; - ppc*-*linux*|powerpc*-*linux*) + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) @@ -1363,27 +1436,28 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" + SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) - if test x"$lt_cv_cc_needs_belf" != x"yes"; then + if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" + CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.o` in + case `$FILECMD conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in - i?86-*-solaris*) + i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) @@ -1392,7 +1466,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then - LD="${LD-ld}_sol2" + LD=${LD-ld}_sol2 fi ;; *) @@ -1408,7 +1482,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) ;; esac -need_locks="$enable_libtool_lock" +need_locks=$enable_libtool_lock ])# _LT_ENABLE_LOCK @@ -1417,9 +1491,22 @@ need_locks="$enable_libtool_lock" m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} -: ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) -_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +# Use ARFLAGS variable as AR's operation code to sync the variable naming with +# Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have +# higher priority because thats what people were doing historically (setting +# ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS +# variable obsoleted/removed. + +test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr} +lt_ar_flags=$AR_FLAGS +_LT_DECL([], [lt_ar_flags], [0], [Flags to create an archive (by configure)]) + +# Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override +# by AR_FLAGS because that was never working and AR_FLAGS is about to die. +_LT_DECL([], [AR_FLAGS], [\@S|@{ARFLAGS-"\@S|@lt_ar_flags"}], + [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no @@ -1427,11 +1514,11 @@ AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) - if test "$ac_status" -eq 0; then + if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) - if test "$ac_status" -ne 0; then + if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi @@ -1439,7 +1526,7 @@ AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], ]) ]) -if test "x$lt_cv_ar_at_file" = xno; then +if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file @@ -1470,7 +1557,7 @@ old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in - openbsd*) + bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) @@ -1506,7 +1593,7 @@ AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$3" + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins @@ -1533,7 +1620,7 @@ AC_CACHE_CHECK([$1], [$2], $RM conftest* ]) -if test x"[$]$2" = xyes; then +if test yes = "[$]$2"; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) @@ -1555,7 +1642,7 @@ AC_DEFUN([_LT_LINKER_OPTION], m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no - save_LDFLAGS="$LDFLAGS" + save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then @@ -1574,10 +1661,10 @@ AC_CACHE_CHECK([$1], [$2], fi fi $RM -r conftest* - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS ]) -if test x"[$]$2" = xyes; then +if test yes = "[$]$2"; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) @@ -1598,7 +1685,7 @@ AC_DEFUN([LT_CMD_MAX_LEN], AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 - teststring="ABCD" + teststring=ABCD case $build_os in msdosdjgpp*) @@ -1638,7 +1725,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl lt_cv_sys_max_cmd_len=8192; ;; - netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` @@ -1681,29 +1768,30 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then - lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` - if test -n "$lt_cv_sys_max_cmd_len"; then + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. - for i in 1 2 3 4 5 6 7 8 ; do + for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. - while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && - test $i != 17 # 1/2 MB should be enough + test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring @@ -1719,7 +1807,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl ;; esac ]) -if test -n $lt_cv_sys_max_cmd_len ; then +if test -n "$lt_cv_sys_max_cmd_len"; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) @@ -1747,7 +1835,7 @@ m4_defun([_LT_HEADER_DLFCN], # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl -if test "$cross_compiling" = yes; then : +if test yes = "$cross_compiling"; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 @@ -1794,9 +1882,9 @@ else # endif #endif -/* When -fvisbility=hidden is used, assume the code has been annotated +/* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ -#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif @@ -1822,7 +1910,7 @@ int main () return status; }] _LT_EOF - if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in @@ -1843,7 +1931,7 @@ rm -fr conftest* # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl -if test "x$enable_dlopen" != xyes; then +if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown @@ -1853,44 +1941,52 @@ else case $host_os in beos*) - lt_cv_dlopen="load_add_on" + lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) - lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) - lt_cv_dlopen="dlopen" + lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) - # if libdl is installed we need to link against it + # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ - lt_cv_dlopen="dyld" + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + *) AC_CHECK_FUNC([shl_load], - [lt_cv_dlopen="shl_load"], + [lt_cv_dlopen=shl_load], [AC_CHECK_LIB([dld], [shl_load], - [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], [AC_CHECK_FUNC([dlopen], - [lt_cv_dlopen="dlopen"], + [lt_cv_dlopen=dlopen], [AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], [AC_CHECK_LIB([svld], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], [AC_CHECK_LIB([dld], [dld_link], - [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) ]) ]) ]) @@ -1899,21 +1995,21 @@ else ;; esac - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else + if test no = "$lt_cv_dlopen"; then enable_dlopen=no + else + enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - save_LDFLAGS="$LDFLAGS" + save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - save_LIBS="$LIBS" + save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], @@ -1923,7 +2019,7 @@ else lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) - if test "x$lt_cv_dlopen_self" = xyes; then + if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl @@ -1933,9 +2029,9 @@ else ]) fi - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS ;; esac @@ -2027,8 +2123,8 @@ m4_defun([_LT_COMPILER_FILE_LOCKS], m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) -hard_links="nottested" -if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes @@ -2038,8 +2134,8 @@ if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) - if test "$hard_links" = no; then - AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) need_locks=warn fi else @@ -2066,8 +2162,8 @@ objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl -AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", - [Define to the sub-directory in which libtool stores uninstalled libraries.]) +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR @@ -2079,15 +2175,15 @@ m4_defun([_LT_LINKER_HARDCODE_LIBPATH], _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || - test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. - if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one - ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && - test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else @@ -2101,12 +2197,12 @@ else fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) -if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || - test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then # Fast installation is not supported enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi @@ -2122,32 +2218,82 @@ m4_defun([_LT_CMD_STRIPLIB], striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) -if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - AC_MSG_RESULT([yes]) +if test -z "$STRIP"; then + AC_MSG_RESULT([no]) else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then + if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + old_striplib="$STRIP --strip-debug" + striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) + else + case $host_os in + darwin*) + # FIXME - insert some real tests, host_os isn't really good enough striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) - else + ;; + freebsd*) + if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then + old_striplib="$STRIP --strip-debug" + striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) AC_MSG_RESULT([no]) - fi - ;; - *) - AC_MSG_RESULT([no]) - ;; - esac + ;; + esac + fi fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics @@ -2158,17 +2304,18 @@ m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ -if test "$GCC" = yes; then +if test yes = "$GCC"; then case $host_os in - darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; - *) lt_awk_arg="/^libraries:/" ;; + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in - mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; - *) lt_sed_strip_eq="s,=/,/,g" ;; + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in @@ -2184,28 +2331,35 @@ if test "$GCC" = yes; then ;; esac # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary. + # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= - lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path/$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" - else + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' -BEGIN {RS=" "; FS="/|\n";} { - lt_foo=""; - lt_count=0; +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { - lt_foo="/" $lt_i lt_foo; + lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } @@ -2219,7 +2373,7 @@ BEGIN {RS=" "; FS="/|\n";} { # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ - $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else @@ -2228,7 +2382,7 @@ fi]) library_names_spec= libname_spec='lib$name' soname_spec= -shrext_cmds=".so" +shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= @@ -2245,14 +2399,17 @@ hardcode_into_libs=no # flags to be left without arguments need_version=unknown +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' + soname_spec='$libname$release$shared_ext$major' ;; aix[[4-9]]*) @@ -2260,41 +2417,91 @@ aix[[4-9]]*) need_lib_prefix=no need_version=no hardcode_into_libs=yes - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' - echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac shlibpath_var=LIBPATH fi ;; @@ -2304,18 +2511,18 @@ amigaos*) powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) - library_names_spec='${libname}${shared_ext}' + library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; @@ -2323,8 +2530,8 @@ beos*) bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" @@ -2336,7 +2543,7 @@ bsdi[[45]]*) cygwin* | mingw* | pw32* | cegcc*) version_type=windows - shrext_cmds=".dll" + shrext_cmds=.dll need_version=no need_lib_prefix=no @@ -2345,8 +2552,8 @@ cygwin* | mingw* | pw32* | cegcc*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ @@ -2362,27 +2569,27 @@ cygwin* | mingw* | pw32* | cegcc*) case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; - *,cl*) - # Native MSVC + *,cl* | *,icl*) + # Native MSVC or ICC libname_spec='$name' - soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - library_names_spec='${libname}.dll.lib' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' case $build_os in mingw*) @@ -2398,7 +2605,7 @@ m4_if([$1], [],[ done IFS=$lt_save_ifs # Convert to MSYS style. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form @@ -2409,7 +2616,7 @@ m4_if([$1], [],[ sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) - sys_lib_search_path_spec="$LIB" + sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` @@ -2422,8 +2629,8 @@ m4_if([$1], [],[ esac # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' @@ -2435,8 +2642,8 @@ m4_if([$1], [],[ ;; *) - # Assume MSVC wrapper - library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + # Assume MSVC and ICC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac @@ -2449,8 +2656,8 @@ darwin* | rhapsody*) version_type=darwin need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' @@ -2463,12 +2670,12 @@ dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; -freebsd* | dragonfly*) +freebsd* | dragonfly* | midnightbsd*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then @@ -2482,12 +2689,13 @@ freebsd* | dragonfly*) version_type=freebsd-$objformat case $version_type in freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac @@ -2512,26 +2720,15 @@ freebsd* | dragonfly*) esac ;; -gnu*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=yes + shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; @@ -2549,14 +2746,15 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' @@ -2564,8 +2762,8 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; @@ -2574,8 +2772,8 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... @@ -2588,8 +2786,8 @@ interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -2600,7 +2798,7 @@ irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) - if test "$lt_cv_prog_gnu_ld" = yes; then + if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix @@ -2608,8 +2806,8 @@ irix5* | irix6* | nonstopux*) esac need_lib_prefix=no need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= @@ -2628,8 +2826,8 @@ irix5* | irix6* | nonstopux*) esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; @@ -2638,13 +2836,33 @@ linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + # This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -2672,11 +2890,15 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu) # Add ABI-specific directories to the system library path. sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" - # Append ld.so.conf contents to the search path + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" - fi # We used to test for /lib/ld.so.1 and disable shared libraries on @@ -2693,12 +2915,12 @@ netbsd*) need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH @@ -2708,7 +2930,7 @@ netbsd*) newsos6) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; @@ -2717,58 +2939,68 @@ newsos6) version_type=qnx need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; -openbsd*) +openbsd* | bitrig*) version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" + sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[[89]] | openbsd2.[[89]].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no else - shlibpath_overrides_runpath=yes + need_version=yes fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' - shrext_cmds=".dll" + version_type=windows + shrext_cmds=.dll + need_version=no need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) @@ -2779,8 +3011,8 @@ solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes @@ -2790,11 +3022,11 @@ solaris*) sunos4*) version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes @@ -2802,8 +3034,8 @@ sunos4*) sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) @@ -2824,24 +3056,24 @@ sysv4 | sysv4.3*) ;; sysv4*MP*) - if test -d /usr/nec ;then + if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf + version_type=sco need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' @@ -2859,7 +3091,7 @@ tpf*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes @@ -2867,8 +3099,8 @@ tpf*) uts4*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; @@ -2877,20 +3109,30 @@ uts4*) ;; esac AC_MSG_RESULT([$dynamic_linker]) -test "$dynamic_linker" = no && can_build_shared=no +test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then +if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi -if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then - sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi -if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then - sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) @@ -2923,39 +3165,41 @@ _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) -_LT_DECL([], [sys_lib_dlsearch_path_spec], [2], - [Run-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- -# find a file program which can recognize shared library +# find a file program that can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$1; then - lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : @@ -2978,11 +3222,11 @@ _LT_EOF break fi done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac]) -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else @@ -3000,7 +3244,7 @@ dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- -# find a file program which can recognize a shared library +# find a file program that can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then @@ -3027,16 +3271,16 @@ m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], - [test "$withval" = no || with_gnu_ld=yes], + [test no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld -if test "$GCC" = yes; then +if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw + # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; @@ -3050,7 +3294,7 @@ if test "$GCC" = yes; then while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done - test -z "$LD" && LD="$ac_prog" + test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. @@ -3061,37 +3305,37 @@ if test "$GCC" = yes; then with_gnu_ld=unknown ;; esac -elif test "$with_gnu_ld" = yes; then +elif test yes = "$with_gnu_ld"; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" + lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies @@ -3177,13 +3458,13 @@ lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. -# `unknown' -- same as none, but documents that we really don't know. +# 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path -# which responds to the $file_magic_cmd with a given extended regex. -# If you have `file' or equivalent on your system and you're not sure -# whether `pass_all' will *always* work, you probably want this one. +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[[4-9]]*) @@ -3196,7 +3477,7 @@ beos*) bsdi[[45]]*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' - lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_cmd='$FILECMD -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; @@ -3210,8 +3491,7 @@ mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. - # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. - if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else @@ -3231,14 +3511,14 @@ darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; -freebsd* | dragonfly*) +freebsd* | dragonfly* | midnightbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_cmd=$FILECMD lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac @@ -3247,16 +3527,12 @@ freebsd* | dragonfly*) fi ;; -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_cmd=$FILECMD case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' @@ -3289,7 +3565,7 @@ irix5* | irix6* | nonstopux*) ;; # This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; @@ -3303,7 +3579,7 @@ netbsd*) newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_cmd=$FILECMD lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; @@ -3311,8 +3587,8 @@ newos6*) lt_cv_deplibs_check_method=pass_all ;; -openbsd*) - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' @@ -3365,6 +3641,9 @@ sysv4 | sysv4.3*) tpf*) lt_cv_deplibs_check_method=pass_all ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; esac ]) @@ -3405,33 +3684,38 @@ AC_DEFUN([LT_PATH_NM], AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. - lt_cv_path_NM="$NM" + lt_cv_path_NM=$NM else - lt_nm_to_check="${ac_tool_prefix}nm" + lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/$lt_tmp_nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" - break + break 2 ;; *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" - break + break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but @@ -3442,21 +3726,21 @@ else esac fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi]) -if test "$lt_cv_path_NM" != "no"; then - NM="$lt_cv_path_NM" +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) - case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in *COFF*) - DUMPBIN="$DUMPBIN -symbols" + DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: @@ -3464,8 +3748,8 @@ else esac fi AC_SUBST([DUMPBIN]) - if test "$DUMPBIN" != ":"; then - NM="$DUMPBIN" + if test : != "$DUMPBIN"; then + NM=$DUMPBIN fi fi test -z "$NM" && NM=nm @@ -3511,8 +3795,8 @@ lt_cv_sharedlib_from_linklib_cmd, case $host_os in cygwin* | mingw* | pw32* | cegcc*) - # two different shell functions defined in ltmain.sh - # decide which to use based on capabilities of $DLLTOOL + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib @@ -3524,7 +3808,7 @@ cygwin* | mingw* | pw32* | cegcc*) ;; *) # fallback: assume linklib IS sharedlib - lt_cv_sharedlib_from_linklib_cmd="$ECHO" + lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac ]) @@ -3551,13 +3835,28 @@ AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) -if test "x$lt_cv_path_mainfest_tool" != xyes; then +if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + # LT_LIB_M # -------- # check for math library @@ -3569,11 +3868,11 @@ case $host in # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) - AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) - AC_CHECK_LIB(m, cos, LIBM="-lm") + AC_CHECK_LIB(m, cos, LIBM=-lm) ;; esac AC_SUBST([LIBM]) @@ -3592,7 +3891,7 @@ m4_defun([_LT_COMPILER_NO_RTTI], _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= -if test "$GCC" = yes; then +if test yes = "$GCC"; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; @@ -3644,7 +3943,7 @@ cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then symcode='[[ABCDEGRST]]' fi ;; @@ -3677,14 +3976,44 @@ case `$NM -V 2>&1` in symcode='[[ABCDGIRSTW]]' ;; esac +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" +lt_cv_sys_global_symbol_to_cdecl="$SED -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= @@ -3702,26 +4031,29 @@ for ac_symprfx in "" "_"; do # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Fake it for dumpbin and say T for any non-static function - # and D for any global variable. - # Also find C++ and __fastcall symbols from MSVC++, + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++ or ICC, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ -" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ -" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ -" s[1]~/^[@?]/{print s[1], s[1]; next};"\ -" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi - lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no @@ -3756,11 +4088,11 @@ _LT_EOF if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -/* DATA imports from DLLs on WIN32 con't be const, because runtime +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST -#elif defined(__osf__) +#elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else @@ -3786,7 +4118,7 @@ lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; @@ -3806,9 +4138,9 @@ _LT_EOF mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS - LIBS="conftstm.$ac_objext" + LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" - if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS @@ -3829,7 +4161,7 @@ _LT_EOF rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then + if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= @@ -3856,12 +4188,16 @@ _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS @@ -3877,17 +4213,18 @@ _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. - if test "$GXX" = yes; then + if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) @@ -3898,8 +4235,8 @@ m4_if([$1], [CXX], [ ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac @@ -3915,6 +4252,11 @@ m4_if([$1], [CXX], [ # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac ;; darwin* | rhapsody*) # PIC is the default on this platform @@ -3964,7 +4306,7 @@ m4_if([$1], [CXX], [ case $host_os in aix[[4-9]]*) # All AIX code is PIC. - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else @@ -3998,21 +4340,21 @@ m4_if([$1], [CXX], [ ;; esac ;; - freebsd* | dragonfly*) + freebsd* | dragonfly* | midnightbsd*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' - if test "$host_cpu" != ia64; then + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default @@ -4041,7 +4383,7 @@ m4_if([$1], [CXX], [ ;; esac ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler @@ -4049,7 +4391,7 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) - # old Intel C++ for x86_64 which still supported -KPIC. + # old Intel C++ for x86_64, which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' @@ -4081,7 +4423,7 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) - case `$CC -V 2>&1 | sed 5q` in + case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' @@ -4194,17 +4536,18 @@ m4_if([$1], [CXX], [ fi ], [ - if test "$GCC" = yes; then + if test yes = "$GCC"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) @@ -4215,8 +4558,8 @@ m4_if([$1], [CXX], [ ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac @@ -4233,6 +4576,11 @@ m4_if([$1], [CXX], [ # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac ;; darwin* | rhapsody*) @@ -4303,7 +4651,7 @@ m4_if([$1], [CXX], [ case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else @@ -4311,11 +4659,30 @@ m4_if([$1], [CXX], [ fi ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac ;; hpux9* | hpux10* | hpux11*) @@ -4331,7 +4698,7 @@ m4_if([$1], [CXX], [ ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? - _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) @@ -4340,9 +4707,9 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in - # old Intel for x86_64 which still supported -KPIC. + # old Intel for x86_64, which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' @@ -4367,6 +4734,12 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) @@ -4386,7 +4759,7 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) - case `$CC -V 2>&1 | sed 5q` in + case `$CC -V 2>&1 | $SED 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' @@ -4464,7 +4837,7 @@ m4_if([$1], [CXX], [ ;; sysv4*MP*) - if test -d /usr/nec ;then + if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi @@ -4493,7 +4866,7 @@ m4_if([$1], [CXX], [ fi ]) case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: + # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; @@ -4559,21 +4932,25 @@ m4_if([$1], [CXX], [ case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - # Also, AIX nm treats weak defined symbols like other global defined - # symbols, whereas GNU nm marks them as "W". + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) - _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in - cl*) + cl* | icl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) @@ -4615,9 +4992,9 @@ m4_if([$1], [CXX], [ # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if @@ -4630,18 +5007,18 @@ dnl Note also adjust exclude_expsyms for C++ above. case $host_os in cygwin* | mingw* | pw32* | cegcc*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time + # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then + # Microsoft Visual C++ or Intel C++ Compiler. + if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) + # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC) with_gnu_ld=yes ;; - openbsd*) + openbsd* | bitrig*) with_gnu_ld=no ;; esac @@ -4651,7 +5028,7 @@ dnl Note also adjust exclude_expsyms for C++ above. # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility @@ -4673,24 +5050,24 @@ dnl Note also adjust exclude_expsyms for C++ above. esac fi - if test "$lt_use_gnu_ld_interface" = yes; then + if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' + wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then - _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no - case `$LD -v 2>&1` in + case `$LD -v | $SED -e 's/([[^)]]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... @@ -4703,7 +5080,7 @@ dnl Note also adjust exclude_expsyms for C++ above. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then + if test ia64 != "$host_cpu"; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 @@ -4722,7 +5099,7 @@ _LT_EOF case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) @@ -4738,7 +5115,7 @@ _LT_EOF _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME - _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -4748,7 +5125,7 @@ _LT_EOF # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes @@ -4756,61 +5133,90 @@ _LT_EOF _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + ;; + interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no - if test "$host_os" = linux-dietlibc; then + if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ - && test "$tmp_diet" = no + && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; @@ -4821,42 +5227,47 @@ _LT_EOF lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac - case `$CC -V 2>&1 | sed 5q` in + case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C 5.9 - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac - _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then + if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then + if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac @@ -4870,8 +5281,8 @@ _LT_EOF _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; @@ -4889,8 +5300,8 @@ _LT_EOF _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -4902,7 +5313,7 @@ _LT_EOF _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify @@ -4917,9 +5328,9 @@ _LT_EOF # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -4936,15 +5347,15 @@ _LT_EOF *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac - if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= @@ -4960,7 +5371,7 @@ _LT_EOF # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported @@ -4968,34 +5379,57 @@ _LT_EOF ;; aix[[4-9]]*) - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' - no_entry_flag="" + no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - # Also, AIX nm treats weak defined symbols like other global - # defined symbols, whereas GNU nm marks them as "W". + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi ;; esac @@ -5014,13 +5448,21 @@ _LT_EOF _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac - if test "$GCC" = yes; then + if test yes = "$GCC"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` + collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then @@ -5039,61 +5481,80 @@ _LT_EOF ;; esac shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' else # not using gcc - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' else - shared_flag='${wl}-bM:SRE' + shared_flag='$wl-bM:SRE' fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' fi fi - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes - if test "$aix_use_runtimelinking" = yes; then + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else - if test "$host_cpu" = ia64; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - if test "$with_gnu_ld" = yes; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds its shared libraries. - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; @@ -5102,7 +5563,7 @@ _LT_EOF case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) @@ -5119,12 +5580,12 @@ _LT_EOF cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. + # Microsoft Visual C++ or Intel C++ Compiler. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in - cl*) - # Native MSVC + cl* | icl*) + # Native MSVC or ICC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes @@ -5132,16 +5593,17 @@ _LT_EOF # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" + shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; - else - sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes @@ -5150,27 +5612,27 @@ _LT_EOF # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile="$lt_outputfile.exe" - lt_tool_outputfile="$lt_tool_outputfile.exe" - ;; - esac~ - if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' ;; *) - # Assume MSVC wrapper + # Assume MSVC and ICC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" + shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. @@ -5212,7 +5674,7 @@ _LT_EOF ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly*) + freebsd* | dragonfly* | midnightbsd*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes @@ -5220,33 +5682,33 @@ _LT_EOF ;; hpux9*) - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; hpux10*) - if test "$GCC" = yes && test "$with_gnu_ld" = no; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi - if test "$with_gnu_ld" = no; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes @@ -5254,25 +5716,25 @@ _LT_EOF ;; hpux11*) - if test "$GCC" = yes && test "$with_gnu_ld" = no; then + if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ @@ -5280,14 +5742,14 @@ _LT_EOF # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], - [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], - [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi - if test "$with_gnu_ld" = no; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in @@ -5298,7 +5760,7 @@ _LT_EOF *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. @@ -5309,16 +5771,16 @@ _LT_EOF ;; irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], - [save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], @@ -5331,21 +5793,31 @@ _LT_EOF end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) - LDFLAGS="$save_LDFLAGS"]) - if test "$lt_cv_irix_exported_symbol" = yes; then - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out @@ -5360,7 +5832,7 @@ _LT_EOF newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; @@ -5368,27 +5840,19 @@ _LT_EOF *nto* | *qnx*) ;; - openbsd*) + openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' else - case $host_os in - openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - ;; - esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' fi else _LT_TAGVAR(ld_shlibs, $1)=no @@ -5399,33 +5863,54 @@ _LT_EOF _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' ;; osf3*) - if test "$GCC" = yes; then - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' @@ -5436,24 +5921,24 @@ _LT_EOF solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' - if test "$GCC" = yes; then - wlarc='${wl}' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' - _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) - wlarc='${wl}' - _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi @@ -5463,11 +5948,11 @@ _LT_EOF solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. GCC discards it without `$wl', + # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) - if test "$GCC" = yes; then - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi @@ -5477,10 +5962,10 @@ _LT_EOF ;; sunos4*) - if test "x$host_vendor" = xsequent; then + if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi @@ -5529,43 +6014,43 @@ _LT_EOF ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not + # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; @@ -5580,17 +6065,17 @@ _LT_EOF ;; esac - if test x$host_vendor = xsni; then + if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) -test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld @@ -5607,7 +6092,7 @@ x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - if test "$enable_shared" = yes && test "$GCC" = yes; then + if test yes,yes = "$GCC,$enable_shared"; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. @@ -5687,12 +6172,12 @@ _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], - [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], - [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary and the resulting library dependency is - "absolute", i.e impossible to change by setting ${shlibpath_var} if the + "absolute", i.e impossible to change by setting $shlibpath_var if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR @@ -5733,10 +6218,10 @@ dnl [Compiler flag to generate thread safe objects]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write -# the compiler configuration to `libtool'. +# the compiler configuration to 'libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl -lt_save_CC="$CC" +lt_save_CC=$CC AC_LANG_PUSH(C) # Source file extension for C test sources. @@ -5776,18 +6261,18 @@ if test -n "$compiler"; then LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB - # Report which library types will actually be built + # Report what library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) - test "$can_build_shared" = "no" && enable_shared=no + test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) - test "$enable_shared" = yes && enable_static=no + test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' @@ -5795,8 +6280,12 @@ if test -n "$compiler"; then ;; aix[[4-9]]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac fi ;; esac @@ -5804,13 +6293,13 @@ if test -n "$compiler"; then AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes + test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP -CC="$lt_save_CC" +CC=$lt_save_CC ])# _LT_LANG_C_CONFIG @@ -5818,14 +6307,14 @@ CC="$lt_save_CC" # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write -# the compiler configuration to `libtool'. +# the compiler configuration to 'libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl -if test -n "$CXX" && ( test "X$CXX" != "Xno" && - ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || - (test "X$CXX" != "Xg++"))) ; then +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes @@ -5867,7 +6356,7 @@ _LT_TAGVAR(objext, $1)=$objext # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_caught_CXX_error" != yes; then +if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" @@ -5909,35 +6398,35 @@ if test "$_lt_caught_CXX_error" != yes; then if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately - if test "$GXX" = yes; then + if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi - if test "$GXX" = yes; then + if test yes = "$GXX"; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. - if test "$with_gnu_ld" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) - wlarc='${wl}' + wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then - _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi @@ -5973,18 +6462,30 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' - no_entry_flag="" + no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in @@ -5994,6 +6495,13 @@ if test "$_lt_caught_CXX_error" != yes; then ;; esac done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi ;; esac @@ -6012,13 +6520,21 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac - if test "$GXX" = yes; then + if test yes = "$GXX"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` + collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then @@ -6036,64 +6552,84 @@ if test "$_lt_caught_CXX_error" != yes; then fi esac shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' else # not using gcc - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' else - shared_flag='${wl}-bM:SRE' + shared_flag='$wl-bM:SRE' fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' fi fi - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes - if test "$aix_use_runtimelinking" = yes; then + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else - if test "$host_cpu" = ia64; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - if test "$with_gnu_ld" = yes; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds its shared - # libraries. - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; @@ -6103,7 +6639,7 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME - _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -6120,8 +6656,8 @@ if test "$_lt_caught_CXX_error" != yes; then cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in - ,cl* | no,cl*) - # Native MSVC + ,cl* | no,cl* | ,icl* | no,icl*) + # Native MSVC or ICC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' @@ -6131,57 +6667,58 @@ if test "$_lt_caught_CXX_error" != yes; then # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" + shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; - else - $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile="$lt_outputfile.exe" - lt_tool_outputfile="$lt_tool_outputfile.exe" - ;; - esac~ - func_to_tool_file "$lt_outputfile"~ - if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -6192,6 +6729,35 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_DARWIN_LINKER_FEATURES($1) ;; + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + ;; + dgux*) case $cc_basename in ec++*) @@ -6220,24 +6786,21 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; - freebsd* | dragonfly*) + freebsd* | dragonfly* | midnightbsd*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; - gnu*) - ;; - haiku*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default @@ -6249,7 +6812,7 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. @@ -6258,11 +6821,11 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) - if test "$GXX" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no @@ -6272,15 +6835,15 @@ if test "$_lt_caught_CXX_error" != yes; then ;; hpux10*|hpux11*) - if test $with_gnu_ld = no; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; esac fi @@ -6306,13 +6869,13 @@ if test "$_lt_caught_CXX_error" != yes; then aCC*) case $host_cpu in hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists @@ -6323,20 +6886,20 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) - if test "$GXX" = yes; then - if test $with_gnu_ld = no; then + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi @@ -6351,22 +6914,22 @@ if test "$_lt_caught_CXX_error" != yes; then interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is @@ -6375,22 +6938,22 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) - if test "$GXX" = yes; then - if test "$with_gnu_ld" = no; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler @@ -6398,8 +6961,8 @@ if test "$_lt_caught_CXX_error" != yes; then # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. - _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. @@ -6408,10 +6971,10 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. @@ -6425,59 +6988,59 @@ if test "$_lt_caught_CXX_error" != yes; then # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac - _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ - compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ - $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ - $RANLIB $oldlib' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' @@ -6491,29 +7054,29 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) - case `$CC -V 2>&1 | sed 5q` in + case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on @@ -6571,22 +7134,17 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(ld_shlibs, $1)=yes ;; - openbsd2*) - # C++ shared libraries are fairly broken - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - openbsd*) + openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else @@ -6602,9 +7160,9 @@ if test "$_lt_caught_CXX_error" != yes; then # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. - _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using @@ -6622,17 +7180,17 @@ if test "$_lt_caught_CXX_error" != yes; then cxx*) case $host in osf3*) - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ - $RM $lib.exp' + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac @@ -6647,21 +7205,21 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' case $host in osf3*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists @@ -6707,9 +7265,9 @@ if test "$_lt_caught_CXX_error" != yes; then # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no @@ -6717,7 +7275,7 @@ if test "$_lt_caught_CXX_error" != yes; then solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. + # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; @@ -6734,30 +7292,30 @@ if test "$_lt_caught_CXX_error" != yes; then ;; gcx*) # Green Hills C++ Compiler - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else - # g++ 2.7 appears to require `-G' NOT `-shared' on this + # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. - _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when @@ -6765,11 +7323,11 @@ if test "$_lt_caught_CXX_error" != yes; then output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi @@ -6778,52 +7336,52 @@ if test "$_lt_caught_CXX_error" != yes; then ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not + # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ - '"$_LT_TAGVAR(old_archive_cmds, $1)" + '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ - '"$_LT_TAGVAR(reload_cmds, $1)" + '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; @@ -6854,10 +7412,10 @@ if test "$_lt_caught_CXX_error" != yes; then esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) - test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no - _LT_TAGVAR(GCC, $1)="$GXX" - _LT_TAGVAR(LD, $1)="$LD" + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change @@ -6884,7 +7442,7 @@ if test "$_lt_caught_CXX_error" != yes; then lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld -fi # test "$_lt_caught_CXX_error" != yes +fi # test yes != "$_lt_caught_CXX_error" AC_LANG_POP ])# _LT_LANG_CXX_CONFIG @@ -6906,13 +7464,14 @@ AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { - case ${2} in - .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF + # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose @@ -6996,13 +7555,13 @@ if AC_TRY_EVAL(ac_compile); then pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do - case ${prev}${p} in + case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. - if test $p = "-L" || - test $p = "-R"; then + if test x-L = "$p" || + test x-R = "$p"; then prev=$p continue fi @@ -7018,16 +7577,16 @@ if AC_TRY_EVAL(ac_compile); then case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac - if test "$pre_test_object_deps_done" = no; then - case ${prev} in + if test no = "$pre_test_object_deps_done"; then + case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then - _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p else - _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" fi ;; # The "-l" case would never come before the object being @@ -7035,9 +7594,9 @@ if AC_TRY_EVAL(ac_compile); then esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then - _LT_TAGVAR(postdeps, $1)="${prev}${p}" + _LT_TAGVAR(postdeps, $1)=$prev$p else - _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" fi fi prev= @@ -7052,15 +7611,15 @@ if AC_TRY_EVAL(ac_compile); then continue fi - if test "$pre_test_object_deps_done" = no; then + if test no = "$pre_test_object_deps_done"; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then - _LT_TAGVAR(predep_objects, $1)="$p" + _LT_TAGVAR(predep_objects, $1)=$p else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then - _LT_TAGVAR(postdep_objects, $1)="$p" + _LT_TAGVAR(postdep_objects, $1)=$p else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi @@ -7091,51 +7650,6 @@ interix[[3-9]]*) _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; - -linux*) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - - if test "$solaris_use_stlport4" != yes; then - _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' - fi - ;; - esac - ;; - -solaris*) - case $cc_basename in - CC* | sunCC*) - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - - # Adding this requires a known-good setup of shared libraries for - # Sun compiler versions before 5.6, else PIC objects from an old - # archive will be linked into the output, leading to subtle bugs. - if test "$solaris_use_stlport4" != yes; then - _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' - fi - ;; - esac - ;; esac ]) @@ -7144,7 +7658,7 @@ case " $_LT_TAGVAR(postdeps, $1) " in esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then - _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) @@ -7164,10 +7678,10 @@ _LT_TAGDECL([], [compiler_lib_search_path], [1], # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. +# to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) -if test -z "$F77" || test "X$F77" = "Xno"; then +if test -z "$F77" || test no = "$F77"; then _lt_disable_F77=yes fi @@ -7204,7 +7718,7 @@ _LT_TAGVAR(objext, $1)=$objext # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_disable_F77" != yes; then +if test yes != "$_lt_disable_F77"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t @@ -7226,7 +7740,7 @@ if test "$_lt_disable_F77" != yes; then _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. - lt_save_CC="$CC" + lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} @@ -7240,21 +7754,25 @@ if test "$_lt_disable_F77" != yes; then AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) - test "$can_build_shared" = "no" && enable_shared=no + test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) - test "$enable_shared" = yes && enable_static=no + test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac fi ;; esac @@ -7262,11 +7780,11 @@ if test "$_lt_disable_F77" != yes; then AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes + test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) - _LT_TAGVAR(GCC, $1)="$G77" - _LT_TAGVAR(LD, $1)="$LD" + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change @@ -7283,9 +7801,9 @@ if test "$_lt_disable_F77" != yes; then fi # test -n "$compiler" GCC=$lt_save_GCC - CC="$lt_save_CC" - CFLAGS="$lt_save_CFLAGS" -fi # test "$_lt_disable_F77" != yes + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" AC_LANG_POP ])# _LT_LANG_F77_CONFIG @@ -7295,11 +7813,11 @@ AC_LANG_POP # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. +# to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) -if test -z "$FC" || test "X$FC" = "Xno"; then +if test -z "$FC" || test no = "$FC"; then _lt_disable_FC=yes fi @@ -7336,7 +7854,7 @@ _LT_TAGVAR(objext, $1)=$objext # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_disable_FC" != yes; then +if test yes != "$_lt_disable_FC"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t @@ -7358,7 +7876,7 @@ if test "$_lt_disable_FC" != yes; then _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. - lt_save_CC="$CC" + lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} @@ -7374,21 +7892,25 @@ if test "$_lt_disable_FC" != yes; then AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) - test "$can_build_shared" = "no" && enable_shared=no + test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) - test "$enable_shared" = yes && enable_static=no + test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac fi ;; esac @@ -7396,11 +7918,11 @@ if test "$_lt_disable_FC" != yes; then AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes + test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) - _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" - _LT_TAGVAR(LD, $1)="$LD" + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change @@ -7420,7 +7942,7 @@ if test "$_lt_disable_FC" != yes; then GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS -fi # test "$_lt_disable_FC" != yes +fi # test yes != "$_lt_disable_FC" AC_LANG_POP ])# _LT_LANG_FC_CONFIG @@ -7430,7 +7952,7 @@ AC_LANG_POP # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. +# to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE @@ -7464,7 +7986,7 @@ CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC -_LT_TAGVAR(LD, $1)="$LD" +_LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. @@ -7501,7 +8023,7 @@ CFLAGS=$lt_save_CFLAGS # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. +# to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE @@ -7535,7 +8057,7 @@ CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC -_LT_TAGVAR(LD, $1)="$LD" +_LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. @@ -7572,7 +8094,7 @@ CFLAGS=$lt_save_CFLAGS # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. +# to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE @@ -7588,7 +8110,7 @@ _LT_TAGVAR(objext, $1)=$objext lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests -lt_simple_link_test_code="$lt_simple_compile_test_code" +lt_simple_link_test_code=$lt_simple_compile_test_code # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER @@ -7598,7 +8120,7 @@ _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. -lt_save_CC="$CC" +lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= @@ -7627,7 +8149,7 @@ AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) - test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) @@ -7693,6 +8215,14 @@ _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) +# _LT_DECL_FILECMD +# ---------------- +# Check for a file(cmd) program that can be used to detect file type and magic +m4_defun([_LT_DECL_FILECMD], +[AC_CHECK_TOOL([FILECMD], [file], [:]) +_LT_DECL([], [FILECMD], [1], [A file(cmd) program that detects file types]) +])# _LD_DECL_FILECMD + # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates @@ -7738,7 +8268,7 @@ lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do - test ! -f $lt_ac_sed && continue + test ! -f "$lt_ac_sed" && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in @@ -7755,9 +8285,9 @@ for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough - test $lt_ac_count -gt 10 && break + test 10 -lt "$lt_ac_count" && break lt_ac_count=`expr $lt_ac_count + 1` - if test $lt_ac_count -gt $lt_ac_max; then + if test "$lt_ac_count" -gt "$lt_ac_max"; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi @@ -7781,27 +8311,7 @@ dnl AC_DEFUN([LT_AC_PROG_SED], []) # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], -[AC_MSG_CHECKING([whether the shell understands some XSI constructs]) -# Try some XSI features -xsi_shell=no -( _lt_dummy="a/b/c" - test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ - = c,a/b,b/c, \ - && eval 'test $(( 1 + 1 )) -eq 2 \ - && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ - && xsi_shell=yes -AC_MSG_RESULT([$xsi_shell]) -_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) - -AC_MSG_CHECKING([whether the shell understands "+="]) -lt_shell_append=no -( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ - >/dev/null 2>&1 \ - && lt_shell_append=yes -AC_MSG_RESULT([$lt_shell_append]) -_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) - -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false @@ -7825,102 +8335,9 @@ _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES -# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) -# ------------------------------------------------------ -# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and -# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. -m4_defun([_LT_PROG_FUNCTION_REPLACE], -[dnl { -sed -e '/^$1 ()$/,/^} # $1 /c\ -$1 ()\ -{\ -m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) -} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: -]) - - -# _LT_PROG_REPLACE_SHELLFNS -# ------------------------- -# Replace existing portable implementations of several shell functions with -# equivalent extended shell implementations where those features are available.. -m4_defun([_LT_PROG_REPLACE_SHELLFNS], -[if test x"$xsi_shell" = xyes; then - _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac]) - - _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl - func_basename_result="${1##*/}"]) - - _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac - func_basename_result="${1##*/}"]) - - _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl - # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are - # positional parameters, so assign one to ordinary parameter first. - func_stripname_result=${3} - func_stripname_result=${func_stripname_result#"${1}"} - func_stripname_result=${func_stripname_result%"${2}"}]) - - _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl - func_split_long_opt_name=${1%%=*} - func_split_long_opt_arg=${1#*=}]) - - _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl - func_split_short_opt_arg=${1#??} - func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) - - _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl - case ${1} in - *.lo) func_lo2o_result=${1%.lo}.${objext} ;; - *) func_lo2o_result=${1} ;; - esac]) - - _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) - - _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) - - _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) -fi - -if test x"$lt_shell_append" = xyes; then - _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) - - _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl - func_quote_for_eval "${2}" -dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ - eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) - - # Save a `func_append' function call where possible by direct use of '+=' - sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") - test 0 -eq $? || _lt_function_replace_fail=: -else - # Save a `func_append' function call even when '+=' is not available - sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") - test 0 -eq $? || _lt_function_replace_fail=: -fi - -if test x"$_lt_function_replace_fail" = x":"; then - AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) -fi -]) - # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- -# Determine which file name conversion functions should be used by +# Determine what file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4 index 5d9acd8..b0b5e9c 100644 --- a/m4/ltoptions.m4 +++ b/m4/ltoptions.m4 @@ -1,14 +1,14 @@ # Helper functions for option handling. -*- Autoconf -*- # -# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, -# Inc. +# Copyright (C) 2004-2005, 2007-2009, 2011-2019, 2021-2022 Free +# Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. -# serial 7 ltoptions.m4 +# serial 8 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) @@ -29,7 +29,7 @@ m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), - [m4_warning([Unknown $1 option `$2'])])[]dnl + [m4_warning([Unknown $1 option '$2'])])[]dnl ]) @@ -75,13 +75,15 @@ m4_if([$1],[LT_INIT],[ dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither - dnl `shared' nor `disable-shared' was passed, we enable building of shared + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], - [_LT_ENABLE_FAST_INSTALL]) + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS @@ -112,7 +114,7 @@ AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you -put the `dlopen' option into LT_INIT's first parameter.]) +put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: @@ -148,7 +150,7 @@ AU_DEFUN([AC_LIBTOOL_WIN32_DLL], _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you -put the `win32-dll' option into LT_INIT's first parameter.]) +put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: @@ -157,9 +159,9 @@ dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- -# implement the --enable-shared flag, and supports the `shared' and -# `disable-shared' LT_INIT options. -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], @@ -172,14 +174,14 @@ AC_ARG_ENABLE([shared], *) enable_shared=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) @@ -211,9 +213,9 @@ dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- -# implement the --enable-static flag, and support the `static' and -# `disable-static' LT_INIT options. -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], @@ -226,14 +228,14 @@ AC_ARG_ENABLE([static], *) enable_static=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) @@ -265,9 +267,9 @@ dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- -# implement the --enable-fast-install flag, and support the `fast-install' -# and `disable-fast-install' LT_INIT options. -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], @@ -280,14 +282,14 @@ AC_ARG_ENABLE([fast-install], *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) @@ -304,14 +306,14 @@ AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put -the `fast-install' option into LT_INIT's first parameter.]) +the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put -the `disable-fast-install' option into LT_INIT's first parameter.]) +the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: @@ -319,11 +321,64 @@ dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + # _LT_WITH_PIC([MODE]) # -------------------- -# implement the --with-pic flag, and support the `pic-only' and `no-pic' +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. -# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], @@ -334,19 +389,17 @@ m4_define([_LT_WITH_PIC], *) pic_mode=default # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac], - [pic_mode=default]) - -test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) + [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC @@ -359,7 +412,7 @@ AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you -put the `pic-only' option into LT_INIT's first parameter.]) +put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: diff --git a/m4/ltsugar.m4 b/m4/ltsugar.m4 index 9000a05..902508b 100644 --- a/m4/ltsugar.m4 +++ b/m4/ltsugar.m4 @@ -1,6 +1,7 @@ # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # -# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Copyright (C) 2004-2005, 2007-2008, 2011-2019, 2021-2022 Free Software +# Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives @@ -33,7 +34,7 @@ m4_define([_lt_join], # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support -# Autoconf-2.59 which quotes differently. +# Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], @@ -44,7 +45,7 @@ m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ -# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different diff --git a/m4/ltversion.m4 b/m4/ltversion.m4 index 07a8602..b155d0a 100644 --- a/m4/ltversion.m4 +++ b/m4/ltversion.m4 @@ -1,6 +1,7 @@ # ltversion.m4 -- version numbers -*- Autoconf -*- # -# Copyright (C) 2004 Free Software Foundation, Inc. +# Copyright (C) 2004, 2011-2019, 2021-2022 Free Software Foundation, +# Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives @@ -9,15 +10,15 @@ # @configure_input@ -# serial 3337 ltversion.m4 +# serial 4245 ltversion.m4 # This file is part of GNU Libtool -m4_define([LT_PACKAGE_VERSION], [2.4.2]) -m4_define([LT_PACKAGE_REVISION], [1.3337]) +m4_define([LT_PACKAGE_VERSION], [2.4.7]) +m4_define([LT_PACKAGE_REVISION], [2.4.7]) AC_DEFUN([LTVERSION_VERSION], -[macro_version='2.4.2' -macro_revision='1.3337' +[macro_version='2.4.7' +macro_revision='2.4.7' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4 index c573da9..0f7a875 100644 --- a/m4/lt~obsolete.m4 +++ b/m4/lt~obsolete.m4 @@ -1,6 +1,7 @@ # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # -# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. +# Copyright (C) 2004-2005, 2007, 2009, 2011-2019, 2021-2022 Free +# Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives @@ -11,7 +12,7 @@ # These exist entirely to fool aclocal when bootstrapping libtool. # -# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # @@ -25,7 +26,7 @@ # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. -# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until diff --git a/man/Makefile.am b/man/Makefile.am deleted file mode 100644 index af1277b..0000000 --- a/man/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -# -*- Makefile -*- - -dist_man8_MANS = \ - nl-classid-lookup.8 \ - nl-pktloc-lookup.8 \ - nl-qdisc-add.8 nl-qdisc-delete.8 nl-qdisc-list.8 \ - genl-ctrl-list.8 diff --git a/man/Makefile.in b/man/Makefile.in deleted file mode 100644 index 69b1803..0000000 --- a/man/Makefile.in +++ /dev/null @@ -1,502 +0,0 @@ -# Makefile.in generated by automake 1.11.6 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -# -*- Makefile -*- -VPATH = @srcdir@ -am__make_dryrun = \ - { \ - am__dry=no; \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ - esac; \ - test $$am__dry = yes; \ - } -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = man -DIST_COMMON = $(dist_man8_MANS) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/lib/defs.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -SOURCES = -DIST_SOURCES = -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -man8dir = $(mandir)/man8 -am__installdirs = "$(DESTDIR)$(man8dir)" -NROFF = nroff -MANS = $(dist_man8_MANS) -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CHECK_CFLAGS = @CHECK_CFLAGS@ -CHECK_LIBS = @CHECK_LIBS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -FLEX = @FLEX@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBNL_VERSION = @LIBNL_VERSION@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_AGE = @LT_AGE@ -LT_CURRENT = @LT_CURRENT@ -LT_REVISION = @LT_REVISION@ -MAJ_VERSION = @MAJ_VERSION@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MIC_VERSION = @MIC_VERSION@ -MIN_VERSION = @MIN_VERSION@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -YACC = @YACC@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgconfigdir = @pkgconfigdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -subdirs = @subdirs@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -dist_man8_MANS = \ - nl-classid-lookup.8 \ - nl-pktloc-lookup.8 \ - nl-qdisc-add.8 nl-qdisc-delete.8 nl-qdisc-list.8 \ - genl-ctrl-list.8 - -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign man/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign man/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -install-man8: $(dist_man8_MANS) - @$(NORMAL_INSTALL) - @list1='$(dist_man8_MANS)'; \ - list2=''; \ - test -n "$(man8dir)" \ - && test -n "`echo $$list1$$list2`" \ - || exit 0; \ - echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ - { for i in $$list1; do echo "$$i"; done; \ - if test -n "$$list2"; then \ - for i in $$list2; do echo "$$i"; done \ - | sed -n '/\.8[a-z]*$$/p'; \ - fi; \ - } | while read p; do \ - if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; echo "$$p"; \ - done | \ - sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ - -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ - sed 'N;N;s,\n, ,g' | { \ - list=; while read file base inst; do \ - if test "$$base" = "$$inst"; then list="$$list $$file"; else \ - echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ - $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ - fi; \ - done; \ - for i in $$list; do echo "$$i"; done | $(am__base_list) | \ - while read files; do \ - test -z "$$files" || { \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ - done; } - -uninstall-man8: - @$(NORMAL_UNINSTALL) - @list='$(dist_man8_MANS)'; test -n "$(man8dir)" || exit 0; \ - files=`{ for i in $$list; do echo "$$i"; done; \ - } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ - -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ - dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) -tags: TAGS -TAGS: - -ctags: CTAGS -CTAGS: - - -distdir: $(DISTFILES) - @list='$(MANS)'; if test -n "$$list"; then \ - list=`for p in $$list; do \ - if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ - if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ - if test -n "$$list" && \ - grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ - echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ - grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ - echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ - echo " typically \`make maintainer-clean' will remove them" >&2; \ - exit 1; \ - else :; fi; \ - else :; fi - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(MANS) -installdirs: - for dir in "$(DESTDIR)$(man8dir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: install-man - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: install-man8 - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-man - -uninstall-man: uninstall-man8 - -.MAKE: install-am install-strip - -.PHONY: all all-am check check-am clean clean-generic clean-libtool \ - distclean distclean-generic distclean-libtool distdir dvi \ - dvi-am html html-am info info-am install install-am \ - install-data install-data-am install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-man8 \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - uninstall uninstall-am uninstall-man uninstall-man8 - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/python/Makefile.am b/python/Makefile.am deleted file mode 100644 index bd5ac11..0000000 --- a/python/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -# -*- Makefile -*- - -SUBDIRS = netlink diff --git a/python/Makefile.in b/python/Makefile.in deleted file mode 100644 index ba2d070..0000000 --- a/python/Makefile.in +++ /dev/null @@ -1,607 +0,0 @@ -# Makefile.in generated by automake 1.11.6 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -# -*- Makefile -*- -VPATH = @srcdir@ -am__make_dryrun = \ - { \ - am__dry=no; \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ - esac; \ - test $$am__dry = yes; \ - } -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = python -DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(srcdir)/setup.py.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/lib/defs.h -CONFIG_CLEAN_FILES = setup.py -CONFIG_CLEAN_VPATH_FILES = -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -SOURCES = -DIST_SOURCES = -RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ - html-recursive info-recursive install-data-recursive \ - install-dvi-recursive install-exec-recursive \ - install-html-recursive install-info-recursive \ - install-pdf-recursive install-ps-recursive install-recursive \ - installcheck-recursive installdirs-recursive pdf-recursive \ - ps-recursive uninstall-recursive -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ - distclean-recursive maintainer-clean-recursive -AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ - $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ - distdir -ETAGS = etags -CTAGS = ctags -DIST_SUBDIRS = $(SUBDIRS) -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -am__relativize = \ - dir0=`pwd`; \ - sed_first='s,^\([^/]*\)/.*$$,\1,'; \ - sed_rest='s,^[^/]*/*,,'; \ - sed_last='s,^.*/\([^/]*\)$$,\1,'; \ - sed_butlast='s,/*[^/]*$$,,'; \ - while test -n "$$dir1"; do \ - first=`echo "$$dir1" | sed -e "$$sed_first"`; \ - if test "$$first" != "."; then \ - if test "$$first" = ".."; then \ - dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ - dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ - else \ - first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ - if test "$$first2" = "$$first"; then \ - dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ - else \ - dir2="../$$dir2"; \ - fi; \ - dir0="$$dir0"/"$$first"; \ - fi; \ - fi; \ - dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ - done; \ - reldir="$$dir2" -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CHECK_CFLAGS = @CHECK_CFLAGS@ -CHECK_LIBS = @CHECK_LIBS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -FLEX = @FLEX@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBNL_VERSION = @LIBNL_VERSION@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_AGE = @LT_AGE@ -LT_CURRENT = @LT_CURRENT@ -LT_REVISION = @LT_REVISION@ -MAJ_VERSION = @MAJ_VERSION@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MIC_VERSION = @MIC_VERSION@ -MIN_VERSION = @MIN_VERSION@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -YACC = @YACC@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgconfigdir = @pkgconfigdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -subdirs = @subdirs@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -SUBDIRS = netlink -all: all-recursive - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign python/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign python/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): -setup.py: $(top_builddir)/config.status $(srcdir)/setup.py.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -# This directory's subdirectories are mostly independent; you can cd -# into them and run `make' without going through this Makefile. -# To change the values of `make' variables: instead of editing Makefiles, -# (1) if the variable is set in `config.status', edit `config.status' -# (which will cause the Makefiles to be regenerated when you run `make'); -# (2) otherwise, pass the desired values on the `make' command line. -$(RECURSIVE_TARGETS): - @fail= failcom='exit 1'; \ - for f in x $$MAKEFLAGS; do \ - case $$f in \ - *=* | --[!k]*);; \ - *k*) failcom='fail=yes';; \ - esac; \ - done; \ - dot_seen=no; \ - target=`echo $@ | sed s/-recursive//`; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - dot_seen=yes; \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || eval $$failcom; \ - done; \ - if test "$$dot_seen" = "no"; then \ - $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ - fi; test -z "$$fail" - -$(RECURSIVE_CLEAN_TARGETS): - @fail= failcom='exit 1'; \ - for f in x $$MAKEFLAGS; do \ - case $$f in \ - *=* | --[!k]*);; \ - *k*) failcom='fail=yes';; \ - esac; \ - done; \ - dot_seen=no; \ - case "$@" in \ - distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ - *) list='$(SUBDIRS)' ;; \ - esac; \ - rev=''; for subdir in $$list; do \ - if test "$$subdir" = "."; then :; else \ - rev="$$subdir $$rev"; \ - fi; \ - done; \ - rev="$$rev ."; \ - target=`echo $@ | sed s/-recursive//`; \ - for subdir in $$rev; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || eval $$failcom; \ - done && test -z "$$fail" -tags-recursive: - list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ - done -ctags-recursive: - list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ - done - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - set x; \ - here=`pwd`; \ - if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ - include_option=--etags-include; \ - empty_fix=.; \ - else \ - include_option=--include; \ - empty_fix=; \ - fi; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - test ! -f $$subdir/TAGS || \ - set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ - fi; \ - done; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: CTAGS -CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - $(am__make_dryrun) \ - || test -d "$(distdir)/$$subdir" \ - || $(MKDIR_P) "$(distdir)/$$subdir" \ - || exit 1; \ - dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ - $(am__relativize); \ - new_distdir=$$reldir; \ - dir1=$$subdir; dir2="$(top_distdir)"; \ - $(am__relativize); \ - new_top_distdir=$$reldir; \ - echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ - echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ - ($(am__cd) $$subdir && \ - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$$new_top_distdir" \ - distdir="$$new_distdir" \ - am__remove_distdir=: \ - am__skip_length_check=: \ - am__skip_mode_fix=: \ - distdir) \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-recursive -all-am: Makefile -installdirs: installdirs-recursive -installdirs-am: -install: install-recursive -install-exec: install-exec-recursive -install-data: install-data-recursive -uninstall: uninstall-recursive - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-recursive -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-recursive - -clean-am: clean-generic clean-libtool mostlyclean-am - -distclean: distclean-recursive - -rm -f Makefile -distclean-am: clean-am distclean-generic distclean-tags - -dvi: dvi-recursive - -dvi-am: - -html: html-recursive - -html-am: - -info: info-recursive - -info-am: - -install-data-am: - -install-dvi: install-dvi-recursive - -install-dvi-am: - -install-exec-am: - -install-html: install-html-recursive - -install-html-am: - -install-info: install-info-recursive - -install-info-am: - -install-man: - -install-pdf: install-pdf-recursive - -install-pdf-am: - -install-ps: install-ps-recursive - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-recursive - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-recursive - -mostlyclean-am: mostlyclean-generic mostlyclean-libtool - -pdf: pdf-recursive - -pdf-am: - -ps: ps-recursive - -ps-am: - -uninstall-am: - -.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ - install-am install-strip tags-recursive - -.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ - all all-am check check-am clean clean-generic clean-libtool \ - ctags ctags-recursive distclean distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs installdirs-am maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-generic \ - mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ - uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/python/doc/conf.py b/python/doc/conf.py new file mode 100644 index 0000000..dfa53ab --- /dev/null +++ b/python/doc/conf.py @@ -0,0 +1,224 @@ +# -*- coding: utf-8 -*- +# +# libnl-python documentation build configuration file, created by +# sphinx-quickstart on Mon May 9 10:58:58 2011. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ["sphinx.ext.todo", "sphinx.ext.ifconfig", "sphinx.ext.viewcode"] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# The suffix of source filenames. +source_suffix = ".rst" + +# The encoding of source files. +# source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = "index" + +# General information about the project. +project = "libnl-python" +copyright = "2011, Thomas Graf " + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = "1.0" +# The full version, including alpha/beta/rc tags. +release = "1.0" + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +# today = '' +# Else, today_fmt is used as the format for a strftime call. +# today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ["_build"] + +# The reST default role (used for this markup: `text`) to use for all documents. +# default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +# add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +# add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +# show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = "sphinx" + +# A list of ignored prefixes for module index sorting. +# modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = "default" + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +# html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +# html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +# html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +# html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +# html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ["_static"] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +# html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +# html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +# html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +# html_additional_pages = {} + +# If false, no module index is generated. +# html_domain_indices = True + +# If false, no index is generated. +# html_use_index = True + +# If true, the index is split into individual pages for each letter. +# html_split_index = False + +# If true, links to the reST sources are added to the pages. +# html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +# html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +# html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +# html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +# html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = "libnl-pythondoc" + + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +# latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +# latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ( + "index", + "libnl-python.tex", + "libnl-python Documentation", + "Thomas Graf \\textless{}tgraf@suug.ch\\textgreater{}", + "manual", + ), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +# latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +# latex_use_parts = False + +# If true, show page references after internal links. +# latex_show_pagerefs = False + +# If true, show URL addresses after external links. +# latex_show_urls = False + +# Additional stuff for the LaTeX preamble. +# latex_preamble = '' + +# Documents to append as an appendix to all manuals. +# latex_appendices = [] + +# If false, no module index is generated. +# latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ( + "index", + "libnl-python", + "libnl-python Documentation", + ["Thomas Graf "], + 1, + ) +] diff --git a/python/doc/core.rst b/python/doc/core.rst new file mode 100644 index 0000000..012e14c --- /dev/null +++ b/python/doc/core.rst @@ -0,0 +1,215 @@ +******************* +Netlink Core Module +******************* + +.. py:module:: netlink.core + +Examples:: + + import netlink.core as netlink + +=============== +Object +=============== + +.. py:class:: Object + + Base class for all classes representing a cacheable object + + Example:: + obj = netlink.Object("route/link", "link") + + .. py:method:: clone + + Clone the object and return a duplicate (used for COW) + + .. py:method:: dump([params=None]) + + Call the libnl internal dump mechanism to dump the object + according to the parameters specified. + + .. py:method:: apply(attr, val) + + Applies a attribute=value pair and modifies the object accordingly. + Example:: + obj.apply("mtu", 1200) # Sets attribute mtu to 1200 (link obj) + + :raises: KeyError if attribute is unknown + :raises: ImmutableError if attribute is not mutable + + .. py:attribute:: mark + + True if the object is marked, otherwise False. + + .. py:attribute:: shared + + True if the object is used by multiple parties, otherwise False. + + .. py:attribute:: refcnt + + Number of users sharing a reference to the object + :rtype: int + + .. py:attribute:: attrs + + List of attributes + + :rtype: list of strings + +=============== +Cache +=============== + +.. py:class:: Cache + + Base class for all cache implementations. + + A cache is a collection of cacheable objects which is typically used + by netlink protocols which handle any kind of object, e.g. network + links, network addresses, neighbours, ... + + .. py:method:: subset(filter) + + Returns a new cache containing the subset which matches the + provided filter. + + :raises: ValueError if no filter is specified + :rtype: :py:class:`Cache` + + .. py:method:: dump([params=None, filter=None]) + + Calls the libnl internal dump mechanism to dump the cache according + to the parameters and filter specified. + + .. py:method:: clear() + + Remove and possibly destroy all objects in the cache + + .. py:method:: refill([socket=None]) -> :py:class:`Cache` + + Clears and refills the cache with the content which is provided by + the kernel, e.g. for a link cache this would mean refilling the + cache with all configured network links. + + .. py:method:: provide() + + Caches which have been "provided" are made available to other users + (of the same application context) which "require" it. F.e. a link + cache is generally provided to allow others to translate interface + indexes to link names + + + .. py:method:: unprovide() + + No longer make the cache available to others. If the cache has been + handed out already, that reference will still be valid. + +=============== +AbstractAddress +=============== + +.. py:class:: AbstractAddress + + Abstract representation of an address. This class is not to be mistaken + with :py:class:`route.Address` which represents a configured network + address. This class represents the actual address in a family independent + way:: + + addr = netlink.AbstractAddress('127.0.0.1/8') + print addr # => '127.0.0.1/8' + print addr.prefixlen # => '8' + print addr.family # => 'inet' + print len(addr) # => '4' (32bit ipv4 address) + + a = netlink.AbstractAddress('10.0.0.1/24') + b = netlink.AbstractAddress('10.0.0.2/24') + print a == b # => False + + .. py:attribute:: prefixlen + + Length of prefix in number of bits. + + :rtype: int + + .. py:attribute:: family + + The family type of the address. Setting the address family can be + done with a string or a :py:class:`AddressFamily` object. + + :rtype: :py:class:`AddressFamily` + + .. py:attribute:: shared + + True if address is in use by multiple callers, otherwise False + + :rtype: bool + +=============== +AddressFamily +=============== + +.. py:class:: AddressFamily + + Address family representation:: + + af = netlink.AddressFamily('inet6') + # raises: + # - ValueError if family name is not known + # - TypeError if invalid type is specified for family + + print af # => 'inet6' (string representation) + print int(af) # => 10 (numeric representation) + print repr(af) # => AddressFamily('inet6') + +=============== +Exceptions +=============== + +.. py:exception:: NetlinkError + + Generic exception raised by netlink modules. + +.. py:exception:: KernelError + + Raised if an error occured while communicating with the kernel. Contains + the error code returning which is automatically included in the error + message. + +.. py:exception:: ImmutableError + + Raised if an attribute is modified which is marked immutable. + +=============== +Socket +=============== + +.. py:class:: Socket + + Netlink socket. + + Note: It is not required to manually create and connect netlink sockets + when using caches. The caches will automatically lookup or create a + socket as needed. + + .. py:attribute:: local_port + + Local port (address) of netlink socket + + .. py:attribute:: peer_port + + Peer port (remote address) of netlink socket. If set, all messages + will be sent to that peer. + + .. py:method:: connect(proto) + + Connect the netlink socket using the specified netlink protocol:: + sock.connect(netlink.NETLINK_ROUTE) + + .. py:method:: disconnect() + + Disconnect the socket + + .. py:method:: set_bufsize(rx, tx) + + Sets the size of the socket buffer + diff --git a/python/doc/index.rst b/python/doc/index.rst new file mode 100644 index 0000000..8de8ae3 --- /dev/null +++ b/python/doc/index.rst @@ -0,0 +1,24 @@ +.. libnl-python documentation master file, created by + sphinx-quickstart on Mon May 9 10:58:58 2011. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to libnl-python's documentation! +======================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + core + route + route_addr + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/python/doc/route.rst b/python/doc/route.rst new file mode 100644 index 0000000..0b8f3f9 --- /dev/null +++ b/python/doc/route.rst @@ -0,0 +1,3 @@ +********************** +Routing +********************** diff --git a/python/doc/route_addr.rst b/python/doc/route_addr.rst new file mode 100644 index 0000000..2cfe139 --- /dev/null +++ b/python/doc/route_addr.rst @@ -0,0 +1,47 @@ +================= +Network Addresses +================= + +The **Address** module provides access to the network address configuration +of the kernel. It provides an interface to fetch all configured addresses, +add new addresses and to delete existing addresses. + +Fetching the list of network addresses is achieved by creating a new +address cache:: + + import netlink.route.address as Address + + addr_cache = Address.AddressCache() + addr_cache.refill() + + for addr in addr_cache: + print addr + +.. py:module:: netlink.route.addr + + +AddressCache +------------ + +.. py:class:: AddressCache + + Represents a cache containing all or a subset of network addresses. + + .. py:method:: lookup(ifindex, local) + + Lookup the address which matches ifindex and local address + + :raises: KeyError if address is not found. + +Address +------- + +.. py:class:: Address + + Representation of a configured network address. + + .. py:attribute:: ifindex + + Interface index + + :rtype: int diff --git a/python/examples/iface.py b/python/examples/iface.py new file mode 100644 index 0000000..afeafff --- /dev/null +++ b/python/examples/iface.py @@ -0,0 +1,112 @@ +from __future__ import print_function +import netlink.capi as nl +import netlink.genl.capi as genl +import nl80211 +import sys +import traceback + + +class test_class: + def __init__(self): + self.done = 1 + + +def msg_handler(m, a): + try: + e, attr = genl.py_genlmsg_parse( + nl.nlmsg_hdr(m), 0, nl80211.NL80211_ATTR_MAX, None + ) + if nl80211.NL80211_ATTR_WIPHY in attr: + thiswiphy = nl.nla_get_u32(attr[nl80211.NL80211_ATTR_WIPHY]) + print("phy#%d" % thiswiphy) + if nl80211.NL80211_ATTR_IFNAME in attr: + print( + "\tinterface %s" % nl.nla_get_string(attr[nl80211.NL80211_ATTR_IFNAME]) + ) + if nl80211.NL80211_ATTR_IFINDEX in attr: + print("\tifindex %d" % nl.nla_get_u32(attr[nl80211.NL80211_ATTR_IFINDEX])) + if nl80211.NL80211_ATTR_WDEV in attr: + print("\twdev 0x%lx" % nl.nla_get_u64(attr[nl80211.NL80211_ATTR_WDEV])) + if nl80211.NL80211_ATTR_MAC in attr: + print( + "\tmac %02x:%02x:%02x:%02x:%02x:%02x" + % tuple(nl.nla_data(attr[nl80211.NL80211_ATTR_MAC])) + ) + if nl80211.NL80211_ATTR_SSID in attr: + print("\tssid ", nl.nla_data(attr[nl80211.NL80211_ATTR_SSID])) + if nl80211.NL80211_ATTR_IFTYPE in attr: + iftype = nl.nla_get_u32(attr[nl80211.NL80211_ATTR_IFTYPE]) + print("\ttype %s" % nl80211.nl80211_iftype2str[iftype]) + if nl80211.NL80211_ATTR_WIPHY_FREQ in attr: + freq = nl.nla_get_u32(attr[nl80211.NL80211_ATTR_WIPHY_FREQ]) + + sys.stdout.write("\tfreq %d MHz" % freq) + + if nl80211.NL80211_ATTR_CHANNEL_WIDTH in attr: + chanw = nl.nla_get_u32(attr[nl80211.NL80211_ATTR_CHANNEL_WIDTH]) + sys.stdout.write(", width: %s" % nl80211.nl80211_chan_width2str[chanw]) + if nl80211.NL80211_ATTR_CENTER_FREQ1 in attr: + sys.stdout.write( + ", center1: %d MHz" + % nl.nla_get_u32(attr[nl80211.NL80211_ATTR_CENTER_FREQ1]) + ) + if nl80211.NL80211_ATTR_CENTER_FREQ2 in attr: + sys.stdout.write( + ", center2: %d MHz" + % nl.nla_get_u32(attr[nl80211.NL80211_ATTR_CENTER_FREQ2]) + ) + elif nl80211.NL80211_ATTR_WIPHY_CHANNEL_TYPE in attr: + channel_type = nl.nla_get_u32( + attr[nl80211.NL80211_ATTR_WIPHY_CHANNEL_TYPE] + ) + sys.stdout.write(" %s" % nl80211.nl80211_channel_type2str(channel_type)) + + sys.stdout.write("\n") + return nl.NL_SKIP + except Exception: + (t, v, tb) = sys.exc_info() + print(v.message) + traceback.print_tb(tb) + + +def error_handler(err, a): + a.done = err.error + return nl.NL_STOP + + +def finish_handler(m, a): + return nl.NL_SKIP + + +def ack_handler(m, a): + a.done = 0 + return nl.NL_STOP + + +try: + cbd = test_class() + tx_cb = nl.nl_cb_alloc(nl.NL_CB_DEFAULT) + rx_cb = nl.nl_cb_clone(tx_cb) + s = nl.nl_socket_alloc_cb(tx_cb) + nl.py_nl_cb_err(rx_cb, nl.NL_CB_CUSTOM, error_handler, cbd) + nl.py_nl_cb_set(rx_cb, nl.NL_CB_FINISH, nl.NL_CB_CUSTOM, finish_handler, cbd) + nl.py_nl_cb_set(rx_cb, nl.NL_CB_ACK, nl.NL_CB_CUSTOM, ack_handler, cbd) + nl.py_nl_cb_set(rx_cb, nl.NL_CB_VALID, nl.NL_CB_CUSTOM, msg_handler, cbd) + + genl.genl_connect(s) + family = genl.genl_ctrl_resolve(s, "nl80211") + m = nl.nlmsg_alloc() + genl.genlmsg_put(m, 0, 0, family, 0, 0, nl80211.NL80211_CMD_GET_INTERFACE, 0) + nl.nla_put_u32(m, nl80211.NL80211_ATTR_IFINDEX, nl.if_nametoindex("wlan0")) + + err = nl.nl_send_auto_complete(s, m) + if err < 0: + nl.nlmsg_free(m) + + while cbd.done > 0 and not err < 0: + err = nl.nl_recvmsgs(s, rx_cb) + +except Exception: + (t, v, tb) = sys.exc_info() + print(v.message) + traceback.print_tb(tb) diff --git a/python/examples/nl80211.py b/python/examples/nl80211.py new file mode 100644 index 0000000..88ea535 --- /dev/null +++ b/python/examples/nl80211.py @@ -0,0 +1,1575 @@ +########################################################### +# file: nl80211.py +# --------------------------------------------------------- +# This file is generated using extract.py using pycparser +########################################################### +NL80211_GENL_FAMILY = "nl80211" + +NL80211_CMD_UNSPEC = 0 +NL80211_CMD_GET_WIPHY = 1 +NL80211_CMD_SET_WIPHY = 2 +NL80211_CMD_NEW_WIPHY = 3 +NL80211_CMD_DEL_WIPHY = 4 +NL80211_CMD_GET_INTERFACE = 5 +NL80211_CMD_SET_INTERFACE = 6 +NL80211_CMD_NEW_INTERFACE = 7 +NL80211_CMD_DEL_INTERFACE = 8 +NL80211_CMD_GET_KEY = 9 +NL80211_CMD_SET_KEY = 10 +NL80211_CMD_NEW_KEY = 11 +NL80211_CMD_DEL_KEY = 12 +NL80211_CMD_GET_BEACON = 13 +NL80211_CMD_SET_BEACON = 14 +NL80211_CMD_START_AP = 15 +NL80211_CMD_NEW_BEACON = NL80211_CMD_START_AP +NL80211_CMD_STOP_AP = 16 +NL80211_CMD_DEL_BEACON = NL80211_CMD_STOP_AP +NL80211_CMD_GET_STATION = 17 +NL80211_CMD_SET_STATION = 18 +NL80211_CMD_NEW_STATION = 19 +NL80211_CMD_DEL_STATION = 20 +NL80211_CMD_GET_MPATH = 21 +NL80211_CMD_SET_MPATH = 22 +NL80211_CMD_NEW_MPATH = 23 +NL80211_CMD_DEL_MPATH = 24 +NL80211_CMD_SET_BSS = 25 +NL80211_CMD_SET_REG = 26 +NL80211_CMD_REQ_SET_REG = 27 +NL80211_CMD_GET_MESH_CONFIG = 28 +NL80211_CMD_SET_MESH_CONFIG = 29 +NL80211_CMD_SET_MGMT_EXTRA_IE = 30 +NL80211_CMD_GET_REG = 31 +NL80211_CMD_GET_SCAN = 32 +NL80211_CMD_TRIGGER_SCAN = 33 +NL80211_CMD_NEW_SCAN_RESULTS = 34 +NL80211_CMD_SCAN_ABORTED = 35 +NL80211_CMD_REG_CHANGE = 36 +NL80211_CMD_AUTHENTICATE = 37 +NL80211_CMD_ASSOCIATE = 38 +NL80211_CMD_DEAUTHENTICATE = 39 +NL80211_CMD_DISASSOCIATE = 40 +NL80211_CMD_MICHAEL_MIC_FAILURE = 41 +NL80211_CMD_REG_BEACON_HINT = 42 +NL80211_CMD_JOIN_IBSS = 43 +NL80211_CMD_LEAVE_IBSS = 44 +NL80211_CMD_TESTMODE = 45 +NL80211_CMD_CONNECT = 46 +NL80211_CMD_ROAM = 47 +NL80211_CMD_DISCONNECT = 48 +NL80211_CMD_SET_WIPHY_NETNS = 49 +NL80211_CMD_GET_SURVEY = 50 +NL80211_CMD_NEW_SURVEY_RESULTS = 51 +NL80211_CMD_SET_PMKSA = 52 +NL80211_CMD_DEL_PMKSA = 53 +NL80211_CMD_FLUSH_PMKSA = 54 +NL80211_CMD_REMAIN_ON_CHANNEL = 55 +NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL = 56 +NL80211_CMD_SET_TX_BITRATE_MASK = 57 +NL80211_CMD_REGISTER_FRAME = 58 +NL80211_CMD_REGISTER_ACTION = NL80211_CMD_REGISTER_FRAME +NL80211_CMD_FRAME = 59 +NL80211_CMD_ACTION = NL80211_CMD_FRAME +NL80211_CMD_FRAME_TX_STATUS = 60 +NL80211_CMD_ACTION_TX_STATUS = NL80211_CMD_FRAME_TX_STATUS +NL80211_CMD_SET_POWER_SAVE = 61 +NL80211_CMD_GET_POWER_SAVE = 62 +NL80211_CMD_SET_CQM = 63 +NL80211_CMD_NOTIFY_CQM = 64 +NL80211_CMD_SET_CHANNEL = 65 +NL80211_CMD_SET_WDS_PEER = 66 +NL80211_CMD_FRAME_WAIT_CANCEL = 67 +NL80211_CMD_JOIN_MESH = 68 +NL80211_CMD_LEAVE_MESH = 69 +NL80211_CMD_UNPROT_DEAUTHENTICATE = 70 +NL80211_CMD_UNPROT_DISASSOCIATE = 71 +NL80211_CMD_NEW_PEER_CANDIDATE = 72 +NL80211_CMD_GET_WOWLAN = 73 +NL80211_CMD_SET_WOWLAN = 74 +NL80211_CMD_START_SCHED_SCAN = 75 +NL80211_CMD_STOP_SCHED_SCAN = 76 +NL80211_CMD_SCHED_SCAN_RESULTS = 77 +NL80211_CMD_SCHED_SCAN_STOPPED = 78 +NL80211_CMD_SET_REKEY_OFFLOAD = 79 +NL80211_CMD_PMKSA_CANDIDATE = 80 +NL80211_CMD_TDLS_OPER = 81 +NL80211_CMD_TDLS_MGMT = 82 +NL80211_CMD_UNEXPECTED_FRAME = 83 +NL80211_CMD_PROBE_CLIENT = 84 +NL80211_CMD_REGISTER_BEACONS = 85 +NL80211_CMD_UNEXPECTED_4ADDR_FRAME = 86 +NL80211_CMD_SET_NOACK_MAP = 87 +NL80211_CMD_CH_SWITCH_NOTIFY = 88 +NL80211_CMD_START_P2P_DEVICE = 89 +NL80211_CMD_STOP_P2P_DEVICE = 90 +NL80211_CMD_CONN_FAILED = 91 +NL80211_CMD_SET_MCAST_RATE = 92 +NL80211_CMD_SET_MAC_ACL = 93 +NL80211_CMD_RADAR_DETECT = 94 +NL80211_CMD_GET_PROTOCOL_FEATURES = 95 +NL80211_CMD_UPDATE_FT_IES = 96 +NL80211_CMD_FT_EVENT = 97 +NL80211_CMD_CRIT_PROTOCOL_START = 98 +NL80211_CMD_CRIT_PROTOCOL_STOP = 99 +__NL80211_CMD_AFTER_LAST = 100 +NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1 +NL80211_ATTR_UNSPEC = 0 +NL80211_ATTR_WIPHY = 1 +NL80211_ATTR_WIPHY_NAME = 2 +NL80211_ATTR_IFINDEX = 3 +NL80211_ATTR_IFNAME = 4 +NL80211_ATTR_IFTYPE = 5 +NL80211_ATTR_MAC = 6 +NL80211_ATTR_KEY_DATA = 7 +NL80211_ATTR_KEY_IDX = 8 +NL80211_ATTR_KEY_CIPHER = 9 +NL80211_ATTR_KEY_SEQ = 10 +NL80211_ATTR_KEY_DEFAULT = 11 +NL80211_ATTR_BEACON_INTERVAL = 12 +NL80211_ATTR_DTIM_PERIOD = 13 +NL80211_ATTR_BEACON_HEAD = 14 +NL80211_ATTR_BEACON_TAIL = 15 +NL80211_ATTR_STA_AID = 16 +NL80211_ATTR_STA_FLAGS = 17 +NL80211_ATTR_STA_LISTEN_INTERVAL = 18 +NL80211_ATTR_STA_SUPPORTED_RATES = 19 +NL80211_ATTR_STA_VLAN = 20 +NL80211_ATTR_STA_INFO = 21 +NL80211_ATTR_WIPHY_BANDS = 22 +NL80211_ATTR_MNTR_FLAGS = 23 +NL80211_ATTR_MESH_ID = 24 +NL80211_ATTR_STA_PLINK_ACTION = 25 +NL80211_ATTR_MPATH_NEXT_HOP = 26 +NL80211_ATTR_MPATH_INFO = 27 +NL80211_ATTR_BSS_CTS_PROT = 28 +NL80211_ATTR_BSS_SHORT_PREAMBLE = 29 +NL80211_ATTR_BSS_SHORT_SLOT_TIME = 30 +NL80211_ATTR_HT_CAPABILITY = 31 +NL80211_ATTR_SUPPORTED_IFTYPES = 32 +NL80211_ATTR_REG_ALPHA2 = 33 +NL80211_ATTR_REG_RULES = 34 +NL80211_ATTR_MESH_CONFIG = 35 +NL80211_ATTR_BSS_BASIC_RATES = 36 +NL80211_ATTR_WIPHY_TXQ_PARAMS = 37 +NL80211_ATTR_WIPHY_FREQ = 38 +NL80211_ATTR_WIPHY_CHANNEL_TYPE = 39 +NL80211_ATTR_KEY_DEFAULT_MGMT = 40 +NL80211_ATTR_MGMT_SUBTYPE = 41 +NL80211_ATTR_IE = 42 +NL80211_ATTR_MAX_NUM_SCAN_SSIDS = 43 +NL80211_ATTR_SCAN_FREQUENCIES = 44 +NL80211_ATTR_SCAN_SSIDS = 45 +NL80211_ATTR_GENERATION = 46 +NL80211_ATTR_BSS = 47 +NL80211_ATTR_REG_INITIATOR = 48 +NL80211_ATTR_REG_TYPE = 49 +NL80211_ATTR_SUPPORTED_COMMANDS = 50 +NL80211_ATTR_FRAME = 51 +NL80211_ATTR_SSID = 52 +NL80211_ATTR_AUTH_TYPE = 53 +NL80211_ATTR_REASON_CODE = 54 +NL80211_ATTR_KEY_TYPE = 55 +NL80211_ATTR_MAX_SCAN_IE_LEN = 56 +NL80211_ATTR_CIPHER_SUITES = 57 +NL80211_ATTR_FREQ_BEFORE = 58 +NL80211_ATTR_FREQ_AFTER = 59 +NL80211_ATTR_FREQ_FIXED = 60 +NL80211_ATTR_WIPHY_RETRY_SHORT = 61 +NL80211_ATTR_WIPHY_RETRY_LONG = 62 +NL80211_ATTR_WIPHY_FRAG_THRESHOLD = 63 +NL80211_ATTR_WIPHY_RTS_THRESHOLD = 64 +NL80211_ATTR_TIMED_OUT = 65 +NL80211_ATTR_USE_MFP = 66 +NL80211_ATTR_STA_FLAGS2 = 67 +NL80211_ATTR_CONTROL_PORT = 68 +NL80211_ATTR_TESTDATA = 69 +NL80211_ATTR_PRIVACY = 70 +NL80211_ATTR_DISCONNECTED_BY_AP = 71 +NL80211_ATTR_STATUS_CODE = 72 +NL80211_ATTR_CIPHER_SUITES_PAIRWISE = 73 +NL80211_ATTR_CIPHER_SUITE_GROUP = 74 +NL80211_ATTR_WPA_VERSIONS = 75 +NL80211_ATTR_AKM_SUITES = 76 +NL80211_ATTR_REQ_IE = 77 +NL80211_ATTR_RESP_IE = 78 +NL80211_ATTR_PREV_BSSID = 79 +NL80211_ATTR_KEY = 80 +NL80211_ATTR_KEYS = 81 +NL80211_ATTR_PID = 82 +NL80211_ATTR_4ADDR = 83 +NL80211_ATTR_SURVEY_INFO = 84 +NL80211_ATTR_PMKID = 85 +NL80211_ATTR_MAX_NUM_PMKIDS = 86 +NL80211_ATTR_DURATION = 87 +NL80211_ATTR_COOKIE = 88 +NL80211_ATTR_WIPHY_COVERAGE_CLASS = 89 +NL80211_ATTR_TX_RATES = 90 +NL80211_ATTR_FRAME_MATCH = 91 +NL80211_ATTR_ACK = 92 +NL80211_ATTR_PS_STATE = 93 +NL80211_ATTR_CQM = 94 +NL80211_ATTR_LOCAL_STATE_CHANGE = 95 +NL80211_ATTR_AP_ISOLATE = 96 +NL80211_ATTR_WIPHY_TX_POWER_SETTING = 97 +NL80211_ATTR_WIPHY_TX_POWER_LEVEL = 98 +NL80211_ATTR_TX_FRAME_TYPES = 99 +NL80211_ATTR_RX_FRAME_TYPES = 100 +NL80211_ATTR_FRAME_TYPE = 101 +NL80211_ATTR_CONTROL_PORT_ETHERTYPE = 102 +NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT = 103 +NL80211_ATTR_SUPPORT_IBSS_RSN = 104 +NL80211_ATTR_WIPHY_ANTENNA_TX = 105 +NL80211_ATTR_WIPHY_ANTENNA_RX = 106 +NL80211_ATTR_MCAST_RATE = 107 +NL80211_ATTR_OFFCHANNEL_TX_OK = 108 +NL80211_ATTR_BSS_HT_OPMODE = 109 +NL80211_ATTR_KEY_DEFAULT_TYPES = 110 +NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION = 111 +NL80211_ATTR_MESH_SETUP = 112 +NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX = 113 +NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX = 114 +NL80211_ATTR_SUPPORT_MESH_AUTH = 115 +NL80211_ATTR_STA_PLINK_STATE = 116 +NL80211_ATTR_WOWLAN_TRIGGERS = 117 +NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED = 118 +NL80211_ATTR_SCHED_SCAN_INTERVAL = 119 +NL80211_ATTR_INTERFACE_COMBINATIONS = 120 +NL80211_ATTR_SOFTWARE_IFTYPES = 121 +NL80211_ATTR_REKEY_DATA = 122 +NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS = 123 +NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN = 124 +NL80211_ATTR_SCAN_SUPP_RATES = 125 +NL80211_ATTR_HIDDEN_SSID = 126 +NL80211_ATTR_IE_PROBE_RESP = 127 +NL80211_ATTR_IE_ASSOC_RESP = 128 +NL80211_ATTR_STA_WME = 129 +NL80211_ATTR_SUPPORT_AP_UAPSD = 130 +NL80211_ATTR_ROAM_SUPPORT = 131 +NL80211_ATTR_SCHED_SCAN_MATCH = 132 +NL80211_ATTR_MAX_MATCH_SETS = 133 +NL80211_ATTR_PMKSA_CANDIDATE = 134 +NL80211_ATTR_TX_NO_CCK_RATE = 135 +NL80211_ATTR_TDLS_ACTION = 136 +NL80211_ATTR_TDLS_DIALOG_TOKEN = 137 +NL80211_ATTR_TDLS_OPERATION = 138 +NL80211_ATTR_TDLS_SUPPORT = 139 +NL80211_ATTR_TDLS_EXTERNAL_SETUP = 140 +NL80211_ATTR_DEVICE_AP_SME = 141 +NL80211_ATTR_DONT_WAIT_FOR_ACK = 142 +NL80211_ATTR_FEATURE_FLAGS = 143 +NL80211_ATTR_PROBE_RESP_OFFLOAD = 144 +NL80211_ATTR_PROBE_RESP = 145 +NL80211_ATTR_DFS_REGION = 146 +NL80211_ATTR_DISABLE_HT = 147 +NL80211_ATTR_HT_CAPABILITY_MASK = 148 +NL80211_ATTR_NOACK_MAP = 149 +NL80211_ATTR_INACTIVITY_TIMEOUT = 150 +NL80211_ATTR_RX_SIGNAL_DBM = 151 +NL80211_ATTR_BG_SCAN_PERIOD = 152 +NL80211_ATTR_WDEV = 153 +NL80211_ATTR_USER_REG_HINT_TYPE = 154 +NL80211_ATTR_CONN_FAILED_REASON = 155 +NL80211_ATTR_SAE_DATA = 156 +NL80211_ATTR_VHT_CAPABILITY = 157 +NL80211_ATTR_SCAN_FLAGS = 158 +NL80211_ATTR_CHANNEL_WIDTH = 159 +NL80211_ATTR_CENTER_FREQ1 = 160 +NL80211_ATTR_CENTER_FREQ2 = 161 +NL80211_ATTR_P2P_CTWINDOW = 162 +NL80211_ATTR_P2P_OPPPS = 163 +NL80211_ATTR_LOCAL_MESH_POWER_MODE = 164 +NL80211_ATTR_ACL_POLICY = 165 +NL80211_ATTR_MAC_ADDRS = 166 +NL80211_ATTR_MAC_ACL_MAX = 167 +NL80211_ATTR_RADAR_EVENT = 168 +NL80211_ATTR_EXT_CAPA = 169 +NL80211_ATTR_EXT_CAPA_MASK = 170 +NL80211_ATTR_STA_CAPABILITY = 171 +NL80211_ATTR_STA_EXT_CAPABILITY = 172 +NL80211_ATTR_PROTOCOL_FEATURES = 173 +NL80211_ATTR_SPLIT_WIPHY_DUMP = 174 +NL80211_ATTR_DISABLE_VHT = 175 +NL80211_ATTR_VHT_CAPABILITY_MASK = 176 +NL80211_ATTR_MDID = 177 +NL80211_ATTR_IE_RIC = 178 +NL80211_ATTR_CRIT_PROT_ID = 179 +NL80211_ATTR_MAX_CRIT_PROT_DURATION = 180 +NL80211_ATTR_PEER_AID = 181 +__NL80211_ATTR_AFTER_LAST = 182 +NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1 +NL80211_IFTYPE_UNSPECIFIED = 0 +NL80211_IFTYPE_ADHOC = 1 +NL80211_IFTYPE_STATION = 2 +NL80211_IFTYPE_AP = 3 +NL80211_IFTYPE_AP_VLAN = 4 +NL80211_IFTYPE_WDS = 5 +NL80211_IFTYPE_MONITOR = 6 +NL80211_IFTYPE_MESH_POINT = 7 +NL80211_IFTYPE_P2P_CLIENT = 8 +NL80211_IFTYPE_P2P_GO = 9 +NL80211_IFTYPE_P2P_DEVICE = 10 +NUM_NL80211_IFTYPES = 11 +NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 1 +__NL80211_STA_FLAG_INVALID = 0 +NL80211_STA_FLAG_AUTHORIZED = 1 +NL80211_STA_FLAG_SHORT_PREAMBLE = 2 +NL80211_STA_FLAG_WME = 3 +NL80211_STA_FLAG_MFP = 4 +NL80211_STA_FLAG_AUTHENTICATED = 5 +NL80211_STA_FLAG_TDLS_PEER = 6 +NL80211_STA_FLAG_ASSOCIATED = 7 +__NL80211_STA_FLAG_AFTER_LAST = 8 +NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1 +__NL80211_RATE_INFO_INVALID = 0 +NL80211_RATE_INFO_BITRATE = 1 +NL80211_RATE_INFO_MCS = 2 +NL80211_RATE_INFO_40_MHZ_WIDTH = 3 +NL80211_RATE_INFO_SHORT_GI = 4 +NL80211_RATE_INFO_BITRATE32 = 5 +NL80211_RATE_INFO_VHT_MCS = 6 +NL80211_RATE_INFO_VHT_NSS = 7 +NL80211_RATE_INFO_80_MHZ_WIDTH = 8 +NL80211_RATE_INFO_80P80_MHZ_WIDTH = 9 +NL80211_RATE_INFO_160_MHZ_WIDTH = 10 +__NL80211_RATE_INFO_AFTER_LAST = 11 +NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1 +__NL80211_STA_BSS_PARAM_INVALID = 0 +NL80211_STA_BSS_PARAM_CTS_PROT = 1 +NL80211_STA_BSS_PARAM_SHORT_PREAMBLE = 2 +NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME = 3 +NL80211_STA_BSS_PARAM_DTIM_PERIOD = 4 +NL80211_STA_BSS_PARAM_BEACON_INTERVAL = 5 +__NL80211_STA_BSS_PARAM_AFTER_LAST = 6 +NL80211_STA_BSS_PARAM_MAX = __NL80211_STA_BSS_PARAM_AFTER_LAST - 1 +__NL80211_STA_INFO_INVALID = 0 +NL80211_STA_INFO_INACTIVE_TIME = 1 +NL80211_STA_INFO_RX_BYTES = 2 +NL80211_STA_INFO_TX_BYTES = 3 +NL80211_STA_INFO_LLID = 4 +NL80211_STA_INFO_PLID = 5 +NL80211_STA_INFO_PLINK_STATE = 6 +NL80211_STA_INFO_SIGNAL = 7 +NL80211_STA_INFO_TX_BITRATE = 8 +NL80211_STA_INFO_RX_PACKETS = 9 +NL80211_STA_INFO_TX_PACKETS = 10 +NL80211_STA_INFO_TX_RETRIES = 11 +NL80211_STA_INFO_TX_FAILED = 12 +NL80211_STA_INFO_SIGNAL_AVG = 13 +NL80211_STA_INFO_RX_BITRATE = 14 +NL80211_STA_INFO_BSS_PARAM = 15 +NL80211_STA_INFO_CONNECTED_TIME = 16 +NL80211_STA_INFO_STA_FLAGS = 17 +NL80211_STA_INFO_BEACON_LOSS = 18 +NL80211_STA_INFO_T_OFFSET = 19 +NL80211_STA_INFO_LOCAL_PM = 20 +NL80211_STA_INFO_PEER_PM = 21 +NL80211_STA_INFO_NONPEER_PM = 22 +NL80211_STA_INFO_RX_BYTES64 = 23 +NL80211_STA_INFO_TX_BYTES64 = 24 +NL80211_STA_INFO_CHAIN_SIGNAL = 25 +NL80211_STA_INFO_CHAIN_SIGNAL_AVG = 26 +__NL80211_STA_INFO_AFTER_LAST = 27 +NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1 +NL80211_MPATH_FLAG_ACTIVE = 1 << 0 +NL80211_MPATH_FLAG_RESOLVING = 1 << 1 +NL80211_MPATH_FLAG_SN_VALID = 1 << 2 +NL80211_MPATH_FLAG_FIXED = 1 << 3 +NL80211_MPATH_FLAG_RESOLVED = 1 << 4 +__NL80211_MPATH_INFO_INVALID = 0 +NL80211_MPATH_INFO_FRAME_QLEN = 1 +NL80211_MPATH_INFO_SN = 2 +NL80211_MPATH_INFO_METRIC = 3 +NL80211_MPATH_INFO_EXPTIME = 4 +NL80211_MPATH_INFO_FLAGS = 5 +NL80211_MPATH_INFO_DISCOVERY_TIMEOUT = 6 +NL80211_MPATH_INFO_DISCOVERY_RETRIES = 7 +__NL80211_MPATH_INFO_AFTER_LAST = 8 +NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1 +__NL80211_BAND_ATTR_INVALID = 0 +NL80211_BAND_ATTR_FREQS = 1 +NL80211_BAND_ATTR_RATES = 2 +NL80211_BAND_ATTR_HT_MCS_SET = 3 +NL80211_BAND_ATTR_HT_CAPA = 4 +NL80211_BAND_ATTR_HT_AMPDU_FACTOR = 5 +NL80211_BAND_ATTR_HT_AMPDU_DENSITY = 6 +NL80211_BAND_ATTR_VHT_MCS_SET = 7 +NL80211_BAND_ATTR_VHT_CAPA = 8 +__NL80211_BAND_ATTR_AFTER_LAST = 9 +NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1 +__NL80211_FREQUENCY_ATTR_INVALID = 0 +NL80211_FREQUENCY_ATTR_FREQ = 1 +NL80211_FREQUENCY_ATTR_DISABLED = 2 +NL80211_FREQUENCY_ATTR_PASSIVE_SCAN = 3 +NL80211_FREQUENCY_ATTR_NO_IBSS = 4 +NL80211_FREQUENCY_ATTR_RADAR = 5 +NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 6 +NL80211_FREQUENCY_ATTR_DFS_STATE = 7 +NL80211_FREQUENCY_ATTR_DFS_TIME = 8 +NL80211_FREQUENCY_ATTR_NO_HT40_MINUS = 9 +NL80211_FREQUENCY_ATTR_NO_HT40_PLUS = 10 +NL80211_FREQUENCY_ATTR_NO_80MHZ = 11 +NL80211_FREQUENCY_ATTR_NO_160MHZ = 12 +__NL80211_FREQUENCY_ATTR_AFTER_LAST = 13 +NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1 +__NL80211_BITRATE_ATTR_INVALID = 0 +NL80211_BITRATE_ATTR_RATE = 1 +NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE = 2 +__NL80211_BITRATE_ATTR_AFTER_LAST = 3 +NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1 +NL80211_REGDOM_SET_BY_CORE = 0 +NL80211_REGDOM_SET_BY_USER = 1 +NL80211_REGDOM_SET_BY_DRIVER = 2 +NL80211_REGDOM_SET_BY_COUNTRY_IE = 3 +NL80211_REGDOM_TYPE_COUNTRY = 0 +NL80211_REGDOM_TYPE_WORLD = 1 +NL80211_REGDOM_TYPE_CUSTOM_WORLD = 2 +NL80211_REGDOM_TYPE_INTERSECTION = 3 +__NL80211_REG_RULE_ATTR_INVALID = 0 +NL80211_ATTR_REG_RULE_FLAGS = 1 +NL80211_ATTR_FREQ_RANGE_START = 2 +NL80211_ATTR_FREQ_RANGE_END = 3 +NL80211_ATTR_FREQ_RANGE_MAX_BW = 4 +NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN = 5 +NL80211_ATTR_POWER_RULE_MAX_EIRP = 6 +__NL80211_REG_RULE_ATTR_AFTER_LAST = 7 +NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 +__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID = 0 +NL80211_SCHED_SCAN_MATCH_ATTR_SSID = 1 +NL80211_SCHED_SCAN_MATCH_ATTR_RSSI = 2 +__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST = 3 +NL80211_SCHED_SCAN_MATCH_ATTR_MAX = __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST - 1 +NL80211_RRF_NO_OFDM = 1 << 0 +NL80211_RRF_NO_CCK = 1 << 1 +NL80211_RRF_NO_INDOOR = 1 << 2 +NL80211_RRF_NO_OUTDOOR = 1 << 3 +NL80211_RRF_DFS = 1 << 4 +NL80211_RRF_PTP_ONLY = 1 << 5 +NL80211_RRF_PTMP_ONLY = 1 << 6 +NL80211_RRF_PASSIVE_SCAN = 1 << 7 +NL80211_RRF_NO_IBSS = 1 << 8 +NL80211_DFS_UNSET = 0 +NL80211_DFS_FCC = 1 +NL80211_DFS_ETSI = 2 +NL80211_DFS_JP = 3 +NL80211_USER_REG_HINT_USER = 0 +NL80211_USER_REG_HINT_CELL_BASE = 1 +__NL80211_SURVEY_INFO_INVALID = 0 +NL80211_SURVEY_INFO_FREQUENCY = 1 +NL80211_SURVEY_INFO_NOISE = 2 +NL80211_SURVEY_INFO_IN_USE = 3 +NL80211_SURVEY_INFO_CHANNEL_TIME = 4 +NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY = 5 +NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY = 6 +NL80211_SURVEY_INFO_CHANNEL_TIME_RX = 7 +NL80211_SURVEY_INFO_CHANNEL_TIME_TX = 8 +__NL80211_SURVEY_INFO_AFTER_LAST = 9 +NL80211_SURVEY_INFO_MAX = __NL80211_SURVEY_INFO_AFTER_LAST - 1 +__NL80211_MNTR_FLAG_INVALID = 0 +NL80211_MNTR_FLAG_FCSFAIL = 1 +NL80211_MNTR_FLAG_PLCPFAIL = 2 +NL80211_MNTR_FLAG_CONTROL = 3 +NL80211_MNTR_FLAG_OTHER_BSS = 4 +NL80211_MNTR_FLAG_COOK_FRAMES = 5 +NL80211_MNTR_FLAG_ACTIVE = 6 +__NL80211_MNTR_FLAG_AFTER_LAST = 7 +NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1 +NL80211_MESH_POWER_UNKNOWN = 0 +NL80211_MESH_POWER_ACTIVE = 1 +NL80211_MESH_POWER_LIGHT_SLEEP = 2 +NL80211_MESH_POWER_DEEP_SLEEP = 3 +__NL80211_MESH_POWER_AFTER_LAST = 4 +NL80211_MESH_POWER_MAX = __NL80211_MESH_POWER_AFTER_LAST - 1 +__NL80211_MESHCONF_INVALID = 0 +NL80211_MESHCONF_RETRY_TIMEOUT = 1 +NL80211_MESHCONF_CONFIRM_TIMEOUT = 2 +NL80211_MESHCONF_HOLDING_TIMEOUT = 3 +NL80211_MESHCONF_MAX_PEER_LINKS = 4 +NL80211_MESHCONF_MAX_RETRIES = 5 +NL80211_MESHCONF_TTL = 6 +NL80211_MESHCONF_AUTO_OPEN_PLINKS = 7 +NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES = 8 +NL80211_MESHCONF_PATH_REFRESH_TIME = 9 +NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT = 10 +NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT = 11 +NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL = 12 +NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME = 13 +NL80211_MESHCONF_HWMP_ROOTMODE = 14 +NL80211_MESHCONF_ELEMENT_TTL = 15 +NL80211_MESHCONF_HWMP_RANN_INTERVAL = 16 +NL80211_MESHCONF_GATE_ANNOUNCEMENTS = 17 +NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL = 18 +NL80211_MESHCONF_FORWARDING = 19 +NL80211_MESHCONF_RSSI_THRESHOLD = 20 +NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR = 21 +NL80211_MESHCONF_HT_OPMODE = 22 +NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT = 23 +NL80211_MESHCONF_HWMP_ROOT_INTERVAL = 24 +NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL = 25 +NL80211_MESHCONF_POWER_MODE = 26 +NL80211_MESHCONF_AWAKE_WINDOW = 27 +NL80211_MESHCONF_PLINK_TIMEOUT = 28 +__NL80211_MESHCONF_ATTR_AFTER_LAST = 29 +NL80211_MESHCONF_ATTR_MAX = __NL80211_MESHCONF_ATTR_AFTER_LAST - 1 +__NL80211_MESH_SETUP_INVALID = 0 +NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL = 1 +NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC = 2 +NL80211_MESH_SETUP_IE = 3 +NL80211_MESH_SETUP_USERSPACE_AUTH = 4 +NL80211_MESH_SETUP_USERSPACE_AMPE = 5 +NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC = 6 +NL80211_MESH_SETUP_USERSPACE_MPM = 7 +NL80211_MESH_SETUP_AUTH_PROTOCOL = 8 +__NL80211_MESH_SETUP_ATTR_AFTER_LAST = 9 +NL80211_MESH_SETUP_ATTR_MAX = __NL80211_MESH_SETUP_ATTR_AFTER_LAST - 1 +__NL80211_TXQ_ATTR_INVALID = 0 +NL80211_TXQ_ATTR_AC = 1 +NL80211_TXQ_ATTR_TXOP = 2 +NL80211_TXQ_ATTR_CWMIN = 3 +NL80211_TXQ_ATTR_CWMAX = 4 +NL80211_TXQ_ATTR_AIFS = 5 +__NL80211_TXQ_ATTR_AFTER_LAST = 6 +NL80211_TXQ_ATTR_MAX = __NL80211_TXQ_ATTR_AFTER_LAST - 1 +NL80211_AC_VO = 0 +NL80211_AC_VI = 1 +NL80211_AC_BE = 2 +NL80211_AC_BK = 3 +NL80211_NUM_ACS = 4 +NL80211_CHAN_NO_HT = 0 +NL80211_CHAN_HT20 = 1 +NL80211_CHAN_HT40MINUS = 2 +NL80211_CHAN_HT40PLUS = 3 +NL80211_CHAN_WIDTH_20_NOHT = 0 +NL80211_CHAN_WIDTH_20 = 1 +NL80211_CHAN_WIDTH_40 = 2 +NL80211_CHAN_WIDTH_80 = 3 +NL80211_CHAN_WIDTH_80P80 = 4 +NL80211_CHAN_WIDTH_160 = 5 +__NL80211_BSS_INVALID = 0 +NL80211_BSS_BSSID = 1 +NL80211_BSS_FREQUENCY = 2 +NL80211_BSS_TSF = 3 +NL80211_BSS_BEACON_INTERVAL = 4 +NL80211_BSS_CAPABILITY = 5 +NL80211_BSS_INFORMATION_ELEMENTS = 6 +NL80211_BSS_SIGNAL_MBM = 7 +NL80211_BSS_SIGNAL_UNSPEC = 8 +NL80211_BSS_STATUS = 9 +NL80211_BSS_SEEN_MS_AGO = 10 +NL80211_BSS_BEACON_IES = 11 +__NL80211_BSS_AFTER_LAST = 12 +NL80211_BSS_MAX = __NL80211_BSS_AFTER_LAST - 1 +NL80211_BSS_STATUS_AUTHENTICATED = 0 +NL80211_BSS_STATUS_ASSOCIATED = 1 +NL80211_BSS_STATUS_IBSS_JOINED = 2 +NL80211_AUTHTYPE_OPEN_SYSTEM = 0 +NL80211_AUTHTYPE_SHARED_KEY = 1 +NL80211_AUTHTYPE_FT = 2 +NL80211_AUTHTYPE_NETWORK_EAP = 3 +NL80211_AUTHTYPE_SAE = 4 +__NL80211_AUTHTYPE_NUM = 5 +NL80211_AUTHTYPE_MAX = __NL80211_AUTHTYPE_NUM - 1 +NL80211_AUTHTYPE_AUTOMATIC = 6 +NL80211_KEYTYPE_GROUP = 0 +NL80211_KEYTYPE_PAIRWISE = 1 +NL80211_KEYTYPE_PEERKEY = 2 +NUM_NL80211_KEYTYPES = 3 +NL80211_MFP_NO = 0 +NL80211_MFP_REQUIRED = 1 +NL80211_WPA_VERSION_1 = 1 << 0 +NL80211_WPA_VERSION_2 = 1 << 1 +__NL80211_KEY_DEFAULT_TYPE_INVALID = 0 +NL80211_KEY_DEFAULT_TYPE_UNICAST = 1 +NL80211_KEY_DEFAULT_TYPE_MULTICAST = 2 +NUM_NL80211_KEY_DEFAULT_TYPES = 3 +__NL80211_KEY_INVALID = 0 +NL80211_KEY_DATA = 1 +NL80211_KEY_IDX = 2 +NL80211_KEY_CIPHER = 3 +NL80211_KEY_SEQ = 4 +NL80211_KEY_DEFAULT = 5 +NL80211_KEY_DEFAULT_MGMT = 6 +NL80211_KEY_TYPE = 7 +NL80211_KEY_DEFAULT_TYPES = 8 +__NL80211_KEY_AFTER_LAST = 9 +NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1 +__NL80211_TXRATE_INVALID = 0 +NL80211_TXRATE_LEGACY = 1 +NL80211_TXRATE_MCS = 2 +__NL80211_TXRATE_AFTER_LAST = 3 +NL80211_TXRATE_MAX = __NL80211_TXRATE_AFTER_LAST - 1 +NL80211_BAND_2GHZ = 0 +NL80211_BAND_5GHZ = 1 +NL80211_BAND_60GHZ = 2 +NL80211_PS_DISABLED = 0 +NL80211_PS_ENABLED = 1 +__NL80211_ATTR_CQM_INVALID = 0 +NL80211_ATTR_CQM_RSSI_THOLD = 1 +NL80211_ATTR_CQM_RSSI_HYST = 2 +NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT = 3 +NL80211_ATTR_CQM_PKT_LOSS_EVENT = 4 +NL80211_ATTR_CQM_TXE_RATE = 5 +NL80211_ATTR_CQM_TXE_PKTS = 6 +NL80211_ATTR_CQM_TXE_INTVL = 7 +__NL80211_ATTR_CQM_AFTER_LAST = 8 +NL80211_ATTR_CQM_MAX = __NL80211_ATTR_CQM_AFTER_LAST - 1 +NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW = 0 +NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH = 1 +NL80211_CQM_RSSI_BEACON_LOSS_EVENT = 2 +NL80211_TX_POWER_AUTOMATIC = 0 +NL80211_TX_POWER_LIMITED = 1 +NL80211_TX_POWER_FIXED = 2 +__NL80211_WOWLAN_PKTPAT_INVALID = 0 +NL80211_WOWLAN_PKTPAT_MASK = 1 +NL80211_WOWLAN_PKTPAT_PATTERN = 2 +NL80211_WOWLAN_PKTPAT_OFFSET = 3 +NUM_NL80211_WOWLAN_PKTPAT = 4 +MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1 +__NL80211_WOWLAN_TRIG_INVALID = 0 +NL80211_WOWLAN_TRIG_ANY = 1 +NL80211_WOWLAN_TRIG_DISCONNECT = 2 +NL80211_WOWLAN_TRIG_MAGIC_PKT = 3 +NL80211_WOWLAN_TRIG_PKT_PATTERN = 4 +NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED = 5 +NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE = 6 +NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST = 7 +NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE = 8 +NL80211_WOWLAN_TRIG_RFKILL_RELEASE = 9 +NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211 = 10 +NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN = 11 +NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023 = 12 +NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN = 13 +NL80211_WOWLAN_TRIG_TCP_CONNECTION = 14 +NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH = 15 +NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST = 16 +NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS = 17 +NUM_NL80211_WOWLAN_TRIG = 18 +MAX_NL80211_WOWLAN_TRIG = NUM_NL80211_WOWLAN_TRIG - 1 +__NL80211_WOWLAN_TCP_INVALID = 0 +NL80211_WOWLAN_TCP_SRC_IPV4 = 1 +NL80211_WOWLAN_TCP_DST_IPV4 = 2 +NL80211_WOWLAN_TCP_DST_MAC = 3 +NL80211_WOWLAN_TCP_SRC_PORT = 4 +NL80211_WOWLAN_TCP_DST_PORT = 5 +NL80211_WOWLAN_TCP_DATA_PAYLOAD = 6 +NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ = 7 +NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN = 8 +NL80211_WOWLAN_TCP_DATA_INTERVAL = 9 +NL80211_WOWLAN_TCP_WAKE_PAYLOAD = 10 +NL80211_WOWLAN_TCP_WAKE_MASK = 11 +NUM_NL80211_WOWLAN_TCP = 12 +MAX_NL80211_WOWLAN_TCP = NUM_NL80211_WOWLAN_TCP - 1 +NL80211_IFACE_LIMIT_UNSPEC = 0 +NL80211_IFACE_LIMIT_MAX = 1 +NL80211_IFACE_LIMIT_TYPES = 2 +NUM_NL80211_IFACE_LIMIT = 3 +MAX_NL80211_IFACE_LIMIT = NUM_NL80211_IFACE_LIMIT - 1 +NL80211_IFACE_COMB_UNSPEC = 0 +NL80211_IFACE_COMB_LIMITS = 1 +NL80211_IFACE_COMB_MAXNUM = 2 +NL80211_IFACE_COMB_STA_AP_BI_MATCH = 3 +NL80211_IFACE_COMB_NUM_CHANNELS = 4 +NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS = 5 +NUM_NL80211_IFACE_COMB = 6 +MAX_NL80211_IFACE_COMB = NUM_NL80211_IFACE_COMB - 1 +NL80211_PLINK_LISTEN = 0 +NL80211_PLINK_OPN_SNT = 1 +NL80211_PLINK_OPN_RCVD = 2 +NL80211_PLINK_CNF_RCVD = 3 +NL80211_PLINK_ESTAB = 4 +NL80211_PLINK_HOLDING = 5 +NL80211_PLINK_BLOCKED = 6 +NUM_NL80211_PLINK_STATES = 7 +MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 1 +NL80211_PLINK_ACTION_NO_ACTION = 0 +NL80211_PLINK_ACTION_OPEN = 1 +NL80211_PLINK_ACTION_BLOCK = 2 +NUM_NL80211_PLINK_ACTIONS = 3 +__NL80211_REKEY_DATA_INVALID = 0 +NL80211_REKEY_DATA_KEK = 1 +NL80211_REKEY_DATA_KCK = 2 +NL80211_REKEY_DATA_REPLAY_CTR = 3 +NUM_NL80211_REKEY_DATA = 4 +MAX_NL80211_REKEY_DATA = NUM_NL80211_REKEY_DATA - 1 +NL80211_HIDDEN_SSID_NOT_IN_USE = 0 +NL80211_HIDDEN_SSID_ZERO_LEN = 1 +NL80211_HIDDEN_SSID_ZERO_CONTENTS = 2 +__NL80211_STA_WME_INVALID = 0 +NL80211_STA_WME_UAPSD_QUEUES = 1 +NL80211_STA_WME_MAX_SP = 2 +__NL80211_STA_WME_AFTER_LAST = 3 +NL80211_STA_WME_MAX = __NL80211_STA_WME_AFTER_LAST - 1 +__NL80211_PMKSA_CANDIDATE_INVALID = 0 +NL80211_PMKSA_CANDIDATE_INDEX = 1 +NL80211_PMKSA_CANDIDATE_BSSID = 2 +NL80211_PMKSA_CANDIDATE_PREAUTH = 3 +NUM_NL80211_PMKSA_CANDIDATE = 4 +MAX_NL80211_PMKSA_CANDIDATE = NUM_NL80211_PMKSA_CANDIDATE - 1 +NL80211_TDLS_DISCOVERY_REQ = 0 +NL80211_TDLS_SETUP = 1 +NL80211_TDLS_TEARDOWN = 2 +NL80211_TDLS_ENABLE_LINK = 3 +NL80211_TDLS_DISABLE_LINK = 4 +NL80211_FEATURE_SK_TX_STATUS = 1 << 0 +NL80211_FEATURE_HT_IBSS = 1 << 1 +NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2 +NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3 +NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 1 << 4 +NL80211_FEATURE_SAE = 1 << 5 +NL80211_FEATURE_LOW_PRIORITY_SCAN = 1 << 6 +NL80211_FEATURE_SCAN_FLUSH = 1 << 7 +NL80211_FEATURE_AP_SCAN = 1 << 8 +NL80211_FEATURE_VIF_TXPOWER = 1 << 9 +NL80211_FEATURE_NEED_OBSS_SCAN = 1 << 10 +NL80211_FEATURE_P2P_GO_CTWIN = 1 << 11 +NL80211_FEATURE_P2P_GO_OPPPS = 1 << 12 +NL80211_FEATURE_ADVERTISE_CHAN_LIMITS = 1 << 14 +NL80211_FEATURE_FULL_AP_CLIENT_STATE = 1 << 15 +NL80211_FEATURE_USERSPACE_MPM = 1 << 16 +NL80211_FEATURE_ACTIVE_MONITOR = 1 << 17 +NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS = 1 << 0 +NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 = 1 << 1 +NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P = 1 << 2 +NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U = 1 << 3 +NL80211_CONN_FAIL_MAX_CLIENTS = 0 +NL80211_CONN_FAIL_BLOCKED_CLIENT = 1 +NL80211_SCAN_FLAG_LOW_PRIORITY = 1 << 0 +NL80211_SCAN_FLAG_FLUSH = 1 << 1 +NL80211_SCAN_FLAG_AP = 1 << 2 +NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED = 0 +NL80211_ACL_POLICY_DENY_UNLESS_LISTED = 1 +NL80211_RADAR_DETECTED = 0 +NL80211_RADAR_CAC_FINISHED = 1 +NL80211_RADAR_CAC_ABORTED = 2 +NL80211_RADAR_NOP_FINISHED = 3 +NL80211_DFS_USABLE = 0 +NL80211_DFS_UNAVAILABLE = 1 +NL80211_DFS_AVAILABLE = 2 +NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP = 1 << 0 +NL80211_CRIT_PROTO_UNSPEC = 0 +NL80211_CRIT_PROTO_DHCP = 1 +NL80211_CRIT_PROTO_EAPOL = 2 +NL80211_CRIT_PROTO_APIPA = 3 +NUM_NL80211_CRIT_PROTO = 4 +nl80211_commands2str = { + NL80211_CMD_UNSPEC: "NL80211_CMD_UNSPEC", + NL80211_CMD_GET_WIPHY: "NL80211_CMD_GET_WIPHY", + NL80211_CMD_SET_WIPHY: "NL80211_CMD_SET_WIPHY", + NL80211_CMD_NEW_WIPHY: "NL80211_CMD_NEW_WIPHY", + NL80211_CMD_DEL_WIPHY: "NL80211_CMD_DEL_WIPHY", + NL80211_CMD_GET_INTERFACE: "NL80211_CMD_GET_INTERFACE", + NL80211_CMD_SET_INTERFACE: "NL80211_CMD_SET_INTERFACE", + NL80211_CMD_NEW_INTERFACE: "NL80211_CMD_NEW_INTERFACE", + NL80211_CMD_DEL_INTERFACE: "NL80211_CMD_DEL_INTERFACE", + NL80211_CMD_GET_KEY: "NL80211_CMD_GET_KEY", + NL80211_CMD_SET_KEY: "NL80211_CMD_SET_KEY", + NL80211_CMD_NEW_KEY: "NL80211_CMD_NEW_KEY", + NL80211_CMD_DEL_KEY: "NL80211_CMD_DEL_KEY", + NL80211_CMD_GET_BEACON: "NL80211_CMD_GET_BEACON", + NL80211_CMD_SET_BEACON: "NL80211_CMD_SET_BEACON", + NL80211_CMD_START_AP: "NL80211_CMD_START_AP", + NL80211_CMD_STOP_AP: "NL80211_CMD_STOP_AP", + NL80211_CMD_GET_STATION: "NL80211_CMD_GET_STATION", + NL80211_CMD_SET_STATION: "NL80211_CMD_SET_STATION", + NL80211_CMD_NEW_STATION: "NL80211_CMD_NEW_STATION", + NL80211_CMD_DEL_STATION: "NL80211_CMD_DEL_STATION", + NL80211_CMD_GET_MPATH: "NL80211_CMD_GET_MPATH", + NL80211_CMD_SET_MPATH: "NL80211_CMD_SET_MPATH", + NL80211_CMD_NEW_MPATH: "NL80211_CMD_NEW_MPATH", + NL80211_CMD_DEL_MPATH: "NL80211_CMD_DEL_MPATH", + NL80211_CMD_SET_BSS: "NL80211_CMD_SET_BSS", + NL80211_CMD_SET_REG: "NL80211_CMD_SET_REG", + NL80211_CMD_REQ_SET_REG: "NL80211_CMD_REQ_SET_REG", + NL80211_CMD_GET_MESH_CONFIG: "NL80211_CMD_GET_MESH_CONFIG", + NL80211_CMD_SET_MESH_CONFIG: "NL80211_CMD_SET_MESH_CONFIG", + NL80211_CMD_SET_MGMT_EXTRA_IE: "NL80211_CMD_SET_MGMT_EXTRA_IE", + NL80211_CMD_GET_REG: "NL80211_CMD_GET_REG", + NL80211_CMD_GET_SCAN: "NL80211_CMD_GET_SCAN", + NL80211_CMD_TRIGGER_SCAN: "NL80211_CMD_TRIGGER_SCAN", + NL80211_CMD_NEW_SCAN_RESULTS: "NL80211_CMD_NEW_SCAN_RESULTS", + NL80211_CMD_SCAN_ABORTED: "NL80211_CMD_SCAN_ABORTED", + NL80211_CMD_REG_CHANGE: "NL80211_CMD_REG_CHANGE", + NL80211_CMD_AUTHENTICATE: "NL80211_CMD_AUTHENTICATE", + NL80211_CMD_ASSOCIATE: "NL80211_CMD_ASSOCIATE", + NL80211_CMD_DEAUTHENTICATE: "NL80211_CMD_DEAUTHENTICATE", + NL80211_CMD_DISASSOCIATE: "NL80211_CMD_DISASSOCIATE", + NL80211_CMD_MICHAEL_MIC_FAILURE: "NL80211_CMD_MICHAEL_MIC_FAILURE", + NL80211_CMD_REG_BEACON_HINT: "NL80211_CMD_REG_BEACON_HINT", + NL80211_CMD_JOIN_IBSS: "NL80211_CMD_JOIN_IBSS", + NL80211_CMD_LEAVE_IBSS: "NL80211_CMD_LEAVE_IBSS", + NL80211_CMD_TESTMODE: "NL80211_CMD_TESTMODE", + NL80211_CMD_CONNECT: "NL80211_CMD_CONNECT", + NL80211_CMD_ROAM: "NL80211_CMD_ROAM", + NL80211_CMD_DISCONNECT: "NL80211_CMD_DISCONNECT", + NL80211_CMD_SET_WIPHY_NETNS: "NL80211_CMD_SET_WIPHY_NETNS", + NL80211_CMD_GET_SURVEY: "NL80211_CMD_GET_SURVEY", + NL80211_CMD_NEW_SURVEY_RESULTS: "NL80211_CMD_NEW_SURVEY_RESULTS", + NL80211_CMD_SET_PMKSA: "NL80211_CMD_SET_PMKSA", + NL80211_CMD_DEL_PMKSA: "NL80211_CMD_DEL_PMKSA", + NL80211_CMD_FLUSH_PMKSA: "NL80211_CMD_FLUSH_PMKSA", + NL80211_CMD_REMAIN_ON_CHANNEL: "NL80211_CMD_REMAIN_ON_CHANNEL", + NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL: "NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL", + NL80211_CMD_SET_TX_BITRATE_MASK: "NL80211_CMD_SET_TX_BITRATE_MASK", + NL80211_CMD_REGISTER_FRAME: "NL80211_CMD_REGISTER_FRAME", + NL80211_CMD_FRAME: "NL80211_CMD_FRAME", + NL80211_CMD_FRAME_TX_STATUS: "NL80211_CMD_FRAME_TX_STATUS", + NL80211_CMD_SET_POWER_SAVE: "NL80211_CMD_SET_POWER_SAVE", + NL80211_CMD_GET_POWER_SAVE: "NL80211_CMD_GET_POWER_SAVE", + NL80211_CMD_SET_CQM: "NL80211_CMD_SET_CQM", + NL80211_CMD_NOTIFY_CQM: "NL80211_CMD_NOTIFY_CQM", + NL80211_CMD_SET_CHANNEL: "NL80211_CMD_SET_CHANNEL", + NL80211_CMD_SET_WDS_PEER: "NL80211_CMD_SET_WDS_PEER", + NL80211_CMD_FRAME_WAIT_CANCEL: "NL80211_CMD_FRAME_WAIT_CANCEL", + NL80211_CMD_JOIN_MESH: "NL80211_CMD_JOIN_MESH", + NL80211_CMD_LEAVE_MESH: "NL80211_CMD_LEAVE_MESH", + NL80211_CMD_UNPROT_DEAUTHENTICATE: "NL80211_CMD_UNPROT_DEAUTHENTICATE", + NL80211_CMD_UNPROT_DISASSOCIATE: "NL80211_CMD_UNPROT_DISASSOCIATE", + NL80211_CMD_NEW_PEER_CANDIDATE: "NL80211_CMD_NEW_PEER_CANDIDATE", + NL80211_CMD_GET_WOWLAN: "NL80211_CMD_GET_WOWLAN", + NL80211_CMD_SET_WOWLAN: "NL80211_CMD_SET_WOWLAN", + NL80211_CMD_START_SCHED_SCAN: "NL80211_CMD_START_SCHED_SCAN", + NL80211_CMD_STOP_SCHED_SCAN: "NL80211_CMD_STOP_SCHED_SCAN", + NL80211_CMD_SCHED_SCAN_RESULTS: "NL80211_CMD_SCHED_SCAN_RESULTS", + NL80211_CMD_SCHED_SCAN_STOPPED: "NL80211_CMD_SCHED_SCAN_STOPPED", + NL80211_CMD_SET_REKEY_OFFLOAD: "NL80211_CMD_SET_REKEY_OFFLOAD", + NL80211_CMD_PMKSA_CANDIDATE: "NL80211_CMD_PMKSA_CANDIDATE", + NL80211_CMD_TDLS_OPER: "NL80211_CMD_TDLS_OPER", + NL80211_CMD_TDLS_MGMT: "NL80211_CMD_TDLS_MGMT", + NL80211_CMD_UNEXPECTED_FRAME: "NL80211_CMD_UNEXPECTED_FRAME", + NL80211_CMD_PROBE_CLIENT: "NL80211_CMD_PROBE_CLIENT", + NL80211_CMD_REGISTER_BEACONS: "NL80211_CMD_REGISTER_BEACONS", + NL80211_CMD_UNEXPECTED_4ADDR_FRAME: "NL80211_CMD_UNEXPECTED_4ADDR_FRAME", + NL80211_CMD_SET_NOACK_MAP: "NL80211_CMD_SET_NOACK_MAP", + NL80211_CMD_CH_SWITCH_NOTIFY: "NL80211_CMD_CH_SWITCH_NOTIFY", + NL80211_CMD_START_P2P_DEVICE: "NL80211_CMD_START_P2P_DEVICE", + NL80211_CMD_STOP_P2P_DEVICE: "NL80211_CMD_STOP_P2P_DEVICE", + NL80211_CMD_CONN_FAILED: "NL80211_CMD_CONN_FAILED", + NL80211_CMD_SET_MCAST_RATE: "NL80211_CMD_SET_MCAST_RATE", + NL80211_CMD_SET_MAC_ACL: "NL80211_CMD_SET_MAC_ACL", + NL80211_CMD_RADAR_DETECT: "NL80211_CMD_RADAR_DETECT", + NL80211_CMD_GET_PROTOCOL_FEATURES: "NL80211_CMD_GET_PROTOCOL_FEATURES", + NL80211_CMD_UPDATE_FT_IES: "NL80211_CMD_UPDATE_FT_IES", + NL80211_CMD_FT_EVENT: "NL80211_CMD_FT_EVENT", + NL80211_CMD_CRIT_PROTOCOL_START: "NL80211_CMD_CRIT_PROTOCOL_START", + NL80211_CMD_CRIT_PROTOCOL_STOP: "NL80211_CMD_CRIT_PROTOCOL_STOP", + __NL80211_CMD_AFTER_LAST: "__NL80211_CMD_AFTER_LAST", +} +nl80211_attrs2str = { + NL80211_ATTR_UNSPEC: "NL80211_ATTR_UNSPEC", + NL80211_ATTR_WIPHY: "NL80211_ATTR_WIPHY", + NL80211_ATTR_WIPHY_NAME: "NL80211_ATTR_WIPHY_NAME", + NL80211_ATTR_IFINDEX: "NL80211_ATTR_IFINDEX", + NL80211_ATTR_IFNAME: "NL80211_ATTR_IFNAME", + NL80211_ATTR_IFTYPE: "NL80211_ATTR_IFTYPE", + NL80211_ATTR_MAC: "NL80211_ATTR_MAC", + NL80211_ATTR_KEY_DATA: "NL80211_ATTR_KEY_DATA", + NL80211_ATTR_KEY_IDX: "NL80211_ATTR_KEY_IDX", + NL80211_ATTR_KEY_CIPHER: "NL80211_ATTR_KEY_CIPHER", + NL80211_ATTR_KEY_SEQ: "NL80211_ATTR_KEY_SEQ", + NL80211_ATTR_KEY_DEFAULT: "NL80211_ATTR_KEY_DEFAULT", + NL80211_ATTR_BEACON_INTERVAL: "NL80211_ATTR_BEACON_INTERVAL", + NL80211_ATTR_DTIM_PERIOD: "NL80211_ATTR_DTIM_PERIOD", + NL80211_ATTR_BEACON_HEAD: "NL80211_ATTR_BEACON_HEAD", + NL80211_ATTR_BEACON_TAIL: "NL80211_ATTR_BEACON_TAIL", + NL80211_ATTR_STA_AID: "NL80211_ATTR_STA_AID", + NL80211_ATTR_STA_FLAGS: "NL80211_ATTR_STA_FLAGS", + NL80211_ATTR_STA_LISTEN_INTERVAL: "NL80211_ATTR_STA_LISTEN_INTERVAL", + NL80211_ATTR_STA_SUPPORTED_RATES: "NL80211_ATTR_STA_SUPPORTED_RATES", + NL80211_ATTR_STA_VLAN: "NL80211_ATTR_STA_VLAN", + NL80211_ATTR_STA_INFO: "NL80211_ATTR_STA_INFO", + NL80211_ATTR_WIPHY_BANDS: "NL80211_ATTR_WIPHY_BANDS", + NL80211_ATTR_MNTR_FLAGS: "NL80211_ATTR_MNTR_FLAGS", + NL80211_ATTR_MESH_ID: "NL80211_ATTR_MESH_ID", + NL80211_ATTR_STA_PLINK_ACTION: "NL80211_ATTR_STA_PLINK_ACTION", + NL80211_ATTR_MPATH_NEXT_HOP: "NL80211_ATTR_MPATH_NEXT_HOP", + NL80211_ATTR_MPATH_INFO: "NL80211_ATTR_MPATH_INFO", + NL80211_ATTR_BSS_CTS_PROT: "NL80211_ATTR_BSS_CTS_PROT", + NL80211_ATTR_BSS_SHORT_PREAMBLE: "NL80211_ATTR_BSS_SHORT_PREAMBLE", + NL80211_ATTR_BSS_SHORT_SLOT_TIME: "NL80211_ATTR_BSS_SHORT_SLOT_TIME", + NL80211_ATTR_HT_CAPABILITY: "NL80211_ATTR_HT_CAPABILITY", + NL80211_ATTR_SUPPORTED_IFTYPES: "NL80211_ATTR_SUPPORTED_IFTYPES", + NL80211_ATTR_REG_ALPHA2: "NL80211_ATTR_REG_ALPHA2", + NL80211_ATTR_REG_RULES: "NL80211_ATTR_REG_RULES", + NL80211_ATTR_MESH_CONFIG: "NL80211_ATTR_MESH_CONFIG", + NL80211_ATTR_BSS_BASIC_RATES: "NL80211_ATTR_BSS_BASIC_RATES", + NL80211_ATTR_WIPHY_TXQ_PARAMS: "NL80211_ATTR_WIPHY_TXQ_PARAMS", + NL80211_ATTR_WIPHY_FREQ: "NL80211_ATTR_WIPHY_FREQ", + NL80211_ATTR_WIPHY_CHANNEL_TYPE: "NL80211_ATTR_WIPHY_CHANNEL_TYPE", + NL80211_ATTR_KEY_DEFAULT_MGMT: "NL80211_ATTR_KEY_DEFAULT_MGMT", + NL80211_ATTR_MGMT_SUBTYPE: "NL80211_ATTR_MGMT_SUBTYPE", + NL80211_ATTR_IE: "NL80211_ATTR_IE", + NL80211_ATTR_MAX_NUM_SCAN_SSIDS: "NL80211_ATTR_MAX_NUM_SCAN_SSIDS", + NL80211_ATTR_SCAN_FREQUENCIES: "NL80211_ATTR_SCAN_FREQUENCIES", + NL80211_ATTR_SCAN_SSIDS: "NL80211_ATTR_SCAN_SSIDS", + NL80211_ATTR_GENERATION: "NL80211_ATTR_GENERATION", + NL80211_ATTR_BSS: "NL80211_ATTR_BSS", + NL80211_ATTR_REG_INITIATOR: "NL80211_ATTR_REG_INITIATOR", + NL80211_ATTR_REG_TYPE: "NL80211_ATTR_REG_TYPE", + NL80211_ATTR_SUPPORTED_COMMANDS: "NL80211_ATTR_SUPPORTED_COMMANDS", + NL80211_ATTR_FRAME: "NL80211_ATTR_FRAME", + NL80211_ATTR_SSID: "NL80211_ATTR_SSID", + NL80211_ATTR_AUTH_TYPE: "NL80211_ATTR_AUTH_TYPE", + NL80211_ATTR_REASON_CODE: "NL80211_ATTR_REASON_CODE", + NL80211_ATTR_KEY_TYPE: "NL80211_ATTR_KEY_TYPE", + NL80211_ATTR_MAX_SCAN_IE_LEN: "NL80211_ATTR_MAX_SCAN_IE_LEN", + NL80211_ATTR_CIPHER_SUITES: "NL80211_ATTR_CIPHER_SUITES", + NL80211_ATTR_FREQ_BEFORE: "NL80211_ATTR_FREQ_BEFORE", + NL80211_ATTR_FREQ_AFTER: "NL80211_ATTR_FREQ_AFTER", + NL80211_ATTR_FREQ_FIXED: "NL80211_ATTR_FREQ_FIXED", + NL80211_ATTR_WIPHY_RETRY_SHORT: "NL80211_ATTR_WIPHY_RETRY_SHORT", + NL80211_ATTR_WIPHY_RETRY_LONG: "NL80211_ATTR_WIPHY_RETRY_LONG", + NL80211_ATTR_WIPHY_FRAG_THRESHOLD: "NL80211_ATTR_WIPHY_FRAG_THRESHOLD", + NL80211_ATTR_WIPHY_RTS_THRESHOLD: "NL80211_ATTR_WIPHY_RTS_THRESHOLD", + NL80211_ATTR_TIMED_OUT: "NL80211_ATTR_TIMED_OUT", + NL80211_ATTR_USE_MFP: "NL80211_ATTR_USE_MFP", + NL80211_ATTR_STA_FLAGS2: "NL80211_ATTR_STA_FLAGS2", + NL80211_ATTR_CONTROL_PORT: "NL80211_ATTR_CONTROL_PORT", + NL80211_ATTR_TESTDATA: "NL80211_ATTR_TESTDATA", + NL80211_ATTR_PRIVACY: "NL80211_ATTR_PRIVACY", + NL80211_ATTR_DISCONNECTED_BY_AP: "NL80211_ATTR_DISCONNECTED_BY_AP", + NL80211_ATTR_STATUS_CODE: "NL80211_ATTR_STATUS_CODE", + NL80211_ATTR_CIPHER_SUITES_PAIRWISE: "NL80211_ATTR_CIPHER_SUITES_PAIRWISE", + NL80211_ATTR_CIPHER_SUITE_GROUP: "NL80211_ATTR_CIPHER_SUITE_GROUP", + NL80211_ATTR_WPA_VERSIONS: "NL80211_ATTR_WPA_VERSIONS", + NL80211_ATTR_AKM_SUITES: "NL80211_ATTR_AKM_SUITES", + NL80211_ATTR_REQ_IE: "NL80211_ATTR_REQ_IE", + NL80211_ATTR_RESP_IE: "NL80211_ATTR_RESP_IE", + NL80211_ATTR_PREV_BSSID: "NL80211_ATTR_PREV_BSSID", + NL80211_ATTR_KEY: "NL80211_ATTR_KEY", + NL80211_ATTR_KEYS: "NL80211_ATTR_KEYS", + NL80211_ATTR_PID: "NL80211_ATTR_PID", + NL80211_ATTR_4ADDR: "NL80211_ATTR_4ADDR", + NL80211_ATTR_SURVEY_INFO: "NL80211_ATTR_SURVEY_INFO", + NL80211_ATTR_PMKID: "NL80211_ATTR_PMKID", + NL80211_ATTR_MAX_NUM_PMKIDS: "NL80211_ATTR_MAX_NUM_PMKIDS", + NL80211_ATTR_DURATION: "NL80211_ATTR_DURATION", + NL80211_ATTR_COOKIE: "NL80211_ATTR_COOKIE", + NL80211_ATTR_WIPHY_COVERAGE_CLASS: "NL80211_ATTR_WIPHY_COVERAGE_CLASS", + NL80211_ATTR_TX_RATES: "NL80211_ATTR_TX_RATES", + NL80211_ATTR_FRAME_MATCH: "NL80211_ATTR_FRAME_MATCH", + NL80211_ATTR_ACK: "NL80211_ATTR_ACK", + NL80211_ATTR_PS_STATE: "NL80211_ATTR_PS_STATE", + NL80211_ATTR_CQM: "NL80211_ATTR_CQM", + NL80211_ATTR_LOCAL_STATE_CHANGE: "NL80211_ATTR_LOCAL_STATE_CHANGE", + NL80211_ATTR_AP_ISOLATE: "NL80211_ATTR_AP_ISOLATE", + NL80211_ATTR_WIPHY_TX_POWER_SETTING: "NL80211_ATTR_WIPHY_TX_POWER_SETTING", + NL80211_ATTR_WIPHY_TX_POWER_LEVEL: "NL80211_ATTR_WIPHY_TX_POWER_LEVEL", + NL80211_ATTR_TX_FRAME_TYPES: "NL80211_ATTR_TX_FRAME_TYPES", + NL80211_ATTR_RX_FRAME_TYPES: "NL80211_ATTR_RX_FRAME_TYPES", + NL80211_ATTR_FRAME_TYPE: "NL80211_ATTR_FRAME_TYPE", + NL80211_ATTR_CONTROL_PORT_ETHERTYPE: "NL80211_ATTR_CONTROL_PORT_ETHERTYPE", + NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT: "NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT", + NL80211_ATTR_SUPPORT_IBSS_RSN: "NL80211_ATTR_SUPPORT_IBSS_RSN", + NL80211_ATTR_WIPHY_ANTENNA_TX: "NL80211_ATTR_WIPHY_ANTENNA_TX", + NL80211_ATTR_WIPHY_ANTENNA_RX: "NL80211_ATTR_WIPHY_ANTENNA_RX", + NL80211_ATTR_MCAST_RATE: "NL80211_ATTR_MCAST_RATE", + NL80211_ATTR_OFFCHANNEL_TX_OK: "NL80211_ATTR_OFFCHANNEL_TX_OK", + NL80211_ATTR_BSS_HT_OPMODE: "NL80211_ATTR_BSS_HT_OPMODE", + NL80211_ATTR_KEY_DEFAULT_TYPES: "NL80211_ATTR_KEY_DEFAULT_TYPES", + NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION: "NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION", + NL80211_ATTR_MESH_SETUP: "NL80211_ATTR_MESH_SETUP", + NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX: "NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX", + NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX: "NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX", + NL80211_ATTR_SUPPORT_MESH_AUTH: "NL80211_ATTR_SUPPORT_MESH_AUTH", + NL80211_ATTR_STA_PLINK_STATE: "NL80211_ATTR_STA_PLINK_STATE", + NL80211_ATTR_WOWLAN_TRIGGERS: "NL80211_ATTR_WOWLAN_TRIGGERS", + NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: "NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED", + NL80211_ATTR_SCHED_SCAN_INTERVAL: "NL80211_ATTR_SCHED_SCAN_INTERVAL", + NL80211_ATTR_INTERFACE_COMBINATIONS: "NL80211_ATTR_INTERFACE_COMBINATIONS", + NL80211_ATTR_SOFTWARE_IFTYPES: "NL80211_ATTR_SOFTWARE_IFTYPES", + NL80211_ATTR_REKEY_DATA: "NL80211_ATTR_REKEY_DATA", + NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS: "NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS", + NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN: "NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN", + NL80211_ATTR_SCAN_SUPP_RATES: "NL80211_ATTR_SCAN_SUPP_RATES", + NL80211_ATTR_HIDDEN_SSID: "NL80211_ATTR_HIDDEN_SSID", + NL80211_ATTR_IE_PROBE_RESP: "NL80211_ATTR_IE_PROBE_RESP", + NL80211_ATTR_IE_ASSOC_RESP: "NL80211_ATTR_IE_ASSOC_RESP", + NL80211_ATTR_STA_WME: "NL80211_ATTR_STA_WME", + NL80211_ATTR_SUPPORT_AP_UAPSD: "NL80211_ATTR_SUPPORT_AP_UAPSD", + NL80211_ATTR_ROAM_SUPPORT: "NL80211_ATTR_ROAM_SUPPORT", + NL80211_ATTR_SCHED_SCAN_MATCH: "NL80211_ATTR_SCHED_SCAN_MATCH", + NL80211_ATTR_MAX_MATCH_SETS: "NL80211_ATTR_MAX_MATCH_SETS", + NL80211_ATTR_PMKSA_CANDIDATE: "NL80211_ATTR_PMKSA_CANDIDATE", + NL80211_ATTR_TX_NO_CCK_RATE: "NL80211_ATTR_TX_NO_CCK_RATE", + NL80211_ATTR_TDLS_ACTION: "NL80211_ATTR_TDLS_ACTION", + NL80211_ATTR_TDLS_DIALOG_TOKEN: "NL80211_ATTR_TDLS_DIALOG_TOKEN", + NL80211_ATTR_TDLS_OPERATION: "NL80211_ATTR_TDLS_OPERATION", + NL80211_ATTR_TDLS_SUPPORT: "NL80211_ATTR_TDLS_SUPPORT", + NL80211_ATTR_TDLS_EXTERNAL_SETUP: "NL80211_ATTR_TDLS_EXTERNAL_SETUP", + NL80211_ATTR_DEVICE_AP_SME: "NL80211_ATTR_DEVICE_AP_SME", + NL80211_ATTR_DONT_WAIT_FOR_ACK: "NL80211_ATTR_DONT_WAIT_FOR_ACK", + NL80211_ATTR_FEATURE_FLAGS: "NL80211_ATTR_FEATURE_FLAGS", + NL80211_ATTR_PROBE_RESP_OFFLOAD: "NL80211_ATTR_PROBE_RESP_OFFLOAD", + NL80211_ATTR_PROBE_RESP: "NL80211_ATTR_PROBE_RESP", + NL80211_ATTR_DFS_REGION: "NL80211_ATTR_DFS_REGION", + NL80211_ATTR_DISABLE_HT: "NL80211_ATTR_DISABLE_HT", + NL80211_ATTR_HT_CAPABILITY_MASK: "NL80211_ATTR_HT_CAPABILITY_MASK", + NL80211_ATTR_NOACK_MAP: "NL80211_ATTR_NOACK_MAP", + NL80211_ATTR_INACTIVITY_TIMEOUT: "NL80211_ATTR_INACTIVITY_TIMEOUT", + NL80211_ATTR_RX_SIGNAL_DBM: "NL80211_ATTR_RX_SIGNAL_DBM", + NL80211_ATTR_BG_SCAN_PERIOD: "NL80211_ATTR_BG_SCAN_PERIOD", + NL80211_ATTR_WDEV: "NL80211_ATTR_WDEV", + NL80211_ATTR_USER_REG_HINT_TYPE: "NL80211_ATTR_USER_REG_HINT_TYPE", + NL80211_ATTR_CONN_FAILED_REASON: "NL80211_ATTR_CONN_FAILED_REASON", + NL80211_ATTR_SAE_DATA: "NL80211_ATTR_SAE_DATA", + NL80211_ATTR_VHT_CAPABILITY: "NL80211_ATTR_VHT_CAPABILITY", + NL80211_ATTR_SCAN_FLAGS: "NL80211_ATTR_SCAN_FLAGS", + NL80211_ATTR_CHANNEL_WIDTH: "NL80211_ATTR_CHANNEL_WIDTH", + NL80211_ATTR_CENTER_FREQ1: "NL80211_ATTR_CENTER_FREQ1", + NL80211_ATTR_CENTER_FREQ2: "NL80211_ATTR_CENTER_FREQ2", + NL80211_ATTR_P2P_CTWINDOW: "NL80211_ATTR_P2P_CTWINDOW", + NL80211_ATTR_P2P_OPPPS: "NL80211_ATTR_P2P_OPPPS", + NL80211_ATTR_LOCAL_MESH_POWER_MODE: "NL80211_ATTR_LOCAL_MESH_POWER_MODE", + NL80211_ATTR_ACL_POLICY: "NL80211_ATTR_ACL_POLICY", + NL80211_ATTR_MAC_ADDRS: "NL80211_ATTR_MAC_ADDRS", + NL80211_ATTR_MAC_ACL_MAX: "NL80211_ATTR_MAC_ACL_MAX", + NL80211_ATTR_RADAR_EVENT: "NL80211_ATTR_RADAR_EVENT", + NL80211_ATTR_EXT_CAPA: "NL80211_ATTR_EXT_CAPA", + NL80211_ATTR_EXT_CAPA_MASK: "NL80211_ATTR_EXT_CAPA_MASK", + NL80211_ATTR_STA_CAPABILITY: "NL80211_ATTR_STA_CAPABILITY", + NL80211_ATTR_STA_EXT_CAPABILITY: "NL80211_ATTR_STA_EXT_CAPABILITY", + NL80211_ATTR_PROTOCOL_FEATURES: "NL80211_ATTR_PROTOCOL_FEATURES", + NL80211_ATTR_SPLIT_WIPHY_DUMP: "NL80211_ATTR_SPLIT_WIPHY_DUMP", + NL80211_ATTR_DISABLE_VHT: "NL80211_ATTR_DISABLE_VHT", + NL80211_ATTR_VHT_CAPABILITY_MASK: "NL80211_ATTR_VHT_CAPABILITY_MASK", + NL80211_ATTR_MDID: "NL80211_ATTR_MDID", + NL80211_ATTR_IE_RIC: "NL80211_ATTR_IE_RIC", + NL80211_ATTR_CRIT_PROT_ID: "NL80211_ATTR_CRIT_PROT_ID", + NL80211_ATTR_MAX_CRIT_PROT_DURATION: "NL80211_ATTR_MAX_CRIT_PROT_DURATION", + NL80211_ATTR_PEER_AID: "NL80211_ATTR_PEER_AID", + __NL80211_ATTR_AFTER_LAST: "__NL80211_ATTR_AFTER_LAST", +} +nl80211_iftype2str = { + NL80211_IFTYPE_UNSPECIFIED: "NL80211_IFTYPE_UNSPECIFIED", + NL80211_IFTYPE_ADHOC: "NL80211_IFTYPE_ADHOC", + NL80211_IFTYPE_STATION: "NL80211_IFTYPE_STATION", + NL80211_IFTYPE_AP: "NL80211_IFTYPE_AP", + NL80211_IFTYPE_AP_VLAN: "NL80211_IFTYPE_AP_VLAN", + NL80211_IFTYPE_WDS: "NL80211_IFTYPE_WDS", + NL80211_IFTYPE_MONITOR: "NL80211_IFTYPE_MONITOR", + NL80211_IFTYPE_MESH_POINT: "NL80211_IFTYPE_MESH_POINT", + NL80211_IFTYPE_P2P_CLIENT: "NL80211_IFTYPE_P2P_CLIENT", + NL80211_IFTYPE_P2P_GO: "NL80211_IFTYPE_P2P_GO", + NL80211_IFTYPE_P2P_DEVICE: "NL80211_IFTYPE_P2P_DEVICE", + NUM_NL80211_IFTYPES: "NUM_NL80211_IFTYPES", +} +nl80211_sta_flags2str = { + __NL80211_STA_FLAG_INVALID: "__NL80211_STA_FLAG_INVALID", + NL80211_STA_FLAG_AUTHORIZED: "NL80211_STA_FLAG_AUTHORIZED", + NL80211_STA_FLAG_SHORT_PREAMBLE: "NL80211_STA_FLAG_SHORT_PREAMBLE", + NL80211_STA_FLAG_WME: "NL80211_STA_FLAG_WME", + NL80211_STA_FLAG_MFP: "NL80211_STA_FLAG_MFP", + NL80211_STA_FLAG_AUTHENTICATED: "NL80211_STA_FLAG_AUTHENTICATED", + NL80211_STA_FLAG_TDLS_PEER: "NL80211_STA_FLAG_TDLS_PEER", + NL80211_STA_FLAG_ASSOCIATED: "NL80211_STA_FLAG_ASSOCIATED", + __NL80211_STA_FLAG_AFTER_LAST: "__NL80211_STA_FLAG_AFTER_LAST", +} +nl80211_rate_info2str = { + __NL80211_RATE_INFO_INVALID: "__NL80211_RATE_INFO_INVALID", + NL80211_RATE_INFO_BITRATE: "NL80211_RATE_INFO_BITRATE", + NL80211_RATE_INFO_MCS: "NL80211_RATE_INFO_MCS", + NL80211_RATE_INFO_40_MHZ_WIDTH: "NL80211_RATE_INFO_40_MHZ_WIDTH", + NL80211_RATE_INFO_SHORT_GI: "NL80211_RATE_INFO_SHORT_GI", + NL80211_RATE_INFO_BITRATE32: "NL80211_RATE_INFO_BITRATE32", + NL80211_RATE_INFO_VHT_MCS: "NL80211_RATE_INFO_VHT_MCS", + NL80211_RATE_INFO_VHT_NSS: "NL80211_RATE_INFO_VHT_NSS", + NL80211_RATE_INFO_80_MHZ_WIDTH: "NL80211_RATE_INFO_80_MHZ_WIDTH", + NL80211_RATE_INFO_80P80_MHZ_WIDTH: "NL80211_RATE_INFO_80P80_MHZ_WIDTH", + NL80211_RATE_INFO_160_MHZ_WIDTH: "NL80211_RATE_INFO_160_MHZ_WIDTH", + __NL80211_RATE_INFO_AFTER_LAST: "__NL80211_RATE_INFO_AFTER_LAST", +} +nl80211_sta_bss_param2str = { + __NL80211_STA_BSS_PARAM_INVALID: "__NL80211_STA_BSS_PARAM_INVALID", + NL80211_STA_BSS_PARAM_CTS_PROT: "NL80211_STA_BSS_PARAM_CTS_PROT", + NL80211_STA_BSS_PARAM_SHORT_PREAMBLE: "NL80211_STA_BSS_PARAM_SHORT_PREAMBLE", + NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME: "NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME", + NL80211_STA_BSS_PARAM_DTIM_PERIOD: "NL80211_STA_BSS_PARAM_DTIM_PERIOD", + NL80211_STA_BSS_PARAM_BEACON_INTERVAL: "NL80211_STA_BSS_PARAM_BEACON_INTERVAL", + __NL80211_STA_BSS_PARAM_AFTER_LAST: "__NL80211_STA_BSS_PARAM_AFTER_LAST", +} +nl80211_sta_info2str = { + __NL80211_STA_INFO_INVALID: "__NL80211_STA_INFO_INVALID", + NL80211_STA_INFO_INACTIVE_TIME: "NL80211_STA_INFO_INACTIVE_TIME", + NL80211_STA_INFO_RX_BYTES: "NL80211_STA_INFO_RX_BYTES", + NL80211_STA_INFO_TX_BYTES: "NL80211_STA_INFO_TX_BYTES", + NL80211_STA_INFO_LLID: "NL80211_STA_INFO_LLID", + NL80211_STA_INFO_PLID: "NL80211_STA_INFO_PLID", + NL80211_STA_INFO_PLINK_STATE: "NL80211_STA_INFO_PLINK_STATE", + NL80211_STA_INFO_SIGNAL: "NL80211_STA_INFO_SIGNAL", + NL80211_STA_INFO_TX_BITRATE: "NL80211_STA_INFO_TX_BITRATE", + NL80211_STA_INFO_RX_PACKETS: "NL80211_STA_INFO_RX_PACKETS", + NL80211_STA_INFO_TX_PACKETS: "NL80211_STA_INFO_TX_PACKETS", + NL80211_STA_INFO_TX_RETRIES: "NL80211_STA_INFO_TX_RETRIES", + NL80211_STA_INFO_TX_FAILED: "NL80211_STA_INFO_TX_FAILED", + NL80211_STA_INFO_SIGNAL_AVG: "NL80211_STA_INFO_SIGNAL_AVG", + NL80211_STA_INFO_RX_BITRATE: "NL80211_STA_INFO_RX_BITRATE", + NL80211_STA_INFO_BSS_PARAM: "NL80211_STA_INFO_BSS_PARAM", + NL80211_STA_INFO_CONNECTED_TIME: "NL80211_STA_INFO_CONNECTED_TIME", + NL80211_STA_INFO_STA_FLAGS: "NL80211_STA_INFO_STA_FLAGS", + NL80211_STA_INFO_BEACON_LOSS: "NL80211_STA_INFO_BEACON_LOSS", + NL80211_STA_INFO_T_OFFSET: "NL80211_STA_INFO_T_OFFSET", + NL80211_STA_INFO_LOCAL_PM: "NL80211_STA_INFO_LOCAL_PM", + NL80211_STA_INFO_PEER_PM: "NL80211_STA_INFO_PEER_PM", + NL80211_STA_INFO_NONPEER_PM: "NL80211_STA_INFO_NONPEER_PM", + NL80211_STA_INFO_RX_BYTES64: "NL80211_STA_INFO_RX_BYTES64", + NL80211_STA_INFO_TX_BYTES64: "NL80211_STA_INFO_TX_BYTES64", + NL80211_STA_INFO_CHAIN_SIGNAL: "NL80211_STA_INFO_CHAIN_SIGNAL", + NL80211_STA_INFO_CHAIN_SIGNAL_AVG: "NL80211_STA_INFO_CHAIN_SIGNAL_AVG", + __NL80211_STA_INFO_AFTER_LAST: "__NL80211_STA_INFO_AFTER_LAST", +} +nl80211_mpath_flags2str = { + NL80211_MPATH_FLAG_ACTIVE: "NL80211_MPATH_FLAG_ACTIVE", + NL80211_MPATH_FLAG_RESOLVING: "NL80211_MPATH_FLAG_RESOLVING", + NL80211_MPATH_FLAG_SN_VALID: "NL80211_MPATH_FLAG_SN_VALID", + NL80211_MPATH_FLAG_FIXED: "NL80211_MPATH_FLAG_FIXED", + NL80211_MPATH_FLAG_RESOLVED: "NL80211_MPATH_FLAG_RESOLVED", +} +nl80211_mpath_info2str = { + __NL80211_MPATH_INFO_INVALID: "__NL80211_MPATH_INFO_INVALID", + NL80211_MPATH_INFO_FRAME_QLEN: "NL80211_MPATH_INFO_FRAME_QLEN", + NL80211_MPATH_INFO_SN: "NL80211_MPATH_INFO_SN", + NL80211_MPATH_INFO_METRIC: "NL80211_MPATH_INFO_METRIC", + NL80211_MPATH_INFO_EXPTIME: "NL80211_MPATH_INFO_EXPTIME", + NL80211_MPATH_INFO_FLAGS: "NL80211_MPATH_INFO_FLAGS", + NL80211_MPATH_INFO_DISCOVERY_TIMEOUT: "NL80211_MPATH_INFO_DISCOVERY_TIMEOUT", + NL80211_MPATH_INFO_DISCOVERY_RETRIES: "NL80211_MPATH_INFO_DISCOVERY_RETRIES", + __NL80211_MPATH_INFO_AFTER_LAST: "__NL80211_MPATH_INFO_AFTER_LAST", +} +nl80211_band_attr2str = { + __NL80211_BAND_ATTR_INVALID: "__NL80211_BAND_ATTR_INVALID", + NL80211_BAND_ATTR_FREQS: "NL80211_BAND_ATTR_FREQS", + NL80211_BAND_ATTR_RATES: "NL80211_BAND_ATTR_RATES", + NL80211_BAND_ATTR_HT_MCS_SET: "NL80211_BAND_ATTR_HT_MCS_SET", + NL80211_BAND_ATTR_HT_CAPA: "NL80211_BAND_ATTR_HT_CAPA", + NL80211_BAND_ATTR_HT_AMPDU_FACTOR: "NL80211_BAND_ATTR_HT_AMPDU_FACTOR", + NL80211_BAND_ATTR_HT_AMPDU_DENSITY: "NL80211_BAND_ATTR_HT_AMPDU_DENSITY", + NL80211_BAND_ATTR_VHT_MCS_SET: "NL80211_BAND_ATTR_VHT_MCS_SET", + NL80211_BAND_ATTR_VHT_CAPA: "NL80211_BAND_ATTR_VHT_CAPA", + __NL80211_BAND_ATTR_AFTER_LAST: "__NL80211_BAND_ATTR_AFTER_LAST", +} +nl80211_frequency_attr2str = { + __NL80211_FREQUENCY_ATTR_INVALID: "__NL80211_FREQUENCY_ATTR_INVALID", + NL80211_FREQUENCY_ATTR_FREQ: "NL80211_FREQUENCY_ATTR_FREQ", + NL80211_FREQUENCY_ATTR_DISABLED: "NL80211_FREQUENCY_ATTR_DISABLED", + NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: "NL80211_FREQUENCY_ATTR_PASSIVE_SCAN", + NL80211_FREQUENCY_ATTR_NO_IBSS: "NL80211_FREQUENCY_ATTR_NO_IBSS", + NL80211_FREQUENCY_ATTR_RADAR: "NL80211_FREQUENCY_ATTR_RADAR", + NL80211_FREQUENCY_ATTR_MAX_TX_POWER: "NL80211_FREQUENCY_ATTR_MAX_TX_POWER", + NL80211_FREQUENCY_ATTR_DFS_STATE: "NL80211_FREQUENCY_ATTR_DFS_STATE", + NL80211_FREQUENCY_ATTR_DFS_TIME: "NL80211_FREQUENCY_ATTR_DFS_TIME", + NL80211_FREQUENCY_ATTR_NO_HT40_MINUS: "NL80211_FREQUENCY_ATTR_NO_HT40_MINUS", + NL80211_FREQUENCY_ATTR_NO_HT40_PLUS: "NL80211_FREQUENCY_ATTR_NO_HT40_PLUS", + NL80211_FREQUENCY_ATTR_NO_80MHZ: "NL80211_FREQUENCY_ATTR_NO_80MHZ", + NL80211_FREQUENCY_ATTR_NO_160MHZ: "NL80211_FREQUENCY_ATTR_NO_160MHZ", + __NL80211_FREQUENCY_ATTR_AFTER_LAST: "__NL80211_FREQUENCY_ATTR_AFTER_LAST", +} +nl80211_bitrate_attr2str = { + __NL80211_BITRATE_ATTR_INVALID: "__NL80211_BITRATE_ATTR_INVALID", + NL80211_BITRATE_ATTR_RATE: "NL80211_BITRATE_ATTR_RATE", + NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: "NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE", + __NL80211_BITRATE_ATTR_AFTER_LAST: "__NL80211_BITRATE_ATTR_AFTER_LAST", +} +nl80211_reg_initiator2str = { + NL80211_REGDOM_SET_BY_CORE: "NL80211_REGDOM_SET_BY_CORE", + NL80211_REGDOM_SET_BY_USER: "NL80211_REGDOM_SET_BY_USER", + NL80211_REGDOM_SET_BY_DRIVER: "NL80211_REGDOM_SET_BY_DRIVER", + NL80211_REGDOM_SET_BY_COUNTRY_IE: "NL80211_REGDOM_SET_BY_COUNTRY_IE", +} +nl80211_reg_type2str = { + NL80211_REGDOM_TYPE_COUNTRY: "NL80211_REGDOM_TYPE_COUNTRY", + NL80211_REGDOM_TYPE_WORLD: "NL80211_REGDOM_TYPE_WORLD", + NL80211_REGDOM_TYPE_CUSTOM_WORLD: "NL80211_REGDOM_TYPE_CUSTOM_WORLD", + NL80211_REGDOM_TYPE_INTERSECTION: "NL80211_REGDOM_TYPE_INTERSECTION", +} +nl80211_reg_rule_attr2str = { + __NL80211_REG_RULE_ATTR_INVALID: "__NL80211_REG_RULE_ATTR_INVALID", + NL80211_ATTR_REG_RULE_FLAGS: "NL80211_ATTR_REG_RULE_FLAGS", + NL80211_ATTR_FREQ_RANGE_START: "NL80211_ATTR_FREQ_RANGE_START", + NL80211_ATTR_FREQ_RANGE_END: "NL80211_ATTR_FREQ_RANGE_END", + NL80211_ATTR_FREQ_RANGE_MAX_BW: "NL80211_ATTR_FREQ_RANGE_MAX_BW", + NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: "NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN", + NL80211_ATTR_POWER_RULE_MAX_EIRP: "NL80211_ATTR_POWER_RULE_MAX_EIRP", + __NL80211_REG_RULE_ATTR_AFTER_LAST: "__NL80211_REG_RULE_ATTR_AFTER_LAST", +} +nl80211_sched_scan_match_attr2str = { + __NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: "__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID", + NL80211_SCHED_SCAN_MATCH_ATTR_SSID: "NL80211_SCHED_SCAN_MATCH_ATTR_SSID", + NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: "NL80211_SCHED_SCAN_MATCH_ATTR_RSSI", + __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: "__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST", +} +nl80211_reg_rule_flags2str = { + NL80211_RRF_NO_OFDM: "NL80211_RRF_NO_OFDM", + NL80211_RRF_NO_CCK: "NL80211_RRF_NO_CCK", + NL80211_RRF_NO_INDOOR: "NL80211_RRF_NO_INDOOR", + NL80211_RRF_NO_OUTDOOR: "NL80211_RRF_NO_OUTDOOR", + NL80211_RRF_DFS: "NL80211_RRF_DFS", + NL80211_RRF_PTP_ONLY: "NL80211_RRF_PTP_ONLY", + NL80211_RRF_PTMP_ONLY: "NL80211_RRF_PTMP_ONLY", + NL80211_RRF_PASSIVE_SCAN: "NL80211_RRF_PASSIVE_SCAN", + NL80211_RRF_NO_IBSS: "NL80211_RRF_NO_IBSS", +} +nl80211_dfs_regions2str = {} +nl80211_user_reg_hint_type2str = {} +nl80211_survey_info2str = { + __NL80211_SURVEY_INFO_INVALID: "__NL80211_SURVEY_INFO_INVALID", + NL80211_SURVEY_INFO_FREQUENCY: "NL80211_SURVEY_INFO_FREQUENCY", + NL80211_SURVEY_INFO_NOISE: "NL80211_SURVEY_INFO_NOISE", + NL80211_SURVEY_INFO_IN_USE: "NL80211_SURVEY_INFO_IN_USE", + NL80211_SURVEY_INFO_CHANNEL_TIME: "NL80211_SURVEY_INFO_CHANNEL_TIME", + NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY: "NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY", + NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: "NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY", + NL80211_SURVEY_INFO_CHANNEL_TIME_RX: "NL80211_SURVEY_INFO_CHANNEL_TIME_RX", + NL80211_SURVEY_INFO_CHANNEL_TIME_TX: "NL80211_SURVEY_INFO_CHANNEL_TIME_TX", + __NL80211_SURVEY_INFO_AFTER_LAST: "__NL80211_SURVEY_INFO_AFTER_LAST", +} +nl80211_mntr_flags2str = { + __NL80211_MNTR_FLAG_INVALID: "__NL80211_MNTR_FLAG_INVALID", + NL80211_MNTR_FLAG_FCSFAIL: "NL80211_MNTR_FLAG_FCSFAIL", + NL80211_MNTR_FLAG_PLCPFAIL: "NL80211_MNTR_FLAG_PLCPFAIL", + NL80211_MNTR_FLAG_CONTROL: "NL80211_MNTR_FLAG_CONTROL", + NL80211_MNTR_FLAG_OTHER_BSS: "NL80211_MNTR_FLAG_OTHER_BSS", + NL80211_MNTR_FLAG_COOK_FRAMES: "NL80211_MNTR_FLAG_COOK_FRAMES", + NL80211_MNTR_FLAG_ACTIVE: "NL80211_MNTR_FLAG_ACTIVE", + __NL80211_MNTR_FLAG_AFTER_LAST: "__NL80211_MNTR_FLAG_AFTER_LAST", +} +nl80211_mesh_power_mode2str = { + NL80211_MESH_POWER_UNKNOWN: "NL80211_MESH_POWER_UNKNOWN", + NL80211_MESH_POWER_ACTIVE: "NL80211_MESH_POWER_ACTIVE", + NL80211_MESH_POWER_LIGHT_SLEEP: "NL80211_MESH_POWER_LIGHT_SLEEP", + NL80211_MESH_POWER_DEEP_SLEEP: "NL80211_MESH_POWER_DEEP_SLEEP", + __NL80211_MESH_POWER_AFTER_LAST: "__NL80211_MESH_POWER_AFTER_LAST", +} +nl80211_meshconf_params2str = { + __NL80211_MESHCONF_INVALID: "__NL80211_MESHCONF_INVALID", + NL80211_MESHCONF_RETRY_TIMEOUT: "NL80211_MESHCONF_RETRY_TIMEOUT", + NL80211_MESHCONF_CONFIRM_TIMEOUT: "NL80211_MESHCONF_CONFIRM_TIMEOUT", + NL80211_MESHCONF_HOLDING_TIMEOUT: "NL80211_MESHCONF_HOLDING_TIMEOUT", + NL80211_MESHCONF_MAX_PEER_LINKS: "NL80211_MESHCONF_MAX_PEER_LINKS", + NL80211_MESHCONF_MAX_RETRIES: "NL80211_MESHCONF_MAX_RETRIES", + NL80211_MESHCONF_TTL: "NL80211_MESHCONF_TTL", + NL80211_MESHCONF_AUTO_OPEN_PLINKS: "NL80211_MESHCONF_AUTO_OPEN_PLINKS", + NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: "NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES", + NL80211_MESHCONF_PATH_REFRESH_TIME: "NL80211_MESHCONF_PATH_REFRESH_TIME", + NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT: "NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT", + NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT: "NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT", + NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL: "NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL", + NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: "NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME", + NL80211_MESHCONF_HWMP_ROOTMODE: "NL80211_MESHCONF_HWMP_ROOTMODE", + NL80211_MESHCONF_ELEMENT_TTL: "NL80211_MESHCONF_ELEMENT_TTL", + NL80211_MESHCONF_HWMP_RANN_INTERVAL: "NL80211_MESHCONF_HWMP_RANN_INTERVAL", + NL80211_MESHCONF_GATE_ANNOUNCEMENTS: "NL80211_MESHCONF_GATE_ANNOUNCEMENTS", + NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL: "NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL", + NL80211_MESHCONF_FORWARDING: "NL80211_MESHCONF_FORWARDING", + NL80211_MESHCONF_RSSI_THRESHOLD: "NL80211_MESHCONF_RSSI_THRESHOLD", + NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR: "NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR", + NL80211_MESHCONF_HT_OPMODE: "NL80211_MESHCONF_HT_OPMODE", + NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT: "NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT", + NL80211_MESHCONF_HWMP_ROOT_INTERVAL: "NL80211_MESHCONF_HWMP_ROOT_INTERVAL", + NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL: "NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL", + NL80211_MESHCONF_POWER_MODE: "NL80211_MESHCONF_POWER_MODE", + NL80211_MESHCONF_AWAKE_WINDOW: "NL80211_MESHCONF_AWAKE_WINDOW", + NL80211_MESHCONF_PLINK_TIMEOUT: "NL80211_MESHCONF_PLINK_TIMEOUT", + __NL80211_MESHCONF_ATTR_AFTER_LAST: "__NL80211_MESHCONF_ATTR_AFTER_LAST", +} +nl80211_mesh_setup_params2str = { + __NL80211_MESH_SETUP_INVALID: "__NL80211_MESH_SETUP_INVALID", + NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL: "NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL", + NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC: "NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC", + NL80211_MESH_SETUP_IE: "NL80211_MESH_SETUP_IE", + NL80211_MESH_SETUP_USERSPACE_AUTH: "NL80211_MESH_SETUP_USERSPACE_AUTH", + NL80211_MESH_SETUP_USERSPACE_AMPE: "NL80211_MESH_SETUP_USERSPACE_AMPE", + NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC: "NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC", + NL80211_MESH_SETUP_USERSPACE_MPM: "NL80211_MESH_SETUP_USERSPACE_MPM", + NL80211_MESH_SETUP_AUTH_PROTOCOL: "NL80211_MESH_SETUP_AUTH_PROTOCOL", + __NL80211_MESH_SETUP_ATTR_AFTER_LAST: "__NL80211_MESH_SETUP_ATTR_AFTER_LAST", +} +nl80211_txq_attr2str = { + __NL80211_TXQ_ATTR_INVALID: "__NL80211_TXQ_ATTR_INVALID", + NL80211_TXQ_ATTR_AC: "NL80211_TXQ_ATTR_AC", + NL80211_TXQ_ATTR_TXOP: "NL80211_TXQ_ATTR_TXOP", + NL80211_TXQ_ATTR_CWMIN: "NL80211_TXQ_ATTR_CWMIN", + NL80211_TXQ_ATTR_CWMAX: "NL80211_TXQ_ATTR_CWMAX", + NL80211_TXQ_ATTR_AIFS: "NL80211_TXQ_ATTR_AIFS", + __NL80211_TXQ_ATTR_AFTER_LAST: "__NL80211_TXQ_ATTR_AFTER_LAST", +} +nl80211_ac2str = { + NL80211_AC_VO: "NL80211_AC_VO", + NL80211_AC_VI: "NL80211_AC_VI", + NL80211_AC_BE: "NL80211_AC_BE", + NL80211_AC_BK: "NL80211_AC_BK", + NL80211_NUM_ACS: "NL80211_NUM_ACS", +} +nl80211_channel_type2str = { + NL80211_CHAN_NO_HT: "NL80211_CHAN_NO_HT", + NL80211_CHAN_HT20: "NL80211_CHAN_HT20", + NL80211_CHAN_HT40MINUS: "NL80211_CHAN_HT40MINUS", + NL80211_CHAN_HT40PLUS: "NL80211_CHAN_HT40PLUS", +} +nl80211_chan_width2str = { + NL80211_CHAN_WIDTH_20_NOHT: "NL80211_CHAN_WIDTH_20_NOHT", + NL80211_CHAN_WIDTH_20: "NL80211_CHAN_WIDTH_20", + NL80211_CHAN_WIDTH_40: "NL80211_CHAN_WIDTH_40", + NL80211_CHAN_WIDTH_80: "NL80211_CHAN_WIDTH_80", + NL80211_CHAN_WIDTH_80P80: "NL80211_CHAN_WIDTH_80P80", + NL80211_CHAN_WIDTH_160: "NL80211_CHAN_WIDTH_160", +} +nl80211_bss2str = { + __NL80211_BSS_INVALID: "__NL80211_BSS_INVALID", + NL80211_BSS_BSSID: "NL80211_BSS_BSSID", + NL80211_BSS_FREQUENCY: "NL80211_BSS_FREQUENCY", + NL80211_BSS_TSF: "NL80211_BSS_TSF", + NL80211_BSS_BEACON_INTERVAL: "NL80211_BSS_BEACON_INTERVAL", + NL80211_BSS_CAPABILITY: "NL80211_BSS_CAPABILITY", + NL80211_BSS_INFORMATION_ELEMENTS: "NL80211_BSS_INFORMATION_ELEMENTS", + NL80211_BSS_SIGNAL_MBM: "NL80211_BSS_SIGNAL_MBM", + NL80211_BSS_SIGNAL_UNSPEC: "NL80211_BSS_SIGNAL_UNSPEC", + NL80211_BSS_STATUS: "NL80211_BSS_STATUS", + NL80211_BSS_SEEN_MS_AGO: "NL80211_BSS_SEEN_MS_AGO", + NL80211_BSS_BEACON_IES: "NL80211_BSS_BEACON_IES", + __NL80211_BSS_AFTER_LAST: "__NL80211_BSS_AFTER_LAST", +} +nl80211_bss_status2str = { + NL80211_BSS_STATUS_AUTHENTICATED: "NL80211_BSS_STATUS_AUTHENTICATED", + NL80211_BSS_STATUS_ASSOCIATED: "NL80211_BSS_STATUS_ASSOCIATED", + NL80211_BSS_STATUS_IBSS_JOINED: "NL80211_BSS_STATUS_IBSS_JOINED", +} +nl80211_auth_type2str = { + NL80211_AUTHTYPE_OPEN_SYSTEM: "NL80211_AUTHTYPE_OPEN_SYSTEM", + NL80211_AUTHTYPE_SHARED_KEY: "NL80211_AUTHTYPE_SHARED_KEY", + NL80211_AUTHTYPE_FT: "NL80211_AUTHTYPE_FT", + NL80211_AUTHTYPE_NETWORK_EAP: "NL80211_AUTHTYPE_NETWORK_EAP", + NL80211_AUTHTYPE_SAE: "NL80211_AUTHTYPE_SAE", + __NL80211_AUTHTYPE_NUM: "__NL80211_AUTHTYPE_NUM", + NL80211_AUTHTYPE_AUTOMATIC: "NL80211_AUTHTYPE_AUTOMATIC", +} +nl80211_key_type2str = { + NL80211_KEYTYPE_GROUP: "NL80211_KEYTYPE_GROUP", + NL80211_KEYTYPE_PAIRWISE: "NL80211_KEYTYPE_PAIRWISE", + NL80211_KEYTYPE_PEERKEY: "NL80211_KEYTYPE_PEERKEY", + NUM_NL80211_KEYTYPES: "NUM_NL80211_KEYTYPES", +} +nl80211_mfp2str = { + NL80211_MFP_NO: "NL80211_MFP_NO", + NL80211_MFP_REQUIRED: "NL80211_MFP_REQUIRED", +} +nl80211_wpa_versions2str = { + NL80211_WPA_VERSION_1: "NL80211_WPA_VERSION_1", + NL80211_WPA_VERSION_2: "NL80211_WPA_VERSION_2", +} +nl80211_key_default_types2str = { + __NL80211_KEY_DEFAULT_TYPE_INVALID: "__NL80211_KEY_DEFAULT_TYPE_INVALID", + NL80211_KEY_DEFAULT_TYPE_UNICAST: "NL80211_KEY_DEFAULT_TYPE_UNICAST", + NL80211_KEY_DEFAULT_TYPE_MULTICAST: "NL80211_KEY_DEFAULT_TYPE_MULTICAST", + NUM_NL80211_KEY_DEFAULT_TYPES: "NUM_NL80211_KEY_DEFAULT_TYPES", +} +nl80211_key_attributes2str = { + __NL80211_KEY_INVALID: "__NL80211_KEY_INVALID", + NL80211_KEY_DATA: "NL80211_KEY_DATA", + NL80211_KEY_IDX: "NL80211_KEY_IDX", + NL80211_KEY_CIPHER: "NL80211_KEY_CIPHER", + NL80211_KEY_SEQ: "NL80211_KEY_SEQ", + NL80211_KEY_DEFAULT: "NL80211_KEY_DEFAULT", + NL80211_KEY_DEFAULT_MGMT: "NL80211_KEY_DEFAULT_MGMT", + NL80211_KEY_TYPE: "NL80211_KEY_TYPE", + NL80211_KEY_DEFAULT_TYPES: "NL80211_KEY_DEFAULT_TYPES", + __NL80211_KEY_AFTER_LAST: "__NL80211_KEY_AFTER_LAST", +} +nl80211_tx_rate_attributes2str = { + __NL80211_TXRATE_INVALID: "__NL80211_TXRATE_INVALID", + NL80211_TXRATE_LEGACY: "NL80211_TXRATE_LEGACY", + NL80211_TXRATE_MCS: "NL80211_TXRATE_MCS", + __NL80211_TXRATE_AFTER_LAST: "__NL80211_TXRATE_AFTER_LAST", +} +nl80211_band2str = { + NL80211_BAND_2GHZ: "NL80211_BAND_2GHZ", + NL80211_BAND_5GHZ: "NL80211_BAND_5GHZ", + NL80211_BAND_60GHZ: "NL80211_BAND_60GHZ", +} +nl80211_ps_state2str = { + NL80211_PS_DISABLED: "NL80211_PS_DISABLED", + NL80211_PS_ENABLED: "NL80211_PS_ENABLED", +} +nl80211_attr_cqm2str = { + __NL80211_ATTR_CQM_INVALID: "__NL80211_ATTR_CQM_INVALID", + NL80211_ATTR_CQM_RSSI_THOLD: "NL80211_ATTR_CQM_RSSI_THOLD", + NL80211_ATTR_CQM_RSSI_HYST: "NL80211_ATTR_CQM_RSSI_HYST", + NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT: "NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT", + NL80211_ATTR_CQM_PKT_LOSS_EVENT: "NL80211_ATTR_CQM_PKT_LOSS_EVENT", + NL80211_ATTR_CQM_TXE_RATE: "NL80211_ATTR_CQM_TXE_RATE", + NL80211_ATTR_CQM_TXE_PKTS: "NL80211_ATTR_CQM_TXE_PKTS", + NL80211_ATTR_CQM_TXE_INTVL: "NL80211_ATTR_CQM_TXE_INTVL", + __NL80211_ATTR_CQM_AFTER_LAST: "__NL80211_ATTR_CQM_AFTER_LAST", +} +nl80211_cqm_rssi_threshold_event2str = { + NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW: "NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW", + NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH: "NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH", + NL80211_CQM_RSSI_BEACON_LOSS_EVENT: "NL80211_CQM_RSSI_BEACON_LOSS_EVENT", +} +nl80211_tx_power_setting2str = { + NL80211_TX_POWER_AUTOMATIC: "NL80211_TX_POWER_AUTOMATIC", + NL80211_TX_POWER_LIMITED: "NL80211_TX_POWER_LIMITED", + NL80211_TX_POWER_FIXED: "NL80211_TX_POWER_FIXED", +} +nl80211_wowlan_packet_pattern_attr2str = { + __NL80211_WOWLAN_PKTPAT_INVALID: "__NL80211_WOWLAN_PKTPAT_INVALID", + NL80211_WOWLAN_PKTPAT_MASK: "NL80211_WOWLAN_PKTPAT_MASK", + NL80211_WOWLAN_PKTPAT_PATTERN: "NL80211_WOWLAN_PKTPAT_PATTERN", + NL80211_WOWLAN_PKTPAT_OFFSET: "NL80211_WOWLAN_PKTPAT_OFFSET", + NUM_NL80211_WOWLAN_PKTPAT: "NUM_NL80211_WOWLAN_PKTPAT", +} +nl80211_wowlan_triggers2str = { + __NL80211_WOWLAN_TRIG_INVALID: "__NL80211_WOWLAN_TRIG_INVALID", + NL80211_WOWLAN_TRIG_ANY: "NL80211_WOWLAN_TRIG_ANY", + NL80211_WOWLAN_TRIG_DISCONNECT: "NL80211_WOWLAN_TRIG_DISCONNECT", + NL80211_WOWLAN_TRIG_MAGIC_PKT: "NL80211_WOWLAN_TRIG_MAGIC_PKT", + NL80211_WOWLAN_TRIG_PKT_PATTERN: "NL80211_WOWLAN_TRIG_PKT_PATTERN", + NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED: "NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED", + NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE: "NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE", + NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST: "NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST", + NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE: "NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE", + NL80211_WOWLAN_TRIG_RFKILL_RELEASE: "NL80211_WOWLAN_TRIG_RFKILL_RELEASE", + NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211: "NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211", + NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN: "NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN", + NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023: "NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023", + NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN: "NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN", + NL80211_WOWLAN_TRIG_TCP_CONNECTION: "NL80211_WOWLAN_TRIG_TCP_CONNECTION", + NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH: "NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH", + NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST: "NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST", + NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS: "NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS", + NUM_NL80211_WOWLAN_TRIG: "NUM_NL80211_WOWLAN_TRIG", +} +nl80211_wowlan_tcp_attrs2str = { + __NL80211_WOWLAN_TCP_INVALID: "__NL80211_WOWLAN_TCP_INVALID", + NL80211_WOWLAN_TCP_SRC_IPV4: "NL80211_WOWLAN_TCP_SRC_IPV4", + NL80211_WOWLAN_TCP_DST_IPV4: "NL80211_WOWLAN_TCP_DST_IPV4", + NL80211_WOWLAN_TCP_DST_MAC: "NL80211_WOWLAN_TCP_DST_MAC", + NL80211_WOWLAN_TCP_SRC_PORT: "NL80211_WOWLAN_TCP_SRC_PORT", + NL80211_WOWLAN_TCP_DST_PORT: "NL80211_WOWLAN_TCP_DST_PORT", + NL80211_WOWLAN_TCP_DATA_PAYLOAD: "NL80211_WOWLAN_TCP_DATA_PAYLOAD", + NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ: "NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ", + NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN: "NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN", + NL80211_WOWLAN_TCP_DATA_INTERVAL: "NL80211_WOWLAN_TCP_DATA_INTERVAL", + NL80211_WOWLAN_TCP_WAKE_PAYLOAD: "NL80211_WOWLAN_TCP_WAKE_PAYLOAD", + NL80211_WOWLAN_TCP_WAKE_MASK: "NL80211_WOWLAN_TCP_WAKE_MASK", + NUM_NL80211_WOWLAN_TCP: "NUM_NL80211_WOWLAN_TCP", +} +nl80211_iface_limit_attrs2str = { + NL80211_IFACE_LIMIT_UNSPEC: "NL80211_IFACE_LIMIT_UNSPEC", + NL80211_IFACE_LIMIT_MAX: "NL80211_IFACE_LIMIT_MAX", + NL80211_IFACE_LIMIT_TYPES: "NL80211_IFACE_LIMIT_TYPES", + NUM_NL80211_IFACE_LIMIT: "NUM_NL80211_IFACE_LIMIT", +} +nl80211_if_combination_attrs2str = { + NL80211_IFACE_COMB_UNSPEC: "NL80211_IFACE_COMB_UNSPEC", + NL80211_IFACE_COMB_LIMITS: "NL80211_IFACE_COMB_LIMITS", + NL80211_IFACE_COMB_MAXNUM: "NL80211_IFACE_COMB_MAXNUM", + NL80211_IFACE_COMB_STA_AP_BI_MATCH: "NL80211_IFACE_COMB_STA_AP_BI_MATCH", + NL80211_IFACE_COMB_NUM_CHANNELS: "NL80211_IFACE_COMB_NUM_CHANNELS", + NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS: "NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS", + NUM_NL80211_IFACE_COMB: "NUM_NL80211_IFACE_COMB", +} +nl80211_plink_state2str = { + NL80211_PLINK_LISTEN: "NL80211_PLINK_LISTEN", + NL80211_PLINK_OPN_SNT: "NL80211_PLINK_OPN_SNT", + NL80211_PLINK_OPN_RCVD: "NL80211_PLINK_OPN_RCVD", + NL80211_PLINK_CNF_RCVD: "NL80211_PLINK_CNF_RCVD", + NL80211_PLINK_ESTAB: "NL80211_PLINK_ESTAB", + NL80211_PLINK_HOLDING: "NL80211_PLINK_HOLDING", + NL80211_PLINK_BLOCKED: "NL80211_PLINK_BLOCKED", + NUM_NL80211_PLINK_STATES: "NUM_NL80211_PLINK_STATES", +} +plink_actions2str = { + NL80211_PLINK_ACTION_NO_ACTION: "NL80211_PLINK_ACTION_NO_ACTION", + NL80211_PLINK_ACTION_OPEN: "NL80211_PLINK_ACTION_OPEN", + NL80211_PLINK_ACTION_BLOCK: "NL80211_PLINK_ACTION_BLOCK", + NUM_NL80211_PLINK_ACTIONS: "NUM_NL80211_PLINK_ACTIONS", +} +nl80211_rekey_data2str = { + __NL80211_REKEY_DATA_INVALID: "__NL80211_REKEY_DATA_INVALID", + NL80211_REKEY_DATA_KEK: "NL80211_REKEY_DATA_KEK", + NL80211_REKEY_DATA_KCK: "NL80211_REKEY_DATA_KCK", + NL80211_REKEY_DATA_REPLAY_CTR: "NL80211_REKEY_DATA_REPLAY_CTR", + NUM_NL80211_REKEY_DATA: "NUM_NL80211_REKEY_DATA", +} +nl80211_hidden_ssid2str = { + NL80211_HIDDEN_SSID_NOT_IN_USE: "NL80211_HIDDEN_SSID_NOT_IN_USE", + NL80211_HIDDEN_SSID_ZERO_LEN: "NL80211_HIDDEN_SSID_ZERO_LEN", + NL80211_HIDDEN_SSID_ZERO_CONTENTS: "NL80211_HIDDEN_SSID_ZERO_CONTENTS", +} +nl80211_sta_wme_attr2str = { + __NL80211_STA_WME_INVALID: "__NL80211_STA_WME_INVALID", + NL80211_STA_WME_UAPSD_QUEUES: "NL80211_STA_WME_UAPSD_QUEUES", + NL80211_STA_WME_MAX_SP: "NL80211_STA_WME_MAX_SP", + __NL80211_STA_WME_AFTER_LAST: "__NL80211_STA_WME_AFTER_LAST", +} +nl80211_pmksa_candidate_attr2str = { + __NL80211_PMKSA_CANDIDATE_INVALID: "__NL80211_PMKSA_CANDIDATE_INVALID", + NL80211_PMKSA_CANDIDATE_INDEX: "NL80211_PMKSA_CANDIDATE_INDEX", + NL80211_PMKSA_CANDIDATE_BSSID: "NL80211_PMKSA_CANDIDATE_BSSID", + NL80211_PMKSA_CANDIDATE_PREAUTH: "NL80211_PMKSA_CANDIDATE_PREAUTH", + NUM_NL80211_PMKSA_CANDIDATE: "NUM_NL80211_PMKSA_CANDIDATE", +} +nl80211_tdls_operation2str = { + NL80211_TDLS_DISCOVERY_REQ: "NL80211_TDLS_DISCOVERY_REQ", + NL80211_TDLS_SETUP: "NL80211_TDLS_SETUP", + NL80211_TDLS_TEARDOWN: "NL80211_TDLS_TEARDOWN", + NL80211_TDLS_ENABLE_LINK: "NL80211_TDLS_ENABLE_LINK", + NL80211_TDLS_DISABLE_LINK: "NL80211_TDLS_DISABLE_LINK", +} +nl80211_feature_flags2str = { + NL80211_FEATURE_SK_TX_STATUS: "NL80211_FEATURE_SK_TX_STATUS", + NL80211_FEATURE_HT_IBSS: "NL80211_FEATURE_HT_IBSS", + NL80211_FEATURE_INACTIVITY_TIMER: "NL80211_FEATURE_INACTIVITY_TIMER", + NL80211_FEATURE_CELL_BASE_REG_HINTS: "NL80211_FEATURE_CELL_BASE_REG_HINTS", + NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: "NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL", + NL80211_FEATURE_SAE: "NL80211_FEATURE_SAE", + NL80211_FEATURE_LOW_PRIORITY_SCAN: "NL80211_FEATURE_LOW_PRIORITY_SCAN", + NL80211_FEATURE_SCAN_FLUSH: "NL80211_FEATURE_SCAN_FLUSH", + NL80211_FEATURE_AP_SCAN: "NL80211_FEATURE_AP_SCAN", + NL80211_FEATURE_VIF_TXPOWER: "NL80211_FEATURE_VIF_TXPOWER", + NL80211_FEATURE_NEED_OBSS_SCAN: "NL80211_FEATURE_NEED_OBSS_SCAN", + NL80211_FEATURE_P2P_GO_CTWIN: "NL80211_FEATURE_P2P_GO_CTWIN", + NL80211_FEATURE_P2P_GO_OPPPS: "NL80211_FEATURE_P2P_GO_OPPPS", + NL80211_FEATURE_ADVERTISE_CHAN_LIMITS: "NL80211_FEATURE_ADVERTISE_CHAN_LIMITS", + NL80211_FEATURE_FULL_AP_CLIENT_STATE: "NL80211_FEATURE_FULL_AP_CLIENT_STATE", + NL80211_FEATURE_USERSPACE_MPM: "NL80211_FEATURE_USERSPACE_MPM", + NL80211_FEATURE_ACTIVE_MONITOR: "NL80211_FEATURE_ACTIVE_MONITOR", +} +nl80211_probe_resp_offload_support_attr2str = { + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS: "NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS", + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2: "NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2", + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P: "NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P", + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U: "NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U", +} +nl80211_connect_failed_reason2str = { + NL80211_CONN_FAIL_MAX_CLIENTS: "NL80211_CONN_FAIL_MAX_CLIENTS", + NL80211_CONN_FAIL_BLOCKED_CLIENT: "NL80211_CONN_FAIL_BLOCKED_CLIENT", +} +nl80211_scan_flags2str = { + NL80211_SCAN_FLAG_LOW_PRIORITY: "NL80211_SCAN_FLAG_LOW_PRIORITY", + NL80211_SCAN_FLAG_FLUSH: "NL80211_SCAN_FLAG_FLUSH", + NL80211_SCAN_FLAG_AP: "NL80211_SCAN_FLAG_AP", +} +nl80211_acl_policy2str = { + NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: "NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED", + NL80211_ACL_POLICY_DENY_UNLESS_LISTED: "NL80211_ACL_POLICY_DENY_UNLESS_LISTED", +} +nl80211_radar_event2str = { + NL80211_RADAR_DETECTED: "NL80211_RADAR_DETECTED", + NL80211_RADAR_CAC_FINISHED: "NL80211_RADAR_CAC_FINISHED", + NL80211_RADAR_CAC_ABORTED: "NL80211_RADAR_CAC_ABORTED", + NL80211_RADAR_NOP_FINISHED: "NL80211_RADAR_NOP_FINISHED", +} +nl80211_dfs_state2str = { + NL80211_DFS_USABLE: "NL80211_DFS_USABLE", + NL80211_DFS_UNAVAILABLE: "NL80211_DFS_UNAVAILABLE", + NL80211_DFS_AVAILABLE: "NL80211_DFS_AVAILABLE", +} +nl80211_protocol_features2str = { + NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP: "NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP", +} +nl80211_crit_proto_id2str = { + NL80211_CRIT_PROTO_UNSPEC: "NL80211_CRIT_PROTO_UNSPEC", + NL80211_CRIT_PROTO_DHCP: "NL80211_CRIT_PROTO_DHCP", + NL80211_CRIT_PROTO_EAPOL: "NL80211_CRIT_PROTO_EAPOL", + NL80211_CRIT_PROTO_APIPA: "NL80211_CRIT_PROTO_APIPA", + NUM_NL80211_CRIT_PROTO: "NUM_NL80211_CRIT_PROTO", +} diff --git a/python/examples/wiphy.py b/python/examples/wiphy.py new file mode 100644 index 0000000..572e95a --- /dev/null +++ b/python/examples/wiphy.py @@ -0,0 +1,161 @@ +from __future__ import print_function +import netlink.capi as nl +import netlink.genl.capi as genl +import nl80211 +import sys +import traceback + + +class test_class: + def __init__(self): + self.done = 1 + + +def freq_to_ch(freq): + if freq == 2484: + return 14 + + if freq < 2484: + return (freq - 2407) / 5 + + # FIXME: dot11ChannelStartingFactor (802.11-2007 17.3.8.3.2) + if freq < 45000: + return freq / 5 - 1000 + + if freq >= 58320 and freq <= 64800: + return (freq - 56160) / 2160 + + return 0 + + +def handle_freq(attr, pol): + e, fattr = nl.py_nla_parse_nested(nl80211.NL80211_FREQUENCY_ATTR_MAX, attr, pol) + if nl80211.NL80211_FREQUENCY_ATTR_FREQ in fattr: + freq = nl.nla_get_u32(fattr[nl80211.NL80211_FREQUENCY_ATTR_FREQ]) + sys.stdout.write("\t\tfreq %d MHz [%d]" % (freq, freq_to_ch(freq))) + if nl80211.NL80211_FREQUENCY_ATTR_MAX_TX_POWER in fattr and not ( + nl80211.NL80211_FREQUENCY_ATTR_DISABLED in fattr + ): + sys.stdout.write( + " (%.1f dBm)" + % ( + 0.01 + * nl.nla_get_u32(fattr[nl80211.NL80211_FREQUENCY_ATTR_MAX_TX_POWER]) + ) + ) + if nl80211.NL80211_FREQUENCY_ATTR_DISABLED in fattr: + sys.stdout.write(" (disabled)") + sys.stdout.write("\n") + + +def handle_band(attr, fpol): + e, battr = nl.py_nla_parse_nested(nl80211.NL80211_BAND_ATTR_MAX, attr, None) + print("\tband %d:" % nl.nla_type(attr)) + if nl80211.NL80211_BAND_ATTR_FREQS in battr: + for fattr in nl.nla_get_nested(battr[nl80211.NL80211_BAND_ATTR_FREQS]): + handle_freq(fattr, fpol) + + +def cipher_name(suite): + suite_val = "%02x%02x%02x%02x" % tuple(reversed(suite)) + if suite_val == "000fac01": + return "WEP40 (00-0f-ac:1)" + elif suite_val == "000fac05": + return "WEP104 (00-0f-ac:5)" + elif suite_val == "000fac02": + return "TKIP (00-0f-ac:2)" + elif suite_val == "000fac04": + return "CCMP (00-0f-ac:4)" + elif suite_val == "000fac06": + return "CMAC (00-0f-ac:6)" + elif suite_val == "000fac08": + return "GCMP (00-0f-ac:8)" + elif suite_val == "00147201": + return "WPI-SMS4 (00-14-72:1)" + else: + return suite_val + + +def msg_handler(m, a): + try: + e, attr = genl.py_genlmsg_parse( + nl.nlmsg_hdr(m), 0, nl80211.NL80211_ATTR_MAX, None + ) + if nl80211.NL80211_ATTR_WIPHY_NAME in attr: + print("wiphy %s" % nl.nla_get_string(attr[nl80211.NL80211_ATTR_WIPHY_NAME])) + if nl80211.NL80211_ATTR_WIPHY_BANDS in attr: + fpol = nl.nla_policy_array(nl80211.NL80211_FREQUENCY_ATTR_MAX + 1) + fpol[nl80211.NL80211_FREQUENCY_ATTR_FREQ].type = nl.NLA_U32 + fpol[nl80211.NL80211_FREQUENCY_ATTR_DISABLED].type = nl.NLA_FLAG + fpol[nl80211.NL80211_FREQUENCY_ATTR_PASSIVE_SCAN].type = nl.NLA_FLAG + fpol[nl80211.NL80211_FREQUENCY_ATTR_NO_IBSS].type = nl.NLA_FLAG + fpol[nl80211.NL80211_FREQUENCY_ATTR_RADAR].type = nl.NLA_FLAG + fpol[nl80211.NL80211_FREQUENCY_ATTR_MAX_TX_POWER].type = nl.NLA_U32 + + nattrs = nl.nla_get_nested(attr[nl80211.NL80211_ATTR_WIPHY_BANDS]) + for nattr in nattrs: + handle_band(nattr, fpol) + if nl80211.NL80211_ATTR_CIPHER_SUITES in attr: + ciphers = nl.nla_data(attr[nl80211.NL80211_ATTR_CIPHER_SUITES]) + num = len(ciphers) / 4 + if num > 0: + print("\tSupported Ciphers:") + for i in range(0, num, 4): + print("\t\t* %s" % cipher_name(ciphers[i : i + 4])) + if nl80211.NL80211_ATTR_SUPPORTED_IFTYPES in attr: + print("\tSupported interface modes:") + ifattr = nl.nla_get_nested(attr[nl80211.NL80211_ATTR_SUPPORTED_IFTYPES]) + for nl_mode in ifattr: + print("\t\t* %s" % nl80211.nl80211_iftype2str[nl.nla_type(nl_mode)]) + if nl80211.NL80211_ATTR_SOFTWARE_IFTYPES in attr: + print("\tsoftware interface modes (can always be added):") + ifattr = nl.nla_get_nested(attr[nl80211.NL80211_ATTR_SOFTWARE_IFTYPES]) + for nl_mode in ifattr: + print("\t\t* %s" % nl80211.nl80211_iftype2str[nl.nla_type(nl_mode)]) + return nl.NL_SKIP + except Exception: + (t, v, tb) = sys.exc_info() + print(v.message) + traceback.print_tb(tb) + + +def error_handler(err, a): + a.done = err.error + return nl.NL_STOP + + +def finish_handler(m, a): + return nl.NL_SKIP + + +def ack_handler(m, a): + a.done = 0 + return nl.NL_STOP + + +try: + cbd = test_class() + tx_cb = nl.nl_cb_alloc(nl.NL_CB_DEFAULT) + rx_cb = nl.nl_cb_clone(tx_cb) + s = nl.nl_socket_alloc_cb(tx_cb) + nl.py_nl_cb_err(rx_cb, nl.NL_CB_CUSTOM, error_handler, cbd) + nl.py_nl_cb_set(rx_cb, nl.NL_CB_FINISH, nl.NL_CB_CUSTOM, finish_handler, cbd) + nl.py_nl_cb_set(rx_cb, nl.NL_CB_ACK, nl.NL_CB_CUSTOM, ack_handler, cbd) + nl.py_nl_cb_set(rx_cb, nl.NL_CB_VALID, nl.NL_CB_CUSTOM, msg_handler, cbd) + + genl.genl_connect(s) + family = genl.genl_ctrl_resolve(s, "nl80211") + m = nl.nlmsg_alloc() + genl.genlmsg_put(m, 0, 0, family, 0, 0, nl80211.NL80211_CMD_GET_WIPHY, 0) + nl.nla_put_u32(m, nl80211.NL80211_ATTR_WIPHY, 7) + + err = nl.nl_send_auto_complete(s, m) + if err < 0: + nl.nlmsg_free(m) + + while cbd.done > 0 and not err < 0: + err = nl.nl_recvmsgs(s, rx_cb) +except Exception: + (t, v, tb) = sys.exc_info() + print(v.message) + traceback.print_tb(tb) diff --git a/python/netlink/Makefile.am b/python/netlink/Makefile.am deleted file mode 100644 index 0f1045b..0000000 --- a/python/netlink/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -# -*- Makefile -*- - -SUBDIRS = route - -EXTRA_DIST = \ - capi.i \ - fixes.h \ - __init__.py \ - core.py \ - util.py diff --git a/python/netlink/Makefile.in b/python/netlink/Makefile.in deleted file mode 100644 index 60f6672..0000000 --- a/python/netlink/Makefile.in +++ /dev/null @@ -1,611 +0,0 @@ -# Makefile.in generated by automake 1.11.6 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -# -*- Makefile -*- -VPATH = @srcdir@ -am__make_dryrun = \ - { \ - am__dry=no; \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ - esac; \ - test $$am__dry = yes; \ - } -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = python/netlink -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/lib/defs.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -SOURCES = -DIST_SOURCES = -RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ - html-recursive info-recursive install-data-recursive \ - install-dvi-recursive install-exec-recursive \ - install-html-recursive install-info-recursive \ - install-pdf-recursive install-ps-recursive install-recursive \ - installcheck-recursive installdirs-recursive pdf-recursive \ - ps-recursive uninstall-recursive -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ - distclean-recursive maintainer-clean-recursive -AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ - $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ - distdir -ETAGS = etags -CTAGS = ctags -DIST_SUBDIRS = $(SUBDIRS) -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -am__relativize = \ - dir0=`pwd`; \ - sed_first='s,^\([^/]*\)/.*$$,\1,'; \ - sed_rest='s,^[^/]*/*,,'; \ - sed_last='s,^.*/\([^/]*\)$$,\1,'; \ - sed_butlast='s,/*[^/]*$$,,'; \ - while test -n "$$dir1"; do \ - first=`echo "$$dir1" | sed -e "$$sed_first"`; \ - if test "$$first" != "."; then \ - if test "$$first" = ".."; then \ - dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ - dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ - else \ - first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ - if test "$$first2" = "$$first"; then \ - dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ - else \ - dir2="../$$dir2"; \ - fi; \ - dir0="$$dir0"/"$$first"; \ - fi; \ - fi; \ - dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ - done; \ - reldir="$$dir2" -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CHECK_CFLAGS = @CHECK_CFLAGS@ -CHECK_LIBS = @CHECK_LIBS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -FLEX = @FLEX@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBNL_VERSION = @LIBNL_VERSION@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_AGE = @LT_AGE@ -LT_CURRENT = @LT_CURRENT@ -LT_REVISION = @LT_REVISION@ -MAJ_VERSION = @MAJ_VERSION@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MIC_VERSION = @MIC_VERSION@ -MIN_VERSION = @MIN_VERSION@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -YACC = @YACC@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgconfigdir = @pkgconfigdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -subdirs = @subdirs@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -SUBDIRS = route -EXTRA_DIST = \ - capi.i \ - fixes.h \ - __init__.py \ - core.py \ - util.py - -all: all-recursive - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign python/netlink/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign python/netlink/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -# This directory's subdirectories are mostly independent; you can cd -# into them and run `make' without going through this Makefile. -# To change the values of `make' variables: instead of editing Makefiles, -# (1) if the variable is set in `config.status', edit `config.status' -# (which will cause the Makefiles to be regenerated when you run `make'); -# (2) otherwise, pass the desired values on the `make' command line. -$(RECURSIVE_TARGETS): - @fail= failcom='exit 1'; \ - for f in x $$MAKEFLAGS; do \ - case $$f in \ - *=* | --[!k]*);; \ - *k*) failcom='fail=yes';; \ - esac; \ - done; \ - dot_seen=no; \ - target=`echo $@ | sed s/-recursive//`; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - dot_seen=yes; \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || eval $$failcom; \ - done; \ - if test "$$dot_seen" = "no"; then \ - $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ - fi; test -z "$$fail" - -$(RECURSIVE_CLEAN_TARGETS): - @fail= failcom='exit 1'; \ - for f in x $$MAKEFLAGS; do \ - case $$f in \ - *=* | --[!k]*);; \ - *k*) failcom='fail=yes';; \ - esac; \ - done; \ - dot_seen=no; \ - case "$@" in \ - distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ - *) list='$(SUBDIRS)' ;; \ - esac; \ - rev=''; for subdir in $$list; do \ - if test "$$subdir" = "."; then :; else \ - rev="$$subdir $$rev"; \ - fi; \ - done; \ - rev="$$rev ."; \ - target=`echo $@ | sed s/-recursive//`; \ - for subdir in $$rev; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || eval $$failcom; \ - done && test -z "$$fail" -tags-recursive: - list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ - done -ctags-recursive: - list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ - done - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - set x; \ - here=`pwd`; \ - if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ - include_option=--etags-include; \ - empty_fix=.; \ - else \ - include_option=--include; \ - empty_fix=; \ - fi; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - test ! -f $$subdir/TAGS || \ - set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ - fi; \ - done; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: CTAGS -CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - $(am__make_dryrun) \ - || test -d "$(distdir)/$$subdir" \ - || $(MKDIR_P) "$(distdir)/$$subdir" \ - || exit 1; \ - dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ - $(am__relativize); \ - new_distdir=$$reldir; \ - dir1=$$subdir; dir2="$(top_distdir)"; \ - $(am__relativize); \ - new_top_distdir=$$reldir; \ - echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ - echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ - ($(am__cd) $$subdir && \ - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$$new_top_distdir" \ - distdir="$$new_distdir" \ - am__remove_distdir=: \ - am__skip_length_check=: \ - am__skip_mode_fix=: \ - distdir) \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-recursive -all-am: Makefile -installdirs: installdirs-recursive -installdirs-am: -install: install-recursive -install-exec: install-exec-recursive -install-data: install-data-recursive -uninstall: uninstall-recursive - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-recursive -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-recursive - -clean-am: clean-generic clean-libtool mostlyclean-am - -distclean: distclean-recursive - -rm -f Makefile -distclean-am: clean-am distclean-generic distclean-tags - -dvi: dvi-recursive - -dvi-am: - -html: html-recursive - -html-am: - -info: info-recursive - -info-am: - -install-data-am: - -install-dvi: install-dvi-recursive - -install-dvi-am: - -install-exec-am: - -install-html: install-html-recursive - -install-html-am: - -install-info: install-info-recursive - -install-info-am: - -install-man: - -install-pdf: install-pdf-recursive - -install-pdf-am: - -install-ps: install-ps-recursive - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-recursive - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-recursive - -mostlyclean-am: mostlyclean-generic mostlyclean-libtool - -pdf: pdf-recursive - -pdf-am: - -ps: ps-recursive - -ps-am: - -uninstall-am: - -.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ - install-am install-strip tags-recursive - -.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ - all all-am check check-am clean clean-generic clean-libtool \ - ctags ctags-recursive distclean distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs installdirs-am maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-generic \ - mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ - uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/python/netlink/capi.i b/python/netlink/capi.i index 73c4bf3..98f4e33 100644 --- a/python/netlink/capi.i +++ b/python/netlink/capi.i @@ -6,10 +6,18 @@ #include #include #include +#include +#include + +/* enable define below to get swig api debug messages */ +/*#define DEBUG*/ +#include "utils.h" %} %include %include +%include +%include %inline %{ struct nl_dump_params *alloc_dump_params(void) @@ -113,6 +121,9 @@ struct nl_dump_params unsigned int dp_line; }; +/* */ +extern unsigned int if_nametoindex(const char *ifname); + /* */ extern const char *nl_geterror(int); @@ -175,6 +186,13 @@ extern uint32_t nl_socket_get_peer_groups(const struct nl_sock *sk); extern void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups); extern int nl_socket_set_buffer_size(struct nl_sock *, int, int); +extern void nl_socket_set_cb(struct nl_sock *, struct nl_cb *); + +extern int nl_socket_add_membership(struct nl_sock *, int); +extern int nl_socket_drop_membership(struct nl_sock *, int); + +extern int nl_send_auto_complete(struct nl_sock *, struct nl_msg *); +extern int nl_recvmsgs(struct nl_sock *, struct nl_cb *); /* */ extern int nlmsg_size(int); @@ -452,3 +470,513 @@ extern int nl_str2af(const char *); %cstring_output_maxsize(char *buf, size_t len) extern char *nl_addr2str(struct nl_addr *, char *buf, size_t len); + +/* Message Handlers */ +/** + * Callback actions + * @ingroup cb + */ +enum nl_cb_action { + /** Proceed with wathever would come next */ + NL_OK, + /** Skip this message */ + NL_SKIP, + /** Stop parsing altogether and discard remaining messages */ + NL_STOP, +}; + +/** + * Callback kinds + * @ingroup cb + */ +enum nl_cb_kind { + /** Default handlers (quiet) */ + NL_CB_DEFAULT, + /** Verbose default handlers (error messages printed) */ + NL_CB_VERBOSE, + /** Debug handlers for debugging */ + NL_CB_DEBUG, + /** Customized handler specified by the user */ + NL_CB_CUSTOM, + __NL_CB_KIND_MAX, +}; + +#define NL_CB_KIND_MAX (__NL_CB_KIND_MAX - 1) + +/** + * Callback types + * @ingroup cb + */ +enum nl_cb_type { + /** Message is valid */ + NL_CB_VALID, + /** Last message in a series of multi part messages received */ + NL_CB_FINISH, + /** Report received that data was lost */ + NL_CB_OVERRUN, + /** Message wants to be skipped */ + NL_CB_SKIPPED, + /** Message is an acknowledge */ + NL_CB_ACK, + /** Called for every message received */ + NL_CB_MSG_IN, + /** Called for every message sent out except for nl_sendto() */ + NL_CB_MSG_OUT, + /** Message is malformed and invalid */ + NL_CB_INVALID, + /** Called instead of internal sequence number checking */ + NL_CB_SEQ_CHECK, + /** Sending of an acknowledge message has been requested */ + NL_CB_SEND_ACK, + /** Flag NLM_F_DUMP_INTR is set in message */ + NL_CB_DUMP_INTR, + __NL_CB_TYPE_MAX, +}; + +#define NL_CB_TYPE_MAX (__NL_CB_TYPE_MAX - 1) + +extern struct nl_cb *nl_cb_alloc(enum nl_cb_kind); +extern struct nl_cb *nl_cb_clone(struct nl_cb *); + +struct nlmsgerr { + int error; +}; + +%{ + +struct pynl_callback { + PyObject *cbf; + PyObject *cba; +}; + +struct pynl_cbinfo { + struct nl_cb *cb; + struct pynl_callback cbtype[NL_CB_TYPE_MAX+1]; + struct pynl_callback cberr; + struct list_head list; +}; + +LIST_HEAD(callback_list); + +static struct pynl_cbinfo *pynl_find_cbinfo(struct nl_cb *cb, int unlink) +{ + struct list_head *pos, *prev; + struct pynl_cbinfo *info; + + list_for_each_safe(pos, prev, &callback_list) { + info = container_of(pos, struct pynl_cbinfo, list); + if (info->cb == cb) { + if (unlink) + list_del(pos, prev); + pynl_dbg("cb=%p: found=%p\n", cb, info); + return info; + } + } + pynl_dbg("cb=%p: not found\n", cb); + return NULL; +} + +static struct pynl_cbinfo *pynl_get_cbinfo(struct nl_cb *cb, int unlink) +{ + struct pynl_cbinfo *info; + + info = pynl_find_cbinfo(cb, unlink); + + if (info || unlink) { + /* found or no need to allocate a new one */ + pynl_dbg("cb=%p: done\n", cb); + return info; + } + + info = calloc(1, sizeof(*info)); + info->cb = cb; + list_add(&info->list, &callback_list); + pynl_dbg("cb=%p: added %p\n", cb, info); + return info; +} + +static int nl_recv_msg_handler(struct nl_msg *msg, void *arg) +{ + struct pynl_callback *cbd = arg; + PyObject *msgobj; + PyObject *cbparobj; + PyObject *resobj; + PyObject *funcobj; + int result; + + if (!cbd) { + result = NL_STOP; + goto done; + } + msgobj = SWIG_NewPointerObj(SWIG_as_voidptr(msg), + SWIGTYPE_p_nl_msg, 0 | 0 ); + /* add selfobj if callback is a method */ + if (cbd->cbf && PyMethod_Check(cbd->cbf)) { + PyObject *selfobj = PyMethod_Self(cbd->cbf); + cbparobj = Py_BuildValue("(OOO)", selfobj ? selfobj : cbd->cba, + msgobj, cbd->cba); + funcobj = PyMethod_Function(cbd->cbf); + pynl_dbg("callback %sbounded instance method %p\n", + selfobj ? "" : "un", funcobj); + } else { + cbparobj = Py_BuildValue("(OO)", msgobj, cbd->cba); + funcobj = cbd->cbf; + pynl_dbg("callback function %p\n", funcobj); + } + resobj = PyObject_CallObject(funcobj, cbparobj); + Py_DECREF(cbparobj); + if (resobj && PyInt_Check(resobj)) + result = (int)PyInt_AsLong(resobj); + else + result = NL_STOP; + Py_XDECREF(resobj); +done: + pynl_dbg("result=%d\n", result); + return result; +} + +static int nl_recv_err_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, + void *arg) +{ + struct pynl_callback *cbd = arg; + PyObject *errobj; + PyObject *cbparobj; + PyObject *resobj; + PyObject *funcobj; + int result; + + if (!cbd) + return NL_STOP; + errobj = SWIG_NewPointerObj(SWIG_as_voidptr(err), + SWIGTYPE_p_nlmsgerr, 0 | 0 ); + /* add selfobj if callback is a method */ + if (cbd->cbf && PyMethod_Check(cbd->cbf)) { + PyObject *selfobj = PyMethod_Self(cbd->cbf); + cbparobj = Py_BuildValue("(OOO)", selfobj ? selfobj : cbd->cba, + errobj, cbd->cba); + funcobj = PyMethod_Function(cbd->cbf); + } else { + cbparobj = Py_BuildValue("(OO)", errobj, cbd->cba); + funcobj = cbd->cbf; + } + resobj = PyObject_CallObject(funcobj, cbparobj); + Py_DECREF(cbparobj); + if (resobj && PyInt_Check(resobj)) + result = (int)PyInt_AsLong(resobj); + else + result = NL_STOP; + Py_XDECREF(resobj); + pynl_dbg("error: err=%d ret=%d\n", err->error, result); + return result; +} + +%} +%inline %{ +struct nl_cb *py_nl_cb_clone(struct nl_cb *cb) +{ + struct pynl_cbinfo *info, *clone_info; + struct nl_cb *clone; + int i; + + clone = nl_cb_clone(cb); + info = pynl_find_cbinfo(cb, 0); + if (info) { + clone_info = pynl_get_cbinfo(clone, 0); + /* increase refcnt to callback parameters and copy them */ + for (i = 0; info && i <= NL_CB_TYPE_MAX; i++) { + Py_XINCREF(info->cbtype[i].cbf); + Py_XINCREF(info->cbtype[i].cba); + clone_info->cbtype[i].cbf = info->cbtype[i].cbf; + clone_info->cbtype[i].cba = info->cbtype[i].cba; + } + Py_XINCREF(info->cberr.cbf); + Py_XINCREF(info->cberr.cba); + clone_info->cberr.cbf = info->cberr.cbf; + clone_info->cberr.cba = info->cberr.cba; + } + return clone; +} + +void py_nl_cb_put(struct nl_cb *cb) +{ + struct pynl_cbinfo *info; + int i; + + /* obtain callback info (and unlink) */ + info = pynl_get_cbinfo(cb, 1); + pynl_dbg("cb=%p, info=%p\n", cb, info); + /* decrease refcnt for callback type handlers */ + for (i = 0; info && i <= NL_CB_TYPE_MAX; i++) { + Py_XDECREF(info->cbtype[i].cbf); + Py_XDECREF(info->cbtype[i].cba); + } + /* decrease refcnt for error handler and free callback info */ + if (info) { + Py_XDECREF(info->cberr.cbf); + Py_XDECREF(info->cberr.cba); + free(info); + } + nl_cb_put(cb); +} + +int py_nl_cb_set(struct nl_cb *cb, enum nl_cb_type t, enum nl_cb_kind k, + PyObject *func, PyObject *a) +{ + struct pynl_cbinfo *info; + + /* obtain callback info */ + info = pynl_get_cbinfo(cb, 0); + + /* clear existing handlers (if any) */ + Py_XDECREF(info->cbtype[t].cbf); + Py_XDECREF(info->cbtype[t].cba); + info->cbtype[t].cbf = NULL; + info->cbtype[t].cba = NULL; + pynl_dbg("cb=%p, info=%p, type=%d, kind=%d\n", cb, info, t, k); + /* handle custom callback */ + if (k == NL_CB_CUSTOM) { + Py_XINCREF(func); + Py_XINCREF(a); + info->cbtype[t].cbf = func; + info->cbtype[t].cba = a; + return nl_cb_set(cb, t, k, + nl_recv_msg_handler, &info->cbtype[t]); + } + return nl_cb_set(cb, t, k, NULL, NULL); +} + +int py_nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind k, + PyObject *func , PyObject *a) +{ + struct pynl_cbinfo *info; + int t; + + info = pynl_get_cbinfo(cb, 0); + pynl_dbg("cb=%p, info=%p, kind=%d\n", cb, info, k); + for (t = 0; t <= NL_CB_TYPE_MAX; t++) { + /* (possibly) free existing handler */ + Py_XDECREF(info->cbtype[t].cbf); + Py_XDECREF(info->cbtype[t].cba); + info->cbtype[t].cbf = NULL; + info->cbtype[t].cba = NULL; + if (k == NL_CB_CUSTOM) { + Py_XINCREF(func); + Py_XINCREF(a); + info->cbtype[t].cbf = func; + info->cbtype[t].cba = a; + } + } + if (k == NL_CB_CUSTOM) + /* callback argument is same for all so using idx 0 here */ + return nl_cb_set_all(cb, k, nl_recv_msg_handler, + &info->cbtype[0]); + else + return nl_cb_set_all(cb, k, NULL, NULL); +} + +int py_nl_cb_err(struct nl_cb *cb, enum nl_cb_kind k, + PyObject *func, PyObject *a) +{ + struct pynl_cbinfo *info; + + /* obtain callback info */ + info = pynl_get_cbinfo(cb, 0); + pynl_dbg("cb=%p, info=%p, kind=%d\n", cb, info, k); + /* clear existing handlers (if any) */ + Py_XDECREF(info->cberr.cbf); + Py_XDECREF(info->cberr.cba); + info->cberr.cbf = NULL; + info->cberr.cba = NULL; + + /* handle custom callback */ + if (k == NL_CB_CUSTOM) { + Py_XINCREF(func); + Py_XINCREF(a); + info->cberr.cbf = func; + info->cberr.cba = a; + return nl_cb_err(cb, k, + nl_recv_err_handler, &info->cberr); + } + return nl_cb_err(cb, k, NULL, NULL); +} +%} + +/* Attributes */ +/* + * This typemap is a bit tricky as it uses arg1, which is knowledge about + * the SWIGged wrapper output. + */ +%typemap(out) void * { + $result = PyByteArray_FromStringAndSize($1, nla_len(arg1)); +} +extern void *nla_data(struct nlattr *); +%typemap(out) void *; +extern int nla_type(const struct nlattr *); + +%typemap(in) (int, const void *) { + $1 = Py_SIZE($input); + if (PyByteArray_Check($input)) { + $2 = ($2_ltype)PyByteArray_AsString($input); + } else if (PyString_Check($input)) { + $2 = ($2_ltype)PyString_AsString($input); + } else + SWIG_exception(SWIG_TypeError, + "pointer must be bytearray or string."); +} +extern int nla_put(struct nl_msg *, int, int, const void *); +%typemap(in) const void *; + +/* Integer attribute */ +extern uint8_t nla_get_u8(struct nlattr *); +extern int nla_put_u8(struct nl_msg *, int, uint8_t); +extern uint16_t nla_get_u16(struct nlattr *); +extern int nla_put_u16(struct nl_msg *, int, uint16_t); +extern uint32_t nla_get_u32(struct nlattr *); +extern int nla_put_u32(struct nl_msg *, int, uint32_t); +extern uint64_t nla_get_u64(struct nlattr *); +extern int nla_put_u64(struct nl_msg *, int, uint64_t); + +/* String attribute */ +extern char * nla_get_string(struct nlattr *); +extern char * nla_strdup(struct nlattr *); +extern int nla_put_string(struct nl_msg *, int, const char *); + +/* Flag attribute */ +extern int nla_get_flag(struct nlattr *); +extern int nla_put_flag(struct nl_msg *, int); + +/* Msec attribute */ +extern unsigned long nla_get_msecs(struct nlattr *); +extern int nla_put_msecs(struct nl_msg *, int, unsigned long); + +/* Attribute nesting */ +extern int nla_put_nested(struct nl_msg *, int, struct nl_msg *); +extern struct nlattr * nla_nest_start(struct nl_msg *, int); +extern int nla_nest_end(struct nl_msg *, struct nlattr *); +%inline %{ +PyObject *py_nla_parse_nested(int max, struct nlattr *nest_attr, PyObject *p) +{ + struct nlattr *tb_msg[max + 1]; + struct nla_policy *policy = NULL; + void *pol; + PyObject *attrs = Py_None; + PyObject *k; + PyObject *v; + PyObject *resobj; + int err; + int i; + + if (p != Py_None) { + PyObject *pobj; + + if (!PyList_Check(p)) { + fprintf(stderr, "expected list object\n"); + err = -1; + goto fail; + } + pobj = PyList_GetItem(p, 0); + err = SWIG_ConvertPtr(pobj, &pol, SWIGTYPE_p_nla_policy, 0 | 0 ); + if (!SWIG_IsOK(err)) + goto fail; + policy = pol; + } + err = nla_parse_nested(tb_msg, max, nest_attr, policy); + if (err < 0) { + fprintf(stderr, "Failed to parse response message\n"); + } else { + attrs = PyDict_New(); + for (i = 0; i <= max; i++) + if (tb_msg[i]) { + k = PyInt_FromLong((long)i); + v = SWIG_NewPointerObj(SWIG_as_voidptr(tb_msg[i]), SWIGTYPE_p_nlattr, 0 | 0 ); + PyDict_SetItem(attrs, k, v); + } + } +fail: + if (attrs == Py_None) + Py_INCREF(attrs); + resobj = Py_BuildValue("(iO)", err, attrs); + return resobj; +} + +/* + * nla_get_nested() - get list of nested attributes. + * + * nla_for_each_() is a macro construct that needs another approach + * for Python. Create and return list of nested attributes. + */ +PyObject *nla_get_nested(struct nlattr *nest_attr) +{ + PyObject *listobj; + PyObject *nestattrobj; + struct nlattr *pos; + int rem; + + listobj = PyList_New(0); + nla_for_each_nested(pos, nest_attr, rem) { + nestattrobj = SWIG_NewPointerObj(SWIG_as_voidptr(pos), + SWIGTYPE_p_nlattr, 0 | 0 ); + PyList_Append(listobj, nestattrobj); + } + return listobj; +} +%} + + /** + * @ingroup attr + * Basic attribute data types + * + * See \ref attr_datatypes for more details. + */ +enum { + NLA_UNSPEC, /**< Unspecified type, binary data chunk */ + NLA_U8, /**< 8 bit integer */ + NLA_U16, /**< 16 bit integer */ + NLA_U32, /**< 32 bit integer */ + NLA_U64, /**< 64 bit integer */ + NLA_STRING, /**< NUL terminated character string */ + NLA_FLAG, /**< Flag */ + NLA_MSECS, /**< Micro seconds (64bit) */ + NLA_NESTED, /**< Nested attributes */ + __NLA_TYPE_MAX, +}; + +#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1) + +/** @} */ + +/** + * @ingroup attr + * Attribute validation policy. + * + * See \ref attr_datatypes for more details. + */ +struct nla_policy { + /** Type of attribute or NLA_UNSPEC */ + uint16_t type; + + /** Minimal length of payload required */ + uint16_t minlen; + + /** Maximal length of payload allowed */ + uint16_t maxlen; +}; + +%inline %{ +PyObject *nla_policy_array(int n_items) +{ + struct nla_policy *policies; + PyObject *listobj; + PyObject *polobj; + int i; + + policies = calloc(n_items, sizeof(*policies)); + listobj = PyList_New(n_items); + for (i = 0; i < n_items; i++) { + polobj = SWIG_NewPointerObj(SWIG_as_voidptr(&policies[i]), + SWIGTYPE_p_nla_policy, 0 | 0 ); + PyList_SetItem(listobj, i, polobj); + } + return listobj; +} +%} diff --git a/python/netlink/core.py b/python/netlink/core.py index 3298e2c..b994a73 100644 --- a/python/netlink/core.py +++ b/python/netlink/core.py @@ -10,6 +10,8 @@ This module provides an interface to netlink sockets The module contains the following public classes: - Socket -- The netlink socket + - Message -- The netlink message + - Callback -- The netlink callback handler - Object -- Abstract object (based on struct nl_obect in libnl) used as base class for all object types which can be put into a Cache - Cache -- A collection of objects which are derived from the base @@ -28,22 +30,22 @@ details. from __future__ import absolute_import - from . import capi import sys import socket __all__ = [ - 'Message', - 'Socket', - 'DumpParams', - 'Object', - 'Cache', - 'KernelError', - 'NetlinkError', + "Socket", + "Message", + "Callback", + "DumpParams", + "Object", + "Cache", + "KernelError", + "NetlinkError", ] -__version__ = '0.1' +__version__ = "0.1" # netlink protocols NETLINK_ROUTE = 0 @@ -89,6 +91,7 @@ NLM_F_EXCL = 0x200 NLM_F_CREATE = 0x400 NLM_F_APPEND = 0x800 + class NetlinkError(Exception): def __init__(self, error): self._error = error @@ -97,16 +100,19 @@ class NetlinkError(Exception): def __str__(self): return self._msg + class KernelError(NetlinkError): def __str__(self): - return 'Kernel returned: {0}'.format(self._msg) + return "Kernel returned: {0}".format(self._msg) + class ImmutableError(NetlinkError): def __init__(self, msg): self._msg = msg def __str__(self): - return 'Immutable attribute: {0}'.format(self._msg) + return "Immutable attribute: {0}".format(self._msg) + class Message(object): """Netlink message""" @@ -118,13 +124,13 @@ class Message(object): self._msg = capi.nlmsg_alloc_size(size) if self._msg is None: - raise Exception('Message allocation returned NULL') + raise Exception("Message allocation returned NULL") def __del__(self): capi.nlmsg_free(self._msg) def __len__(self): - return capi.nlmsg_len(nlmsg_hdr(self._msg)) + return capi.nlmsg_len(capi.nlmsg_hdr(self._msg)) @property def protocol(self): @@ -153,23 +159,51 @@ class Message(object): def send(self, sock): sock.send(self) + +class Callback(object): + """Netlink callback""" + + def __init__(self, kind=capi.NL_CB_DEFAULT): + if isinstance(kind, Callback): + self._cb = capi.py_nl_cb_clone(kind._cb) + else: + self._cb = capi.nl_cb_alloc(kind) + + def __del__(self): + capi.py_nl_cb_put(self._cb) + + def set_type(self, t, k, handler, obj): + return capi.py_nl_cb_set(self._cb, t, k, handler, obj) + + def set_all(self, k, handler, obj): + return capi.py_nl_cb_set_all(self._cb, k, handler, obj) + + def set_err(self, k, handler, obj): + return capi.py_nl_cb_err(self._cb, k, handler, obj) + + def clone(self): + return Callback(self) + + class Socket(object): """Netlink socket""" def __init__(self, cb=None): - if cb is None: + if isinstance(cb, Callback): + self._sock = capi.nl_socket_alloc_cb(cb._cb) + elif cb is None: self._sock = capi.nl_socket_alloc() else: - self._sock = capi.nl_socket_alloc_cb(cb) + raise Exception("'cb' parameter has wrong type") if self._sock is None: - raise Exception('NULL pointer returned while allocating socket') + raise Exception("NULL pointer returned while allocating socket") def __del__(self): capi.nl_socket_free(self._sock) def __str__(self): - return 'nlsock<{0}>'.format(self.localPort) + return "nlsock<{0}>".format(self.local_port) @property def local_port(self): @@ -208,12 +242,29 @@ class Socket(object): def sendto(self, buf): ret = capi.nl_sendto(self._sock, buf, len(buf)) if ret < 0: - raise Exception('Failed to send') + raise Exception("Failed to send") else: return ret + def send_auto_complete(self, msg): + if not isinstance(msg, Message): + raise Exception("must provide Message instance") + ret = capi.nl_send_auto_complete(self._sock, msg._msg) + if ret < 0: + raise Exception("send_auto_complete failed: ret=%d" % ret) + return ret + + def recvmsgs(self, recv_cb): + if not isinstance(recv_cb, Callback): + raise Exception("must provide Callback instance") + ret = capi.nl_recvmsgs(self._sock, recv_cb._cb) + if ret < 0: + raise Exception("recvmsg failed: ret=%d" % ret) + + _sockets = {} + def lookup_socket(protocol): try: sock = _sockets[protocol] @@ -224,13 +275,14 @@ def lookup_socket(protocol): return sock + class DumpParams(object): """Dumping parameters""" def __init__(self, type_=NL_DUMP_LINE): self._dp = capi.alloc_dump_params() if not self._dp: - raise Exception('Unable to allocate struct nl_dump_params') + raise Exception("Unable to allocate struct nl_dump_params") self._dp.dp_type = type_ @@ -253,9 +305,11 @@ class DumpParams(object): def prefix(self, value): self._dp.dp_prefix = value + # underscore this to make sure it is deleted first upon module deletion _defaultDumpParams = DumpParams(NL_DUMP_LINE) + class Object(object): """Cacheable object (base class)""" @@ -281,7 +335,7 @@ class Object(object): capi.nl_object_put(self._nl_object) def __str__(self): - if hasattr(self, 'format'): + if hasattr(self, "format"): return self.format() else: return capi.nl_object_dump_buf(self._nl_object, 4096).rstrip() @@ -324,10 +378,10 @@ class Object(object): self._modules.append(ret) def _module_brief(self): - ret = '' + ret = "" for module in self._modules: - if hasattr(module, 'brief'): + if hasattr(module, "brief"): ret += module.brief() return ret @@ -339,7 +393,6 @@ class Object(object): capi.nl_object_dump(self._nl_object, params._dp) - @property def mark(self): return bool(capi.nl_object_is_marked(self._nl_object)) @@ -368,10 +421,10 @@ class Object(object): # accessing properties of subclass/subtypes (e.g. link.vlan.id) def _resolve(self, attr): obj = self - l = attr.split('.') - while len(l) > 1: - obj = getattr(obj, l.pop(0)) - return (obj, l.pop(0)) + lst = attr.split(".") + while len(lst) > 1: + obj = getattr(obj, lst.pop(0)) + return (obj, lst.pop(0)) def _setattr(self, attr, val): obj, attr = self._resolve(attr) @@ -381,6 +434,7 @@ class Object(object): obj, attr = self._resolve(attr) return hasattr(obj, attr) + class ObjIterator(object): def __init__(self, cache, obj): self._cache = cache @@ -405,6 +459,9 @@ class ObjIterator(object): return capi.nl_cache_get_next(self._nl_object) def next(self): + return self.__next__() + + def __next__(self): if self._end: raise StopIteration() @@ -433,8 +490,10 @@ class ReverseObjIterator(ObjIterator): def get_next(self): return capi.nl_cache_get_prev(self._nl_object) + class Cache(object): """Collection of netlink objects""" + def __init__(self): if self.__class__ is Cache: raise NotImplementedError() @@ -522,12 +581,12 @@ class Cache(object): capi.nl_cache_refill(socket._sock, self._nl_cache) return self - def resync(self, socket=None, cb=None): + def resync(self, socket=None, cb=None, args=None): """Synchronize cache with content in kernel""" if socket is None: socket = lookup_socket(self._protocol) - capi.nl_cache_resync(socket._sock, self._nl_cache, cb) + capi.nl_cache_resync(socket._sock, self._nl_cache, cb, args) def provide(self): """Provide this cache to others @@ -550,8 +609,11 @@ class Cache(object): """ capi.nl_cache_mngt_unprovide(self._nl_cache) + # Cache Manager (Work in Progress) NL_AUTO_PROVIDE = 1 + + class CacheManager(object): def __init__(self, protocol, flags=None): @@ -573,6 +635,7 @@ class CacheManager(object): def add(self, name): capi.cache_mngr_add(self._mngr, name, None, None) + class AddressFamily(object): """Address family representation @@ -585,11 +648,12 @@ class AddressFamily(object): print int(af) # => 10 (numeric representation) print repr(af) # => AddressFamily('inet6') """ + def __init__(self, family=socket.AF_UNSPEC): if isinstance(family, str): family = capi.nl_str2af(family) if family < 0: - raise ValueError('Unknown family name') + raise ValueError("Unknown family name") elif not isinstance(family, int): raise TypeError() @@ -602,7 +666,7 @@ class AddressFamily(object): return self._family def __repr__(self): - return 'AddressFamily({0!r})'.format(str(self)) + return "AddressFamily({0!r})".format(str(self)) class AbstractAddress(object): @@ -620,13 +684,16 @@ class AbstractAddress(object): """ + def __init__(self, addr): self._nl_addr = None if isinstance(addr, str): + # returns None on success I guess + # TO CORRECT addr = capi.addr_parse(addr, socket.AF_UNSPEC) if addr is None: - raise ValueError('Invalid address format') + raise ValueError("Invalid address format") elif addr: capi.nl_addr_get(addr) @@ -673,7 +740,7 @@ class AbstractAddress(object): if self._nl_addr: return capi.nl_addr2str(self._nl_addr, 64)[0] else: - return 'none' + return "none" @property def shared(self): @@ -724,6 +791,7 @@ class AbstractAddress(object): # fmt = func (formatting function) # title = string + def nlattr(**kwds): """netlink object attribute decorator @@ -741,4 +809,5 @@ def nlattr(**kwds): def wrap_fn(func): func.formatinfo = kwds return func + return wrap_fn diff --git a/python/netlink/fixes.h b/python/netlink/fixes.h deleted file mode 100644 index 9a6118b..0000000 --- a/python/netlink/fixes.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/python/netlink/genl/__init__.py b/python/netlink/genl/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/netlink/genl/capi.i b/python/netlink/genl/capi.i new file mode 100644 index 0000000..fbf448f --- /dev/null +++ b/python/netlink/genl/capi.i @@ -0,0 +1,116 @@ +%module capi +%{ +#include +#include +#include +#include +%} + +%include +%include + +/* #include */ +extern int genl_ctrl_alloc_cache(struct nl_sock *, struct nl_cache **o_cache); +extern struct genl_family *genl_ctrl_search(struct nl_cache *, int); +extern struct genl_family *genl_ctrl_search_by_name(struct nl_cache *, + const char *); +extern int genl_ctrl_resolve(struct nl_sock *, const char *); +extern int genl_ctrl_resolve_grp(struct nl_sock *sk, const char *family, + const char *grp); + +/* #include */ +extern struct genl_family *genl_family_alloc(void); +extern void genl_family_put(struct genl_family *); + +extern unsigned int genl_family_get_id(struct genl_family *); +extern void genl_family_set_id(struct genl_family *, unsigned int); +extern char *genl_family_get_name(struct genl_family *); +extern void genl_family_set_name(struct genl_family *, const char *name); +extern uint8_t genl_family_get_version(struct genl_family *); +extern void genl_family_set_version(struct genl_family *, uint8_t); +extern uint32_t genl_family_get_hdrsize(struct genl_family *); +extern void genl_family_set_hdrsize(struct genl_family *, uint32_t); +extern uint32_t genl_family_get_maxattr(struct genl_family *); +extern void genl_family_set_maxattr(struct genl_family *, uint32_t); + +extern int genl_family_add_op(struct genl_family *, int, int); +extern int genl_family_add_grp(struct genl_family *, uint32_t , const char *); + +/* #include */ +struct genlmsghdr { + uint8_t cmd; + uint8_t version; + uint16_t reserved; +}; + +/* #include */ +extern int genl_connect(struct nl_sock *); +extern struct genlmsghdr *genlmsg_hdr(struct nlmsghdr *); + +extern void *genlmsg_put(struct nl_msg *, uint32_t, uint32_t, + int, int, int, uint8_t, uint8_t); + +struct nlattr { +}; + +struct nla_policy { + /** Type of attribute or NLA_UNSPEC */ + uint16_t type; + + /** Minimal length of payload required */ + uint16_t minlen; + + /** Maximal length of payload allowed */ + uint16_t maxlen; +}; + +%inline %{ +PyObject *py_genlmsg_parse(struct nlmsghdr *nlh, int uhl, int max, + PyObject *p) +{ + struct nlattr *tb_msg[max + 1]; + struct nla_policy *policy = NULL; + void *pol; + PyObject *attrs = Py_None; + PyObject *k; + PyObject *v; + PyObject *resobj; + int err; + int i; + + if (p != Py_None) { + PyObject *pobj; + + if (!PyList_Check(p)) { + fprintf(stderr, "expected list object\n"); + err = -1; + goto fail; + } + pobj = PyList_GetItem(p, 0); + err = SWIG_ConvertPtr(pobj, &pol, SWIGTYPE_p_nla_policy, 0 | 0 ); + if (!SWIG_IsOK(err)) + goto fail; + policy = pol; + } + err = genlmsg_parse(nlh, uhl, tb_msg, max, policy); + if (err < 0) { + fprintf(stderr, "Failed to parse response message\n"); + } else { + attrs = PyDict_New(); + for (i = 0; i <= max; i++) + if (tb_msg[i]) { + k = PyInt_FromLong((long)i); + v = SWIG_NewPointerObj(SWIG_as_voidptr(tb_msg[i]), SWIGTYPE_p_nlattr, 0 | 0 ); + PyDict_SetItem(attrs, k, v); + } + } +fail: + if (attrs == Py_None) + Py_INCREF(Py_None); + resobj = Py_BuildValue("(iO)", err, attrs); + return resobj; +} + +%} +/* #include */ +/* nothing yet */ diff --git a/python/netlink/route/Makefile.am b/python/netlink/route/Makefile.am deleted file mode 100644 index ef714f4..0000000 --- a/python/netlink/route/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -# -*- Makefile -*- - -EXTRA_DIST = \ - capi.i \ - __init__.py \ - address.py \ - link.py \ - tc.py \ - links/__init__.py \ - links/dummy.py \ - links/inet.py \ - links/vlan.py \ - qdisc/__init__.py \ - qdisc/htb.py diff --git a/python/netlink/route/Makefile.in b/python/netlink/route/Makefile.in deleted file mode 100644 index 7ea4d10..0000000 --- a/python/netlink/route/Makefile.in +++ /dev/null @@ -1,417 +0,0 @@ -# Makefile.in generated by automake 1.11.6 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -# -*- Makefile -*- -VPATH = @srcdir@ -am__make_dryrun = \ - { \ - am__dry=no; \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ - esac; \ - test $$am__dry = yes; \ - } -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = python/netlink/route -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/lib/defs.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -SOURCES = -DIST_SOURCES = -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CHECK_CFLAGS = @CHECK_CFLAGS@ -CHECK_LIBS = @CHECK_LIBS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -FLEX = @FLEX@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBNL_VERSION = @LIBNL_VERSION@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_AGE = @LT_AGE@ -LT_CURRENT = @LT_CURRENT@ -LT_REVISION = @LT_REVISION@ -MAJ_VERSION = @MAJ_VERSION@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MIC_VERSION = @MIC_VERSION@ -MIN_VERSION = @MIN_VERSION@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -YACC = @YACC@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgconfigdir = @pkgconfigdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -subdirs = @subdirs@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -EXTRA_DIST = \ - capi.i \ - __init__.py \ - address.py \ - link.py \ - tc.py \ - links/__init__.py \ - links/dummy.py \ - links/inet.py \ - links/vlan.py \ - qdisc/__init__.py \ - qdisc/htb.py - -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign python/netlink/route/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign python/netlink/route/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -tags: TAGS -TAGS: - -ctags: CTAGS -CTAGS: - - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: all all-am check check-am clean clean-generic clean-libtool \ - distclean distclean-generic distclean-libtool distdir dvi \ - dvi-am html html-am info info-am install install-am \ - install-data install-data-am install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-generic \ - mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/python/netlink/route/address.py b/python/netlink/route/address.py index cab2a97..541f428 100644 --- a/python/netlink/route/address.py +++ b/python/netlink/route/address.py @@ -8,23 +8,22 @@ from __future__ import absolute_import -__version__ = '1.0' -__all__ = [ - 'AddressCache', - 'Address'] +__version__ = "1.0" +__all__ = ["AddressCache", "Address"] import datetime from .. import core as netlink -from . import capi as capi -from . import link as Link +from . import capi as capi +from . import link as Link from .. import util as util + class AddressCache(netlink.Cache): """Cache containing network addresses""" def __init__(self, cache=None): if not cache: - cache = self._alloc_cache_name('route/addr') + cache = self._alloc_cache_name("route/addr") self._protocol = netlink.NETLINK_ROUTE self._nl_cache = cache @@ -38,8 +37,7 @@ class AddressCache(netlink.Cache): if type(local) is str: local = netlink.AbstractAddress(local) - addr = capi.rtnl_addr_get(self._nl_cache, ifindex, - local._nl_addr) + addr = capi.rtnl_addr_get(self._nl_cache, ifindex, local._nl_addr) if addr is None: raise KeyError() @@ -53,11 +51,12 @@ class AddressCache(netlink.Cache): def _new_cache(cache): return AddressCache(cache=cache) + class Address(netlink.Object): """Network address""" def __init__(self, obj=None): - netlink.Object.__init__(self, 'route/addr', 'address', obj) + netlink.Object.__init__(self, "route/addr", "address", obj) self._rtnl_addr = self._obj2type(self._nl_object) @classmethod @@ -148,13 +147,13 @@ class Address(netlink.Object): addr.flags = [ '+xxx', '-yyy' ] # list operation """ flags = capi.rtnl_addr_get_flags(self._rtnl_addr) - return capi.rtnl_addr_flags2str(flags, 256)[0].split(',') + return capi.rtnl_addr_flags2str(flags, 256)[0].split(",") def _set_flag(self, flag): - if flag.startswith('-'): + if flag.startswith("-"): i = capi.rtnl_addr_str2flags(flag[1:]) capi.rtnl_addr_unset_flags(self._rtnl_addr, i) - elif flag.startswith('+'): + elif flag.startswith("+"): i = capi.rtnl_addr_str2flags(flag[1:]) capi.rtnl_addr_set_flags(self._rtnl_addr, i) else: @@ -249,7 +248,7 @@ class Address(netlink.Object): try: a = netlink.AbstractAddress(value) except ValueError as err: - raise AttributeError('multicast', err) + raise AttributeError("multicast", err) capi.rtnl_addr_set_multicast(self._rtnl_addr, a._nl_addr) @@ -298,14 +297,14 @@ class Address(netlink.Object): def create_time(self): """Creation time""" hsec = capi.rtnl_addr_get_create_time(self._rtnl_addr) - return datetime.timedelta(milliseconds=10*hsec) + return datetime.timedelta(milliseconds=10 * hsec) @property @netlink.nlattr(type=int, immutable=True, fmt=util.num) def last_update(self): """Last update""" hsec = capi.rtnl_addr_get_last_update_time(self._rtnl_addr) - return datetime.timedelta(milliseconds=10*hsec) + return datetime.timedelta(milliseconds=10 * hsec) def add(self, socket=None, flags=None): if not socket: @@ -330,38 +329,38 @@ class Address(netlink.Object): # Used for formatting output. USE AT OWN RISK @property def _flags(self): - return ','.join(self.flags) + return ",".join(self.flags) - def format(self, details=False, stats=False, nodev=False, indent=''): + def format(self, details=False, stats=False, nodev=False, indent=""): """Return address as formatted text""" fmt = util.MyFormatter(self, indent) - buf = fmt.format('{a|local!b}') + buf = fmt.format("{a|local!b}") if not nodev: - buf += fmt.format(' {a|ifindex}') + buf += fmt.format(" {a|ifindex}") - buf += fmt.format(' {a|scope}') + buf += fmt.format(" {a|scope}") if self.label: buf += fmt.format(' "{a|label}"') - buf += fmt.format(' <{a|_flags}>') + buf += fmt.format(" <{a|_flags}>") if details: - buf += fmt.nl('\t{t|broadcast} {t|multicast}') \ - + fmt.nl('\t{t|peer} {t|anycast}') + buf += fmt.nl("\t{t|broadcast} {t|multicast}") + fmt.nl( + "\t{t|peer} {t|anycast}" + ) if self.valid_lifetime: - buf += fmt.nl('\t{s|valid-lifetime!k} '\ - '{a|valid_lifetime}') + buf += fmt.nl("\t{s|valid-lifetime!k} " "{a|valid_lifetime}") if self.preferred_lifetime: - buf += fmt.nl('\t{s|preferred-lifetime!k} '\ - '{a|preferred_lifetime}') + buf += fmt.nl("\t{s|preferred-lifetime!k} " "{a|preferred_lifetime}") if stats and (self.create_time or self.last_update): - buf += self.nl('\t{s|created!k} {a|create_time}'\ - ' {s|last-updated!k} {a|last_update}') + buf += self.nl( + "\t{s|created!k} {a|create_time}" " {s|last-updated!k} {a|last_update}" + ) return buf diff --git a/python/netlink/route/capi.i b/python/netlink/route/capi.i index 8ac114b..2d72bd7 100644 --- a/python/netlink/route/capi.i +++ b/python/netlink/route/capi.i @@ -3,6 +3,9 @@ #include #include #include +#include +#include +#include #include #include @@ -142,6 +145,9 @@ extern int rtnl_link_set_stat(struct rtnl_link *, const unsigned int, const uint extern int rtnl_link_set_type(struct rtnl_link *, const char *); extern char *rtnl_link_get_type(struct rtnl_link *); +extern int rtnl_link_enslave(struct nl_sock * sock, struct rtnl_link * master, struct rtnl_link * slave); +extern int rtnl_link_release(struct nl_sock * sock, struct rtnl_link * slave); + /* */ struct vlan_map @@ -169,6 +175,111 @@ extern uint32_t *rtnl_link_vlan_get_ingress_map(struct rtnl_link *); extern int rtnl_link_vlan_set_egress_map(struct rtnl_link *, uint32_t, int); extern struct vlan_map *rtnl_link_vlan_get_egress_map(struct rtnl_link *, int *); +/* */ + +%cstring_output_maxsize(char *buf, size_t len) +extern struct rtnl_link *rtnl_link_macvlan_alloc(void); +extern int rtnl_link_is_macvlan(struct rtnl_link *); +extern char * rtnl_link_macvlan_mode2str(int, char *, size_t); +extern int rtnl_link_macvlan_str2mode(const char *); +extern char * rtnl_link_macvlan_flags2str(int, char *, size_t); +extern int rtnl_link_macvlan_str2flags(const char *); +extern int rtnl_link_macvlan_set_mode(struct rtnl_link *, uint32_t); +extern uint32_t rtnl_link_macvlan_get_mode(struct rtnl_link *); +extern int rtnl_link_macvlan_set_flags(struct rtnl_link *, uint16_t); +extern int rtnl_link_macvlan_unset_flags(struct rtnl_link *, uint16_t); +extern uint16_t rtnl_link_macvlan_get_flags(struct rtnl_link *); + +/* */ + +#define VXLAN_ID_MAX 16777215 + +extern struct rtnl_link *rtnl_link_vxlan_alloc(void); + +extern int rtnl_link_is_vxlan(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_id(struct rtnl_link *, uint32_t); +extern int rtnl_link_vxlan_get_id(struct rtnl_link *, uint32_t *); + +extern int rtnl_link_vxlan_set_group(struct rtnl_link *, struct nl_addr *); +extern int rtnl_link_vxlan_get_group(struct rtnl_link *, struct nl_addr **); + +extern int rtnl_link_vxlan_set_link(struct rtnl_link *, uint32_t); +extern int rtnl_link_vxlan_get_link(struct rtnl_link *, uint32_t *); + +extern int rtnl_link_vxlan_set_local(struct rtnl_link *, struct nl_addr *); +extern int rtnl_link_vxlan_get_local(struct rtnl_link *, struct nl_addr **); + +extern int rtnl_link_vxlan_set_ttl(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_ttl(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_tos(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_tos(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_learning(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_learning(struct rtnl_link *); +extern int rtnl_link_vxlan_enable_learning(struct rtnl_link *); +extern int rtnl_link_vxlan_disable_learning(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_ageing(struct rtnl_link *, uint32_t); +extern int rtnl_link_vxlan_get_ageing(struct rtnl_link *, uint32_t *); + +extern int rtnl_link_vxlan_set_limit(struct rtnl_link *, uint32_t); +extern int rtnl_link_vxlan_get_limit(struct rtnl_link *, uint32_t *); + +extern int rtnl_link_vxlan_set_port_range(struct rtnl_link *, + struct ifla_vxlan_port_range *); +extern int rtnl_link_vxlan_get_port_range(struct rtnl_link *, + struct ifla_vxlan_port_range *); + +extern int rtnl_link_vxlan_set_proxy(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_proxy(struct rtnl_link *); +extern int rtnl_link_vxlan_enable_proxy(struct rtnl_link *); +extern int rtnl_link_vxlan_disable_proxy(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_rsc(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_rsc(struct rtnl_link *); +extern int rtnl_link_vxlan_enable_rsc(struct rtnl_link *); +extern int rtnl_link_vxlan_disable_rsc(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_l2miss(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_l2miss(struct rtnl_link *); +extern int rtnl_link_vxlan_enable_l2miss(struct rtnl_link *); +extern int rtnl_link_vxlan_disable_l2miss(struct rtnl_link *); + +extern int rtnl_link_vxlan_set_l3miss(struct rtnl_link *, uint8_t); +extern int rtnl_link_vxlan_get_l3miss(struct rtnl_link *); +extern int rtnl_link_vxlan_enable_l3miss(struct rtnl_link *); +extern int rtnl_link_vxlan_disable_l3miss(struct rtnl_link *); + +/* */ + +enum rtnl_link_bridge_flags { + RTNL_BRIDGE_HAIRPIN_MODE = 0x0001, + RTNL_BRIDGE_BPDU_GUARD = 0x0002, + RTNL_BRIDGE_ROOT_BLOCK = 0x0004, + RTNL_BRIDGE_FAST_LEAVE = 0x0008, +}; + +extern int rtnl_link_is_bridge(struct rtnl_link *); +extern int rtnl_link_bridge_has_ext_info(struct rtnl_link *); + +extern int rtnl_link_bridge_set_port_state(struct rtnl_link *, uint8_t ); +extern int rtnl_link_bridge_get_port_state(struct rtnl_link *); + +extern int rtnl_link_bridge_set_priority(struct rtnl_link *, uint16_t); +extern int rtnl_link_bridge_get_priority(struct rtnl_link *); + +extern int rtnl_link_bridge_set_cost(struct rtnl_link *, uint32_t); +extern int rtnl_link_bridge_get_cost(struct rtnl_link *, uint32_t *); + +extern int rtnl_link_bridge_unset_flags(struct rtnl_link *, unsigned int); +extern int rtnl_link_bridge_set_flags(struct rtnl_link *, unsigned int); +extern int rtnl_link_bridge_get_flags(struct rtnl_link *); + +extern char * rtnl_link_bridge_flags2str(int, char *, size_t); +extern int rtnl_link_bridge_str2flags(const char *); + /* */ %cstring_output_maxsize(char *buf, size_t len) extern const char *rtnl_link_inet_devconf2str(int, char *buf, size_t len); diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py index 36d0e9d..e6089e2 100644 --- a/python/netlink/route/link.py +++ b/python/netlink/route/link.py @@ -36,18 +36,17 @@ The following public functions exist: from __future__ import absolute_import -__version__ = '0.1' +__version__ = "0.1" __all__ = [ - 'LinkCache', - 'Link', - 'get_from_kernel', + "LinkCache", + "Link", ] import socket from .. import core as netlink from .. import capi as core_capi -from . import capi as capi -from .links import inet as inet +from . import capi as capi +from .links import inet as inet from .. import util as util # Link statistics definitions @@ -109,12 +108,13 @@ ICMP6_INERRORS = 54 ICMP6_OUTMSGS = 55 ICMP6_OUTERRORS = 56 + class LinkCache(netlink.Cache): """Cache of network links""" def __init__(self, family=socket.AF_UNSPEC, cache=None): if not cache: - cache = self._alloc_cache_name('route/link') + cache = self._alloc_cache_name("route/link") self._info_module = None self._protocol = netlink.NETLINK_ROUTE @@ -139,18 +139,19 @@ class LinkCache(netlink.Cache): def _new_cache(self, cache): return LinkCache(family=self.arg1, cache=cache) + class Link(netlink.Object): """Network link""" def __init__(self, obj=None): - netlink.Object.__init__(self, 'route/link', 'link', obj) + netlink.Object.__init__(self, "route/link", "link", obj) self._rtnl_link = self._obj2type(self._nl_object) if self.type: - self._module_lookup('netlink.route.links.' + self.type) + self._module_lookup("netlink.route.links." + self.type) self.inet = inet.InetLink(self) - self.af = {'inet' : self.inet } + self.af = {"inet": self.inet} def __enter__(self): return self @@ -159,7 +160,7 @@ class Link(netlink.Object): if exc_type is None: self.change() else: - return false + return False @classmethod def from_capi(cls, obj): @@ -223,13 +224,13 @@ class Link(netlink.Object): link.flags = [ '+xxx', '-yyy' ] # list operation """ flags = capi.rtnl_link_get_flags(self._rtnl_link) - return capi.rtnl_link_flags2str(flags, 256)[0].split(',') + return capi.rtnl_link_flags2str(flags, 256)[0].split(",") def _set_flag(self, flag): - if flag.startswith('-'): + if flag.startswith("-"): i = capi.rtnl_link_str2flags(flag[1:]) capi.rtnl_link_unset_flags(self._rtnl_link, i) - elif flag.startswith('+'): + elif flag.startswith("+"): i = capi.rtnl_link_str2flags(flag[1:]) capi.rtnl_link_set_flags(self._rtnl_link, i) else: @@ -319,7 +320,7 @@ class Link(netlink.Object): capi.rtnl_link_set_arptype(self._rtnl_link, i) @property - @netlink.nlattr(type=str, immutable=True, fmt=util.string, title='state') + @netlink.nlattr(type=str, immutable=True, fmt=util.string, title="state") def operstate(self): """Operational status""" operstate = capi.rtnl_link_get_operstate(self._rtnl_link) @@ -361,19 +362,31 @@ class Link(netlink.Object): @type.setter def type(self, value): if capi.rtnl_link_set_type(self._rtnl_link, value) < 0: - raise NameError('unknown info type') + raise NameError("unknown info type") - self._module_lookup('netlink.route.links.' + value) + self._module_lookup("netlink.route.links." + value) def get_stat(self, stat): """Retrieve statistical information""" if type(stat) is str: stat = capi.rtnl_link_str2stat(stat) if stat < 0: - raise NameError('unknown name of statistic') + raise NameError("unknown name of statistic") return capi.rtnl_link_get_stat(self._rtnl_link, stat) + def enslave(self, slave, sock=None): + if not sock: + sock = netlink.lookup_socket(netlink.NETLINK_ROUTE) + + return capi.rtnl_link_enslave(sock._sock, self._rtnl_link, slave._rtnl_link) + + def release(self, slave, sock=None): + if not sock: + sock = netlink.lookup_socket(netlink.NETLINK_ROUTE) + + return capi.rtnl_link_release(sock._sock, self._rtnl_link, slave._rtnl_link) + def add(self, sock=None, flags=None): if not sock: sock = netlink.lookup_socket(netlink.NETLINK_ROUTE) @@ -391,7 +404,7 @@ class Link(netlink.Object): sock = netlink.lookup_socket(netlink.NETLINK_ROUTE) if not self._orig: - raise netlink.NetlinkError('Original link not available') + raise netlink.NetlinkError("Original link not available") ret = capi.rtnl_link_change(sock._sock, self._orig, self._rtnl_link, flags) if ret < 0: raise netlink.KernelError(ret) @@ -411,113 +424,121 @@ class Link(netlink.Object): # Used for formatting output. USE AT OWN RISK @property def _state(self): - if 'up' in self.flags: - buf = util.good('up') - if 'lowerup' not in self.flags: - buf += ' ' + util.bad('no-carrier') + if "up" in self.flags: + buf = util.good("up") + if "lowerup" not in self.flags: + buf += " " + util.bad("no-carrier") else: - buf = util.bad('down') + buf = util.bad("down") return buf @property def _brief(self): - return self._module_brief() + self._foreach_af('brief') + return self._module_brief() + self._foreach_af("brief") @property def _flags(self): ignore = [ - 'up', - 'running', - 'lowerup', + "up", + "running", + "lowerup", ] - return ','.join([flag for flag in self.flags if flag not in ignore]) + return ",".join([flag for flag in self.flags if flag not in ignore]) def _foreach_af(self, name, args=None): - buf = '' + buf = "" for af in self.af: try: func = getattr(self.af[af], name) s = str(func(args)) if len(s) > 0: - buf += ' ' + s + buf += " " + s except AttributeError: pass return buf - def format(self, details=False, stats=False, indent=''): + def format(self, details=False, stats=False, indent=""): """Return link as formatted text""" fmt = util.MyFormatter(self, indent) - buf = fmt.format('{a|ifindex} {a|name} {a|arptype} {a|address} '\ - '{a|_state} <{a|_flags}> {a|_brief}') + buf = fmt.format( + "{a|ifindex} {a|name} {a|arptype} {a|address} " + "{a|_state} <{a|_flags}> {a|_brief}" + ) if details: - buf += fmt.nl('\t{t|mtu} {t|txqlen} {t|weight} '\ - '{t|qdisc} {t|operstate}') - buf += fmt.nl('\t{t|broadcast} {t|alias}') + buf += fmt.nl("\t{t|mtu} {t|txqlen} {t|weight} " "{t|qdisc} {t|operstate}") + buf += fmt.nl("\t{t|broadcast} {t|alias}") - buf += self._foreach_af('details', fmt) + buf += self._foreach_af("details", fmt) if stats: - l = [['Packets', RX_PACKETS, TX_PACKETS], - ['Bytes', RX_BYTES, TX_BYTES], - ['Errors', RX_ERRORS, TX_ERRORS], - ['Dropped', RX_DROPPED, TX_DROPPED], - ['Compressed', RX_COMPRESSED, TX_COMPRESSED], - ['FIFO Errors', RX_FIFO_ERR, TX_FIFO_ERR], - ['Length Errors', RX_LEN_ERR, None], - ['Over Errors', RX_OVER_ERR, None], - ['CRC Errors', RX_CRC_ERR, None], - ['Frame Errors', RX_FRAME_ERR, None], - ['Missed Errors', RX_MISSED_ERR, None], - ['Abort Errors', None, TX_ABORT_ERR], - ['Carrier Errors', None, TX_CARRIER_ERR], - ['Heartbeat Errors', None, TX_HBEAT_ERR], - ['Window Errors', None, TX_WIN_ERR], - ['Collisions', None, COLLISIONS], - ['Multicast', None, MULTICAST], - ['', None, None], - ['Ipv6:', None, None], - ['Packets', IP6_INPKTS, IP6_OUTPKTS], - ['Bytes', IP6_INOCTETS, IP6_OUTOCTETS], - ['Discards', IP6_INDISCARDS, IP6_OUTDISCARDS], - ['Multicast Packets', IP6_INMCASTPKTS, IP6_OUTMCASTPKTS], - ['Multicast Bytes', IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS], - ['Broadcast Packets', IP6_INBCASTPKTS, IP6_OUTBCASTPKTS], - ['Broadcast Bytes', IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS], - ['Delivers', IP6_INDELIVERS, None], - ['Forwarded', None, IP6_OUTFORWDATAGRAMS], - ['No Routes', IP6_INNOROUTES, IP6_OUTNOROUTES], - ['Header Errors', IP6_INHDRERRORS, None], - ['Too Big Errors', IP6_INTOOBIGERRORS, None], - ['Address Errors', IP6_INADDRERRORS, None], - ['Unknown Protocol', IP6_INUNKNOWNPROTOS, None], - ['Truncated Packets', IP6_INTRUNCATEDPKTS, None], - ['Reasm Timeouts', IP6_REASMTIMEOUT, None], - ['Reasm Requests', IP6_REASMREQDS, None], - ['Reasm Failures', IP6_REASMFAILS, None], - ['Reasm OK', IP6_REASMOKS, None], - ['Frag Created', None, IP6_FRAGCREATES], - ['Frag Failures', None, IP6_FRAGFAILS], - ['Frag OK', None, IP6_FRAGOKS], - ['', None, None], - ['ICMPv6:', None, None], - ['Messages', ICMP6_INMSGS, ICMP6_OUTMSGS], - ['Errors', ICMP6_INERRORS, ICMP6_OUTERRORS]] - - buf += '\n\t%s%s%s%s\n' % (33 * ' ', util.title('RX'), - 15 * ' ', util.title('TX')) - - for row in l: + lst = [ + ["Packets", RX_PACKETS, TX_PACKETS], + ["Bytes", RX_BYTES, TX_BYTES], + ["Errors", RX_ERRORS, TX_ERRORS], + ["Dropped", RX_DROPPED, TX_DROPPED], + ["Compressed", RX_COMPRESSED, TX_COMPRESSED], + ["FIFO Errors", RX_FIFO_ERR, TX_FIFO_ERR], + ["Length Errors", RX_LEN_ERR, None], + ["Over Errors", RX_OVER_ERR, None], + ["CRC Errors", RX_CRC_ERR, None], + ["Frame Errors", RX_FRAME_ERR, None], + ["Missed Errors", RX_MISSED_ERR, None], + ["Abort Errors", None, TX_ABORT_ERR], + ["Carrier Errors", None, TX_CARRIER_ERR], + ["Heartbeat Errors", None, TX_HBEAT_ERR], + ["Window Errors", None, TX_WIN_ERR], + ["Collisions", None, COLLISIONS], + ["Multicast", None, MULTICAST], + ["", None, None], + ["Ipv6:", None, None], + ["Packets", IP6_INPKTS, IP6_OUTPKTS], + ["Bytes", IP6_INOCTETS, IP6_OUTOCTETS], + ["Discards", IP6_INDISCARDS, IP6_OUTDISCARDS], + ["Multicast Packets", IP6_INMCASTPKTS, IP6_OUTMCASTPKTS], + ["Multicast Bytes", IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS], + ["Broadcast Packets", IP6_INBCASTPKTS, IP6_OUTBCASTPKTS], + ["Broadcast Bytes", IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS], + ["Delivers", IP6_INDELIVERS, None], + ["Forwarded", None, IP6_OUTFORWDATAGRAMS], + ["No Routes", IP6_INNOROUTES, IP6_OUTNOROUTES], + ["Header Errors", IP6_INHDRERRORS, None], + ["Too Big Errors", IP6_INTOOBIGERRORS, None], + ["Address Errors", IP6_INADDRERRORS, None], + ["Unknown Protocol", IP6_INUNKNOWNPROTOS, None], + ["Truncated Packets", IP6_INTRUNCATEDPKTS, None], + ["Reasm Timeouts", IP6_REASMTIMEOUT, None], + ["Reasm Requests", IP6_REASMREQDS, None], + ["Reasm Failures", IP6_REASMFAILS, None], + ["Reasm OK", IP6_REASMOKS, None], + ["Frag Created", None, IP6_FRAGCREATES], + ["Frag Failures", None, IP6_FRAGFAILS], + ["Frag OK", None, IP6_FRAGOKS], + ["", None, None], + ["ICMPv6:", None, None], + ["Messages", ICMP6_INMSGS, ICMP6_OUTMSGS], + ["Errors", ICMP6_INERRORS, ICMP6_OUTERRORS], + ] + + buf += "\n\t%s%s%s%s\n" % ( + 33 * " ", + util.title("RX"), + 15 * " ", + util.title("TX"), + ) + + for row in lst: row[0] = util.kw(row[0]) - row[1] = self.get_stat(row[1]) if row[1] else '' - row[2] = self.get_stat(row[2]) if row[2] else '' - buf += '\t{0[0]:27} {0[1]:>16} {0[2]:>16}\n'.format(row) + row[1] = self.get_stat(row[1]) if row[1] else "" + row[2] = self.get_stat(row[2]) if row[2] else "" + buf += "\t{0[0]:27} {0[1]:>16} {0[2]:>16}\n".format(row) - buf += self._foreach_af('stats') + buf += self._foreach_af("stats") return buf + def get(name, sock=None): """Lookup Link object directly from kernel""" if not name: @@ -532,8 +553,10 @@ def get(name, sock=None): return Link.from_capi(link) + _link_cache = LinkCache() + def resolve(name): _link_cache.refill() return _link_cache[name] diff --git a/python/netlink/route/links/dummy.py b/python/netlink/route/links/dummy.py index e9491cc..1dc3c68 100644 --- a/python/netlink/route/links/dummy.py +++ b/python/netlink/route/links/dummy.py @@ -7,9 +7,9 @@ """ from __future__ import absolute_import -__version__ = '1.0' +__version__ = "1.0" __all__ = [ - 'init', + "init", ] @@ -19,7 +19,8 @@ class DummyLink(object): @staticmethod def brief(): - return 'dummy' + return "dummy" + def init(link): link.dummy = DummyLink(link._rtnl_link) diff --git a/python/netlink/route/links/inet.py b/python/netlink/route/links/inet.py index f5f45cb..7aeedcd 100644 --- a/python/netlink/route/links/inet.py +++ b/python/netlink/route/links/inet.py @@ -8,13 +8,12 @@ from __future__ import absolute_import -__all__ = [ - '', -] +__all__ = [] from ... import core as netlink -from .. import capi as capi +from .. import capi as capi from ... import util as util + DEVCONF_FORWARDING = 1 DEVCONF_MC_FORWARDING = 2 DEVCONF_PROXY_ARP = 3 @@ -42,27 +41,27 @@ DEVCONF_SRC_VMARK = 24 DEVCONF_PROXY_ARP_PVLAN = 25 DEVCONF_MAX = DEVCONF_PROXY_ARP_PVLAN + def _resolve(id): if type(id) is str: id = capi.rtnl_link_inet_str2devconf(id)[0] if id < 0: - raise NameError('unknown configuration id') + raise NameError("unknown configuration id") return id + class InetLink(object): def __init__(self, link): self._link = link def details(self, fmt): - buf = fmt.nl('\n\t{0}\n\t'.format(util.title('Configuration:'))) + buf = fmt.nl("\n\t{0}\n\t".format(util.title("Configuration:"))) - for i in range(DEVCONF_FORWARDING, DEVCONF_MAX+1): + for i in range(DEVCONF_FORWARDING, DEVCONF_MAX + 1): if i & 1 and i > 1: - buf += fmt.nl('\t') + buf += fmt.nl("\t") txt = util.kw(capi.rtnl_link_inet_devconf2str(i, 32)[0]) - buf += fmt.format('{0:28s} {1:12} ', txt, - self.get_conf(i)) - + buf += fmt.format("{0:28s} {1:12} ", txt, self.get_conf(i)) return buf @@ -70,8 +69,9 @@ class InetLink(object): return capi.inet_get_conf(self._link._rtnl_link, _resolve(id)) def set_conf(self, id, value): - return capi.rtnl_link_inet_set_conf(self._link._rtnl_link, - _resolve(id), int(value)) + return capi.rtnl_link_inet_set_conf( + self._link._rtnl_link, _resolve(id), int(value) + ) @property @netlink.nlattr(type=bool, fmt=util.boolean) @@ -82,7 +82,6 @@ class InetLink(object): def forwarding(self, value): self.set_conf(DEVCONF_FORWARDING, int(value)) - @property @netlink.nlattr(type=bool, fmt=util.boolean) def mc_forwarding(self): @@ -92,7 +91,6 @@ class InetLink(object): def mc_forwarding(self, value): self.set_conf(DEVCONF_MC_FORWARDING, int(value)) - @property @netlink.nlattr(type=bool, fmt=util.boolean) def proxy_arp(self): @@ -138,21 +136,22 @@ class InetLink(object): def shared_media(self, value): self.set_conf(DEVCONF_SHARED_MEDIA, int(value)) -# IPV4_DEVCONF_RP_FILTER, -# IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE, -# IPV4_DEVCONF_BOOTP_RELAY, -# IPV4_DEVCONF_LOG_MARTIANS, -# IPV4_DEVCONF_TAG, -# IPV4_DEVCONF_ARPFILTER, -# IPV4_DEVCONF_MEDIUM_ID, -# IPV4_DEVCONF_NOXFRM, -# IPV4_DEVCONF_NOPOLICY, -# IPV4_DEVCONF_FORCE_IGMP_VERSION, -# IPV4_DEVCONF_ARP_ANNOUNCE, -# IPV4_DEVCONF_ARP_IGNORE, -# IPV4_DEVCONF_PROMOTE_SECONDARIES, -# IPV4_DEVCONF_ARP_ACCEPT, -# IPV4_DEVCONF_ARP_NOTIFY, -# IPV4_DEVCONF_ACCEPT_LOCAL, -# IPV4_DEVCONF_SRC_VMARK, -# IPV4_DEVCONF_PROXY_ARP_PVLAN, + +# IPV4_DEVCONF_RP_FILTER, +# IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE, +# IPV4_DEVCONF_BOOTP_RELAY, +# IPV4_DEVCONF_LOG_MARTIANS, +# IPV4_DEVCONF_TAG, +# IPV4_DEVCONF_ARPFILTER, +# IPV4_DEVCONF_MEDIUM_ID, +# IPV4_DEVCONF_NOXFRM, +# IPV4_DEVCONF_NOPOLICY, +# IPV4_DEVCONF_FORCE_IGMP_VERSION, +# IPV4_DEVCONF_ARP_ANNOUNCE, +# IPV4_DEVCONF_ARP_IGNORE, +# IPV4_DEVCONF_PROMOTE_SECONDARIES, +# IPV4_DEVCONF_ARP_ACCEPT, +# IPV4_DEVCONF_ARP_NOTIFY, +# IPV4_DEVCONF_ACCEPT_LOCAL, +# IPV4_DEVCONF_SRC_VMARK, +# IPV4_DEVCONF_PROXY_ARP_PVLAN, diff --git a/python/netlink/route/links/vlan.py b/python/netlink/route/links/vlan.py index 70045d5..8bee3c9 100644 --- a/python/netlink/route/links/vlan.py +++ b/python/netlink/route/links/vlan.py @@ -10,7 +10,9 @@ from __future__ import absolute_import from ... import core as netlink -from .. import capi as capi +from .. import capi as capi + + class VLANLink(object): def __init__(self, link): self._link = link @@ -28,7 +30,7 @@ class VLANLink(object): @property @netlink.nlattr(type=str) def flags(self): - """ VLAN flags + """VLAN flags Setting this property will *Not* reset flags to value you supply in Examples: link.flags = '+xxx' # add xxx flag @@ -37,13 +39,13 @@ class VLANLink(object): link.flags = [ '+xxx', '-yyy' ] # list operation """ flags = capi.rtnl_link_vlan_get_flags(self._link) - return capi.rtnl_link_vlan_flags2str(flags, 256)[0].split(',') + return capi.rtnl_link_vlan_flags2str(flags, 256)[0].split(",") def _set_flag(self, flag): - if flag.startswith('-'): + if flag.startswith("-"): i = capi.rtnl_link_vlan_str2flags(flag[1:]) capi.rtnl_link_vlan_unset_flags(self._link, i) - elif flag.startswith('+'): + elif flag.startswith("+"): i = capi.rtnl_link_vlan_str2flags(flag[1:]) capi.rtnl_link_vlan_set_flags(self._link, i) else: @@ -64,8 +66,9 @@ class VLANLink(object): # - egress map def brief(self): - return 'vlan-id {0}'.format(self.id) + return "vlan-id {0}".format(self.id) + def init(link): - link.vlan = VLANLink(link._link) + link.vlan = VLANLink(link._rtnl_link) return link.vlan diff --git a/python/netlink/route/qdisc/htb.py b/python/netlink/route/qdisc/htb.py index d051c8d..0dc70f4 100644 --- a/python/netlink/route/qdisc/htb.py +++ b/python/netlink/route/qdisc/htb.py @@ -10,8 +10,9 @@ from __future__ import absolute_import from ... import core as netlink from ... import util as util -from .. import capi as capi -from .. import tc as tc +from .. import capi as capi +from .. import tc as tc + class HTBQdisc(object): def __init__(self, qdisc): @@ -27,25 +28,25 @@ class HTBQdisc(object): capi.rtnl_htb_set_defcls(self._qdisc._rtnl_qdisc, int(value)) @property - @netlink.nlattr('r2q', type=int) + @netlink.nlattr(type=int) def r2q(self): return capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc) @r2q.setter def r2q(self, value): - capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc, - int(value)) + capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc, int(value)) def brief(self): fmt = util.MyFormatter(self) - ret = ' {s|default-class!k} {a|default_class}' + ret = " {s|default-class!k} {a|default_class}" if self.r2q: - ret += ' {s|r2q!k} {a|r2q}' + ret += " {s|r2q!k} {a|r2q}" return fmt.format(ret) + class HTBClass(object): def __init__(self, cl): self._class = cl @@ -120,26 +121,29 @@ class HTBClass(object): def brief(self): fmt = util.MyFormatter(self) - ret = ' {t|prio} {t|rate}' + ret = " {t|prio} {t|rate}" if self.rate != self.ceil: - ret += ' {s|borrow-up-to!k} {a|ceil}' + ret += " {s|borrow-up-to!k} {a|ceil}" - ret += ' {t|burst}' + ret += " {t|burst}" return fmt.format(ret) def details(self): fmt = util.MyFormatter(self) - return fmt.nl('\t{t|level} {t|quantum}') + return fmt.nl("\t{t|level} {t|quantum}") + def init_qdisc(qdisc): qdisc.htb = HTBQdisc(qdisc) return qdisc.htb + def init_class(cl): cl.htb = HTBClass(cl) return cl.htb -#extern void rtnl_htb_set_quantum(struct rtnl_class *, uint32_t quantum); + +# extern void rtnl_htb_set_quantum(struct rtnl_class *, uint32_t quantum); diff --git a/python/netlink/route/tc.py b/python/netlink/route/tc.py index 0689b71..daad697 100644 --- a/python/netlink/route/tc.py +++ b/python/netlink/route/tc.py @@ -4,18 +4,18 @@ from __future__ import absolute_import __all__ = [ - 'TcCache', - 'Tc', - 'QdiscCache', - 'Qdisc', - 'TcClassCache', - 'TcClass', + "TcCache", + "Tc", + "QdiscCache", + "Qdisc", + "TcClassCache", + "TcClass", ] from .. import core as netlink -from . import capi as capi +from . import capi as capi from .. import util as util -from . import link as Link +from . import link as Link TC_PACKETS = 0 TC_BYTES = 1 @@ -43,7 +43,7 @@ STAT_MAX = STAT_OVERLIMITS class Handle(object): - """ Traffic control handle + """Traffic control handle Representation of a traffic control handle which uniquely identifies each traffic control object in its link namespace. @@ -53,6 +53,7 @@ class Handle(object): print int(handle) print str(handle) """ + def __init__(self, val=None): if type(val) is str: val = capi.tc_str2handle(val) @@ -81,12 +82,14 @@ class Handle(object): def isroot(self): return self._val == TC_H_ROOT or self._val == TC_H_INGRESS + class TcCache(netlink.Cache): """Cache of traffic control object""" def __getitem__(self, key): raise NotImplementedError() + class Tc(netlink.Object): def __cmp__(self, other): diff = self.ifindex - other.ifindex @@ -95,8 +98,7 @@ class Tc(netlink.Object): return diff def _tc_module_lookup(self): - self._module_lookup(self._module_path + self.kind, - 'init_' + self._name) + self._module_lookup(self._module_path + self.kind, "init_" + self._name) @property def root(self): @@ -189,7 +191,7 @@ class Tc(netlink.Object): @property def _dev(self): - buf = util.kw('dev') + ' ' + buf = util.kw("dev") + " " if self.link: return buf + util.string(self.link.name) @@ -197,19 +199,19 @@ class Tc(netlink.Object): return buf + util.num(self.ifindex) def brief(self, title, nodev=False, noparent=False): - ret = title + ' {a|kind} {a|handle}' + ret = title + " {a|kind} {a|handle}" if not nodev: - ret += ' {a|_dev}' + ret += " {a|_dev}" if not noparent: - ret += ' {t|parent}' + ret += " {t|parent}" return ret + self._module_brief() @staticmethod def details(): - return '{t|mtu} {t|mpu} {t|overhead} {t|linktype}' + return "{t|mtu} {t|mpu} {t|overhead} {t|linktype}" @property def packets(self): @@ -225,28 +227,29 @@ class Tc(netlink.Object): @staticmethod def stats(fmt): - return fmt.nl('{t|packets} {t|bytes} {t|qlen}') + return fmt.nl("{t|packets} {t|bytes} {t|qlen}") + class QdiscCache(netlink.Cache): """Cache of qdiscs""" def __init__(self, cache=None): if not cache: - cache = self._alloc_cache_name('route/qdisc') + cache = self._alloc_cache_name("route/qdisc") self._protocol = netlink.NETLINK_ROUTE self._nl_cache = cache -# def __getitem__(self, key): -# if type(key) is int: -# link = capi.rtnl_link_get(self._this, key) -# elif type(key) is str: -# link = capi.rtnl_link_get_by_name(self._this, key) -# -# if qdisc is None: -# raise KeyError() -# else: -# return Qdisc._from_capi(capi.qdisc2obj(qdisc)) + # def __getitem__(self, key): + # if type(key) is int: + # link = capi.rtnl_link_get(self._this, key) + # elif type(key) is str: + # link = capi.rtnl_link_get_by_name(self._this, key) + # + # if qdisc is None: + # raise KeyError() + # else: + # return Qdisc._from_capi(capi.qdisc2obj(qdisc)) @staticmethod def _new_object(obj): @@ -256,12 +259,13 @@ class QdiscCache(netlink.Cache): def _new_cache(cache): return QdiscCache(cache=cache) + class Qdisc(Tc): """Queueing discipline""" def __init__(self, obj=None): - netlink.Object.__init__(self, 'route/qdisc', 'qdisc', obj) - self._module_path = 'netlink.route.qdisc.' + netlink.Object.__init__(self, "route/qdisc", "qdisc", obj) + self._module_path = "netlink.route.qdisc." self._rtnl_qdisc = self._obj2type(self._nl_object) self._rtnl_tc = capi.obj2tc(self._nl_object) @@ -297,105 +301,107 @@ class Qdisc(Tc): return ret -# def add(self, socket, flags=None): -# if not flags: -# flags = netlink.NLM_F_CREATE -# -# ret = capi.rtnl_link_add(socket._sock, self._link, flags) -# if ret < 0: -# raise netlink.KernelError(ret) -# -# def change(self, socket, flags=0): -# """Commit changes made to the link object""" -# if not self._orig: -# raise NetlinkError('Original link not available') -# ret = capi.rtnl_link_change(socket._sock, self._orig, self._link, flags) -# if ret < 0: -# raise netlink.KernelError(ret) -# -# def delete(self, socket): -# """Attempt to delete this link in the kernel""" -# ret = capi.rtnl_link_delete(socket._sock, self._link) -# if ret < 0: -# raise netlink.KernelError(ret) - - def format(self, details=False, stats=False, nodev=False, - noparent=False, indent=''): + # def add(self, socket, flags=None): + # if not flags: + # flags = netlink.NLM_F_CREATE + # + # ret = capi.rtnl_link_add(socket._sock, self._link, flags) + # if ret < 0: + # raise netlink.KernelError(ret) + # + # def change(self, socket, flags=0): + # """Commit changes made to the link object""" + # if not self._orig: + # raise NetlinkError('Original link not available') + # ret = capi.rtnl_link_change(socket._sock, self._orig, self._link, flags) + # if ret < 0: + # raise netlink.KernelError(ret) + # + # def delete(self, socket): + # """Attempt to delete this link in the kernel""" + # ret = capi.rtnl_link_delete(socket._sock, self._link) + # if ret < 0: + # raise netlink.KernelError(ret) + + def format( + self, details=False, stats=False, nodev=False, noparent=False, indent="" + ): """Return qdisc as formatted text""" fmt = util.MyFormatter(self, indent) - buf = fmt.format(self.brief('qdisc', nodev, noparent)) + buf = fmt.format(self.brief("qdisc", nodev, noparent)) if details: - buf += fmt.nl('\t' + self.details()) + buf += fmt.nl("\t" + self.details()) if stats: buf += self.stats(fmt) -# if stats: -# l = [['Packets', RX_PACKETS, TX_PACKETS], -# ['Bytes', RX_BYTES, TX_BYTES], -# ['Errors', RX_ERRORS, TX_ERRORS], -# ['Dropped', RX_DROPPED, TX_DROPPED], -# ['Compressed', RX_COMPRESSED, TX_COMPRESSED], -# ['FIFO Errors', RX_FIFO_ERR, TX_FIFO_ERR], -# ['Length Errors', RX_LEN_ERR, None], -# ['Over Errors', RX_OVER_ERR, None], -# ['CRC Errors', RX_CRC_ERR, None], -# ['Frame Errors', RX_FRAME_ERR, None], -# ['Missed Errors', RX_MISSED_ERR, None], -# ['Abort Errors', None, TX_ABORT_ERR], -# ['Carrier Errors', None, TX_CARRIER_ERR], -# ['Heartbeat Errors', None, TX_HBEAT_ERR], -# ['Window Errors', None, TX_WIN_ERR], -# ['Collisions', None, COLLISIONS], -# ['Multicast', None, MULTICAST], -# ['', None, None], -# ['Ipv6:', None, None], -# ['Packets', IP6_INPKTS, IP6_OUTPKTS], -# ['Bytes', IP6_INOCTETS, IP6_OUTOCTETS], -# ['Discards', IP6_INDISCARDS, IP6_OUTDISCARDS], -# ['Multicast Packets', IP6_INMCASTPKTS, IP6_OUTMCASTPKTS], -# ['Multicast Bytes', IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS], -# ['Broadcast Packets', IP6_INBCASTPKTS, IP6_OUTBCASTPKTS], -# ['Broadcast Bytes', IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS], -# ['Delivers', IP6_INDELIVERS, None], -# ['Forwarded', None, IP6_OUTFORWDATAGRAMS], -# ['No Routes', IP6_INNOROUTES, IP6_OUTNOROUTES], -# ['Header Errors', IP6_INHDRERRORS, None], -# ['Too Big Errors', IP6_INTOOBIGERRORS, None], -# ['Address Errors', IP6_INADDRERRORS, None], -# ['Unknown Protocol', IP6_INUNKNOWNPROTOS, None], -# ['Truncated Packets', IP6_INTRUNCATEDPKTS, None], -# ['Reasm Timeouts', IP6_REASMTIMEOUT, None], -# ['Reasm Requests', IP6_REASMREQDS, None], -# ['Reasm Failures', IP6_REASMFAILS, None], -# ['Reasm OK', IP6_REASMOKS, None], -# ['Frag Created', None, IP6_FRAGCREATES], -# ['Frag Failures', None, IP6_FRAGFAILS], -# ['Frag OK', None, IP6_FRAGOKS], -# ['', None, None], -# ['ICMPv6:', None, None], -# ['Messages', ICMP6_INMSGS, ICMP6_OUTMSGS], -# ['Errors', ICMP6_INERRORS, ICMP6_OUTERRORS]] -# -# buf += '\n\t%s%s%s%s\n' % (33 * ' ', util.title('RX'), -# 15 * ' ', util.title('TX')) -# -# for row in l: -# row[0] = util.kw(row[0]) -# row[1] = self.get_stat(row[1]) if row[1] else '' -# row[2] = self.get_stat(row[2]) if row[2] else '' -# buf += '\t{0:27} {1:>16} {2:>16}\n'.format(*row) + # if stats: + # l = [['Packets', RX_PACKETS, TX_PACKETS], + # ['Bytes', RX_BYTES, TX_BYTES], + # ['Errors', RX_ERRORS, TX_ERRORS], + # ['Dropped', RX_DROPPED, TX_DROPPED], + # ['Compressed', RX_COMPRESSED, TX_COMPRESSED], + # ['FIFO Errors', RX_FIFO_ERR, TX_FIFO_ERR], + # ['Length Errors', RX_LEN_ERR, None], + # ['Over Errors', RX_OVER_ERR, None], + # ['CRC Errors', RX_CRC_ERR, None], + # ['Frame Errors', RX_FRAME_ERR, None], + # ['Missed Errors', RX_MISSED_ERR, None], + # ['Abort Errors', None, TX_ABORT_ERR], + # ['Carrier Errors', None, TX_CARRIER_ERR], + # ['Heartbeat Errors', None, TX_HBEAT_ERR], + # ['Window Errors', None, TX_WIN_ERR], + # ['Collisions', None, COLLISIONS], + # ['Multicast', None, MULTICAST], + # ['', None, None], + # ['Ipv6:', None, None], + # ['Packets', IP6_INPKTS, IP6_OUTPKTS], + # ['Bytes', IP6_INOCTETS, IP6_OUTOCTETS], + # ['Discards', IP6_INDISCARDS, IP6_OUTDISCARDS], + # ['Multicast Packets', IP6_INMCASTPKTS, IP6_OUTMCASTPKTS], + # ['Multicast Bytes', IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS], + # ['Broadcast Packets', IP6_INBCASTPKTS, IP6_OUTBCASTPKTS], + # ['Broadcast Bytes', IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS], + # ['Delivers', IP6_INDELIVERS, None], + # ['Forwarded', None, IP6_OUTFORWDATAGRAMS], + # ['No Routes', IP6_INNOROUTES, IP6_OUTNOROUTES], + # ['Header Errors', IP6_INHDRERRORS, None], + # ['Too Big Errors', IP6_INTOOBIGERRORS, None], + # ['Address Errors', IP6_INADDRERRORS, None], + # ['Unknown Protocol', IP6_INUNKNOWNPROTOS, None], + # ['Truncated Packets', IP6_INTRUNCATEDPKTS, None], + # ['Reasm Timeouts', IP6_REASMTIMEOUT, None], + # ['Reasm Requests', IP6_REASMREQDS, None], + # ['Reasm Failures', IP6_REASMFAILS, None], + # ['Reasm OK', IP6_REASMOKS, None], + # ['Frag Created', None, IP6_FRAGCREATES], + # ['Frag Failures', None, IP6_FRAGFAILS], + # ['Frag OK', None, IP6_FRAGOKS], + # ['', None, None], + # ['ICMPv6:', None, None], + # ['Messages', ICMP6_INMSGS, ICMP6_OUTMSGS], + # ['Errors', ICMP6_INERRORS, ICMP6_OUTERRORS]] + # + # buf += '\n\t%s%s%s%s\n' % (33 * ' ', util.title('RX'), + # 15 * ' ', util.title('TX')) + # + # for row in l: + # row[0] = util.kw(row[0]) + # row[1] = self.get_stat(row[1]) if row[1] else '' + # row[2] = self.get_stat(row[2]) if row[2] else '' + # buf += '\t{0:27} {1:>16} {2:>16}\n'.format(*row) return buf + class TcClassCache(netlink.Cache): """Cache of traffic classes""" def __init__(self, ifindex, cache=None): if not cache: - cache = self._alloc_cache_name('route/class') + cache = self._alloc_cache_name("route/class") self._protocol = netlink.NETLINK_ROUTE self._nl_cache = cache @@ -408,12 +414,13 @@ class TcClassCache(netlink.Cache): def _new_cache(self, cache): return TcClassCache(self.arg1, cache=cache) + class TcClass(Tc): """Traffic Class""" def __init__(self, obj=None): - netlink.Object.__init__(self, 'route/class', 'class', obj) - self._module_path = 'netlink.route.qdisc.' + netlink.Object.__init__(self, "route/class", "class", obj) + self._module_path = "netlink.route.qdisc." self._rtnl_class = self._obj2type(self._nl_object) self._rtnl_tc = capi.obj2tc(self._nl_object) @@ -447,24 +454,26 @@ class TcClass(Tc): return ret - def format(self, details=False, _stats=False, nodev=False, - noparent=False, indent=''): + def format( + self, details=False, _stats=False, nodev=False, noparent=False, indent="" + ): """Return class as formatted text""" fmt = util.MyFormatter(self, indent) - buf = fmt.format(self.brief('class', nodev, noparent)) + buf = fmt.format(self.brief("class", nodev, noparent)) if details: - buf += fmt.nl('\t' + self.details()) + buf += fmt.nl("\t" + self.details()) return buf + class ClassifierCache(netlink.Cache): """Cache of traffic classifiers objects""" def __init__(self, ifindex, parent, cache=None): if not cache: - cache = self._alloc_cache_name('route/cls') + cache = self._alloc_cache_name("route/cls") self._protocol = netlink.NETLINK_ROUTE self._nl_cache = cache @@ -478,12 +487,13 @@ class ClassifierCache(netlink.Cache): def _new_cache(self, cache): return ClassifierCache(self.arg1, self.arg2, cache=cache) + class Classifier(Tc): """Classifier""" def __init__(self, obj=None): - netlink.Object.__init__(self, 'route/cls', 'cls', obj) - self._module_path = 'netlink.route.cls.' + netlink.Object.__init__(self, "route/cls", "cls", obj) + self._module_path = "netlink.route.cls." self._rtnl_cls = self._obj2type(self._nl_object) self._rtnl_tc = capi.obj2tc(self._nl_object) @@ -522,23 +532,26 @@ class Classifier(Tc): def childs(self): return [] - def format(self, details=False, _stats=False, nodev=False, - noparent=False, indent=''): + def format( + self, details=False, _stats=False, nodev=False, noparent=False, indent="" + ): """Return class as formatted text""" fmt = util.MyFormatter(self, indent) - buf = fmt.format(self.brief('classifier', nodev, noparent)) - buf += fmt.format(' {t|priority} {t|protocol}') + buf = fmt.format(self.brief("classifier", nodev, noparent)) + buf += fmt.format(" {t|priority} {t|protocol}") if details: - buf += fmt.nl('\t' + self.details()) + buf += fmt.nl("\t" + self.details()) return buf + _qdisc_cache = QdiscCache() + def get_qdisc(ifindex, handle=None, parent=None): - l = [] + lst = [] _qdisc_cache.refill() @@ -549,14 +562,16 @@ def get_qdisc(ifindex, handle=None, parent=None): continue if (parent is not None) and (qdisc.parent != parent): continue - l.append(qdisc) + lst.append(qdisc) + + return lst - return l _class_cache = {} + def get_class(ifindex, parent, handle=None): - l = [] + lst = [] try: cache = _class_cache[ifindex] @@ -571,12 +586,14 @@ def get_class(ifindex, parent, handle=None): continue if (handle is not None) and (cl.handle != handle): continue - l.append(cl) + lst.append(cl) + + return lst - return l _cls_cache = {} + def get_cls(ifindex, parent, handle=None): chain = _cls_cache.get(ifindex, dict()) @@ -590,6 +607,6 @@ def get_cls(ifindex, parent, handle=None): cache.refill() if handle is None: - return [ cls for cls in cache ] + return [cls for cls in cache] - return [ cls for cls in cache if cls.handle == handle ] + return [cls for cls in cache if cls.handle == handle] diff --git a/python/netlink/util.py b/python/netlink/util.py index 2394033..afe7ef0 100644 --- a/python/netlink/util.py +++ b/python/netlink/util.py @@ -10,89 +10,108 @@ from __future__ import absolute_import -from . import core as netlink from . import capi as capi from string import Formatter -import types -__version__ = '1.0' +__version__ = "1.0" + +# rename into colored_output def _color(t, c): - return b'{esc}[{color}m{text}{esc}[0m'.format(esc=b'\x1b', color=c, text=t) + return "{esc}[{color}m{text}{esc}[0m".format(esc=b"\x1b".decode(), color=c, text=t) + def black(t): return _color(t, 30) + def red(t): return _color(t, 31) + def green(t): return _color(t, 32) + def yellow(t): return _color(t, 33) + def blue(t): return _color(t, 34) + def magenta(t): return _color(t, 35) + def cyan(t): return _color(t, 36) + def white(t): return _color(t, 37) + def bold(t): return _color(t, 1) + def kw(t): return yellow(t) + def num(t): return str(t) + def string(t): return t + def addr(t): return str(t) + def bad(t): return red(t) + def good(t): return green(t) + def title(t): return t + def boolean(t): return str(t) + def handle(t): return str(t) + class MyFormatter(Formatter): - def __init__(self, obj, indent=''): + def __init__(self, obj, indent=""): self._obj = obj self._indent = indent def _nlattr(self, key): value = getattr(self._obj.__class__, key) if not isinstance(value, property): - raise ValueError('Invalid formatting string {0}'.format(key)) + raise ValueError("Invalid formatting string {0}".format(key)) - d = getattr(value.fget, 'formatinfo', dict()) + d = getattr(value.fget, "formatinfo", dict()) # value = value.fget() is exactly the same value = getattr(self._obj, key) - if 'fmt' in d: - value = d['fmt'](value) + if "fmt" in d: + value = d["fmt"](value) - title_ = d.get('title', None) + title_ = d.get("title", None) return title_, str(value) @@ -103,13 +122,13 @@ class MyFormatter(Formatter): # HACK, we allow defining strings via fields to allow # conversions - if key[:2] == 's|': + if key[:2] == "s|": return key[2:] - if key[:2] == 't|': + if key[:2] == "t|": # title mode ("TITLE ATTR") include_title = True - elif key[:2] == 'a|': + elif key[:2] == "a|": # plain attribute mode ("ATTR") include_title = False else: @@ -121,31 +140,33 @@ class MyFormatter(Formatter): if include_title: if not title_: - title_ = key # fall back to key as title - value = '{0} {1}'.format(kw(title_), value) + title_ = key # fall back to key as title + value = "{0} {1}".format(kw(title_), value) return value def convert_field(self, value, conversion): - if conversion == 'r': + if conversion == "r": return repr(value) - elif conversion == 's': + elif conversion == "s": return str(value) - elif conversion == 'k': + elif conversion == "k": return kw(value) - elif conversion == 'b': + elif conversion == "b": return bold(value) elif conversion is None: return value - raise ValueError('Unknown converion specifier {0!s}'.format(conversion)) + raise ValueError("Unknown converion specifier {0!s}".format(conversion)) + + def nl(self, format_string=""): + return "\n" + self._indent + self.format(format_string) - def nl(self, format_string=''): - return '\n' + self._indent + self.format(format_string) NL_BYTE_RATE = 0 NL_BIT_RATE = 1 + class Rate(object): def __init__(self, rate, mode=NL_BYTE_RATE): self._rate = rate @@ -160,6 +181,7 @@ class Rate(object): def __cmp__(self, other): return int(self) - int(other) + class Size(object): def __init__(self, size): self._size = size diff --git a/python/netlink/utils.h b/python/netlink/utils.h new file mode 100644 index 0000000..3ec2fb5 --- /dev/null +++ b/python/netlink/utils.h @@ -0,0 +1,41 @@ +struct list_head { + struct list_head *next; +}; + +#define LIST_HEAD(name) \ + struct list_head name = { &(name) } + +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +static inline void list_add(struct list_head *new, struct list_head *head) +{ + new->next = head->next; + head->next = new; +} + +static inline void list_del(struct list_head *entry, struct list_head *prev) +{ + prev->next = entry->next; + entry->next = entry; +} + +#define list_for_each_safe(pos, n, head) \ + for (n = (head), pos = (head)->next; pos != (head); \ + n = pos, pos = n->next) + +#undef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +#define container_of(ptr, type, member) ({ \ + const __typeof__( ((type *)0)->member ) *__mptr = (ptr);\ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +#ifdef DEBUG +#define pynl_dbg(fmt, ...) \ + fprintf(stderr, "%s: " fmt, __func__, __VA_ARGS__) +#else +#define pynl_dbg(fmt, ...) +#endif diff --git a/python/setup.py.in b/python/setup.py.in index 7ba90d7..83ffdb0 100644 --- a/python/setup.py.in +++ b/python/setup.py.in @@ -2,29 +2,54 @@ from distutils.core import setup, Extension -opts = ['-O', '-nodefaultctor'] -include = ['@top_builddir@/include'] +opts = ["-O", "-nodefaultctor"] +include = ["@top_builddir@/include", "@top_srcdir@/include"] +library_dirs = ["@top_builddir@/lib/.libs"] -netlink_capi = Extension('netlink/_capi', - sources = ['netlink/capi.i'], - include_dirs = include, - swig_opts = opts, - libraries = ['nl-3'], - ) +netlink_capi = Extension( + "netlink/_capi", + sources=["@srcdir@/netlink/capi.i"], + include_dirs=include, + swig_opts=opts, + library_dirs=library_dirs, + libraries=["nl-3"], +) -route_capi = Extension('netlink/route/_capi', - sources = ['netlink/route/capi.i'], - include_dirs = include, - swig_opts = opts, - libraries = ['nl-3', 'nl-route-3'], - ) +route_capi = Extension( + "netlink/route/_capi", + sources=["@srcdir@/netlink/route/capi.i"], + include_dirs=include, + swig_opts=opts, + library_dirs=library_dirs, + libraries=["nl-3", "nl-route-3"], +) -setup(name = 'netlink', - version = '1.0', - description = 'Python wrapper for netlink protocols', - author = 'Thomas Graf', - author_email = 'tgraf@suug.ch', - ext_modules = [netlink_capi, route_capi], - packages = ['netlink', 'netlink.route', 'netlink.route.links', - 'netlink.route.qdisc'], - ) +genl_capi = Extension( + "netlink/genl/_capi", + sources=["@srcdir@/netlink/genl/capi.i"], + include_dirs=include, + swig_opts=opts, + library_dirs=library_dirs, + libraries=["nl-3", "nl-genl-3"], +) + +setup( + name="netlink", + version="1.0", + description="Python wrapper for netlink protocols", + author="Thomas Graf", + author_email="tgraf@suug.ch", + url="http://www.infradead.org/~tgr/libnl/", + license="LGPL 2", + platforms="linux2", + long_description="Experimental python bindings for libnl", + ext_modules=[netlink_capi, route_capi, genl_capi], + package_dir={"": "@srcdir@"}, + packages=[ + "netlink", + "netlink.genl", + "netlink.route", + "netlink.route.links", + "netlink.route.qdisc", + ], +) diff --git a/python/tests/test-create-bridge.py b/python/tests/test-create-bridge.py new file mode 100644 index 0000000..bfb1459 --- /dev/null +++ b/python/tests/test-create-bridge.py @@ -0,0 +1,29 @@ +from __future__ import print_function +import netlink.core as netlink +import netlink.route.capi as capi +import netlink.route.link as link + +sock = netlink.lookup_socket(netlink.NETLINK_ROUTE) + +cache = link.LinkCache() +cache.refill(sock) + +testtap1 = cache["testtap1"] +print(testtap1) + +lbr = link.Link() +lbr.type = "bridge" +lbr.name = "testbridge" +print(lbr) +lbr.add() + +cache.refill(sock) +lbr = cache["testbridge"] +print(lbr) + +lbr.enslave(testtap1) +cache.refill(sock) +testtap1 = cache["testtap1"] + +print(capi.rtnl_link_is_bridge(lbr._rtnl_link)) +print(capi.rtnl_link_get_master(testtap1._rtnl_link)) diff --git a/src/Makefile.am b/src/Makefile.am deleted file mode 100644 index c318dcc..0000000 --- a/src/Makefile.am +++ /dev/null @@ -1,100 +0,0 @@ -# -*- Makefile -*- - -SUBDIRS = lib - -AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" - -LDADD = \ - ${top_builddir}/src/lib/libnl-cli-3.la \ - ${top_builddir}/lib/libnl-3.la \ - ${top_builddir}/lib/libnl-nf-3.la \ - ${top_builddir}/lib/libnl-genl-3.la \ - ${top_builddir}/lib/libnl-route-3.la - -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 = \ - nf-ct-list 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-set nl-link-stats \ - nl-link-ifindex2name nl-link-name2ifindex \ - nl-neigh-add nl-neigh-delete nl-neigh-list \ - nl-rule-list \ - nl-neightbl-list \ - nl-monitor \ - nl-tctree-list \ - nl-route-add nl-route-delete nl-route-get nl-route-list \ - nl-fib-lookup \ - nl-list-caches nl-list-sockets \ - nl-util-addr \ - nl-link-enslave \ - nl-link-release - -genl_ctrl_list_SOURCES = genl-ctrl-list.c - -nf_ct_list_SOURCES = nf-ct-list.c -nf_log_SOURCES = nf-log.c -nf_queue_SOURCES = nf-queue.c -nf_monitor_SOURCES = nf-monitor.c - -nf_exp_list_SOURCES = nf-exp-list.c -nf_exp_add_SOURCES = nf-exp-add.c -nf_exp_delete_SOURCES = nf-exp-delete.c - -nl_addr_add_SOURCES = nl-addr-add.c -nl_addr_delete_SOURCES = nl-addr-delete.c -nl_addr_list_SOURCES = nl-addr-list.c - -nl_link_list_SOURCES = nl-link-list.c -nl_link_set_SOURCES = nl-link-set.c -nl_link_stats_SOURCES = nl-link-stats.c -nl_link_ifindex2name_SOURCES = nl-link-ifindex2name.c -nl_link_name2ifindex_SOURCES = nl-link-name2ifindex.c - -nl_monitor_SOURCES = nl-monitor.c - -nl_neigh_add_SOURCES = nl-neigh-add.c -nl_neigh_delete_SOURCES = nl-neigh-delete.c -nl_neigh_list_SOURCES = nl-neigh-list.c - -nl_neightbl_list_SOURCES = nl-neightbl-list.c - -nl_qdisc_add_SOURCES = nl-qdisc-add.c -nl_qdisc_delete_SOURCES = nl-qdisc-delete.c -nl_qdisc_list_SOURCES = nl-qdisc-list.c - -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_delete_SOURCES = nl-route-delete.c -nl_route_get_SOURCES = nl-route-get.c -nl_route_list_SOURCES = nl-route-list.c - -nl_rule_list_SOURCES = nl-rule-list.c - -nl_tctree_list_SOURCES = nl-tctree-list.c - -nl_fib_lookup_SOURCES = nl-fib-lookup.c - -nl_list_caches_SOURCES = nl-list-caches.c -nl_list_sockets_SOURCES = nl-list-sockets.c - -nl_util_addr_SOURCES = nl-util-addr.c - -nl_pktloc_lookup_SOURCES = nl-pktloc-lookup.c - -nl_classid_lookup_SOURCES = nl-classid-lookup.c diff --git a/src/Makefile.in b/src/Makefile.in deleted file mode 100644 index 78abc10..0000000 --- a/src/Makefile.in +++ /dev/null @@ -1,1374 +0,0 @@ -# Makefile.in generated by automake 1.11.6 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -# -*- Makefile -*- - -VPATH = @srcdir@ -am__make_dryrun = \ - { \ - am__dry=no; \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ - esac; \ - test $$am__dry = yes; \ - } -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -sbin_PROGRAMS = genl-ctrl-list$(EXEEXT) nl-qdisc-add$(EXEEXT) \ - nl-qdisc-list$(EXEEXT) nl-qdisc-delete$(EXEEXT) \ - nl-class-add$(EXEEXT) nl-class-list$(EXEEXT) \ - nl-class-delete$(EXEEXT) nl-cls-add$(EXEEXT) \ - nl-cls-list$(EXEEXT) nl-cls-delete$(EXEEXT) \ - nl-classid-lookup$(EXEEXT) nl-pktloc-lookup$(EXEEXT) \ - nl-link-list$(EXEEXT) -noinst_PROGRAMS = nf-ct-list$(EXEEXT) nf-log$(EXEEXT) \ - nf-queue$(EXEEXT) nf-monitor$(EXEEXT) nf-exp-list$(EXEEXT) \ - nf-exp-add$(EXEEXT) nf-exp-delete$(EXEEXT) \ - nl-addr-add$(EXEEXT) nl-addr-delete$(EXEEXT) \ - nl-addr-list$(EXEEXT) nl-link-set$(EXEEXT) \ - nl-link-stats$(EXEEXT) nl-link-ifindex2name$(EXEEXT) \ - nl-link-name2ifindex$(EXEEXT) nl-neigh-add$(EXEEXT) \ - nl-neigh-delete$(EXEEXT) nl-neigh-list$(EXEEXT) \ - nl-rule-list$(EXEEXT) nl-neightbl-list$(EXEEXT) \ - nl-monitor$(EXEEXT) nl-tctree-list$(EXEEXT) \ - nl-route-add$(EXEEXT) nl-route-delete$(EXEEXT) \ - nl-route-get$(EXEEXT) nl-route-list$(EXEEXT) \ - nl-fib-lookup$(EXEEXT) nl-list-caches$(EXEEXT) \ - nl-list-sockets$(EXEEXT) nl-util-addr$(EXEEXT) \ - nl-link-enslave$(EXEEXT) nl-link-release$(EXEEXT) -subdir = src -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/lib/defs.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -am__installdirs = "$(DESTDIR)$(sbindir)" -PROGRAMS = $(noinst_PROGRAMS) $(sbin_PROGRAMS) -am_genl_ctrl_list_OBJECTS = genl-ctrl-list.$(OBJEXT) -genl_ctrl_list_OBJECTS = $(am_genl_ctrl_list_OBJECTS) -genl_ctrl_list_LDADD = $(LDADD) -genl_ctrl_list_DEPENDENCIES = ${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 -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am_nf_ct_list_OBJECTS = nf-ct-list.$(OBJEXT) -nf_ct_list_OBJECTS = $(am_nf_ct_list_OBJECTS) -nf_ct_list_LDADD = $(LDADD) -nf_ct_list_DEPENDENCIES = ${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 -am_nf_exp_add_OBJECTS = nf-exp-add.$(OBJEXT) -nf_exp_add_OBJECTS = $(am_nf_exp_add_OBJECTS) -nf_exp_add_LDADD = $(LDADD) -nf_exp_add_DEPENDENCIES = ${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 -am_nf_exp_delete_OBJECTS = nf-exp-delete.$(OBJEXT) -nf_exp_delete_OBJECTS = $(am_nf_exp_delete_OBJECTS) -nf_exp_delete_LDADD = $(LDADD) -nf_exp_delete_DEPENDENCIES = ${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 -am_nf_exp_list_OBJECTS = nf-exp-list.$(OBJEXT) -nf_exp_list_OBJECTS = $(am_nf_exp_list_OBJECTS) -nf_exp_list_LDADD = $(LDADD) -nf_exp_list_DEPENDENCIES = ${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 -am_nf_log_OBJECTS = nf-log.$(OBJEXT) -nf_log_OBJECTS = $(am_nf_log_OBJECTS) -nf_log_LDADD = $(LDADD) -nf_log_DEPENDENCIES = ${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 -am_nf_monitor_OBJECTS = nf-monitor.$(OBJEXT) -nf_monitor_OBJECTS = $(am_nf_monitor_OBJECTS) -nf_monitor_LDADD = $(LDADD) -nf_monitor_DEPENDENCIES = ${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 -am_nf_queue_OBJECTS = nf-queue.$(OBJEXT) -nf_queue_OBJECTS = $(am_nf_queue_OBJECTS) -nf_queue_LDADD = $(LDADD) -nf_queue_DEPENDENCIES = ${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 -am_nl_addr_add_OBJECTS = nl-addr-add.$(OBJEXT) -nl_addr_add_OBJECTS = $(am_nl_addr_add_OBJECTS) -nl_addr_add_LDADD = $(LDADD) -nl_addr_add_DEPENDENCIES = ${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 -am_nl_addr_delete_OBJECTS = nl-addr-delete.$(OBJEXT) -nl_addr_delete_OBJECTS = $(am_nl_addr_delete_OBJECTS) -nl_addr_delete_LDADD = $(LDADD) -nl_addr_delete_DEPENDENCIES = ${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 -am_nl_addr_list_OBJECTS = nl-addr-list.$(OBJEXT) -nl_addr_list_OBJECTS = $(am_nl_addr_list_OBJECTS) -nl_addr_list_LDADD = $(LDADD) -nl_addr_list_DEPENDENCIES = ${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 -am_nl_class_add_OBJECTS = nl-class-add.$(OBJEXT) -nl_class_add_OBJECTS = $(am_nl_class_add_OBJECTS) -nl_class_add_LDADD = $(LDADD) -nl_class_add_DEPENDENCIES = ${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 -am_nl_class_delete_OBJECTS = nl-class-delete.$(OBJEXT) -nl_class_delete_OBJECTS = $(am_nl_class_delete_OBJECTS) -nl_class_delete_LDADD = $(LDADD) -nl_class_delete_DEPENDENCIES = ${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 -am_nl_class_list_OBJECTS = nl-class-list.$(OBJEXT) -nl_class_list_OBJECTS = $(am_nl_class_list_OBJECTS) -nl_class_list_LDADD = $(LDADD) -nl_class_list_DEPENDENCIES = ${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 -am_nl_classid_lookup_OBJECTS = nl-classid-lookup.$(OBJEXT) -nl_classid_lookup_OBJECTS = $(am_nl_classid_lookup_OBJECTS) -nl_classid_lookup_LDADD = $(LDADD) -nl_classid_lookup_DEPENDENCIES = \ - ${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 -am_nl_cls_add_OBJECTS = nl-cls-add.$(OBJEXT) -nl_cls_add_OBJECTS = $(am_nl_cls_add_OBJECTS) -nl_cls_add_LDADD = $(LDADD) -nl_cls_add_DEPENDENCIES = ${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 -am_nl_cls_delete_OBJECTS = nl-cls-delete.$(OBJEXT) -nl_cls_delete_OBJECTS = $(am_nl_cls_delete_OBJECTS) -nl_cls_delete_LDADD = $(LDADD) -nl_cls_delete_DEPENDENCIES = ${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 -am_nl_cls_list_OBJECTS = nl-cls-list.$(OBJEXT) -nl_cls_list_OBJECTS = $(am_nl_cls_list_OBJECTS) -nl_cls_list_LDADD = $(LDADD) -nl_cls_list_DEPENDENCIES = ${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 -am_nl_fib_lookup_OBJECTS = nl-fib-lookup.$(OBJEXT) -nl_fib_lookup_OBJECTS = $(am_nl_fib_lookup_OBJECTS) -nl_fib_lookup_LDADD = $(LDADD) -nl_fib_lookup_DEPENDENCIES = ${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 -nl_link_enslave_SOURCES = nl-link-enslave.c -nl_link_enslave_OBJECTS = nl-link-enslave.$(OBJEXT) -nl_link_enslave_LDADD = $(LDADD) -nl_link_enslave_DEPENDENCIES = ${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 -am_nl_link_ifindex2name_OBJECTS = nl-link-ifindex2name.$(OBJEXT) -nl_link_ifindex2name_OBJECTS = $(am_nl_link_ifindex2name_OBJECTS) -nl_link_ifindex2name_LDADD = $(LDADD) -nl_link_ifindex2name_DEPENDENCIES = \ - ${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 -am_nl_link_list_OBJECTS = nl-link-list.$(OBJEXT) -nl_link_list_OBJECTS = $(am_nl_link_list_OBJECTS) -nl_link_list_LDADD = $(LDADD) -nl_link_list_DEPENDENCIES = ${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 -am_nl_link_name2ifindex_OBJECTS = nl-link-name2ifindex.$(OBJEXT) -nl_link_name2ifindex_OBJECTS = $(am_nl_link_name2ifindex_OBJECTS) -nl_link_name2ifindex_LDADD = $(LDADD) -nl_link_name2ifindex_DEPENDENCIES = \ - ${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 -nl_link_release_SOURCES = nl-link-release.c -nl_link_release_OBJECTS = nl-link-release.$(OBJEXT) -nl_link_release_LDADD = $(LDADD) -nl_link_release_DEPENDENCIES = ${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 -am_nl_link_set_OBJECTS = nl-link-set.$(OBJEXT) -nl_link_set_OBJECTS = $(am_nl_link_set_OBJECTS) -nl_link_set_LDADD = $(LDADD) -nl_link_set_DEPENDENCIES = ${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 -am_nl_link_stats_OBJECTS = nl-link-stats.$(OBJEXT) -nl_link_stats_OBJECTS = $(am_nl_link_stats_OBJECTS) -nl_link_stats_LDADD = $(LDADD) -nl_link_stats_DEPENDENCIES = ${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 -am_nl_list_caches_OBJECTS = nl-list-caches.$(OBJEXT) -nl_list_caches_OBJECTS = $(am_nl_list_caches_OBJECTS) -nl_list_caches_LDADD = $(LDADD) -nl_list_caches_DEPENDENCIES = ${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 -am_nl_list_sockets_OBJECTS = nl-list-sockets.$(OBJEXT) -nl_list_sockets_OBJECTS = $(am_nl_list_sockets_OBJECTS) -nl_list_sockets_LDADD = $(LDADD) -nl_list_sockets_DEPENDENCIES = ${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 -am_nl_monitor_OBJECTS = nl-monitor.$(OBJEXT) -nl_monitor_OBJECTS = $(am_nl_monitor_OBJECTS) -nl_monitor_LDADD = $(LDADD) -nl_monitor_DEPENDENCIES = ${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 -am_nl_neigh_add_OBJECTS = nl-neigh-add.$(OBJEXT) -nl_neigh_add_OBJECTS = $(am_nl_neigh_add_OBJECTS) -nl_neigh_add_LDADD = $(LDADD) -nl_neigh_add_DEPENDENCIES = ${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 -am_nl_neigh_delete_OBJECTS = nl-neigh-delete.$(OBJEXT) -nl_neigh_delete_OBJECTS = $(am_nl_neigh_delete_OBJECTS) -nl_neigh_delete_LDADD = $(LDADD) -nl_neigh_delete_DEPENDENCIES = ${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 -am_nl_neigh_list_OBJECTS = nl-neigh-list.$(OBJEXT) -nl_neigh_list_OBJECTS = $(am_nl_neigh_list_OBJECTS) -nl_neigh_list_LDADD = $(LDADD) -nl_neigh_list_DEPENDENCIES = ${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 -am_nl_neightbl_list_OBJECTS = nl-neightbl-list.$(OBJEXT) -nl_neightbl_list_OBJECTS = $(am_nl_neightbl_list_OBJECTS) -nl_neightbl_list_LDADD = $(LDADD) -nl_neightbl_list_DEPENDENCIES = \ - ${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 -am_nl_pktloc_lookup_OBJECTS = nl-pktloc-lookup.$(OBJEXT) -nl_pktloc_lookup_OBJECTS = $(am_nl_pktloc_lookup_OBJECTS) -nl_pktloc_lookup_LDADD = $(LDADD) -nl_pktloc_lookup_DEPENDENCIES = \ - ${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 -am_nl_qdisc_add_OBJECTS = nl-qdisc-add.$(OBJEXT) -nl_qdisc_add_OBJECTS = $(am_nl_qdisc_add_OBJECTS) -nl_qdisc_add_LDADD = $(LDADD) -nl_qdisc_add_DEPENDENCIES = ${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 -am_nl_qdisc_delete_OBJECTS = nl-qdisc-delete.$(OBJEXT) -nl_qdisc_delete_OBJECTS = $(am_nl_qdisc_delete_OBJECTS) -nl_qdisc_delete_LDADD = $(LDADD) -nl_qdisc_delete_DEPENDENCIES = ${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 -am_nl_qdisc_list_OBJECTS = nl-qdisc-list.$(OBJEXT) -nl_qdisc_list_OBJECTS = $(am_nl_qdisc_list_OBJECTS) -nl_qdisc_list_LDADD = $(LDADD) -nl_qdisc_list_DEPENDENCIES = ${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 -am_nl_route_add_OBJECTS = nl-route-add.$(OBJEXT) -nl_route_add_OBJECTS = $(am_nl_route_add_OBJECTS) -nl_route_add_LDADD = $(LDADD) -nl_route_add_DEPENDENCIES = ${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 -am_nl_route_delete_OBJECTS = nl-route-delete.$(OBJEXT) -nl_route_delete_OBJECTS = $(am_nl_route_delete_OBJECTS) -nl_route_delete_LDADD = $(LDADD) -nl_route_delete_DEPENDENCIES = ${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 -am_nl_route_get_OBJECTS = nl-route-get.$(OBJEXT) -nl_route_get_OBJECTS = $(am_nl_route_get_OBJECTS) -nl_route_get_LDADD = $(LDADD) -nl_route_get_DEPENDENCIES = ${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 -am_nl_route_list_OBJECTS = nl-route-list.$(OBJEXT) -nl_route_list_OBJECTS = $(am_nl_route_list_OBJECTS) -nl_route_list_LDADD = $(LDADD) -nl_route_list_DEPENDENCIES = ${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 -am_nl_rule_list_OBJECTS = nl-rule-list.$(OBJEXT) -nl_rule_list_OBJECTS = $(am_nl_rule_list_OBJECTS) -nl_rule_list_LDADD = $(LDADD) -nl_rule_list_DEPENDENCIES = ${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 -am_nl_tctree_list_OBJECTS = nl-tctree-list.$(OBJEXT) -nl_tctree_list_OBJECTS = $(am_nl_tctree_list_OBJECTS) -nl_tctree_list_LDADD = $(LDADD) -nl_tctree_list_DEPENDENCIES = ${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 -am_nl_util_addr_OBJECTS = nl-util-addr.$(OBJEXT) -nl_util_addr_OBJECTS = $(am_nl_util_addr_OBJECTS) -nl_util_addr_LDADD = $(LDADD) -nl_util_addr_DEPENDENCIES = ${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 -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/lib -depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -SOURCES = $(genl_ctrl_list_SOURCES) $(nf_ct_list_SOURCES) \ - $(nf_exp_add_SOURCES) $(nf_exp_delete_SOURCES) \ - $(nf_exp_list_SOURCES) $(nf_log_SOURCES) $(nf_monitor_SOURCES) \ - $(nf_queue_SOURCES) $(nl_addr_add_SOURCES) \ - $(nl_addr_delete_SOURCES) $(nl_addr_list_SOURCES) \ - $(nl_class_add_SOURCES) $(nl_class_delete_SOURCES) \ - $(nl_class_list_SOURCES) $(nl_classid_lookup_SOURCES) \ - $(nl_cls_add_SOURCES) $(nl_cls_delete_SOURCES) \ - $(nl_cls_list_SOURCES) $(nl_fib_lookup_SOURCES) \ - nl-link-enslave.c $(nl_link_ifindex2name_SOURCES) \ - $(nl_link_list_SOURCES) $(nl_link_name2ifindex_SOURCES) \ - nl-link-release.c $(nl_link_set_SOURCES) \ - $(nl_link_stats_SOURCES) $(nl_list_caches_SOURCES) \ - $(nl_list_sockets_SOURCES) $(nl_monitor_SOURCES) \ - $(nl_neigh_add_SOURCES) $(nl_neigh_delete_SOURCES) \ - $(nl_neigh_list_SOURCES) $(nl_neightbl_list_SOURCES) \ - $(nl_pktloc_lookup_SOURCES) $(nl_qdisc_add_SOURCES) \ - $(nl_qdisc_delete_SOURCES) $(nl_qdisc_list_SOURCES) \ - $(nl_route_add_SOURCES) $(nl_route_delete_SOURCES) \ - $(nl_route_get_SOURCES) $(nl_route_list_SOURCES) \ - $(nl_rule_list_SOURCES) $(nl_tctree_list_SOURCES) \ - $(nl_util_addr_SOURCES) -DIST_SOURCES = $(genl_ctrl_list_SOURCES) $(nf_ct_list_SOURCES) \ - $(nf_exp_add_SOURCES) $(nf_exp_delete_SOURCES) \ - $(nf_exp_list_SOURCES) $(nf_log_SOURCES) $(nf_monitor_SOURCES) \ - $(nf_queue_SOURCES) $(nl_addr_add_SOURCES) \ - $(nl_addr_delete_SOURCES) $(nl_addr_list_SOURCES) \ - $(nl_class_add_SOURCES) $(nl_class_delete_SOURCES) \ - $(nl_class_list_SOURCES) $(nl_classid_lookup_SOURCES) \ - $(nl_cls_add_SOURCES) $(nl_cls_delete_SOURCES) \ - $(nl_cls_list_SOURCES) $(nl_fib_lookup_SOURCES) \ - nl-link-enslave.c $(nl_link_ifindex2name_SOURCES) \ - $(nl_link_list_SOURCES) $(nl_link_name2ifindex_SOURCES) \ - nl-link-release.c $(nl_link_set_SOURCES) \ - $(nl_link_stats_SOURCES) $(nl_list_caches_SOURCES) \ - $(nl_list_sockets_SOURCES) $(nl_monitor_SOURCES) \ - $(nl_neigh_add_SOURCES) $(nl_neigh_delete_SOURCES) \ - $(nl_neigh_list_SOURCES) $(nl_neightbl_list_SOURCES) \ - $(nl_pktloc_lookup_SOURCES) $(nl_qdisc_add_SOURCES) \ - $(nl_qdisc_delete_SOURCES) $(nl_qdisc_list_SOURCES) \ - $(nl_route_add_SOURCES) $(nl_route_delete_SOURCES) \ - $(nl_route_get_SOURCES) $(nl_route_list_SOURCES) \ - $(nl_rule_list_SOURCES) $(nl_tctree_list_SOURCES) \ - $(nl_util_addr_SOURCES) -RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ - html-recursive info-recursive install-data-recursive \ - install-dvi-recursive install-exec-recursive \ - install-html-recursive install-info-recursive \ - install-pdf-recursive install-ps-recursive install-recursive \ - installcheck-recursive installdirs-recursive pdf-recursive \ - ps-recursive uninstall-recursive -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ - distclean-recursive maintainer-clean-recursive -AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ - $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ - distdir -ETAGS = etags -CTAGS = ctags -DIST_SUBDIRS = $(SUBDIRS) -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -am__relativize = \ - dir0=`pwd`; \ - sed_first='s,^\([^/]*\)/.*$$,\1,'; \ - sed_rest='s,^[^/]*/*,,'; \ - sed_last='s,^.*/\([^/]*\)$$,\1,'; \ - sed_butlast='s,/*[^/]*$$,,'; \ - while test -n "$$dir1"; do \ - first=`echo "$$dir1" | sed -e "$$sed_first"`; \ - if test "$$first" != "."; then \ - if test "$$first" = ".."; then \ - dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ - dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ - else \ - first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ - if test "$$first2" = "$$first"; then \ - dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ - else \ - dir2="../$$dir2"; \ - fi; \ - dir0="$$dir0"/"$$first"; \ - fi; \ - fi; \ - dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ - done; \ - reldir="$$dir2" -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CHECK_CFLAGS = @CHECK_CFLAGS@ -CHECK_LIBS = @CHECK_LIBS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -FLEX = @FLEX@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBNL_VERSION = @LIBNL_VERSION@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_AGE = @LT_AGE@ -LT_CURRENT = @LT_CURRENT@ -LT_REVISION = @LT_REVISION@ -MAJ_VERSION = @MAJ_VERSION@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MIC_VERSION = @MIC_VERSION@ -MIN_VERSION = @MIN_VERSION@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -YACC = @YACC@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgconfigdir = @pkgconfigdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -subdirs = @subdirs@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -SUBDIRS = lib -AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" -LDADD = \ - ${top_builddir}/src/lib/libnl-cli-3.la \ - ${top_builddir}/lib/libnl-3.la \ - ${top_builddir}/lib/libnl-nf-3.la \ - ${top_builddir}/lib/libnl-genl-3.la \ - ${top_builddir}/lib/libnl-route-3.la - -genl_ctrl_list_SOURCES = genl-ctrl-list.c -nf_ct_list_SOURCES = nf-ct-list.c -nf_log_SOURCES = nf-log.c -nf_queue_SOURCES = nf-queue.c -nf_monitor_SOURCES = nf-monitor.c -nf_exp_list_SOURCES = nf-exp-list.c -nf_exp_add_SOURCES = nf-exp-add.c -nf_exp_delete_SOURCES = nf-exp-delete.c -nl_addr_add_SOURCES = nl-addr-add.c -nl_addr_delete_SOURCES = nl-addr-delete.c -nl_addr_list_SOURCES = nl-addr-list.c -nl_link_list_SOURCES = nl-link-list.c -nl_link_set_SOURCES = nl-link-set.c -nl_link_stats_SOURCES = nl-link-stats.c -nl_link_ifindex2name_SOURCES = nl-link-ifindex2name.c -nl_link_name2ifindex_SOURCES = nl-link-name2ifindex.c -nl_monitor_SOURCES = nl-monitor.c -nl_neigh_add_SOURCES = nl-neigh-add.c -nl_neigh_delete_SOURCES = nl-neigh-delete.c -nl_neigh_list_SOURCES = nl-neigh-list.c -nl_neightbl_list_SOURCES = nl-neightbl-list.c -nl_qdisc_add_SOURCES = nl-qdisc-add.c -nl_qdisc_delete_SOURCES = nl-qdisc-delete.c -nl_qdisc_list_SOURCES = nl-qdisc-list.c -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_delete_SOURCES = nl-route-delete.c -nl_route_get_SOURCES = nl-route-get.c -nl_route_list_SOURCES = nl-route-list.c -nl_rule_list_SOURCES = nl-rule-list.c -nl_tctree_list_SOURCES = nl-tctree-list.c -nl_fib_lookup_SOURCES = nl-fib-lookup.c -nl_list_caches_SOURCES = nl-list-caches.c -nl_list_sockets_SOURCES = nl-list-sockets.c -nl_util_addr_SOURCES = nl-util-addr.c -nl_pktloc_lookup_SOURCES = nl-pktloc-lookup.c -nl_classid_lookup_SOURCES = nl-classid-lookup.c -all: all-recursive - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstPROGRAMS: - @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ - echo " rm -f" $$list; \ - rm -f $$list || exit $$?; \ - test -n "$(EXEEXT)" || exit 0; \ - list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ - echo " rm -f" $$list; \ - rm -f $$list -install-sbinPROGRAMS: $(sbin_PROGRAMS) - @$(NORMAL_INSTALL) - @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ - fi; \ - for p in $$list; do echo "$$p $$p"; done | \ - sed 's/$(EXEEXT)$$//' | \ - while read p p1; do if test -f $$p || test -f $$p1; \ - then echo "$$p"; echo "$$p"; else :; fi; \ - done | \ - sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ - -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ - sed 'N;N;N;s,\n, ,g' | \ - $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ - { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ - if ($$2 == $$4) files[d] = files[d] " " $$1; \ - else { print "f", $$3 "/" $$4, $$1; } } \ - END { for (d in files) print "f", d, files[d] }' | \ - while read type dir files; do \ - if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ - test -z "$$files" || { \ - echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ - $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ - } \ - ; done - -uninstall-sbinPROGRAMS: - @$(NORMAL_UNINSTALL) - @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ - files=`for p in $$list; do echo "$$p"; done | \ - sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ - -e 's/$$/$(EXEEXT)/' `; \ - test -n "$$list" || exit 0; \ - echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(sbindir)" && rm -f $$files - -clean-sbinPROGRAMS: - @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ - echo " rm -f" $$list; \ - rm -f $$list || exit $$?; \ - test -n "$(EXEEXT)" || exit 0; \ - list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ - echo " rm -f" $$list; \ - rm -f $$list -genl-ctrl-list$(EXEEXT): $(genl_ctrl_list_OBJECTS) $(genl_ctrl_list_DEPENDENCIES) $(EXTRA_genl_ctrl_list_DEPENDENCIES) - @rm -f genl-ctrl-list$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(genl_ctrl_list_OBJECTS) $(genl_ctrl_list_LDADD) $(LIBS) -nf-ct-list$(EXEEXT): $(nf_ct_list_OBJECTS) $(nf_ct_list_DEPENDENCIES) $(EXTRA_nf_ct_list_DEPENDENCIES) - @rm -f nf-ct-list$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nf_ct_list_OBJECTS) $(nf_ct_list_LDADD) $(LIBS) -nf-exp-add$(EXEEXT): $(nf_exp_add_OBJECTS) $(nf_exp_add_DEPENDENCIES) $(EXTRA_nf_exp_add_DEPENDENCIES) - @rm -f nf-exp-add$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nf_exp_add_OBJECTS) $(nf_exp_add_LDADD) $(LIBS) -nf-exp-delete$(EXEEXT): $(nf_exp_delete_OBJECTS) $(nf_exp_delete_DEPENDENCIES) $(EXTRA_nf_exp_delete_DEPENDENCIES) - @rm -f nf-exp-delete$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nf_exp_delete_OBJECTS) $(nf_exp_delete_LDADD) $(LIBS) -nf-exp-list$(EXEEXT): $(nf_exp_list_OBJECTS) $(nf_exp_list_DEPENDENCIES) $(EXTRA_nf_exp_list_DEPENDENCIES) - @rm -f nf-exp-list$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nf_exp_list_OBJECTS) $(nf_exp_list_LDADD) $(LIBS) -nf-log$(EXEEXT): $(nf_log_OBJECTS) $(nf_log_DEPENDENCIES) $(EXTRA_nf_log_DEPENDENCIES) - @rm -f nf-log$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nf_log_OBJECTS) $(nf_log_LDADD) $(LIBS) -nf-monitor$(EXEEXT): $(nf_monitor_OBJECTS) $(nf_monitor_DEPENDENCIES) $(EXTRA_nf_monitor_DEPENDENCIES) - @rm -f nf-monitor$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nf_monitor_OBJECTS) $(nf_monitor_LDADD) $(LIBS) -nf-queue$(EXEEXT): $(nf_queue_OBJECTS) $(nf_queue_DEPENDENCIES) $(EXTRA_nf_queue_DEPENDENCIES) - @rm -f nf-queue$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nf_queue_OBJECTS) $(nf_queue_LDADD) $(LIBS) -nl-addr-add$(EXEEXT): $(nl_addr_add_OBJECTS) $(nl_addr_add_DEPENDENCIES) $(EXTRA_nl_addr_add_DEPENDENCIES) - @rm -f nl-addr-add$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_addr_add_OBJECTS) $(nl_addr_add_LDADD) $(LIBS) -nl-addr-delete$(EXEEXT): $(nl_addr_delete_OBJECTS) $(nl_addr_delete_DEPENDENCIES) $(EXTRA_nl_addr_delete_DEPENDENCIES) - @rm -f nl-addr-delete$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_addr_delete_OBJECTS) $(nl_addr_delete_LDADD) $(LIBS) -nl-addr-list$(EXEEXT): $(nl_addr_list_OBJECTS) $(nl_addr_list_DEPENDENCIES) $(EXTRA_nl_addr_list_DEPENDENCIES) - @rm -f nl-addr-list$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_addr_list_OBJECTS) $(nl_addr_list_LDADD) $(LIBS) -nl-class-add$(EXEEXT): $(nl_class_add_OBJECTS) $(nl_class_add_DEPENDENCIES) $(EXTRA_nl_class_add_DEPENDENCIES) - @rm -f nl-class-add$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_class_add_OBJECTS) $(nl_class_add_LDADD) $(LIBS) -nl-class-delete$(EXEEXT): $(nl_class_delete_OBJECTS) $(nl_class_delete_DEPENDENCIES) $(EXTRA_nl_class_delete_DEPENDENCIES) - @rm -f nl-class-delete$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_class_delete_OBJECTS) $(nl_class_delete_LDADD) $(LIBS) -nl-class-list$(EXEEXT): $(nl_class_list_OBJECTS) $(nl_class_list_DEPENDENCIES) $(EXTRA_nl_class_list_DEPENDENCIES) - @rm -f nl-class-list$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_class_list_OBJECTS) $(nl_class_list_LDADD) $(LIBS) -nl-classid-lookup$(EXEEXT): $(nl_classid_lookup_OBJECTS) $(nl_classid_lookup_DEPENDENCIES) $(EXTRA_nl_classid_lookup_DEPENDENCIES) - @rm -f nl-classid-lookup$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_classid_lookup_OBJECTS) $(nl_classid_lookup_LDADD) $(LIBS) -nl-cls-add$(EXEEXT): $(nl_cls_add_OBJECTS) $(nl_cls_add_DEPENDENCIES) $(EXTRA_nl_cls_add_DEPENDENCIES) - @rm -f nl-cls-add$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_cls_add_OBJECTS) $(nl_cls_add_LDADD) $(LIBS) -nl-cls-delete$(EXEEXT): $(nl_cls_delete_OBJECTS) $(nl_cls_delete_DEPENDENCIES) $(EXTRA_nl_cls_delete_DEPENDENCIES) - @rm -f nl-cls-delete$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_cls_delete_OBJECTS) $(nl_cls_delete_LDADD) $(LIBS) -nl-cls-list$(EXEEXT): $(nl_cls_list_OBJECTS) $(nl_cls_list_DEPENDENCIES) $(EXTRA_nl_cls_list_DEPENDENCIES) - @rm -f nl-cls-list$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_cls_list_OBJECTS) $(nl_cls_list_LDADD) $(LIBS) -nl-fib-lookup$(EXEEXT): $(nl_fib_lookup_OBJECTS) $(nl_fib_lookup_DEPENDENCIES) $(EXTRA_nl_fib_lookup_DEPENDENCIES) - @rm -f nl-fib-lookup$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_fib_lookup_OBJECTS) $(nl_fib_lookup_LDADD) $(LIBS) -nl-link-enslave$(EXEEXT): $(nl_link_enslave_OBJECTS) $(nl_link_enslave_DEPENDENCIES) $(EXTRA_nl_link_enslave_DEPENDENCIES) - @rm -f nl-link-enslave$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_link_enslave_OBJECTS) $(nl_link_enslave_LDADD) $(LIBS) -nl-link-ifindex2name$(EXEEXT): $(nl_link_ifindex2name_OBJECTS) $(nl_link_ifindex2name_DEPENDENCIES) $(EXTRA_nl_link_ifindex2name_DEPENDENCIES) - @rm -f nl-link-ifindex2name$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_link_ifindex2name_OBJECTS) $(nl_link_ifindex2name_LDADD) $(LIBS) -nl-link-list$(EXEEXT): $(nl_link_list_OBJECTS) $(nl_link_list_DEPENDENCIES) $(EXTRA_nl_link_list_DEPENDENCIES) - @rm -f nl-link-list$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_link_list_OBJECTS) $(nl_link_list_LDADD) $(LIBS) -nl-link-name2ifindex$(EXEEXT): $(nl_link_name2ifindex_OBJECTS) $(nl_link_name2ifindex_DEPENDENCIES) $(EXTRA_nl_link_name2ifindex_DEPENDENCIES) - @rm -f nl-link-name2ifindex$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_link_name2ifindex_OBJECTS) $(nl_link_name2ifindex_LDADD) $(LIBS) -nl-link-release$(EXEEXT): $(nl_link_release_OBJECTS) $(nl_link_release_DEPENDENCIES) $(EXTRA_nl_link_release_DEPENDENCIES) - @rm -f nl-link-release$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_link_release_OBJECTS) $(nl_link_release_LDADD) $(LIBS) -nl-link-set$(EXEEXT): $(nl_link_set_OBJECTS) $(nl_link_set_DEPENDENCIES) $(EXTRA_nl_link_set_DEPENDENCIES) - @rm -f nl-link-set$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_link_set_OBJECTS) $(nl_link_set_LDADD) $(LIBS) -nl-link-stats$(EXEEXT): $(nl_link_stats_OBJECTS) $(nl_link_stats_DEPENDENCIES) $(EXTRA_nl_link_stats_DEPENDENCIES) - @rm -f nl-link-stats$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_link_stats_OBJECTS) $(nl_link_stats_LDADD) $(LIBS) -nl-list-caches$(EXEEXT): $(nl_list_caches_OBJECTS) $(nl_list_caches_DEPENDENCIES) $(EXTRA_nl_list_caches_DEPENDENCIES) - @rm -f nl-list-caches$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_list_caches_OBJECTS) $(nl_list_caches_LDADD) $(LIBS) -nl-list-sockets$(EXEEXT): $(nl_list_sockets_OBJECTS) $(nl_list_sockets_DEPENDENCIES) $(EXTRA_nl_list_sockets_DEPENDENCIES) - @rm -f nl-list-sockets$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_list_sockets_OBJECTS) $(nl_list_sockets_LDADD) $(LIBS) -nl-monitor$(EXEEXT): $(nl_monitor_OBJECTS) $(nl_monitor_DEPENDENCIES) $(EXTRA_nl_monitor_DEPENDENCIES) - @rm -f nl-monitor$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_monitor_OBJECTS) $(nl_monitor_LDADD) $(LIBS) -nl-neigh-add$(EXEEXT): $(nl_neigh_add_OBJECTS) $(nl_neigh_add_DEPENDENCIES) $(EXTRA_nl_neigh_add_DEPENDENCIES) - @rm -f nl-neigh-add$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_neigh_add_OBJECTS) $(nl_neigh_add_LDADD) $(LIBS) -nl-neigh-delete$(EXEEXT): $(nl_neigh_delete_OBJECTS) $(nl_neigh_delete_DEPENDENCIES) $(EXTRA_nl_neigh_delete_DEPENDENCIES) - @rm -f nl-neigh-delete$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_neigh_delete_OBJECTS) $(nl_neigh_delete_LDADD) $(LIBS) -nl-neigh-list$(EXEEXT): $(nl_neigh_list_OBJECTS) $(nl_neigh_list_DEPENDENCIES) $(EXTRA_nl_neigh_list_DEPENDENCIES) - @rm -f nl-neigh-list$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_neigh_list_OBJECTS) $(nl_neigh_list_LDADD) $(LIBS) -nl-neightbl-list$(EXEEXT): $(nl_neightbl_list_OBJECTS) $(nl_neightbl_list_DEPENDENCIES) $(EXTRA_nl_neightbl_list_DEPENDENCIES) - @rm -f nl-neightbl-list$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_neightbl_list_OBJECTS) $(nl_neightbl_list_LDADD) $(LIBS) -nl-pktloc-lookup$(EXEEXT): $(nl_pktloc_lookup_OBJECTS) $(nl_pktloc_lookup_DEPENDENCIES) $(EXTRA_nl_pktloc_lookup_DEPENDENCIES) - @rm -f nl-pktloc-lookup$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_pktloc_lookup_OBJECTS) $(nl_pktloc_lookup_LDADD) $(LIBS) -nl-qdisc-add$(EXEEXT): $(nl_qdisc_add_OBJECTS) $(nl_qdisc_add_DEPENDENCIES) $(EXTRA_nl_qdisc_add_DEPENDENCIES) - @rm -f nl-qdisc-add$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_qdisc_add_OBJECTS) $(nl_qdisc_add_LDADD) $(LIBS) -nl-qdisc-delete$(EXEEXT): $(nl_qdisc_delete_OBJECTS) $(nl_qdisc_delete_DEPENDENCIES) $(EXTRA_nl_qdisc_delete_DEPENDENCIES) - @rm -f nl-qdisc-delete$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_qdisc_delete_OBJECTS) $(nl_qdisc_delete_LDADD) $(LIBS) -nl-qdisc-list$(EXEEXT): $(nl_qdisc_list_OBJECTS) $(nl_qdisc_list_DEPENDENCIES) $(EXTRA_nl_qdisc_list_DEPENDENCIES) - @rm -f nl-qdisc-list$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_qdisc_list_OBJECTS) $(nl_qdisc_list_LDADD) $(LIBS) -nl-route-add$(EXEEXT): $(nl_route_add_OBJECTS) $(nl_route_add_DEPENDENCIES) $(EXTRA_nl_route_add_DEPENDENCIES) - @rm -f nl-route-add$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_route_add_OBJECTS) $(nl_route_add_LDADD) $(LIBS) -nl-route-delete$(EXEEXT): $(nl_route_delete_OBJECTS) $(nl_route_delete_DEPENDENCIES) $(EXTRA_nl_route_delete_DEPENDENCIES) - @rm -f nl-route-delete$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_route_delete_OBJECTS) $(nl_route_delete_LDADD) $(LIBS) -nl-route-get$(EXEEXT): $(nl_route_get_OBJECTS) $(nl_route_get_DEPENDENCIES) $(EXTRA_nl_route_get_DEPENDENCIES) - @rm -f nl-route-get$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_route_get_OBJECTS) $(nl_route_get_LDADD) $(LIBS) -nl-route-list$(EXEEXT): $(nl_route_list_OBJECTS) $(nl_route_list_DEPENDENCIES) $(EXTRA_nl_route_list_DEPENDENCIES) - @rm -f nl-route-list$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_route_list_OBJECTS) $(nl_route_list_LDADD) $(LIBS) -nl-rule-list$(EXEEXT): $(nl_rule_list_OBJECTS) $(nl_rule_list_DEPENDENCIES) $(EXTRA_nl_rule_list_DEPENDENCIES) - @rm -f nl-rule-list$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_rule_list_OBJECTS) $(nl_rule_list_LDADD) $(LIBS) -nl-tctree-list$(EXEEXT): $(nl_tctree_list_OBJECTS) $(nl_tctree_list_DEPENDENCIES) $(EXTRA_nl_tctree_list_DEPENDENCIES) - @rm -f nl-tctree-list$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_tctree_list_OBJECTS) $(nl_tctree_list_LDADD) $(LIBS) -nl-util-addr$(EXEEXT): $(nl_util_addr_OBJECTS) $(nl_util_addr_DEPENDENCIES) $(EXTRA_nl_util_addr_DEPENDENCIES) - @rm -f nl-util-addr$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nl_util_addr_OBJECTS) $(nl_util_addr_LDADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/genl-ctrl-list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nf-ct-list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nf-exp-add.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nf-exp-delete.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nf-exp-list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nf-log.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nf-monitor.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nf-queue.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-addr-add.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-addr-delete.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-addr-list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-class-add.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-class-delete.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-class-list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-classid-lookup.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-cls-add.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-cls-delete.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-cls-list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-fib-lookup.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-link-enslave.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-link-ifindex2name.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-link-list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-link-name2ifindex.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-link-release.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-link-set.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-link-stats.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-list-caches.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-list-sockets.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-monitor.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-neigh-add.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-neigh-delete.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-neigh-list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-neightbl-list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-pktloc-lookup.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-qdisc-add.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-qdisc-delete.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-qdisc-list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-route-add.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-route-delete.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-route-get.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-route-list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-rule-list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-tctree-list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl-util-addr.Po@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ -@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ -@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -# This directory's subdirectories are mostly independent; you can cd -# into them and run `make' without going through this Makefile. -# To change the values of `make' variables: instead of editing Makefiles, -# (1) if the variable is set in `config.status', edit `config.status' -# (which will cause the Makefiles to be regenerated when you run `make'); -# (2) otherwise, pass the desired values on the `make' command line. -$(RECURSIVE_TARGETS): - @fail= failcom='exit 1'; \ - for f in x $$MAKEFLAGS; do \ - case $$f in \ - *=* | --[!k]*);; \ - *k*) failcom='fail=yes';; \ - esac; \ - done; \ - dot_seen=no; \ - target=`echo $@ | sed s/-recursive//`; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - dot_seen=yes; \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || eval $$failcom; \ - done; \ - if test "$$dot_seen" = "no"; then \ - $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ - fi; test -z "$$fail" - -$(RECURSIVE_CLEAN_TARGETS): - @fail= failcom='exit 1'; \ - for f in x $$MAKEFLAGS; do \ - case $$f in \ - *=* | --[!k]*);; \ - *k*) failcom='fail=yes';; \ - esac; \ - done; \ - dot_seen=no; \ - case "$@" in \ - distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ - *) list='$(SUBDIRS)' ;; \ - esac; \ - rev=''; for subdir in $$list; do \ - if test "$$subdir" = "."; then :; else \ - rev="$$subdir $$rev"; \ - fi; \ - done; \ - rev="$$rev ."; \ - target=`echo $@ | sed s/-recursive//`; \ - for subdir in $$rev; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || eval $$failcom; \ - done && test -z "$$fail" -tags-recursive: - list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ - done -ctags-recursive: - list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ - done - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - set x; \ - here=`pwd`; \ - if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ - include_option=--etags-include; \ - empty_fix=.; \ - else \ - include_option=--include; \ - empty_fix=; \ - fi; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - test ! -f $$subdir/TAGS || \ - set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ - fi; \ - done; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: CTAGS -CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - $(am__make_dryrun) \ - || test -d "$(distdir)/$$subdir" \ - || $(MKDIR_P) "$(distdir)/$$subdir" \ - || exit 1; \ - dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ - $(am__relativize); \ - new_distdir=$$reldir; \ - dir1=$$subdir; dir2="$(top_distdir)"; \ - $(am__relativize); \ - new_top_distdir=$$reldir; \ - echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ - echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ - ($(am__cd) $$subdir && \ - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$$new_top_distdir" \ - distdir="$$new_distdir" \ - am__remove_distdir=: \ - am__skip_length_check=: \ - am__skip_mode_fix=: \ - distdir) \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-recursive -all-am: Makefile $(PROGRAMS) -installdirs: installdirs-recursive -installdirs-am: - for dir in "$(DESTDIR)$(sbindir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-recursive -install-exec: install-exec-recursive -install-data: install-data-recursive -uninstall: uninstall-recursive - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-recursive -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-recursive - -clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ - clean-sbinPROGRAMS mostlyclean-am - -distclean: distclean-recursive - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-recursive - -dvi-am: - -html: html-recursive - -html-am: - -info: info-recursive - -info-am: - -install-data-am: - -install-dvi: install-dvi-recursive - -install-dvi-am: - -install-exec-am: install-sbinPROGRAMS - -install-html: install-html-recursive - -install-html-am: - -install-info: install-info-recursive - -install-info-am: - -install-man: - -install-pdf: install-pdf-recursive - -install-pdf-am: - -install-ps: install-ps-recursive - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-recursive - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-recursive - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-recursive - -pdf-am: - -ps: ps-recursive - -ps-am: - -uninstall-am: uninstall-sbinPROGRAMS - -.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ - install-am install-strip tags-recursive - -.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ - all all-am check check-am clean clean-generic clean-libtool \ - clean-noinstPROGRAMS clean-sbinPROGRAMS ctags ctags-recursive \ - distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-sbinPROGRAMS install-strip \ - installcheck installcheck-am installdirs installdirs-am \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ - pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ - uninstall-sbinPROGRAMS - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/genl-ctrl-list.c b/src/genl-ctrl-list.c index 0895bcc..035b3e2 100644 --- a/src/genl-ctrl-list.c +++ b/src/genl-ctrl-list.c @@ -1,20 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * 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-2012 Thomas Graf */ +#include "nl-default.h" + +#include + #include static struct nl_cache *alloc_genl_family_cache(struct nl_sock *sk) { return nl_cli_alloc_cache(sk, "generic netlink family", - genl_ctrl_alloc_cache); + genl_ctrl_alloc_cache); } static void print_usage(void) @@ -38,11 +36,11 @@ int main(int argc, char *argv[]) .dp_type = NL_DUMP_LINE, .dp_fd = stdout, }; - + sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_GENERIC); family_cache = alloc_genl_family_cache(sock); - + for (;;) { int c, optidx = 0; static struct option long_opts[] = { @@ -52,7 +50,7 @@ int main(int argc, char *argv[]) { "version", 0, 0, 'v' }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "df:hv", long_opts, &optidx); if (c == -1) break; @@ -63,7 +61,7 @@ int main(int argc, char *argv[]) case 'h': print_usage(); break; case 'v': nl_cli_print_version(); break; } - } + } nl_cache_dump(family_cache, ¶ms); diff --git a/src/idiag-socket-details.c b/src/idiag-socket-details.c new file mode 100644 index 0000000..9f2da41 --- /dev/null +++ b/src/idiag-socket-details.c @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Sassano Systems LLC + */ + +#include "nl-default.h" + +#include + +#include +#include +#include + +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, IDIAGNL_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 deleted file mode 100644 index 6688e7c..0000000 --- a/src/lib/Makefile.am +++ /dev/null @@ -1,43 +0,0 @@ -# -*- Makefile -*- - -AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DPKGLIBDIR=\"$(pkglibdir)\" -DSYSCONFDIR=\"$(sysconfdir)\" -rdynamic -AM_LDFLAGS = \ - -L${top_builddir}/lib \ - -ldl \ - -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) - -#nobase_pkglib_LTLIBRARIES = cls/basic.la cls/ematch/cmp.la -#cls_basic_la_LDFLAGS = -module -version-info 2:0:0 -#cls_ematch_cmp_la_LDFLAGS = -module -version-info 2:0:0 - -#cls/ematch_grammar.c: cls/ematch_grammar.l -# $(LEX) --header-file=cls/ematch_grammar.h $(LFLAGS) -o $@ $^ - -#cls/ematch_syntax.c: cls/ematch_syntax.y -# $(YACC) -d $(YFLAGS) -o $@ $^ - -#cls/pktloc_grammar.c: cls/pktloc_grammar.l -# $(LEX) --header-file=cls/pktloc_grammar.h $(LFLAGS) -o $@ $^ - -#cls/pktloc_syntax.c: cls/pktloc_syntax.y -# $(YACC) -d $(YFLAGS) -o $@ $^ - -#CLEANFILES = \ -# cls/ematch_grammar.c cls/ematch_grammar.h \ -# cls/ematch_syntax.c cls/ematch_syntax.h \ -# cls/pktloc_grammar.c cls/pktloc_grammar.h \ -# cls/pktloc_syntax.c cls/pktloc_syntax.h - -lib_LTLIBRARIES = \ - libnl-cli-3.la - -libnl_cli_3_la_LIBADD = ${top_builddir}/lib/libnl-3.la \ - ${top_builddir}/lib/libnl-route-3.la \ - ${top_builddir}/lib/libnl-nf-3.la \ - ${top_builddir}/lib/libnl-genl-3.la - -libnl_cli_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/Makefile.in b/src/lib/Makefile.in deleted file mode 100644 index 025484a..0000000 --- a/src/lib/Makefile.in +++ /dev/null @@ -1,643 +0,0 @@ -# Makefile.in generated by automake 1.11.6 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -# -*- Makefile -*- - -VPATH = @srcdir@ -am__make_dryrun = \ - { \ - am__dry=no; \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ - esac; \ - test $$am__dry = yes; \ - } -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = src/lib -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/lib/defs.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -am__installdirs = "$(DESTDIR)$(libdir)" -LTLIBRARIES = $(lib_LTLIBRARIES) -libnl_cli_3_la_DEPENDENCIES = ${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 -am_libnl_cli_3_la_OBJECTS = utils.lo addr.lo ct.lo link.lo neigh.lo \ - rule.lo route.lo tc.lo qdisc.lo class.lo cls.lo exp.lo -libnl_cli_3_la_OBJECTS = $(am_libnl_cli_3_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/lib -depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -SOURCES = $(libnl_cli_3_la_SOURCES) -DIST_SOURCES = $(libnl_cli_3_la_SOURCES) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CHECK_CFLAGS = @CHECK_CFLAGS@ -CHECK_LIBS = @CHECK_LIBS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -FLEX = @FLEX@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBNL_VERSION = @LIBNL_VERSION@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_AGE = @LT_AGE@ -LT_CURRENT = @LT_CURRENT@ -LT_REVISION = @LT_REVISION@ -MAJ_VERSION = @MAJ_VERSION@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MIC_VERSION = @MIC_VERSION@ -MIN_VERSION = @MIN_VERSION@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -YACC = @YACC@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgconfigdir = @pkgconfigdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -subdirs = @subdirs@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DPKGLIBDIR=\"$(pkglibdir)\" -DSYSCONFDIR=\"$(sysconfdir)\" -rdynamic -AM_LDFLAGS = \ - -L${top_builddir}/lib \ - -ldl \ - -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) - - -#nobase_pkglib_LTLIBRARIES = cls/basic.la cls/ematch/cmp.la -#cls_basic_la_LDFLAGS = -module -version-info 2:0:0 -#cls_ematch_cmp_la_LDFLAGS = -module -version-info 2:0:0 - -#cls/ematch_grammar.c: cls/ematch_grammar.l -# $(LEX) --header-file=cls/ematch_grammar.h $(LFLAGS) -o $@ $^ - -#cls/ematch_syntax.c: cls/ematch_syntax.y -# $(YACC) -d $(YFLAGS) -o $@ $^ - -#cls/pktloc_grammar.c: cls/pktloc_grammar.l -# $(LEX) --header-file=cls/pktloc_grammar.h $(LFLAGS) -o $@ $^ - -#cls/pktloc_syntax.c: cls/pktloc_syntax.y -# $(YACC) -d $(YFLAGS) -o $@ $^ - -#CLEANFILES = \ -# cls/ematch_grammar.c cls/ematch_grammar.h \ -# cls/ematch_syntax.c cls/ematch_syntax.h \ -# cls/pktloc_grammar.c cls/pktloc_grammar.h \ -# cls/pktloc_syntax.c cls/pktloc_syntax.h -lib_LTLIBRARIES = \ - libnl-cli-3.la - -libnl_cli_3_la_LIBADD = ${top_builddir}/lib/libnl-3.la \ - ${top_builddir}/lib/libnl-route-3.la \ - ${top_builddir}/lib/libnl-nf-3.la \ - ${top_builddir}/lib/libnl-genl-3.la - -libnl_cli_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 - -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/lib/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): -install-libLTLIBRARIES: $(lib_LTLIBRARIES) - @$(NORMAL_INSTALL) - @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ - list2=; for p in $$list; do \ - if test -f $$p; then \ - list2="$$list2 $$p"; \ - else :; fi; \ - done; \ - test -z "$$list2" || { \ - echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ - } - -uninstall-libLTLIBRARIES: - @$(NORMAL_UNINSTALL) - @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ - for p in $$list; do \ - $(am__strip_dir) \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ - done - -clean-libLTLIBRARIES: - -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) - @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ - dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ - test "$$dir" != "$$p" || dir=.; \ - echo "rm -f \"$${dir}/so_locations\""; \ - rm -f "$${dir}/so_locations"; \ - done -libnl-cli-3.la: $(libnl_cli_3_la_OBJECTS) $(libnl_cli_3_la_DEPENDENCIES) $(EXTRA_libnl_cli_3_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) -rpath $(libdir) $(libnl_cli_3_la_OBJECTS) $(libnl_cli_3_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addr.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/class.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cls.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ct.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exp.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/link.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/neigh.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qdisc.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/route.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rule.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ -@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ -@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - set x; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) -installdirs: - for dir in "$(DESTDIR)$(libdir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: install-libLTLIBRARIES - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-libLTLIBRARIES - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ - clean-libLTLIBRARIES clean-libtool ctags distclean \ - distclean-compile distclean-generic distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am \ - install-libLTLIBRARIES install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags uninstall uninstall-am uninstall-libLTLIBRARIES - -# cls/ematch_syntax.c cls/ematch_grammar.c cls/ematch.c -# cls/pktloc_syntax.c cls/pktloc_grammar.c cls/utils.c - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/lib/addr.c b/src/lib/addr.c index a9c137b..7b12f36 100644 --- a/src/lib/addr.c +++ b/src/lib/addr.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/lib/addr.c Address 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 */ @@ -16,6 +10,8 @@ * @{ */ +#include "nl-default.h" + #include #include diff --git a/src/lib/class.c b/src/lib/class.c index 96f60cd..9373b07 100644 --- a/src/lib/class.c +++ b/src/lib/class.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * 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 */ @@ -15,6 +9,8 @@ * @{ */ +#include "nl-default.h" + #include #include diff --git a/src/lib/cls.c b/src/lib/cls.c index 86d775d..9c94b0d 100644 --- a/src/lib/cls.c +++ b/src/lib/cls.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * 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 */ @@ -15,6 +9,8 @@ * @{ */ +#include "nl-default.h" + #include #include #include diff --git a/src/lib/ct.c b/src/lib/ct.c index 5bab08f..959a850 100644 --- a/src/lib/ct.c +++ b/src/lib/ct.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/lib/ct.c CLI Conntrack 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 */ @@ -16,6 +10,8 @@ * @{ */ +#include "nl-default.h" + #include #include @@ -137,6 +133,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 index a7a74f5..dcda30c 100644 --- a/src/lib/exp.c +++ b/src/lib/exp.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * 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 * Copyright (c) 2012 Rich Fought */ @@ -17,6 +11,8 @@ * @{ */ +#include "nl-default.h" + #include #include diff --git a/src/lib/link.c b/src/lib/link.c index 5bce824..67580b4 100644 --- a/src/lib/link.c +++ b/src/lib/link.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/lib/link.c CLI Link 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-2010 Thomas Graf */ @@ -16,9 +10,12 @@ * @{ */ +#include "nl-default.h" + +#include + #include #include -#include struct rtnl_link *nl_cli_link_alloc(void) { @@ -31,12 +28,14 @@ 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 *nl_cli_link_alloc_cache_family_flags(struct nl_sock *sock, + int family, + unsigned int flags) { struct nl_cache *cache; int err; - if ((err = rtnl_link_alloc_cache(sock, family, &cache)) < 0) + if ((err = rtnl_link_alloc_cache_flags(sock, family, &cache, flags)) < 0) nl_cli_fatal(err, "Unable to allocate link cache: %s", nl_geterror(err)); @@ -45,11 +44,22 @@ struct nl_cache *nl_cli_link_alloc_cache_family(struct nl_sock *sock, int family return cache; } +struct nl_cache *nl_cli_link_alloc_cache_family(struct nl_sock *sock, int family) +{ + return nl_cli_link_alloc_cache_family_flags(sock, family, 0); +} + struct nl_cache *nl_cli_link_alloc_cache(struct nl_sock *sock) { return nl_cli_link_alloc_cache_family(sock, AF_UNSPEC); } +struct nl_cache *nl_cli_link_alloc_cache_flags(struct nl_sock *sock, + unsigned int flags) +{ + return nl_cli_link_alloc_cache_family_flags(sock, AF_UNSPEC, flags); +} + void nl_cli_link_parse_family(struct rtnl_link *link, char *arg) { int family; diff --git a/src/lib/neigh.c b/src/lib/neigh.c index a814bd8..a4b211e 100644 --- a/src/lib/neigh.c +++ b/src/lib/neigh.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/lib/neigh.c CLI Neighbour 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 */ @@ -16,6 +10,8 @@ * @{ */ +#include "nl-default.h" + #include #include @@ -25,7 +21,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/nh.c b/src/lib/nh.c new file mode 100644 index 0000000..c1f5137 --- /dev/null +++ b/src/lib/nh.c @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2022 Stanislav Zaikin + */ + +/** + * @ingroup cli + * @defgroup cli_nh nhs + * + * @{ + */ + +#include "nl-default.h" + +#include + +#include +#include +#include + +struct rtnl_nh *nl_cli_nh_alloc(void) +{ + struct rtnl_nh *nh; + + nh = rtnl_nh_alloc(); + if (!nh) + nl_cli_fatal(ENOMEM, "Unable to allocate nh object"); + + return nh; +} + +struct nl_cache *nl_cli_nh_alloc_cache_family_flags(struct nl_sock *sock, + int family, + unsigned int flags) +{ + struct nl_cache *cache; + int err; + + if ((err = rtnl_nh_alloc_cache(sock, family, &cache)) < 0) + nl_cli_fatal(err, "Unable to allocate nh cache: %s", + nl_geterror(err)); + + nl_cache_mngt_provide(cache); + + return cache; +} + +struct nl_cache *nl_cli_nh_alloc_cache_family(struct nl_sock *sock, int family) +{ + return nl_cli_nh_alloc_cache_family_flags(sock, family, 0); +} + +struct nl_cache *nl_cli_nh_alloc_cache(struct nl_sock *sock) +{ + return nl_cli_nh_alloc_cache_family(sock, AF_UNSPEC); +} + +struct nl_cache *nl_cli_nh_alloc_cache_flags(struct nl_sock *sock, + unsigned int flags) +{ + return nl_cli_nh_alloc_cache_family_flags(sock, AF_UNSPEC, flags); +} + +/** @} */ diff --git a/src/lib/qdisc.c b/src/lib/qdisc.c index ccf7d26..659594a 100644 --- a/src/lib/qdisc.c +++ b/src/lib/qdisc.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/lib/qdisc.c CLI QDisc 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-2011 Thomas Graf */ @@ -15,6 +9,8 @@ * @{ */ +#include "nl-default.h" + #include #include #include diff --git a/src/lib/route.c b/src/lib/route.c index cd3e897..d814950 100644 --- a/src/lib/route.c +++ b/src/lib/route.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/lib/route.c CLI Route 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 */ @@ -16,6 +10,8 @@ * @{ */ +#include "nl-default.h" + #include #include @@ -141,11 +137,13 @@ void nl_cli_route_parse_nexthop(struct rtnl_route *route, char *subopts, NH_DEV, NH_VIA, NH_WEIGHT, + NH_AS, }; static char *const tokens[] = { "dev", "via", "weight", + "as", NULL, }; struct rtnl_nexthop *nh; @@ -175,8 +173,20 @@ void nl_cli_route_parse_nexthop(struct rtnl_route *route, char *subopts, break; case NH_VIA: - addr = nl_cli_addr_parse(arg,rtnl_route_get_family(route)); - rtnl_route_nh_set_gateway(nh, addr); + if (rtnl_route_get_family(route) == AF_MPLS) { + addr = nl_cli_addr_parse(arg, 0); + rtnl_route_nh_set_via(nh, addr); + } else { + addr = nl_cli_addr_parse(arg,rtnl_route_get_family(route)); + rtnl_route_nh_set_gateway(nh, addr); + } + nl_addr_put(addr); + break; + + case NH_AS: + addr = nl_cli_addr_parse(arg, + rtnl_route_get_family(route)); + rtnl_route_nh_set_newdst(nh, addr); nl_addr_put(addr); break; diff --git a/src/lib/rule.c b/src/lib/rule.c index 96f1d4c..8a54e73 100644 --- a/src/lib/rule.c +++ b/src/lib/rule.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/lib/rule.c CLI Routing Rule 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 */ @@ -16,6 +10,8 @@ * @{ */ +#include "nl-default.h" + #include #include diff --git a/src/lib/tc.c b/src/lib/tc.c index dde729f..3bed636 100644 --- a/src/lib/tc.c +++ b/src/lib/tc.c @@ -1,17 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * 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 */ +#include "nl-default.h" + #include #include -#include + +#include "nl-priv-dynamic-route/nl-priv-dynamic-route.h" /** * @ingroup cli diff --git a/src/lib/utils.c b/src/lib/utils.c index e5eacde..2839e27 100644 --- a/src/lib/utils.c +++ b/src/lib/utils.c @@ -1,11 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/utils.c Utilities - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2009 Thomas Graf */ @@ -21,6 +15,13 @@ * accordingly via nl_cli_fatal(). */ +#include "nl-default.h" + +#include +#ifdef HAVE_DLFCN_H +#include +#endif + #include /** @@ -70,7 +71,6 @@ void nl_cli_print_version(void) void nl_cli_fatal(int err, const char *fmt, ...) { va_list ap; - char buf[256]; fprintf(stderr, "Error: "); @@ -79,8 +79,28 @@ void nl_cli_fatal(int err, const char *fmt, ...) vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); - } else - fprintf(stderr, "%s\n", strerror_r(err, buf, sizeof(buf))); + } else { + char *buf; +#ifdef HAVE_STRERROR_L + locale_t loc = newlocale(LC_MESSAGES_MASK, "", (locale_t)0); + if (loc == (locale_t)0) { + if (errno == ENOENT) + loc = newlocale(LC_MESSAGES_MASK, + "POSIX", (locale_t)0); + if (loc == (locale_t)0) + buf = "newlocale() failed"; + } + if (loc != (locale_t)0) + buf = strerror_l(err, loc); +#else + buf = strerror(err); +#endif + fprintf(stderr, "%s\n", buf); +#ifdef HAVE_STRERROR_L + if (loc != (locale_t)0) + freelocale(loc); +#endif + } exit(abs(err)); } @@ -153,6 +173,7 @@ int nl_cli_confirm(struct nl_object *obj, struct nl_dump_params *params, switch ((answer = tolower(buf[0]))) { case '\n': answer = default_yes ? 'y' : 'n'; + /* fall through */ case 'y': case 'n': return answer == 'y'; @@ -180,17 +201,46 @@ struct nl_cache *nl_cli_alloc_cache(struct nl_sock *sock, const char *name, return cache; } +struct nl_cache *nl_cli_alloc_cache_flags(struct nl_sock *sock, + const char *name, unsigned int flags, + int (*ac)(struct nl_sock *, struct nl_cache **, + unsigned int)) +{ + struct nl_cache *cache; + int err; + + if ((err = ac(sock, &cache, flags)) < 0) + nl_cli_fatal(err, "Unable to allocate %s cache: %s", + name, nl_geterror(err)); + + nl_cache_mngt_provide(cache); + + 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()); +#ifdef HAVE_DLFCN_H + { + void *handle; + + handle = dlopen(path, RTLD_NOW); + if (!handle) { + nl_cli_fatal(ENOENT, "Unable to load module \"%s\": %s\n", + path, dlerror()); + } + /* We intentionally leak the dlopen handle. */ + /* coverity[RESOURCE_LEAK] */ + } +#else + nl_cli_fatal(ENOTSUP, "Unable to load module \"%s\": built without dynamic libraries support\n", + path); +#endif } /** @} */ diff --git a/src/nf-ct-add.c b/src/nf-ct-add.c new file mode 100644 index 0000000..cefa837 --- /dev/null +++ b/src/nf-ct-add.c @@ -0,0 +1,140 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2003-2009 Thomas Graf + * Copyright (c) 2007 Philip Craig + * Copyright (c) 2007 Secure Computing Corporation + */ + +#include "nl-default.h" + +#include + +#include +#include + +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-ct-events.c b/src/nf-ct-events.c new file mode 100644 index 0000000..cd69045 --- /dev/null +++ b/src/nf-ct-events.c @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2018 Avast software + */ + +#include "nl-default.h" + +#include +#include +#include + +#include +#include + +struct private_nl_object +{ + int ce_refcnt; + struct nl_object_ops * ce_ops; + struct nl_cache * ce_cache; + struct nl_list_head ce_list; + int ce_msgtype; + int ce_flags; + uint64_t ce_mask; +}; + +static void nf_conntrack_parse_callback(struct nl_object *obj, void *opaque) +{ + struct nl_dump_params params = { + .dp_fd = stdout, + .dp_type = NL_DUMP_DETAILS, + }; + + nl_object_dump(obj, ¶ms); +} + +static int nf_conntrack_event_callback(struct nl_msg *msg, void *opaque) +{ + int err; + struct nlmsghdr *hdr = nlmsg_hdr(msg); + + enum cntl_msg_types type = (enum cntl_msg_types) NFNL_MSG_TYPE(hdr->nlmsg_type); + + int flags = hdr->nlmsg_flags; + + if (type == IPCTNL_MSG_CT_DELETE) { + printf("DELETE "); + } else if (type == IPCTNL_MSG_CT_NEW) { + if (flags & (NLM_F_CREATE|NLM_F_EXCL)) { + printf("NEW "); + } else { + printf("UPDATE "); + } + } else { + printf("UNKNOWN "); + } + + if ((err = nl_msg_parse(msg, &nf_conntrack_parse_callback, opaque)) < 0) { + nl_cli_fatal(err, "nl_msg_parse: %s", nl_geterror(err)); + } + /* Continue with next event */ + return NL_OK; +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *socket; + int err; + + socket = nl_cli_alloc_socket(); + if (socket == NULL) { + nl_cli_fatal(ENOBUFS, "Unable to allocate netlink socket"); + } + + /* + * Disable sequence number checking. + * This is required to allow messages to be processed which were not requested by + * a preceding request message, e.g. netlink events. + */ + nl_socket_disable_seq_check(socket); + + /* subscribe conntrack events */ + nl_join_groups(socket, NF_NETLINK_CONNTRACK_NEW | + NF_NETLINK_CONNTRACK_UPDATE | + NF_NETLINK_CONNTRACK_DESTROY | + NF_NETLINK_CONNTRACK_EXP_NEW | + NF_NETLINK_CONNTRACK_EXP_UPDATE | + NF_NETLINK_CONNTRACK_EXP_DESTROY); + + nl_cli_connect(socket, NETLINK_NETFILTER); + + nl_socket_modify_cb(socket, NL_CB_VALID, NL_CB_CUSTOM, &nf_conntrack_event_callback, 0); + + while (1) { + + errno = 0; + if ((err = nl_recvmsgs_default(socket)) < 0) { + switch (errno) { + case ENOBUFS: + // just print warning + fprintf(stderr, "Lost events because of ENOBUFS\n"); + break; + case EAGAIN: + case EINTR: + // continue reading + break; + default: + nl_cli_fatal(err, "Failed to receive: %s", nl_geterror(err)); + } + } + } +} diff --git a/src/nf-ct-list.c b/src/nf-ct-list.c index 5f72998..3b34572 100644 --- a/src/nf-ct-list.c +++ b/src/nf-ct-list.c @@ -1,16 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * 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 * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation */ +#include "nl-default.h" + +#include + #include #include @@ -54,9 +52,9 @@ int main(int argc, char *argv[]) .dp_type = NL_DUMP_LINE, .dp_fd = stdout, }; - - ct = nl_cli_ct_alloc(); - + + ct = nl_cli_ct_alloc(); + for (;;) { int c, optidx = 0; enum { @@ -95,7 +93,7 @@ int main(int argc, char *argv[]) { "refcnt", 1, 0, ARG_REFCNT }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "46f:hvi:p:F:", long_opts, &optidx); if (c == -1) break; @@ -124,7 +122,7 @@ int main(int argc, char *argv[]) case ARG_REFCNT: nl_cli_ct_parse_use(ct, optarg); break; case ARG_FLAGS: nl_cli_ct_parse_status(ct, optarg); break; } - } + } sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_NETFILTER); diff --git a/src/nf-exp-add.c b/src/nf-exp-add.c index 4b7f9d9..68f0898 100644 --- a/src/nf-exp-add.c +++ b/src/nf-exp-add.c @@ -1,18 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * 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 * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation * Copyright (c) 2012 Rich Fought - * */ +#include "nl-default.h" + +#include + #include #include @@ -64,8 +61,8 @@ int main(int argc, char *argv[]) }; int err, nlflags = NLM_F_CREATE; - exp = nl_cli_exp_alloc(); - + exp = nl_cli_exp_alloc(); + for (;;) { int c, optidx = 0; enum { @@ -86,12 +83,12 @@ int main(int argc, char *argv[]) ARG_MASK_SPORT, ARG_MASK_DST, ARG_MASK_DPORT, - ARG_NAT_PROTO, - ARG_NAT_SRC, - ARG_NAT_SPORT, - ARG_NAT_DST, - ARG_NAT_DPORT, - ARG_NAT_DIR, + ARG_NAT_PROTO, + ARG_NAT_SRC, + ARG_NAT_SPORT, + ARG_NAT_DST, + ARG_NAT_DPORT, + ARG_NAT_DIR, ARG_TIMEOUT, ARG_HELPER_NAME, ARG_REPLACE, @@ -118,19 +115,19 @@ int main(int argc, char *argv[]) { "mask-sport", 1, 0, ARG_MASK_SPORT }, { "mask-dst", 1, 0, ARG_MASK_DST }, { "mask-dport", 1, 0, ARG_MASK_DPORT }, - { "nat-proto", 1, 0, ARG_NAT_PROTO }, - { "nat-src", 1, 0, ARG_NAT_SRC }, - { "nat-sport", 1, 0, ARG_NAT_SPORT }, - { "nat-dst", 1, 0, ARG_NAT_DST }, - { "nat-dport", 1, 0, ARG_NAT_DPORT }, - { "nat-dir", 1, 0, ARG_NAT_DIR }, + { "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; @@ -159,18 +156,18 @@ int main(int argc, char *argv[]) case ARG_MASK_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; case ARG_MASK_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASK, optarg); break; case ARG_MASK_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; - case ARG_NAT_PROTO: nl_cli_exp_parse_l4protonum(exp, NFNL_EXP_TUPLE_NAT, optarg); break; - case ARG_NAT_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_NAT, optarg); break; - case ARG_NAT_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_NAT, optarg); break; - case ARG_NAT_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_NAT, optarg); break; - case ARG_NAT_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_NAT, optarg); break; - case ARG_NAT_DIR: nl_cli_exp_parse_nat_dir(exp, optarg); break; + case 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); diff --git a/src/nf-exp-delete.c b/src/nf-exp-delete.c index 2ec45ae..a57a69d 100644 --- a/src/nf-exp-delete.c +++ b/src/nf-exp-delete.c @@ -1,17 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nf-exp-delete.c Delete an expectation - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2009 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation * Copyright (c) 2012 Rich Fought */ +#include "nl-default.h" + +#include + #include #include @@ -63,8 +61,8 @@ int main(int argc, char *argv[]) }; int err, nlflags = 0; - exp = nl_cli_exp_alloc(); - + exp = nl_cli_exp_alloc(); + for (;;) { int c, optidx = 0; enum { @@ -80,17 +78,17 @@ int main(int argc, char *argv[]) ARG_MASTER_SPORT, ARG_MASTER_DST, ARG_MASTER_DPORT, - ARG_MASK_PROTO, - ARG_MASK_SRC, + ARG_MASK_PROTO, + ARG_MASK_SRC, ARG_MASK_SPORT, ARG_MASK_DST, ARG_MASK_DPORT, ARG_TIMEOUT, - ARG_HELPER_NAME, + ARG_HELPER_NAME, ARG_FLAGS, }; static struct option long_opts[] = { - { "quiet", 0, 0, 'q' }, + { "quiet", 0, 0, 'q' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "id", 1, 0, 'i' }, @@ -105,17 +103,17 @@ int main(int argc, char *argv[]) { "master-dst", 1, 0, ARG_MASTER_DST }, { "master-dport", 1, 0, ARG_MASTER_DPORT }, { "mask-proto", 1, 0, ARG_MASK_PROTO }, - { "mask-src", 1, 0, ARG_MASK_SRC }, - { "mask-sport", 1, 0, ARG_MASK_SPORT }, - { "mask-dst", 1, 0, ARG_MASK_DST }, - { "mask-dport", 1, 0, ARG_MASK_DPORT }, + { "mask-src", 1, 0, ARG_MASK_SRC }, + { "mask-sport", 1, 0, ARG_MASK_SPORT }, + { "mask-dst", 1, 0, ARG_MASK_DST }, + { "mask-dport", 1, 0, ARG_MASK_DPORT }, { "family", 1, 0, 'F' }, { "timeout", 1, 0, ARG_TIMEOUT }, { "helper", 1, 0, ARG_HELPER_NAME }, - { "flags", 1, 0, ARG_FLAGS}, + { "flags", 1, 0, ARG_FLAGS}, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "46f:hvi:p:F:", long_opts, &optidx); if (c == -1) break; @@ -142,13 +140,13 @@ int main(int argc, char *argv[]) case ARG_MASK_SRC: nl_cli_exp_parse_src(exp, NFNL_EXP_TUPLE_MASK, optarg); break; case ARG_MASK_SPORT: nl_cli_exp_parse_src_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; case ARG_MASK_DST: nl_cli_exp_parse_dst(exp, NFNL_EXP_TUPLE_MASK, optarg); break; - case ARG_MASK_DPORT: nl_cli_exp_parse_dst_port(exp, NFNL_EXP_TUPLE_MASK, optarg); break; + case ARG_MASK_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); diff --git a/src/nf-exp-list.c b/src/nf-exp-list.c index 1c6ec69..f469fea 100644 --- a/src/nf-exp-list.c +++ b/src/nf-exp-list.c @@ -1,17 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * 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 * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation * Copyright (c) 2012 Rich Fought */ +#include "nl-default.h" + +#include + #include #include @@ -54,9 +52,9 @@ int main(int argc, char *argv[]) .dp_type = NL_DUMP_LINE, .dp_fd = stdout, }; - - exp = nl_cli_exp_alloc(); - + + exp = nl_cli_exp_alloc(); + for (;;) { int c, optidx = 0; enum { @@ -73,7 +71,7 @@ int main(int argc, char *argv[]) ARG_MASTER_DST, ARG_MASTER_DPORT, ARG_TIMEOUT, - ARG_HELPER_NAME, + ARG_HELPER_NAME, ARG_FLAGS, }; static struct option long_opts[] = { @@ -97,7 +95,7 @@ int main(int argc, char *argv[]) { "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; @@ -125,7 +123,7 @@ int main(int argc, char *argv[]) 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); diff --git a/src/nf-log.c b/src/nf-log.c index 913ba16..17f73a8 100644 --- a/src/nf-log.c +++ b/src/nf-log.c @@ -1,19 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nf-log.c Monitor netfilter log events - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation */ +#include "nl-default.h" + +#include +#include + #include #include -#include #include #include @@ -52,9 +50,8 @@ int main(int argc, char *argv[]) { struct nl_sock *nf_sock; struct nl_sock *rt_sock; - struct nl_cache *link_cache; struct nfnl_log *log; - enum nfnl_log_copy_mode copy_mode; + int copy_mode; uint32_t copy_range; int err; int family; @@ -116,7 +113,7 @@ int main(int argc, char *argv[]) rt_sock = nl_cli_alloc_socket(); nl_cli_connect(rt_sock, NETLINK_ROUTE); - link_cache = nl_cli_link_alloc_cache(rt_sock); + nl_cli_link_alloc_cache(rt_sock); while (1) { fd_set rfds; diff --git a/src/nf-monitor.c b/src/nf-monitor.c index fe99af4..21f8edd 100644 --- a/src/nf-monitor.c +++ b/src/nf-monitor.c @@ -1,16 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nf-monitor.c Monitor netfilter events - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf * Copyright (c) 2007 Philip Craig * Copyright (c) 2007 Secure Computing Corporation */ +#include "nl-default.h" + +#include +#include + #include #include diff --git a/src/nf-queue.c b/src/nf-queue.c index 922d9c8..38f20ad 100644 --- a/src/nf-queue.c +++ b/src/nf-queue.c @@ -1,21 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nf-queue.c Monitor netfilter queue events - * - * 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) 2007, 2008 Patrick McHardy * Copyright (c) 2010 Karl Hiramoto */ +#include "nl-default.h" -#include -#include -#include #include #include +#include + +#include +#include #include #include #include @@ -60,9 +56,8 @@ static int event_input(struct nl_msg *msg, void *arg) int main(int argc, char *argv[]) { struct nl_sock *rt_sock; - struct nl_cache *link_cache; struct nfnl_queue *queue; - enum nfnl_queue_copy_mode copy_mode; + int copy_mode; uint32_t copy_range; int err = 1; int family; @@ -116,7 +111,7 @@ int main(int argc, char *argv[]) rt_sock = nl_cli_alloc_socket(); nl_cli_connect(rt_sock, NETLINK_ROUTE); - link_cache = nl_cli_link_alloc_cache(rt_sock); + nl_cli_link_alloc_cache(rt_sock); nl_socket_set_buffer_size(nf_sock, 1024*127, 1024*127); diff --git a/src/nl-addr-add.c b/src/nl-addr-add.c index 52995ec..3b73cb2 100644 --- a/src/nl-addr-add.c +++ b/src/nl-addr-add.c @@ -1,13 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-addr-add.c Add addresses - * - * 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) 2003-2009 Thomas Graf */ +#include "nl-default.h" + +#include + #include #include #include @@ -50,12 +49,12 @@ int main(int argc, char *argv[]) .dp_fd = stdout, }; int err, nlflags = NLM_F_CREATE; - + sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_ROUTE); link_cache = nl_cli_link_alloc_cache(sock); - addr = nl_cli_addr_alloc(); - + addr = nl_cli_addr_alloc(); + for (;;) { int c, optidx = 0; enum { @@ -84,7 +83,7 @@ int main(int argc, char *argv[]) { "valid", 1, 0, ARG_VALID }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "qhva:d:", long_opts, &optidx); if (c == -1) break; @@ -105,7 +104,7 @@ int main(int argc, char *argv[]) case ARG_PREFERRED: nl_cli_addr_parse_preferred(addr, optarg); break; case ARG_VALID: nl_cli_addr_parse_valid(addr, optarg); break; } - } + } if ((err = rtnl_addr_add(sock, addr, nlflags)) < 0) nl_cli_fatal(err, "Unable to add address: %s", @@ -114,7 +113,7 @@ int main(int argc, char *argv[]) if (!quiet) { printf("Added "); nl_object_dump(OBJ_CAST(addr), &dp); - } + } return 0; } diff --git a/src/nl-addr-delete.c b/src/nl-addr-delete.c index 2849c01..58dd439 100644 --- a/src/nl-addr-delete.c +++ b/src/nl-addr-delete.c @@ -1,13 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-addr-delete.c Delete addresses - * - * 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) 2003-2009 Thomas Graf */ +#include "nl-default.h" + +#include + #include #include #include @@ -108,7 +107,7 @@ int main(int argc, char *argv[]) { "valid", 1, 0, ARG_VALID }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "iqhva:d:", long_opts, &optidx); if (c == -1) break; @@ -129,7 +128,7 @@ int main(int argc, char *argv[]) case ARG_PREFERRED: nl_cli_addr_parse_preferred(addr, optarg); break; case ARG_VALID: nl_cli_addr_parse_valid(addr, optarg); break; } - } + } nl_cache_foreach_filter(addr_cache, OBJ_CAST(addr), delete_cb, NULL); diff --git a/src/nl-addr-list.c b/src/nl-addr-list.c index 20995a8..00df1aa 100644 --- a/src/nl-addr-list.c +++ b/src/nl-addr-list.c @@ -1,13 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-addr-list.c List addresses - * - * 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) 2003-2009 Thomas Graf */ +#include "nl-default.h" + +#include + #include #include #include diff --git a/src/nl-class-add.c b/src/nl-class-add.c index b9a17dc..ac37daa 100644 --- a/src/nl-class-add.c +++ b/src/nl-class-add.c @@ -1,21 +1,19 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * 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 */ +#include "nl-default.h" + +#include + #include #include #include #include #include -#include +#include "nl-priv-dynamic-route/nl-priv-dynamic-route.h" static int quiet = 0; @@ -62,15 +60,15 @@ int main(int argc, char *argv[]) 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(); + class = nl_cli_class_alloc(); tc = (struct rtnl_tc *) class; - + for (;;) { int c, optidx = 0; enum { @@ -96,7 +94,7 @@ int main(int argc, char *argv[]) { "linktype", 1, 0, ARG_LINKTYPE }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "+qhvd:p:i:", long_opts, &optidx); if (c == -1) @@ -116,7 +114,7 @@ int main(int argc, char *argv[]) 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(); @@ -146,7 +144,7 @@ int main(int argc, char *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)); diff --git a/src/nl-class-delete.c b/src/nl-class-delete.c index 37657a4..88dc59e 100644 --- a/src/nl-class-delete.c +++ b/src/nl-class-delete.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * 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 */ +#include "nl-default.h" + +#include + #include #include #include @@ -70,13 +68,13 @@ 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(); + class = nl_cli_class_alloc(); tc = (struct rtnl_tc *) class; - + for (;;) { int c, optidx = 0; enum { @@ -95,7 +93,7 @@ int main(int argc, char *argv[]) { "kind", 1, 0, 'k' }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "qhvd:p:i:k:", long_opts, &optidx); if (c == -1) break; @@ -112,7 +110,7 @@ int main(int argc, char *argv[]) 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)"); diff --git a/src/nl-class-list.c b/src/nl-class-list.c index c2423fb..8b5cd6c 100644 --- a/src/nl-class-list.c +++ b/src/nl-class-list.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * 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 */ +#include "nl-default.h" + +#include + #include #include #include @@ -65,15 +63,15 @@ int main(int argc, char *argv[]) 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(); + class = nl_cli_class_alloc(); tc = (struct rtnl_tc *) class; params.dp_fd = stdout; - + for (;;) { int c, optidx = 0; enum { @@ -91,7 +89,7 @@ int main(int argc, char *argv[]) { "kind", 1, 0, 'k' }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "hvd:p:i:k:", long_opts, &optidx); if (c == -1) break; @@ -106,11 +104,11 @@ int main(int argc, char *argv[]) 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 + 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 index 1d45d0b..397fcb4 100644 --- a/src/nl-classid-lookup.c +++ b/src/nl-classid-lookup.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * 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 */ +#include "nl-default.h" + +#include + #include static void print_usage(void) @@ -48,7 +46,7 @@ int main(int argc, char *argv[]) { "raw", 0, 0, ARG_RAW }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "hvr", long_opts, &optidx); if (c == -1) break; @@ -59,7 +57,7 @@ int main(int argc, char *argv[]) case 'r': reverse = 1; break; case ARG_RAW: raw = 1; break; } - } + } if (optind >= argc) print_usage(); diff --git a/src/nl-cls-add.c b/src/nl-cls-add.c index 6acb320..b583872 100644 --- a/src/nl-cls-add.c +++ b/src/nl-cls-add.c @@ -1,19 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-cls-add.c Add 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) 2003-2011 Thomas Graf */ +#include "nl-default.h" + +#include + #include #include #include #include -#include +#include "nl-priv-dynamic-route/nl-priv-dynamic-route.h" static int quiet = 0; @@ -31,7 +30,7 @@ static void print_usage(void) " -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" +" --proto=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" @@ -62,15 +61,15 @@ int main(int argc, char *argv[]) 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); - cls = nl_cli_cls_alloc(); + cls = nl_cli_cls_alloc(); tc = (struct rtnl_tc *) cls; - + for (;;) { int c, optidx = 0; enum { @@ -100,7 +99,7 @@ int main(int argc, char *argv[]) { "linktype", 1, 0, ARG_LINKTYPE }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "+qhvd:p:i:", long_opts, &optidx); if (c == -1) @@ -112,7 +111,7 @@ int main(int argc, char *argv[]) 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 'i': free(id); 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; @@ -124,7 +123,7 @@ int main(int argc, char *argv[]) rtnl_cls_set_prio(cls, nl_cli_parse_u32(optarg)); break; } - } + } if (optind >= argc) print_usage(); @@ -154,7 +153,7 @@ int main(int argc, char *argv[]) if (!quiet) { 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)); diff --git a/src/nl-cls-delete.c b/src/nl-cls-delete.c index 2b3db1f..ca8e370 100644 --- a/src/nl-cls-delete.c +++ b/src/nl-cls-delete.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-cls-delete.c Delete Classifier - * - * 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-2010 Thomas Graf */ +#include "nl-default.h" + +#include + #include #include #include @@ -32,7 +30,7 @@ static void print_usage(void) " -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" +" --proto=PROTO Protocol to match (default: all)\n" " --prio=PRIO Priority (default: 0)\n" "\n" "EXAMPLE\n" @@ -91,13 +89,13 @@ int main(int argc, char *argv[]) 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(); + cls = nl_cli_cls_alloc(); tc = (struct rtnl_tc *) cls; - + for (;;) { int c, optidx = 0; enum { @@ -120,7 +118,7 @@ int main(int argc, char *argv[]) { "prio", 1, 0, ARG_PRIO }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "qhvd:p:i:k:", long_opts, &optidx); if (c == -1) break; @@ -141,11 +139,11 @@ int main(int argc, char *argv[]) rtnl_cls_set_prio(cls, nl_cli_parse_u32(optarg)); break; } - } + } if ((ifindex = rtnl_tc_get_ifindex(tc))) __delete_link(ifindex, cls); - else + else nl_cache_foreach(link_cache, delete_link, cls); if (!quiet) diff --git a/src/nl-cls-list.c b/src/nl-cls-list.c index 5072585..5a4e638 100644 --- a/src/nl-cls-list.c +++ b/src/nl-cls-list.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-cls-list.c List classifiers - * - * 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-2010 Thomas Graf */ +#include "nl-default.h" + +#include + #include #include #include @@ -35,7 +33,7 @@ static void print_usage(void) " -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" +" --proto=PROTO Protocol to match (default: all)\n" " --prio=PRIO Priority (default: 0)\n" "\n" "EXAMPLE\n" @@ -69,15 +67,15 @@ int main(int argc, char *argv[]) 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(); + cls = nl_cli_cls_alloc(); tc = (struct rtnl_tc *) cls; params.dp_fd = stdout; - + for (;;) { int c, optidx = 0; enum { @@ -99,7 +97,7 @@ int main(int argc, char *argv[]) { "prio", 1, 0, ARG_PRIO }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "hvd:p:i:k:", long_opts, &optidx); if (c == -1) break; @@ -118,11 +116,11 @@ int main(int argc, char *argv[]) rtnl_cls_set_prio(cls, nl_cli_parse_u32(optarg)); break; } - } + } if ((ifindex = rtnl_tc_get_ifindex(tc))) __dump_link(ifindex, cls); - else + else nl_cache_foreach(link_cache, dump_link, cls); return 0; diff --git a/src/nl-fib-lookup.c b/src/nl-fib-lookup.c index 705cf32..a1470c7 100644 --- a/src/nl-fib-lookup.c +++ b/src/nl-fib-lookup.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-fib-lookup.c FIB Route Lookup - * - * 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 */ +#include "nl-default.h" + +#include + #include static void print_usage(void) diff --git a/src/nl-link-enslave.c b/src/nl-link-enslave.c index 2b5d47d..5c6dc02 100644 --- a/src/nl-link-enslave.c +++ b/src/nl-link-enslave.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-link-enslave.c Enslave a link - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2011 Thomas Graf */ +#include "nl-default.h" + +#include + #include #include #include diff --git a/src/nl-link-ifindex2name.c b/src/nl-link-ifindex2name.c index 68e5158..200c9f2 100644 --- a/src/nl-link-ifindex2name.c +++ b/src/nl-link-ifindex2name.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-link-ifindex2name.c Transform a interface index to its name - * - * 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 */ +#include "nl-default.h" + +#include + #include #include diff --git a/src/nl-link-list.c b/src/nl-link-list.c index b5c98b4..aec96cb 100644 --- a/src/nl-link-list.c +++ b/src/nl-link-list.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-link-dump.c Dump link 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-2010 Thomas Graf */ +#include "nl-default.h" + +#include + #include #include diff --git a/src/nl-link-name2ifindex.c b/src/nl-link-name2ifindex.c index b8ae4bc..e35ee27 100644 --- a/src/nl-link-name2ifindex.c +++ b/src/nl-link-name2ifindex.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-link-name2ifindex.c Transform a interface name to its index - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2008 Thomas Graf */ +#include "nl-default.h" + +#include + #include #include diff --git a/src/nl-link-release.c b/src/nl-link-release.c index 4c9f15a..9d04413 100644 --- a/src/nl-link-release.c +++ b/src/nl-link-release.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-link-release.c release a link - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2011 Thomas Graf */ +#include "nl-default.h" + +#include + #include #include #include diff --git a/src/nl-link-set.c b/src/nl-link-set.c index 3178a98..c301542 100644 --- a/src/nl-link-set.c +++ b/src/nl-link-set.c @@ -1,14 +1,13 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-link-set.c Set link 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-2010 Thomas Graf */ +#include "nl-default.h" + +#include +#include + #include #include @@ -42,6 +41,7 @@ static void print_usage(void) " --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); } @@ -56,7 +56,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)); @@ -86,6 +86,7 @@ int main(int argc, char *argv[]) ARG_TXQLEN, ARG_WEIGHT, ARG_IFALIAS, + ARG_STATE, }; static struct option long_opts[] = { { "quiet", 0, 0, 'q' }, @@ -98,6 +99,7 @@ int main(int argc, char *argv[]) { "txqlen", 1, 0, ARG_TXQLEN }, { "weight", 1, 0, ARG_WEIGHT }, { "ifalias", 1, 0, ARG_IFALIAS }, + { "state", 1, 0, ARG_STATE }, { 0, 0, 0, 0 } }; @@ -116,6 +118,12 @@ int main(int argc, char *argv[]) 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-link-stats.c b/src/nl-link-stats.c index 4dfca86..07e5e1c 100644 --- a/src/nl-link-stats.c +++ b/src/nl-link-stats.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-link-stats.c Retrieve link statistics - * - * 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 */ +#include "nl-default.h" + +#include + #include #include @@ -34,7 +32,7 @@ static void list_stat_names(void) char buf[64]; int i; - for (i = 0; i < RTNL_LINK_STATS_MAX; i++) + for (i = 0; i <= RTNL_LINK_STATS_MAX; i++) printf("%s\n", rtnl_link_stat2str(i, buf, sizeof(buf))); exit(0); @@ -59,7 +57,7 @@ static void dump_stats(struct nl_object *obj, void *arg) if (optind >= gargc) { int i; - for (i = 0; i < RTNL_LINK_STATS_MAX; i++) + for (i = 0; i <= RTNL_LINK_STATS_MAX; i++) dump_stat(link, i); } else { while (optind < gargc) { diff --git a/src/nl-list-caches.c b/src/nl-list-caches.c index 853d8a4..4c2564a 100644 --- a/src/nl-list-caches.c +++ b/src/nl-list-caches.c @@ -1,17 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * nl-list-caches.c List registered cache types - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2009 Thomas Graf */ -#include +#include "nl-default.h" + #include +#include "nl-priv-dynamic-core/object-api.h" +#include "nl-priv-dynamic-core/cache-api.h" + static void print_usage(void) { fprintf(stderr, "Usage: nl-list-caches\n"); diff --git a/src/nl-list-sockets.c b/src/nl-list-sockets.c index c2fa1cd..bb27df0 100644 --- a/src/nl-list-sockets.c +++ b/src/nl-list-sockets.c @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * nl-list-sockets.c Pretty-print /proc/net/netlink - * - * 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 */ +#include "nl-default.h" + #include #define PROC_NETLINK "/proc/net/netlink" @@ -18,7 +14,7 @@ int main(int argc, char *argv[]) FILE *fd; char buf[2048], p[64]; - fd = fopen(PROC_NETLINK, "r"); + fd = fopen(PROC_NETLINK, "re"); if (fd == NULL) { perror("fopen"); return -1; diff --git a/src/nl-monitor.c b/src/nl-monitor.c index fdf6497..60a02d2 100644 --- a/src/nl-monitor.c +++ b/src/nl-monitor.c @@ -1,82 +1,120 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-monitor.c Monitor events - * - * 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 */ +#include "nl-default.h" + +#include + #include #include +#include + +static const struct { + enum rtnetlink_groups gr_id; + const char* gr_name; +} known_groups[] = { + { RTNLGRP_LINK, "link" }, + { RTNLGRP_NOTIFY, "notify" }, + { RTNLGRP_NEIGH, "neigh" }, + { RTNLGRP_TC, "tc" }, + { RTNLGRP_IPV4_IFADDR, "ipv4-ifaddr" }, + { RTNLGRP_IPV4_MROUTE, "ipv4-mroute" }, + { RTNLGRP_IPV4_ROUTE, "ipv4-route" }, + { RTNLGRP_IPV6_IFADDR, "ipv6-ifaddr" }, + { RTNLGRP_IPV6_MROUTE, "ipv6-mroute" }, + { RTNLGRP_IPV6_ROUTE, "ipv6-route" }, + { RTNLGRP_IPV6_IFINFO, "ipv6-ifinfo" }, + { RTNLGRP_DECnet_IFADDR, "decnet-ifaddr" }, + { RTNLGRP_DECnet_ROUTE, "decnet-route" }, + { RTNLGRP_IPV6_PREFIX, "ipv6-prefix" }, + { RTNLGRP_IPV4_NETCONF, "ipv4-netconf" }, + { RTNLGRP_IPV6_NETCONF, "ipv6-netconf" }, + { RTNLGRP_MPLS_NETCONF, "mpls-netconf" }, + { RTNLGRP_MDB, "mdb" }, + { RTNLGRP_NONE, NULL } +}; static void obj_input(struct nl_object *obj, void *arg) { - struct nl_dump_params dp = { - .dp_type = NL_DUMP_STATS, - .dp_fd = stdout, - .dp_dump_msgtype = 1, - }; - - nl_object_dump(obj, &dp); + nl_object_dump(obj, arg); } static int event_input(struct nl_msg *msg, void *arg) { - if (nl_msg_parse(msg, &obj_input, NULL) < 0) + if (nl_msg_parse(msg, &obj_input, arg) < 0) fprintf(stderr, "<> Unknown message type\n"); /* Exit nl_recvmsgs_def() and return to the main select() */ return NL_STOP; } +static void print_usage(void) +{ + int i; + + printf( + "Usage: nl-monitor [OPTION] []\n" + "\n" + "Options\n" + " -d, --debug=LEVEL Set libnl debug level { 0 - 7 }\n" + " -f, --format=TYPE Output format { brief | details | stats }\n" + " -h, --help Show this help.\n" + "\n" + ); + printf("Known groups:"); + for (i = 0; known_groups[i].gr_id != RTNLGRP_NONE; i++) + printf(" %s", known_groups[i].gr_name); + printf("\n"); + exit(0); +} + int main(int argc, char *argv[]) { + struct nl_dump_params dp = { + .dp_type = NL_DUMP_STATS, + .dp_fd = stdout, + .dp_dump_msgtype = 1, + }; + struct nl_sock *sock; - struct nl_cache *link_cache; int err = 1; int i, idx; - static const struct { - enum rtnetlink_groups gr_id; - const char* gr_name; - } known_groups[] = { - { RTNLGRP_LINK, "link" }, - { RTNLGRP_NOTIFY, "notify" }, - { RTNLGRP_NEIGH, "neigh" }, - { RTNLGRP_TC, "tc" }, - { RTNLGRP_IPV4_IFADDR, "ipv4-ifaddr" }, - { RTNLGRP_IPV4_MROUTE, "ipv4-mroute" }, - { RTNLGRP_IPV4_ROUTE, "ipv4-route" }, - { RTNLGRP_IPV6_IFADDR, "ipv6-ifaddr" }, - { RTNLGRP_IPV6_MROUTE, "ipv6-mroute" }, - { RTNLGRP_IPV6_ROUTE, "ipv6-route" }, - { RTNLGRP_IPV6_IFINFO, "ipv6-ifinfo" }, - { RTNLGRP_DECnet_IFADDR, "decnet-ifaddr" }, - { RTNLGRP_DECnet_ROUTE, "decnet-route" }, - { RTNLGRP_IPV6_PREFIX, "ipv6-prefix" }, - { RTNLGRP_NONE, NULL } - }; - sock = nl_cli_alloc_socket(); nl_socket_disable_seq_check(sock); - nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL); - - if (argc > 1 && !strcasecmp(argv[1], "-h")) { - printf("Usage: nl-monitor []\n"); - - printf("Known groups:"); - for (i = 0; known_groups[i].gr_id != RTNLGRP_NONE; i++) - printf(" %s", known_groups[i].gr_name); - printf("\n"); - return 2; + nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, event_input, &dp); + + for (;;) { + int c, optidx = 0; + static struct option long_opts[] = { + { "debug", 1, 0, 'd' }, + { "format", 1, 0, 'f' }, + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "d:f:h", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'd': + nl_debug = atoi(optarg); + break; + case 'f': + dp.dp_type = nl_cli_parse_dumptype(optarg); + break; + default: + print_usage(); + break; + } } nl_cli_connect(sock, NETLINK_ROUTE); - for (idx = 1; argc > idx; idx++) { + for (idx = optind; argc > idx; idx++) { for (i = 0; known_groups[i].gr_id != RTNLGRP_NONE; i++) { if (!strcmp(argv[idx], known_groups[i].gr_name)) { @@ -92,7 +130,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "Warning: Unknown group: %s\n", argv[idx]); } - link_cache = nl_cli_link_alloc_cache(sock); + nl_cli_link_alloc_cache(sock); while (1) { fd_set rfds; diff --git a/src/nl-neigh-add.c b/src/nl-neigh-add.c index 4cddabe..d4d926d 100644 --- a/src/nl-neigh-add.c +++ b/src/nl-neigh-add.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/ nl-neigh-add.c Add a neighbour - * - * 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 */ +#include "nl-default.h" + +#include + #include #include #include @@ -51,12 +49,12 @@ int main(int argc, char *argv[]) .dp_fd = stdout, }; int err, ok = 0, nlflags = NLM_F_REPLACE | NLM_F_CREATE; - + sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_ROUTE); link_cache = nl_cli_link_alloc_cache(sock); - neigh = nl_cli_neigh_alloc(); - + neigh = nl_cli_neigh_alloc(); + for (;;) { int c, optidx = 0; enum { @@ -76,7 +74,7 @@ int main(int argc, char *argv[]) { "state", 1, 0, ARG_STATE }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "qhva:l:d:", long_opts, &optidx); if (c == -1) break; @@ -92,7 +90,7 @@ int main(int argc, char *argv[]) case 'd': nl_cli_neigh_parse_dev(neigh, link_cache, optarg); break; case ARG_STATE: nl_cli_neigh_parse_state(neigh, optarg); break; } - } + } if (!ok) print_usage(); @@ -104,7 +102,7 @@ int main(int argc, char *argv[]) if (!quiet) { printf("Added "); nl_object_dump(OBJ_CAST(neigh), &dp); - } + } return 0; } diff --git a/src/nl-neigh-delete.c b/src/nl-neigh-delete.c index c418608..29effcb 100644 --- a/src/nl-neigh-delete.c +++ b/src/nl-neigh-delete.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-neigh-delete.c Delete a neighbour - * - * 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 */ +#include "nl-default.h" + +#include + #include #include #include @@ -67,13 +65,13 @@ int main(int argc, char *argv[]) { struct rtnl_neigh *neigh; struct nl_cache *link_cache, *neigh_cache; - + sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_ROUTE); link_cache = nl_cli_link_alloc_cache(sock); neigh_cache = nl_cli_neigh_alloc_cache(sock); - neigh = nl_cli_neigh_alloc(); - + neigh = nl_cli_neigh_alloc(); + for (;;) { int c, optidx = 0; enum { @@ -94,7 +92,7 @@ int main(int argc, char *argv[]) { "state", 1, 0, ARG_STATE }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "qhva:l:d:", long_opts, &optidx); if (c == -1) break; @@ -111,7 +109,7 @@ int main(int argc, char *argv[]) case ARG_FAMILY: nl_cli_neigh_parse_family(neigh, optarg); break; case ARG_STATE: nl_cli_neigh_parse_state(neigh, optarg); break; } - } + } nl_cache_foreach_filter(neigh_cache, OBJ_CAST(neigh), delete_cb, NULL); diff --git a/src/nl-neigh-list.c b/src/nl-neigh-list.c index ebf5486..80fce0b 100644 --- a/src/nl-neigh-list.c +++ b/src/nl-neigh-list.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-neigh-list.c List Neighbours - * - * 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 */ +#include "nl-default.h" + +#include + #include #include #include @@ -42,13 +40,13 @@ int main(int argc, char *argv[]) .dp_type = NL_DUMP_LINE, .dp_fd = stdout, }; - + sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_ROUTE); - link_cache = nl_cli_link_alloc_cache(sock); + link_cache = nl_cli_link_alloc_cache_flags(sock, NL_CACHE_AF_ITER); neigh_cache = nl_cli_neigh_alloc_cache(sock); - neigh = nl_cli_neigh_alloc(); - + neigh = nl_cli_neigh_alloc(); + for (;;) { int c, optidx = 0; enum { @@ -66,7 +64,7 @@ int main(int argc, char *argv[]) { "state", 1, 0, ARG_STATE }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "f:hva:l:d:", long_opts, &optidx); if (c == -1) break; @@ -81,9 +79,14 @@ int main(int argc, char *argv[]) case ARG_FAMILY: nl_cli_neigh_parse_family(neigh, optarg); break; case ARG_STATE: nl_cli_neigh_parse_state(neigh, optarg); break; } - } + } nl_cache_dump_filter(neigh_cache, ¶ms, OBJ_CAST(neigh)); + rtnl_neigh_put(neigh); + nl_cache_put(neigh_cache); + nl_cache_put(link_cache); + nl_socket_free(sock); + return 0; } diff --git a/src/nl-neightbl-list.c b/src/nl-neightbl-list.c index 5010b92..596b6ee 100644 --- a/src/nl-neightbl-list.c +++ b/src/nl-neightbl-list.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-neightbl-list.c Dump neighbour tables - * - * 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 */ +#include "nl-default.h" + +#include + #include #include @@ -28,18 +26,18 @@ static void print_usage(void) int main(int argc, char *argv[]) { struct nl_sock *sock; - struct nl_cache *link_cache, *neightbl_cache; + struct nl_cache *neightbl_cache; struct nl_dump_params params = { .dp_type = NL_DUMP_LINE, .dp_fd = stdout, }; - + sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_ROUTE); - link_cache = nl_cli_link_alloc_cache(sock); + nl_cli_link_alloc_cache(sock); neightbl_cache = nl_cli_alloc_cache(sock, "neighbour table", rtnl_neightbl_alloc_cache); - + for (;;) { int c, optidx = 0; static struct option long_opts[] = { @@ -48,7 +46,7 @@ int main(int argc, char *argv[]) { "version", 0, 0, 'v' }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "f:hv", long_opts, &optidx); if (c == -1) break; @@ -58,7 +56,7 @@ int main(int argc, char *argv[]) case 'h': print_usage(); break; case 'v': nl_cli_print_version(); break; } - } + } nl_cache_dump(neightbl_cache, ¶ms); diff --git a/src/nl-nh-list.c b/src/nl-nh-list.c new file mode 100644 index 0000000..18fc5f4 --- /dev/null +++ b/src/nl-nh-list.c @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2022 Stanislav Zaikin + */ + +#include "nl-default.h" + +#include + +#include +#include +#include + +static void print_usage(void) +{ + printf("Usage: nl-nh-list [OPTIONS]... \n" + "\n" + "OPTIONS\n" + " --details Show detailed information of each link\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"); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct nl_cache *link_cache; + struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + + sock = nl_cli_alloc_socket(); + nl_cli_connect(sock, NETLINK_ROUTE); + + for (;;) { + int c, optidx = 0; + enum { + ARG_FAMILY = 257, + ARG_DETAILS, + }; + static struct option long_opts[] = { { "details", 0, 0, + ARG_DETAILS }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "name", 1, 0, 'n' }, + { 0, 0, 0, 0 } }; + + c = getopt_long(argc, argv, "hvn:i:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case ARG_DETAILS: + params.dp_type = NL_DUMP_DETAILS; + break; + case 'h': + print_usage(); + break; + case 'v': + nl_cli_print_version(); + break; + } + } + + link_cache = nl_cli_nh_alloc_cache(sock); + + nl_cache_dump(link_cache, ¶ms); + + return 0; +} diff --git a/src/nl-pktloc-lookup.c b/src/nl-pktloc-lookup.c index 17c867b..90502a3 100644 --- a/src/nl-pktloc-lookup.c +++ b/src/nl-pktloc-lookup.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-pktloc-lookup.c Lookup packet location alias - * - * 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 */ +#include "nl-default.h" + +#include + #include #include @@ -50,8 +48,19 @@ static const char *layer_txt[] = { [TCF_LAYER_TRANSPORT] = "tcp" }; +static const char *get_align_txt(struct rtnl_pktloc *loc, char buf[static 16]) +{ + if (loc->align < _NL_N_ELEMENTS(align_txt)) + return align_txt[loc->align]; + + snprintf(buf, 16, "%u", loc->align); + return buf; +} + static void dump_u32_style(struct rtnl_pktloc *loc, uint32_t value) { + char buf[16]; + if (loc->align > 4) nl_cli_fatal(EINVAL, "u32 only supports alignments u8|u16|u32."); @@ -62,37 +71,35 @@ static void dump_u32_style(struct rtnl_pktloc *loc, uint32_t value) 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; + printf("%s %x %x at %s%u\n", get_align_txt(loc, buf), value, + loc->mask ? loc->mask : + (loc->align < _NL_N_ELEMENTS(align_mask) ? + align_mask[loc->align] : + 0), + loc->layer == TCF_LAYER_TRANSPORT ? "nexthdr+" : "", + loc->offset); } 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); + char buf[16]; + + printf("%s = %s at %s+%u & %#x >> %u\n", loc->name, + get_align_txt(loc, buf), + loc->layer < _NL_N_ELEMENTS(layer_txt) ? 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); + char buf[16]; + + printf("%-26s %-5s %3s+%-4u %#-10x %-8u %u\n", loc->name, + get_align_txt(loc, buf), + loc->layer < _NL_N_ELEMENTS(layer_txt) ? layer_txt[loc->layer] : + "???", + loc->offset, loc->mask, loc->shift, loc->refcnt); } static void do_list(void) @@ -122,7 +129,7 @@ int main(int argc, char *argv[]) { "u32", 1, 0, ARG_U32 }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "hvl", long_opts, &optidx); if (c == -1) break; @@ -136,7 +143,7 @@ int main(int argc, char *argv[]) uvalue = nl_cli_parse_u32(optarg); break; } - } + } if (optind >= argc) print_usage(); diff --git a/src/nl-qdisc-add.c b/src/nl-qdisc-add.c index c2a7c9f..40b9546 100644 --- a/src/nl-qdisc-add.c +++ b/src/nl-qdisc-add.c @@ -1,20 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * 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 */ +#include "nl-default.h" + +#include + #include #include #include #include -#include +#include "nl-priv-dynamic-route/nl-priv-dynamic-route.h" static int quiet = 0; @@ -59,15 +57,15 @@ int main(int argc, char *argv[]) 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(); + qdisc = nl_cli_qdisc_alloc(); tc = (struct rtnl_tc *) qdisc; - + for (;;) { int c, optidx = 0; enum { @@ -89,7 +87,7 @@ int main(int argc, char *argv[]) { "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) @@ -107,7 +105,7 @@ int main(int argc, char *argv[]) case ARG_UPDATE_ONLY: flags = 0; break; case ARG_REPLACE_ONLY: flags = NLM_F_REPLACE; break; } - } + } if (optind >= argc) print_usage(); @@ -137,7 +135,7 @@ int main(int argc, char *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)); diff --git a/src/nl-qdisc-delete.c b/src/nl-qdisc-delete.c index 2f945bb..8c89372 100644 --- a/src/nl-qdisc-delete.c +++ b/src/nl-qdisc-delete.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-qdisc-delete.c Delete Queuing 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-2010 Thomas Graf */ +#include "nl-default.h" + +#include + #include #include #include @@ -71,14 +69,14 @@ int main(int argc, char *argv[]) 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(); + qdisc = nl_cli_qdisc_alloc(); tc = (struct rtnl_tc *) qdisc; - + for (;;) { int c, optidx = 0; enum { @@ -97,7 +95,7 @@ int main(int argc, char *argv[]) { "kind", 1, 0, 'k' }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "qhvd:p:i:k:", long_opts, &optidx); if (c == -1) break; @@ -126,7 +124,7 @@ int main(int argc, char *argv[]) nl_cli_tc_parse_kind(tc, optarg); break; } - } + } if (nfilter == 0 && !interactive && !default_yes) { nl_cli_fatal(EINVAL, diff --git a/src/nl-qdisc-list.c b/src/nl-qdisc-list.c index 5b0a3f0..f41cca2 100644 --- a/src/nl-qdisc-list.c +++ b/src/nl-qdisc-list.c @@ -1,14 +1,13 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * 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-2010 Thomas Graf */ +#include "nl-default.h" + +#include +#include + #include #include #include @@ -129,15 +128,15 @@ int main(int argc, char *argv[]) struct rtnl_qdisc *qdisc; struct rtnl_tc *tc; struct nl_cache *link_cache, *qdisc_cache; - + 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(); + qdisc = nl_cli_qdisc_alloc(); tc = (struct rtnl_tc *) qdisc; - + for (;;) { int c, optidx = 0; enum { @@ -156,7 +155,7 @@ int main(int argc, char *argv[]) { "kind", 1, 0, 'k' }, { 0, 0, 0, 0 } }; - + c = getopt_long(argc, argv, "rhvd:p:i:k:", long_opts, &optidx); if (c == -1) break; @@ -172,7 +171,7 @@ int main(int argc, char *argv[]) case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break; case 'k': nl_cli_tc_parse_kind(tc, optarg); break; } - } + } if (recursive) nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(qdisc), list_qdisc, NULL); diff --git a/src/nl-route-add.c b/src/nl-route-add.c index d4aa767..04fca9f 100644 --- a/src/nl-route-add.c +++ b/src/nl-route-add.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-route-add.c Route addition utility - * - * 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 */ +#include "nl-default.h" + +#include + #include #include #include diff --git a/src/nl-route-delete.c b/src/nl-route-delete.c index 884fd7f..17d50b5 100644 --- a/src/nl-route-delete.c +++ b/src/nl-route-delete.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-route-delete.c Delete Routes - * - * 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 */ +#include "nl-default.h" + +#include + #include #include #include diff --git a/src/nl-route-get.c b/src/nl-route-get.c index c2f07d4..ce845b2 100644 --- a/src/nl-route-get.c +++ b/src/nl-route-get.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-route-get.c Get Route 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-2009 Thomas Graf */ +#include "nl-default.h" + +#include + #include #include #include @@ -43,7 +41,6 @@ static int cb(struct nl_msg *msg, void *arg) int main(int argc, char *argv[]) { struct nl_sock *sock; - struct nl_cache *link_cache, *route_cache; struct nl_addr *dst; int err = 1; @@ -52,8 +49,8 @@ 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); - route_cache = nl_cli_route_alloc_cache(sock, 0); + nl_cli_link_alloc_cache(sock); + nl_cli_route_alloc_cache(sock, 0); dst = nl_cli_addr_parse(argv[1], AF_INET); @@ -65,8 +62,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); @@ -79,7 +80,5 @@ int main(int argc, char *argv[]) nl_cli_fatal(err, "%s", nl_geterror(err)); } - //nl_cache_dump(route_cache, ¶ms); - return 0; } diff --git a/src/nl-route-list.c b/src/nl-route-list.c index e0e57be..284e240 100644 --- a/src/nl-route-list.c +++ b/src/nl-route-list.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-route-list.c List route 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-2009 Thomas Graf */ +#include "nl-default.h" + +#include + #include #include #include diff --git a/src/nl-rule-list.c b/src/nl-rule-list.c index 8b474fa..b31c575 100644 --- a/src/nl-rule-list.c +++ b/src/nl-rule-list.c @@ -1,14 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-rule-dump.c Dump rule 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-2009 Thomas Graf */ +#include "nl-default.h" + +#include + #include #include #include @@ -34,7 +32,7 @@ int main(int argc, char *argv[]) { struct nl_sock *sock; struct rtnl_rule *rule; - struct nl_cache *link_cache, *rule_cache; + struct nl_cache *rule_cache; struct nl_dump_params params = { .dp_fd = stdout, .dp_type = NL_DUMP_LINE, @@ -42,7 +40,7 @@ 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); + nl_cli_link_alloc_cache(sock); rule_cache = nl_cli_rule_alloc_cache(sock); rule = nl_cli_rule_alloc(); diff --git a/src/nl-tctree-list.c b/src/nl-tctree-list.c index d90cb28..63dcc15 100644 --- a/src/nl-tctree-list.c +++ b/src/nl-tctree-list.c @@ -1,19 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-tctree-list.c List Traffic Control Tree - * - * 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 */ +#include "nl-default.h" + +#include +#include + #include #include #include #include -#include static struct nl_sock *sock; static struct nl_cache *qdisc_cache, *class_cache; @@ -50,9 +48,9 @@ static void print_class(struct nl_object *obj, void *arg) leaf = rtnl_class_leaf_qdisc(class, qdisc_cache); if (leaf) - print_qdisc((struct nl_object *) leaf, arg + 2); + print_qdisc((struct nl_object *) leaf, (char *) arg + 2); - print_tc_childs(TC_CAST(class), arg + 2); + print_tc_childs(TC_CAST(class), (char *) arg + 2); if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0) return; @@ -85,7 +83,7 @@ static void print_qdisc(struct nl_object *obj, void *arg) params.dp_prefix = (int)(long) arg; nl_object_dump(obj, ¶ms); - print_tc_childs(TC_CAST(qdisc), arg + 2); + print_tc_childs(TC_CAST(qdisc), (char *) arg + 2); if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0) return; diff --git a/src/nl-util-addr.c b/src/nl-util-addr.c index 5f0738d..fc8ebdd 100644 --- a/src/nl-util-addr.c +++ b/src/nl-util-addr.c @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * src/nl-util-addr.c Address Helper - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2003-2009 Thomas Graf */ +#include "nl-default.h" + #include int main(int argc, char *argv[]) diff --git a/tests/Makefile.am b/tests/Makefile.am deleted file mode 100644 index 7953176..0000000 --- a/tests/Makefile.am +++ /dev/null @@ -1,54 +0,0 @@ -# -*- Makefile -*- - -EXTRA_DIST = \ - util.h - -if ENABLE_UNIT_TESTS - -AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" - -LDADD = \ - ${top_builddir}/lib/libnl-3.la \ - ${top_builddir}/lib/libnl-nf-3.la \ - ${top_builddir}/lib/libnl-genl-3.la \ - ${top_builddir}/lib/libnl-route-3.la \ - @CHECK_LIBS@ - -CFLAGS += @CHECK_CFLAGS@ - -UNIT_TESTS = check-all - -check_PROGRAMS = \ - test-create-bond \ - test-create-vlan \ - test-delete-link \ - test-socket-creation \ - test-complex-HTB-with-hash-filters \ - ${UNIT_TESTS} - -TESTS = \ - ${UNIT_TESTS} - -if ENABLE_CLI -LDADD += ${top_builddir}/src/lib/libnl-cli-3.la -check_PROGRAMS += \ - test-cache-mngr \ - test-genl \ - test-nf-cache-mngr -endif - -test_cache_mngr_SOURCES = test-cache-mngr.c -test_create_bond_SOURCES = test-create-bond.c -test_create_vlan_SOURCES = test-create-vlan.c -test_delete_link_SOURCES = test-delete-link.c -test_genl_SOURCES = test-genl.c -test_nf_cache_mngr_SOURCES = test-nf-cache-mngr.c -test_socket_creation_SOURCES = test-socket-creation.c -test_complex_HTB_with_hash_filters_SOURCES = test-complex-HTB-with-hash-filters.c - -# Unit tests -check_all_SOURCES = \ - check-all.c \ - check-addr.c \ - check-attr.c -endif diff --git a/tests/Makefile.in b/tests/Makefile.in deleted file mode 100644 index 85d4fd8..0000000 --- a/tests/Makefile.in +++ /dev/null @@ -1,814 +0,0 @@ -# Makefile.in generated by automake 1.11.6 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -# -*- Makefile -*- -VPATH = @srcdir@ -am__make_dryrun = \ - { \ - am__dry=no; \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ - esac; \ - test $$am__dry = yes; \ - } -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -@ENABLE_UNIT_TESTS_TRUE@am__append_1 = @CHECK_CFLAGS@ -@ENABLE_UNIT_TESTS_TRUE@check_PROGRAMS = test-create-bond$(EXEEXT) \ -@ENABLE_UNIT_TESTS_TRUE@ test-create-vlan$(EXEEXT) \ -@ENABLE_UNIT_TESTS_TRUE@ test-delete-link$(EXEEXT) \ -@ENABLE_UNIT_TESTS_TRUE@ test-socket-creation$(EXEEXT) \ -@ENABLE_UNIT_TESTS_TRUE@ test-complex-HTB-with-hash-filters$(EXEEXT) \ -@ENABLE_UNIT_TESTS_TRUE@ $(am__EXEEXT_1) $(am__EXEEXT_2) -@ENABLE_UNIT_TESTS_TRUE@TESTS = $(am__EXEEXT_1) -@ENABLE_CLI_TRUE@@ENABLE_UNIT_TESTS_TRUE@am__append_2 = ${top_builddir}/src/lib/libnl-cli-3.la -@ENABLE_CLI_TRUE@@ENABLE_UNIT_TESTS_TRUE@am__append_3 = \ -@ENABLE_CLI_TRUE@@ENABLE_UNIT_TESTS_TRUE@ test-cache-mngr \ -@ENABLE_CLI_TRUE@@ENABLE_UNIT_TESTS_TRUE@ test-genl \ -@ENABLE_CLI_TRUE@@ENABLE_UNIT_TESTS_TRUE@ test-nf-cache-mngr - -subdir = tests -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/lib/defs.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -@ENABLE_UNIT_TESTS_TRUE@am__EXEEXT_1 = check-all$(EXEEXT) -@ENABLE_CLI_TRUE@@ENABLE_UNIT_TESTS_TRUE@am__EXEEXT_2 = test-cache-mngr$(EXEEXT) \ -@ENABLE_CLI_TRUE@@ENABLE_UNIT_TESTS_TRUE@ test-genl$(EXEEXT) \ -@ENABLE_CLI_TRUE@@ENABLE_UNIT_TESTS_TRUE@ test-nf-cache-mngr$(EXEEXT) -am__check_all_SOURCES_DIST = check-all.c check-addr.c check-attr.c -@ENABLE_UNIT_TESTS_TRUE@am_check_all_OBJECTS = check-all.$(OBJEXT) \ -@ENABLE_UNIT_TESTS_TRUE@ check-addr.$(OBJEXT) \ -@ENABLE_UNIT_TESTS_TRUE@ check-attr.$(OBJEXT) -check_all_OBJECTS = $(am_check_all_OBJECTS) -check_all_LDADD = $(LDADD) -@ENABLE_UNIT_TESTS_TRUE@check_all_DEPENDENCIES = \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ $(am__append_2) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__test_cache_mngr_SOURCES_DIST = test-cache-mngr.c -@ENABLE_UNIT_TESTS_TRUE@am_test_cache_mngr_OBJECTS = \ -@ENABLE_UNIT_TESTS_TRUE@ test-cache-mngr.$(OBJEXT) -test_cache_mngr_OBJECTS = $(am_test_cache_mngr_OBJECTS) -test_cache_mngr_LDADD = $(LDADD) -@ENABLE_UNIT_TESTS_TRUE@test_cache_mngr_DEPENDENCIES = \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ $(am__append_2) -am__test_complex_HTB_with_hash_filters_SOURCES_DIST = \ - test-complex-HTB-with-hash-filters.c -@ENABLE_UNIT_TESTS_TRUE@am_test_complex_HTB_with_hash_filters_OBJECTS = test-complex-HTB-with-hash-filters.$(OBJEXT) -test_complex_HTB_with_hash_filters_OBJECTS = \ - $(am_test_complex_HTB_with_hash_filters_OBJECTS) -test_complex_HTB_with_hash_filters_LDADD = $(LDADD) -@ENABLE_UNIT_TESTS_TRUE@test_complex_HTB_with_hash_filters_DEPENDENCIES = \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ $(am__append_2) -am__test_create_bond_SOURCES_DIST = test-create-bond.c -@ENABLE_UNIT_TESTS_TRUE@am_test_create_bond_OBJECTS = \ -@ENABLE_UNIT_TESTS_TRUE@ test-create-bond.$(OBJEXT) -test_create_bond_OBJECTS = $(am_test_create_bond_OBJECTS) -test_create_bond_LDADD = $(LDADD) -@ENABLE_UNIT_TESTS_TRUE@test_create_bond_DEPENDENCIES = \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ $(am__append_2) -am__test_create_vlan_SOURCES_DIST = test-create-vlan.c -@ENABLE_UNIT_TESTS_TRUE@am_test_create_vlan_OBJECTS = \ -@ENABLE_UNIT_TESTS_TRUE@ test-create-vlan.$(OBJEXT) -test_create_vlan_OBJECTS = $(am_test_create_vlan_OBJECTS) -test_create_vlan_LDADD = $(LDADD) -@ENABLE_UNIT_TESTS_TRUE@test_create_vlan_DEPENDENCIES = \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ $(am__append_2) -am__test_delete_link_SOURCES_DIST = test-delete-link.c -@ENABLE_UNIT_TESTS_TRUE@am_test_delete_link_OBJECTS = \ -@ENABLE_UNIT_TESTS_TRUE@ test-delete-link.$(OBJEXT) -test_delete_link_OBJECTS = $(am_test_delete_link_OBJECTS) -test_delete_link_LDADD = $(LDADD) -@ENABLE_UNIT_TESTS_TRUE@test_delete_link_DEPENDENCIES = \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ $(am__append_2) -am__test_genl_SOURCES_DIST = test-genl.c -@ENABLE_UNIT_TESTS_TRUE@am_test_genl_OBJECTS = test-genl.$(OBJEXT) -test_genl_OBJECTS = $(am_test_genl_OBJECTS) -test_genl_LDADD = $(LDADD) -@ENABLE_UNIT_TESTS_TRUE@test_genl_DEPENDENCIES = \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ $(am__append_2) -am__test_nf_cache_mngr_SOURCES_DIST = test-nf-cache-mngr.c -@ENABLE_UNIT_TESTS_TRUE@am_test_nf_cache_mngr_OBJECTS = \ -@ENABLE_UNIT_TESTS_TRUE@ test-nf-cache-mngr.$(OBJEXT) -test_nf_cache_mngr_OBJECTS = $(am_test_nf_cache_mngr_OBJECTS) -test_nf_cache_mngr_LDADD = $(LDADD) -@ENABLE_UNIT_TESTS_TRUE@test_nf_cache_mngr_DEPENDENCIES = \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ $(am__append_2) -am__test_socket_creation_SOURCES_DIST = test-socket-creation.c -@ENABLE_UNIT_TESTS_TRUE@am_test_socket_creation_OBJECTS = \ -@ENABLE_UNIT_TESTS_TRUE@ test-socket-creation.$(OBJEXT) -test_socket_creation_OBJECTS = $(am_test_socket_creation_OBJECTS) -test_socket_creation_LDADD = $(LDADD) -@ENABLE_UNIT_TESTS_TRUE@test_socket_creation_DEPENDENCIES = \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ $(am__append_2) -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/lib -depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -SOURCES = $(check_all_SOURCES) $(test_cache_mngr_SOURCES) \ - $(test_complex_HTB_with_hash_filters_SOURCES) \ - $(test_create_bond_SOURCES) $(test_create_vlan_SOURCES) \ - $(test_delete_link_SOURCES) $(test_genl_SOURCES) \ - $(test_nf_cache_mngr_SOURCES) $(test_socket_creation_SOURCES) -DIST_SOURCES = $(am__check_all_SOURCES_DIST) \ - $(am__test_cache_mngr_SOURCES_DIST) \ - $(am__test_complex_HTB_with_hash_filters_SOURCES_DIST) \ - $(am__test_create_bond_SOURCES_DIST) \ - $(am__test_create_vlan_SOURCES_DIST) \ - $(am__test_delete_link_SOURCES_DIST) \ - $(am__test_genl_SOURCES_DIST) \ - $(am__test_nf_cache_mngr_SOURCES_DIST) \ - $(am__test_socket_creation_SOURCES_DIST) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -ETAGS = etags -CTAGS = ctags -am__tty_colors = \ -red=; grn=; lgn=; blu=; std= -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ $(am__append_1) -CHECK_CFLAGS = @CHECK_CFLAGS@ -CHECK_LIBS = @CHECK_LIBS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -FLEX = @FLEX@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBNL_VERSION = @LIBNL_VERSION@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_AGE = @LT_AGE@ -LT_CURRENT = @LT_CURRENT@ -LT_REVISION = @LT_REVISION@ -MAJ_VERSION = @MAJ_VERSION@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MIC_VERSION = @MIC_VERSION@ -MIN_VERSION = @MIN_VERSION@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -YACC = @YACC@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgconfigdir = @pkgconfigdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -subdirs = @subdirs@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -EXTRA_DIST = \ - util.h - -@ENABLE_UNIT_TESTS_TRUE@AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" -@ENABLE_UNIT_TESTS_TRUE@LDADD = ${top_builddir}/lib/libnl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-nf-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-genl-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ ${top_builddir}/lib/libnl-route-3.la \ -@ENABLE_UNIT_TESTS_TRUE@ @CHECK_LIBS@ $(am__append_2) -@ENABLE_UNIT_TESTS_TRUE@UNIT_TESTS = check-all -@ENABLE_UNIT_TESTS_TRUE@test_cache_mngr_SOURCES = test-cache-mngr.c -@ENABLE_UNIT_TESTS_TRUE@test_create_bond_SOURCES = test-create-bond.c -@ENABLE_UNIT_TESTS_TRUE@test_create_vlan_SOURCES = test-create-vlan.c -@ENABLE_UNIT_TESTS_TRUE@test_delete_link_SOURCES = test-delete-link.c -@ENABLE_UNIT_TESTS_TRUE@test_genl_SOURCES = test-genl.c -@ENABLE_UNIT_TESTS_TRUE@test_nf_cache_mngr_SOURCES = test-nf-cache-mngr.c -@ENABLE_UNIT_TESTS_TRUE@test_socket_creation_SOURCES = test-socket-creation.c -@ENABLE_UNIT_TESTS_TRUE@test_complex_HTB_with_hash_filters_SOURCES = test-complex-HTB-with-hash-filters.c - -# Unit tests -@ENABLE_UNIT_TESTS_TRUE@check_all_SOURCES = \ -@ENABLE_UNIT_TESTS_TRUE@ check-all.c \ -@ENABLE_UNIT_TESTS_TRUE@ check-addr.c \ -@ENABLE_UNIT_TESTS_TRUE@ check-attr.c - -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign tests/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-checkPROGRAMS: - @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ - echo " rm -f" $$list; \ - rm -f $$list || exit $$?; \ - test -n "$(EXEEXT)" || exit 0; \ - list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ - echo " rm -f" $$list; \ - rm -f $$list -check-all$(EXEEXT): $(check_all_OBJECTS) $(check_all_DEPENDENCIES) $(EXTRA_check_all_DEPENDENCIES) - @rm -f check-all$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(check_all_OBJECTS) $(check_all_LDADD) $(LIBS) -test-cache-mngr$(EXEEXT): $(test_cache_mngr_OBJECTS) $(test_cache_mngr_DEPENDENCIES) $(EXTRA_test_cache_mngr_DEPENDENCIES) - @rm -f test-cache-mngr$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(test_cache_mngr_OBJECTS) $(test_cache_mngr_LDADD) $(LIBS) -test-complex-HTB-with-hash-filters$(EXEEXT): $(test_complex_HTB_with_hash_filters_OBJECTS) $(test_complex_HTB_with_hash_filters_DEPENDENCIES) $(EXTRA_test_complex_HTB_with_hash_filters_DEPENDENCIES) - @rm -f test-complex-HTB-with-hash-filters$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(test_complex_HTB_with_hash_filters_OBJECTS) $(test_complex_HTB_with_hash_filters_LDADD) $(LIBS) -test-create-bond$(EXEEXT): $(test_create_bond_OBJECTS) $(test_create_bond_DEPENDENCIES) $(EXTRA_test_create_bond_DEPENDENCIES) - @rm -f test-create-bond$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(test_create_bond_OBJECTS) $(test_create_bond_LDADD) $(LIBS) -test-create-vlan$(EXEEXT): $(test_create_vlan_OBJECTS) $(test_create_vlan_DEPENDENCIES) $(EXTRA_test_create_vlan_DEPENDENCIES) - @rm -f test-create-vlan$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(test_create_vlan_OBJECTS) $(test_create_vlan_LDADD) $(LIBS) -test-delete-link$(EXEEXT): $(test_delete_link_OBJECTS) $(test_delete_link_DEPENDENCIES) $(EXTRA_test_delete_link_DEPENDENCIES) - @rm -f test-delete-link$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(test_delete_link_OBJECTS) $(test_delete_link_LDADD) $(LIBS) -test-genl$(EXEEXT): $(test_genl_OBJECTS) $(test_genl_DEPENDENCIES) $(EXTRA_test_genl_DEPENDENCIES) - @rm -f test-genl$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(test_genl_OBJECTS) $(test_genl_LDADD) $(LIBS) -test-nf-cache-mngr$(EXEEXT): $(test_nf_cache_mngr_OBJECTS) $(test_nf_cache_mngr_DEPENDENCIES) $(EXTRA_test_nf_cache_mngr_DEPENDENCIES) - @rm -f test-nf-cache-mngr$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(test_nf_cache_mngr_OBJECTS) $(test_nf_cache_mngr_LDADD) $(LIBS) -test-socket-creation$(EXEEXT): $(test_socket_creation_OBJECTS) $(test_socket_creation_DEPENDENCIES) $(EXTRA_test_socket_creation_DEPENDENCIES) - @rm -f test-socket-creation$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(test_socket_creation_OBJECTS) $(test_socket_creation_LDADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check-addr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check-all.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check-attr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-cache-mngr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-complex-HTB-with-hash-filters.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-create-bond.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-create-vlan.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-delete-link.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-genl.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-nf-cache-mngr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-socket-creation.Po@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ -@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ -@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - set x; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -check-TESTS: $(TESTS) - @failed=0; all=0; xfail=0; xpass=0; skip=0; \ - srcdir=$(srcdir); export srcdir; \ - list=' $(TESTS) '; \ - $(am__tty_colors); \ - if test -n "$$list"; then \ - for tst in $$list; do \ - if test -f ./$$tst; then dir=./; \ - elif test -f $$tst; then dir=; \ - else dir="$(srcdir)/"; fi; \ - if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ - all=`expr $$all + 1`; \ - case " $(XFAIL_TESTS) " in \ - *[\ \ ]$$tst[\ \ ]*) \ - xpass=`expr $$xpass + 1`; \ - failed=`expr $$failed + 1`; \ - col=$$red; res=XPASS; \ - ;; \ - *) \ - col=$$grn; res=PASS; \ - ;; \ - esac; \ - elif test $$? -ne 77; then \ - all=`expr $$all + 1`; \ - case " $(XFAIL_TESTS) " in \ - *[\ \ ]$$tst[\ \ ]*) \ - xfail=`expr $$xfail + 1`; \ - col=$$lgn; res=XFAIL; \ - ;; \ - *) \ - failed=`expr $$failed + 1`; \ - col=$$red; res=FAIL; \ - ;; \ - esac; \ - else \ - skip=`expr $$skip + 1`; \ - col=$$blu; res=SKIP; \ - fi; \ - echo "$${col}$$res$${std}: $$tst"; \ - done; \ - if test "$$all" -eq 1; then \ - tests="test"; \ - All=""; \ - else \ - tests="tests"; \ - All="All "; \ - fi; \ - if test "$$failed" -eq 0; then \ - if test "$$xfail" -eq 0; then \ - banner="$$All$$all $$tests passed"; \ - else \ - if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ - banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ - fi; \ - else \ - if test "$$xpass" -eq 0; then \ - banner="$$failed of $$all $$tests failed"; \ - else \ - if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ - banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ - fi; \ - fi; \ - dashes="$$banner"; \ - skipped=""; \ - if test "$$skip" -ne 0; then \ - if test "$$skip" -eq 1; then \ - skipped="($$skip test was not run)"; \ - else \ - skipped="($$skip tests were not run)"; \ - fi; \ - test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ - dashes="$$skipped"; \ - fi; \ - report=""; \ - if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ - report="Please report to $(PACKAGE_BUGREPORT)"; \ - test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ - dashes="$$report"; \ - fi; \ - dashes=`echo "$$dashes" | sed s/./=/g`; \ - if test "$$failed" -eq 0; then \ - col="$$grn"; \ - else \ - col="$$red"; \ - fi; \ - echo "$${col}$$dashes$${std}"; \ - echo "$${col}$$banner$${std}"; \ - test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ - test -z "$$report" || echo "$${col}$$report$${std}"; \ - echo "$${col}$$dashes$${std}"; \ - test "$$failed" -eq 0; \ - else :; fi - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am - $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) - $(MAKE) $(AM_MAKEFLAGS) check-TESTS -check: check-am -all-am: Makefile -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: check-am install-am install-strip - -.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \ - clean-checkPROGRAMS clean-generic clean-libtool ctags \ - distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/tests/check-addr.c b/tests/check-addr.c deleted file mode 100644 index 39f3ede..0000000 --- a/tests/check-addr.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * tests/check-addr.c nl_addr unit tests - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * Copyright (c) 2013 Thomas Graf - */ - -#include -#include - -START_TEST(addr_alloc) -{ - struct nl_addr *addr; - - addr = nl_addr_alloc(16); - fail_if(addr == NULL, - "Allocation should not return NULL"); - - fail_if(nl_addr_iszero(addr) == 0, - "New empty address should be all zeros"); - - fail_if(nl_addr_get_family(addr) != AF_UNSPEC, - "New empty address should have family AF_UNSPEC"); - - fail_if(nl_addr_get_prefixlen(addr) != 0, - "New empty address should have prefix length 0"); - - fail_if(nl_addr_shared(addr), - "New empty address should not be shared"); - - fail_if(nl_addr_get(addr) != addr, - "nl_addr_get() should return pointer to address"); - - fail_if(nl_addr_shared(addr) == 0, - "Address should be shared after call to nl_addr_get()"); - - nl_addr_put(addr); - - fail_if(nl_addr_shared(addr), - "Address should not be shared after call to nl_addr_put()"); - - fail_if(nl_addr_fill_sockaddr(addr, NULL, 0) == 0, - "Socket address filling should fail for empty address"); - - nl_addr_put(addr); -} -END_TEST - -START_TEST(addr_binary_addr) -{ - struct nl_addr *addr, *addr2; - char baddr[4] = { 0x1, 0x2, 0x3, 0x4 }; - char baddr2[6] = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6 }; - - addr = nl_addr_alloc(4); - fail_if(addr == NULL, - "Allocation should not return NULL"); - - fail_if(nl_addr_set_binary_addr(addr, baddr, 4) < 0, - "Valid binary address should be settable"); - - fail_if(nl_addr_get_prefixlen(addr) != 0, - "Prefix length should be unchanged after nl_addr_set_binary_addr()"); - - fail_if(nl_addr_get_len(addr) != 4, - "Address length should be 4"); - - fail_if(nl_addr_set_binary_addr(addr, baddr2, 6) == 0, - "Should not be able to set binary address exceeding maximum length"); - - fail_if(nl_addr_get_len(addr) != 4, - "Address length should still be 4"); - - fail_if(nl_addr_guess_family(addr) != AF_INET, - "Binary address of length 4 should be guessed as AF_INET"); - - fail_if(memcmp(baddr, nl_addr_get_binary_addr(addr), 4) != 0, - "Binary address mismatches"); - - addr2 = nl_addr_build(AF_UNSPEC, baddr, 4); - fail_if(addr2 == NULL, - "Building of address should not fail"); - - nl_addr_set_prefixlen(addr, 32); - fail_if(nl_addr_get_prefixlen(addr) != 32, - "Prefix length should be successful changed after nl_addr_set_prefixlen()"); - - fail_if(nl_addr_cmp(addr, addr2), - "Addresses built from same binary address should match"); - - nl_addr_put(addr); - nl_addr_put(addr2); -} -END_TEST - -START_TEST(addr_parse4) -{ - struct nl_addr *addr4, *clone; - struct sockaddr_in sin; - socklen_t len = sizeof(sin); - char *addr_str = "10.0.0.1/16"; - char buf[128]; - - fail_if(nl_addr_parse(addr_str, AF_INET6, &addr4) == 0, - "Should not be able to parse IPv4 address in IPv6 mode"); - - fail_if(nl_addr_parse(addr_str, AF_UNSPEC, &addr4) != 0, - "Should be able to parse \"%s\"", addr_str); - - fail_if(nl_addr_get_family(addr4) != AF_INET, - "Address family should be AF_INET"); - - fail_if(nl_addr_get_prefixlen(addr4) != 16, - "Prefix length should be 16"); - - fail_if(nl_addr_iszero(addr4), - "Address should not be all zeroes"); - - clone = nl_addr_clone(addr4); - fail_if(clone == NULL, - "Cloned address should not be NULL"); - - fail_if(nl_addr_cmp(addr4, clone) != 0, - "Cloned address should not mismatch original"); - - fail_if(nl_addr_fill_sockaddr(addr4, (struct sockaddr *) &sin, &len) != 0, - "Should be able to fill socketaddr"); - - fail_if(strcmp(nl_addr2str(addr4, buf, sizeof(buf)), addr_str), - "Address translated back to string does not match original"); - - nl_addr_put(addr4); - nl_addr_put(clone); -} -END_TEST - -START_TEST(addr_parse6) -{ - struct nl_addr *addr6, *clone; - struct sockaddr_in6 sin; - socklen_t len = sizeof(sin); - char *addr_str = "2001:1:2::3/64"; - char buf[128]; - - fail_if(nl_addr_parse(addr_str, AF_INET, &addr6) == 0, - "Should not be able to parse IPv6 address in IPv4 mode"); - - fail_if(nl_addr_parse(addr_str, AF_UNSPEC, &addr6) != 0, - "Should be able to parse \"%s\"", addr_str); - - fail_if(nl_addr_get_family(addr6) != AF_INET6, - "Address family should be AF_INET6"); - - fail_if(nl_addr_get_prefixlen(addr6) != 64, - "Prefix length should be 64"); - - fail_if(nl_addr_iszero(addr6), - "Address should not be all zeroes"); - - clone = nl_addr_clone(addr6); - fail_if(clone == NULL, - "Cloned address should not be NULL"); - - fail_if(nl_addr_cmp(addr6, clone) != 0, - "Cloned address should not mismatch original"); - - fail_if(nl_addr_fill_sockaddr(addr6, (struct sockaddr *) &sin, &len) != 0, - "Should be able to fill socketaddr"); - - fail_if(strcmp(nl_addr2str(addr6, buf, sizeof(buf)), addr_str), - "Address translated back to string does not match original"); - - nl_addr_put(addr6); - nl_addr_put(clone); -} -END_TEST - -START_TEST(addr_info) -{ - struct nl_addr *addr; - char *addr_str = "127.0.0.1"; - struct addrinfo *result; - - fail_if(nl_addr_parse(addr_str, AF_UNSPEC, &addr) != 0, - "Parsing of valid address should not fail"); - - fail_if(nl_addr_info(addr, &result) != 0, - "getaddrinfo() on loopback address should work"); - - freeaddrinfo(result); - nl_addr_put(addr); -} -END_TEST - -Suite *make_nl_addr_suite(void) -{ - Suite *suite = suite_create("Abstract addresses"); - - TCase *tc_addr = tcase_create("Core"); - tcase_add_test(tc_addr, addr_alloc); - tcase_add_test(tc_addr, addr_binary_addr); - tcase_add_test(tc_addr, addr_parse4); - tcase_add_test(tc_addr, addr_parse6); - tcase_add_test(tc_addr, addr_info); - suite_add_tcase(suite, tc_addr); - - return suite; -} diff --git a/tests/check-all.c b/tests/check-all.c index e431802..e8a0e80 100644 --- a/tests/check-all.c +++ b/tests/check-all.c @@ -1,18 +1,13 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * tests/check-all.c overall unit test program - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2013 Thomas Graf */ +#include "nl-default.h" + #include -extern Suite *make_nl_addr_suite(void); -extern Suite *make_nl_attr_suite(void); +#include "cksuite-all.h" static Suite *main_suite(void) { @@ -25,15 +20,13 @@ int main(int argc, char *argv[]) { SRunner *runner; int nfailed; - - runner = srunner_create(main_suite()); - /* Add testsuites below */ + runner = srunner_create(main_suite()); srunner_add_suite(runner, make_nl_addr_suite()); srunner_add_suite(runner, make_nl_attr_suite()); - - /* Do not add testsuites below this line */ + srunner_add_suite(runner, make_nl_ematch_tree_clone_suite()); + srunner_add_suite(runner, make_nl_netns_suite()); srunner_run_all(runner, CK_ENV); diff --git a/tests/check-attr.c b/tests/check-attr.c deleted file mode 100644 index d862230..0000000 --- a/tests/check-attr.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * tests/check-attr.c nla_attr unit tests - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * Copyright (c) 2013 Thomas Graf - */ - -#include "util.h" -#include -#include - -START_TEST(attr_size) -{ - fail_if(nla_attr_size(0) != NLA_HDRLEN, - "Length of empty attribute should match header size"); - fail_if(nla_attr_size(1) != NLA_HDRLEN + 1, - "Length of 1 bytes payload should be NLA_HDRLEN + 1"); - fail_if(nla_attr_size(2) != NLA_HDRLEN + 2, - "Length of 2 bytes payload should be NLA_HDRLEN + 2"); - fail_if(nla_attr_size(3) != NLA_HDRLEN + 3, - "Length of 3 bytes payload should be NLA_HDRLEN + 3"); - fail_if(nla_attr_size(4) != NLA_HDRLEN + 4, - "Length of 4 bytes payload should be NLA_HDRLEN + 4"); - - fail_if(nla_total_size(1) != NLA_HDRLEN + 4, - "Total size of 1 bytes payload should result in 8 bytes"); - fail_if(nla_total_size(2) != NLA_HDRLEN + 4, - "Total size of 2 bytes payload should result in 8 bytes"); - fail_if(nla_total_size(3) != NLA_HDRLEN + 4, - "Total size of 3 bytes payload should result in 8 bytes"); - fail_if(nla_total_size(4) != NLA_HDRLEN + 4, - "Total size of 4 bytes payload should result in 8 bytes"); - - fail_if(nla_padlen(1) != 3, - "2 bytes of payload should result in 3 padding bytes"); - fail_if(nla_padlen(2) != 2, - "2 bytes of payload should result in 2 padding bytes"); - fail_if(nla_padlen(3) != 1, - "3 bytes of payload should result in 1 padding bytes"); - fail_if(nla_padlen(4) != 0, - "4 bytes of payload should result in 0 padding bytes"); - fail_if(nla_padlen(5) != 3, - "5 bytes of payload should result in 3 padding bytes"); -} -END_TEST - -START_TEST(msg_construct) -{ - struct nl_msg *msg; - struct nlmsghdr *nlh; - struct nlattr *a; - int i, rem; - - msg = nlmsg_alloc(); - fail_if(!msg, "Unable to allocate netlink message"); - - for (i = 1; i < 256; i++) { - fail_if(nla_put_u32(msg, i, i+1) != 0, - "Unable to add attribute %d", i); - } - - nlh = nlmsg_hdr(msg); - i = 1; - nlmsg_for_each_attr(a, nlh, 0, rem) { - fail_if(nla_type(a) != i, "Expected attribute %d", i); - i++; - fail_if(nla_get_u32(a) != i, "Expected attribute value %d", i); - } - - nlmsg_free(msg); -} -END_TEST - -Suite *make_nl_attr_suite(void) -{ - Suite *suite = suite_create("Netlink attributes"); - - TCase *nl_attr = tcase_create("Core"); - tcase_add_test(nl_attr, attr_size); - tcase_add_test(nl_attr, msg_construct); - suite_add_tcase(suite, nl_attr); - - return suite; -} diff --git a/tests/check-direct.c b/tests/check-direct.c new file mode 100644 index 0000000..db1f48d --- /dev/null +++ b/tests/check-direct.c @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +#include + +#include + +#include "nl-priv-static-route/nl-priv-static-route.h" + +START_TEST(static_checks) +{ + int i, j; + char strbuf[100]; + + _NL_STATIC_ASSERT(RTNL_LINK_RX_PACKETS == 0); + assert(_nltst_map_stat_id_from_IPSTATS_MIB_v2[0] == + RTNL_LINK_RX_PACKETS); + for (i = 1; i < __IPSTATS_MIB_MAX; i++) { + assert(_nltst_map_stat_id_from_IPSTATS_MIB_v2[i] > 0); + assert(_nltst_map_stat_id_from_IPSTATS_MIB_v2[i] < + __RTNL_LINK_STATS_MAX); + for (j = 1; j < i; j++) + assert(_nltst_map_stat_id_from_IPSTATS_MIB_v2[i] != + _nltst_map_stat_id_from_IPSTATS_MIB_v2[j]); + } + + for (i = 0; i <= RTNL_LINK_STATS_MAX + 1; i++) { + const char *s; + + s = rtnl_link_stat2str(i, strbuf, sizeof(strbuf)); + assert(s); + assert(s == strbuf); + assert(strlen(s) < sizeof(strbuf)); + if (strncmp(s, "0x", 2) == 0) { + assert(i == RTNL_LINK_STATS_MAX + 1); + ck_assert_int_eq(strtoll(&s[2], NULL, 16), i); + } else + ck_assert_int_le(i, RTNL_LINK_STATS_MAX); + ck_assert_int_eq(i, rtnl_link_str2stat(s)); + } + + ck_assert_int_eq(nl_str2ip_proto(""), -NLE_OBJ_NOTFOUND); + ck_assert_int_eq(nl_str2ip_proto("5"), 5); + ck_assert_int_eq(nl_str2ip_proto(" 13 "), -NLE_OBJ_NOTFOUND); + ck_assert_int_eq(nl_str2ip_proto("13"), 13); + ck_assert_int_eq(nl_str2ip_proto("0x13"), 0x13); + ck_assert_int_eq(nl_str2ip_proto("0342"), 0342); + ck_assert_int_eq(nl_str2ip_proto("2147483647"), 2147483647); + ck_assert_int_eq(nl_str2ip_proto("2147483648"), -NLE_OBJ_NOTFOUND); +} +END_TEST + +static Suite *make_suite(void) +{ + Suite *suite = suite_create("Direct"); + TCase *tc = tcase_create("Core"); + + tcase_add_test(tc, static_checks); + suite_add_tcase(suite, tc); + return suite; +} + +int main(int argc, char *argv[]) +{ + SRunner *runner; + int nfailed; + + runner = srunner_create(suite_create("main")); + + srunner_add_suite(runner, make_suite()); + + srunner_run_all(runner, CK_ENV); + + nfailed = srunner_ntests_failed(runner); + srunner_free(runner); + return nfailed != 0; +} diff --git a/tests/cksuite-all-addr.c b/tests/cksuite-all-addr.c new file mode 100644 index 0000000..f4ee0dd --- /dev/null +++ b/tests/cksuite-all-addr.c @@ -0,0 +1,229 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Thomas Graf + */ + +#include "nl-default.h" + +#include +#include +#include + +#include "cksuite-all.h" + +START_TEST(addr_alloc) +{ + struct nl_addr *addr; + + addr = nl_addr_alloc(16); + ck_assert_msg(addr, "Allocation should not return NULL"); + + ck_assert_msg(nl_addr_iszero(addr) != 0, + "New empty address should be all zeros"); + + ck_assert_msg(nl_addr_get_family(addr) == AF_UNSPEC, + "New empty address should have family AF_UNSPEC"); + + ck_assert_msg(nl_addr_get_prefixlen(addr) == 0, + "New empty address should have prefix length 0"); + + ck_assert_msg(!nl_addr_shared(addr), + "New empty address should not be shared"); + + ck_assert_msg(nl_addr_get(addr) == addr, + "nl_addr_get() should return pointer to address"); + + ck_assert_msg(nl_addr_shared(addr) != 0, + "Address should be shared after call to nl_addr_get()"); + + nl_addr_put(addr); + + ck_assert_msg( + !nl_addr_shared(addr), + "Address should not be shared after call to nl_addr_put()"); + + ck_assert_msg(nl_addr_fill_sockaddr(addr, NULL, 0) != 0, + "Socket address filling should fail for empty address"); + + nl_addr_put(addr); +} +END_TEST + +START_TEST(addr_binary_addr) +{ + struct nl_addr *addr, *addr2; + char baddr[4] = { 0x1, 0x2, 0x3, 0x4 }; + char baddr2[6] = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6 }; + + addr = nl_addr_alloc(4); + ck_assert_msg(addr != NULL, "Allocation should not return NULL"); + + ck_assert_msg(nl_addr_set_binary_addr(addr, baddr, 4) >= 0, + "Valid binary address should be settable"); + + ck_assert_msg( + nl_addr_get_prefixlen(addr) == 0, + "Prefix length should be unchanged after nl_addr_set_binary_addr()"); + + ck_assert_msg(nl_addr_get_len(addr) == 4, "Address length should be 4"); + + ck_assert_msg( + nl_addr_set_binary_addr(addr, baddr2, 6) != 0, + "Should not be able to set binary address exceeding maximum length"); + + ck_assert_msg(nl_addr_get_len(addr) == 4, + "Address length should still be 4"); + + ck_assert_msg( + nl_addr_guess_family(addr) == AF_INET, + "Binary address of length 4 should be guessed as AF_INET"); + + ck_assert_msg(memcmp(baddr, nl_addr_get_binary_addr(addr), 4) == 0, + "Binary address mismatches"); + + addr2 = nl_addr_build(AF_UNSPEC, baddr, 4); + ck_assert_msg(addr2 != NULL, "Building of address should not fail"); + + nl_addr_set_prefixlen(addr, 32); + ck_assert_msg( + nl_addr_get_prefixlen(addr) == 32, + "Prefix length should be successful changed after nl_addr_set_prefixlen()"); + + ck_assert_msg(!nl_addr_cmp(addr, addr2), + "Addresses built from same binary address should match"); + + nl_addr_put(addr); + nl_addr_put(addr2); +} +END_TEST + +START_TEST(addr_parse4) +{ + struct nl_addr *addr4, *clone; + struct sockaddr_in sin; + socklen_t len = sizeof(sin); + char *addr_str = "10.0.0.1/16"; + char buf[128]; + + ck_assert_msg(nl_addr_parse(addr_str, AF_INET6, &addr4) != 0, + "Should not be able to parse IPv4 address in IPv6 mode"); + + ck_assert_msg(nl_addr_parse(addr_str, AF_UNSPEC, &addr4) == 0, + "Should be able to parse \"%s\"", addr_str); + + ck_assert_msg(nl_addr_get_family(addr4) == AF_INET, + "Address family should be AF_INET"); + + ck_assert_msg(nl_addr_get_prefixlen(addr4) == 16, + "Prefix length should be 16"); + + ck_assert_msg(!nl_addr_iszero(addr4), + "Address should not be all zeroes"); + + clone = nl_addr_clone(addr4); + ck_assert_msg(clone != NULL, "Cloned address should not be NULL"); + + ck_assert_msg(nl_addr_cmp(addr4, clone) == 0, + "Cloned address should not mismatch original"); + + ck_assert_msg(nl_addr_fill_sockaddr(addr4, (struct sockaddr *)&sin, + &len) == 0, + "Should be able to fill socketaddr"); + + ck_assert_msg( + !strcmp(nl_addr2str(addr4, buf, sizeof(buf)), addr_str), + "Address translated back to string does not match original"); + + nl_addr_put(addr4); + nl_addr_put(clone); +} +END_TEST + +START_TEST(addr_parse6) +{ + struct nl_addr *addr6, *clone; + struct sockaddr_in6 sin; + socklen_t len = sizeof(sin); + char *addr_str = "2001:1:2::3/64"; + char buf[128]; + + ck_assert_msg(nl_addr_parse(addr_str, AF_INET, &addr6) != 0, + "Should not be able to parse IPv6 address in IPv4 mode"); + + ck_assert_msg(nl_addr_parse(addr_str, AF_UNSPEC, &addr6) == 0, + "Should be able to parse \"%s\"", addr_str); + + ck_assert_msg(nl_addr_get_family(addr6) == AF_INET6, + "Address family should be AF_INET6"); + + ck_assert_msg(nl_addr_get_prefixlen(addr6) == 64, + "Prefix length should be 64"); + + ck_assert_msg(!nl_addr_iszero(addr6), + "Address should not be all zeroes"); + + clone = nl_addr_clone(addr6); + ck_assert_msg(clone != NULL, "Cloned address should not be NULL"); + + ck_assert_msg(nl_addr_cmp(addr6, clone) == 0, + "Cloned address should not mismatch original"); + + ck_assert_msg(nl_addr_fill_sockaddr(addr6, (struct sockaddr *)&sin, + &len) == 0, + "Should be able to fill socketaddr"); + + ck_assert_msg( + !strcmp(nl_addr2str(addr6, buf, sizeof(buf)), addr_str), + "Address translated back to string does not match original"); + + nl_addr_put(addr6); + nl_addr_put(clone); +} +END_TEST + +START_TEST(addr_info) +{ + struct nl_addr *addr; + char *addr_str = "127.0.0.1"; + struct addrinfo *result; + + ck_assert_msg(nl_addr_parse(addr_str, AF_UNSPEC, &addr) == 0, + "Parsing of valid address should not fail"); + + ck_assert_msg(nl_addr_info(addr, &result) == 0, + "getaddrinfo() on loopback address should work"); + + freeaddrinfo(result); + nl_addr_put(addr); +} +END_TEST + +START_TEST(addr_flags2str) +{ + int ifa_flags = IFA_F_TENTATIVE | IFA_F_DADFAILED; + int ifa_flags2; + char buf[128]; + + rtnl_addr_flags2str(ifa_flags, buf, sizeof(buf)); + ck_assert_str_eq(buf, "dadfailed,tentative"); + + ifa_flags2 = rtnl_addr_str2flags(buf); + ck_assert_int_eq(ifa_flags2, ifa_flags); +} +END_TEST + +Suite *make_nl_addr_suite(void) +{ + Suite *suite = suite_create("Abstract addresses"); + TCase *tc = tcase_create("Core"); + + tcase_add_test(tc, addr_alloc); + tcase_add_test(tc, addr_binary_addr); + tcase_add_test(tc, addr_parse4); + tcase_add_test(tc, addr_parse6); + tcase_add_test(tc, addr_info); + tcase_add_test(tc, addr_flags2str); + suite_add_tcase(suite, tc); + + return suite; +} diff --git a/tests/cksuite-all-attr.c b/tests/cksuite-all-attr.c new file mode 100644 index 0000000..b4ac61f --- /dev/null +++ b/tests/cksuite-all-attr.c @@ -0,0 +1,159 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Thomas Graf + */ + +#include "nl-default.h" + +#include +#include + +#include +#include +#include + +#include "cksuite-all.h" +#include "nl-aux-route/nl-route.h" + +START_TEST(attr_size) +{ + ck_assert_msg(nla_attr_size(0) == NLA_HDRLEN, + "Length of empty attribute should match header size"); + ck_assert_msg(nla_attr_size(1) == NLA_HDRLEN + 1, + "Length of 1 bytes payload should be NLA_HDRLEN + 1"); + ck_assert_msg(nla_attr_size(2) == NLA_HDRLEN + 2, + "Length of 2 bytes payload should be NLA_HDRLEN + 2"); + ck_assert_msg(nla_attr_size(3) == NLA_HDRLEN + 3, + "Length of 3 bytes payload should be NLA_HDRLEN + 3"); + ck_assert_msg(nla_attr_size(4) == NLA_HDRLEN + 4, + "Length of 4 bytes payload should be NLA_HDRLEN + 4"); + + ck_assert_msg(nla_total_size(1) == NLA_HDRLEN + 4, + "Total size of 1 bytes payload should result in 8 bytes"); + ck_assert_msg(nla_total_size(2) == NLA_HDRLEN + 4, + "Total size of 2 bytes payload should result in 8 bytes"); + ck_assert_msg(nla_total_size(3) == NLA_HDRLEN + 4, + "Total size of 3 bytes payload should result in 8 bytes"); + ck_assert_msg(nla_total_size(4) == NLA_HDRLEN + 4, + "Total size of 4 bytes payload should result in 8 bytes"); + + ck_assert_msg(nla_padlen(1) == 3, + "2 bytes of payload should result in 3 padding bytes"); + ck_assert_msg(nla_padlen(2) == 2, + "2 bytes of payload should result in 2 padding bytes"); + ck_assert_msg(nla_padlen(3) == 1, + "3 bytes of payload should result in 1 padding bytes"); + ck_assert_msg(nla_padlen(4) == 0, + "4 bytes of payload should result in 0 padding bytes"); + ck_assert_msg(nla_padlen(5) == 3, + "5 bytes of payload should result in 3 padding bytes"); +} +END_TEST + +START_TEST(msg_construct) +{ + struct nl_msg *msg; + struct nlmsghdr *nlh; + struct nlattr *a; + int i, rem; + + msg = nlmsg_alloc(); + ck_assert_msg(msg, "Unable to allocate netlink message"); + + for (i = 1; i < 256; i++) { + ck_assert_msg(nla_put_u32(msg, i, i + 1) == 0, + "Unable to add attribute %d", i); + } + + nlh = nlmsg_hdr(msg); + i = 1; + nlmsg_for_each_attr(a, nlh, 0, rem) { + ck_assert_msg(nla_type(a) == i, "Expected attribute %d", i); + i++; + ck_assert_msg(nla_get_u32(a) == i, + "Expected attribute value %d", i); + } + + nlmsg_free(msg); +} +END_TEST + +START_TEST(clone_cls_u32) +{ + _nl_auto_rtnl_link struct rtnl_link *link = NULL; + _nl_auto_rtnl_cls struct rtnl_cls *cls = NULL; + _nl_auto_rtnl_cls struct rtnl_cls *cls2 = NULL; + int r; + const uint32_t direction = 16; + + link = rtnl_link_alloc(); + ck_assert(link); + + rtnl_link_set_ifindex(link, 5); + + cls = rtnl_cls_alloc(); + ck_assert(cls); + + rtnl_tc_set_link(TC_CAST(cls), link); + + r = rtnl_tc_set_kind(TC_CAST(cls), "u32"); + ck_assert(r == 0); + + rtnl_cls_set_prio(cls, 1); + rtnl_cls_set_protocol(cls, ETH_P_IP); + + rtnl_tc_set_parent(TC_CAST(cls), TC_HANDLE(1, 0)); + + rtnl_u32_set_hashtable(cls, 5); + + rtnl_u32_add_key_uint32(cls, 0x0a000914, 0xffffffff, direction, 0); + + rtnl_u32_set_hashmask(cls, 0xff000000, direction); + + rtnl_u32_add_mark(cls, 55, 66); + + rtnl_u32_set_link(cls, 44); + + cls2 = (struct rtnl_cls *)nl_object_clone((struct nl_object *)cls); + ck_assert(cls2); +} +END_TEST + +/*****************************************************************************/ + +START_TEST(test_nltst_strtok) +{ +#define _assert_strtok(str, ...) \ + do { \ + const char *const _expected[] = { NULL, ##__VA_ARGS__, NULL }; \ + _nltst_auto_strfreev char **_tokens = NULL; \ + \ + _tokens = _nltst_strtokv(str); \ + _nltst_assert_strv_equal(_tokens, &_expected[1]); \ + } while (0) + + _assert_strtok(""); + _assert_strtok(" \n"); + _assert_strtok("a", "a"); + _assert_strtok(" a ", "a"); + _assert_strtok(" a\\ b", "a\\ ", "b"); + _assert_strtok(" a\\ b cc\\d", "a\\ ", "b", "cc\\d"); + _assert_strtok(" a\\ b\\ cc\\d", "a\\ ", "b\\ ", "cc\\d"); +} +END_TEST + +/*****************************************************************************/ + +Suite *make_nl_attr_suite(void) +{ + Suite *suite = suite_create("Netlink attributes"); + TCase *tc = tcase_create("Core"); + + tcase_add_test(tc, attr_size); + tcase_add_test(tc, msg_construct); + tcase_add_test(tc, clone_cls_u32); + tcase_add_test(tc, test_nltst_strtok); + suite_add_tcase(suite, tc); + + return suite; +} diff --git a/tests/cksuite-all-ematch-tree-clone.c b/tests/cksuite-all-ematch-tree-clone.c new file mode 100644 index 0000000..c48a9dd --- /dev/null +++ b/tests/cksuite-all-ematch-tree-clone.c @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include +#include +#include + +#include + +#include + +#include "cksuite-all.h" +#include "nl-aux-route/nl-route.h" +#include "nl-priv-dynamic-route/nl-priv-dynamic-route.h" + +#define MAX_DEPTH 6 +#define MAX_CHILDREN 5 + +static int current_depth = 0; +static int id = 1; +static long long array_size = 0; + +static long long my_pow(long long x, long long y) +{ + int ret = x; + + if (y == 0) + return 1; + + if (y < 0 || x == 0) + return 0; + + while (--y) { + ret *= x; + } + + return ret; +} + +static int build_children(struct nl_list_head *parent) +{ + int i, num = 0; + struct rtnl_ematch *child = NULL; + + if (!parent) + return 0; + + if (++current_depth > MAX_DEPTH) { + --current_depth; + return 0; + } + + num = _nltst_rand_u32() % ((unsigned)(MAX_CHILDREN + 1)); + for (i = 0; i < num; ++i) { + child = rtnl_ematch_alloc(); + if (!child) { + printf("Mem alloc error\n"); + exit(1); + } + build_children(&child->e_childs); + child->e_id = id++; + nl_list_add_tail(&child->e_list, parent); + } + + --current_depth; + return 0; +} + +static void build_src_cgroup(struct rtnl_ematch_tree *tree) +{ + build_children(&tree->et_list); +} + +static void dump_ematch_list(struct nl_list_head *head, int *result, int *index) +{ + struct rtnl_ematch *pos = NULL; + + nl_list_for_each_entry(pos, head, e_list) { + if (!nl_list_empty(&pos->e_childs)) + dump_ematch_list(&pos->e_childs, result, index); + result[*index] = pos->e_id; + (*index)++; + } +} + +static void dump_ematch_tree(struct rtnl_ematch_tree *tree, int *result, + int *index) +{ + if (!tree) + return; + + dump_ematch_list(&tree->et_list, result, index); +} + +static int compare(int *r1, int *r2, int len) +{ + int i = 0; + for (i = 0; i < len; ++i) { + if (r1[i] != r2[i]) + return -1; + } + return 0; +} + +START_TEST(ematch_tree_clone) +{ + _nl_auto_rtnl_ematch_tree struct rtnl_ematch_tree *src = NULL; + _nl_auto_rtnl_ematch_tree struct rtnl_ematch_tree *dst = NULL; + _nl_auto_free int *src_result = NULL; + _nl_auto_free int *dst_result = NULL; + int i = 0; + int j = 0; + + array_size = (MAX_DEPTH * my_pow(MAX_CHILDREN, MAX_DEPTH)) / 2; + src_result = calloc(4, array_size); + dst_result = calloc(4, array_size); + + src = rtnl_ematch_tree_alloc(2); + + build_src_cgroup(src); + dump_ematch_tree(src, src_result, &i); + + dst = rtnl_ematch_tree_clone(src); + dump_ematch_tree(dst, dst_result, &j); + + ck_assert(dst); + ck_assert(i == j); + ck_assert(!compare(src_result, dst_result, i)); +} +END_TEST + +Suite *make_nl_ematch_tree_clone_suite(void) +{ + Suite *suite = suite_create("Clone ematch tree"); + TCase *tc = tcase_create("Core"); + + tcase_add_test(tc, ematch_tree_clone); + suite_add_tcase(suite, tc); + + return suite; +} diff --git a/tests/cksuite-all-netns.c b/tests/cksuite-all-netns.c new file mode 100644 index 0000000..c6a5ce2 --- /dev/null +++ b/tests/cksuite-all-netns.c @@ -0,0 +1,318 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Author: Susant Sahani + * Copyright (c) 2018 Red Hat, Inc. + */ + +#include "nl-default.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cksuite-all.h" + +/*****************************************************************************/ + +static void _nltst_delete_link2(const char *ifname) +{ + _nltst_delete_link(NULL, ifname); +} +#define _nltst_auto_delete_link _nl_auto(_nltst_auto_delete_link_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(const char *, _nltst_auto_delete_link_fcn, + _nltst_delete_link2); + +/*****************************************************************************/ + +START_TEST(cache_and_clone) +{ + _nl_auto_nl_socket struct nl_sock *sk = NULL; + _nl_auto_nl_cache struct nl_cache *link_cache = NULL; + _nl_auto_free struct nl_object **links_all = NULL; + static const struct { + const char *ifname; + const char *kind; + bool add; + } links[] = { + { + .ifname = "xbr0", + .kind = "bridge", + .add = true, + }, + { + .ifname = "xdummy0", + .kind = "dummy", + .add = true, + }, + { + .ifname = "xbond0", + .kind = "bond", + .add = true, + }, + { + .ifname = "lo", + .kind = NULL, + .add = false, + }, + }; + int i; + int r; + + for (i = 0; i < _NL_N_ELEMENTS(links); i++) { + if (links[i].add) + _nltst_add_link(NULL, links[i].ifname, links[i].kind, + NULL); + } + + sk = _nltst_socket(NETLINK_ROUTE); + + r = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache); + ck_assert_int_eq(r, 0); + + r = nl_cache_refill(sk, link_cache); + ck_assert_int_eq(r, 0); + + for (i = 0; i < _NL_N_ELEMENTS(links); i++) { + _nl_auto_rtnl_link struct rtnl_link *link_clone = NULL; + struct rtnl_link *link; + + link = _nltst_cache_get_link(link_cache, links[i].ifname); + ck_assert_ptr_nonnull(link); + + ck_assert_str_eq(rtnl_link_get_name(link), links[i].ifname); + + if (_nl_streq(links[i].ifname, "lo")) + ck_assert_int_eq(rtnl_link_get_ifindex(link), 1); + else + ck_assert_int_gt(rtnl_link_get_ifindex(link), 1); + + link_clone = (struct rtnl_link *)nl_object_clone( + (struct nl_object *)link); + ck_assert(link_clone); + + _nltst_object_identical(link, link_clone); + } + + links_all = _nltst_cache_get_all(link_cache, NULL); + for (i = 0; links_all[i]; i++) { + struct rtnl_link *link = (struct rtnl_link *)links_all[i]; + _nl_auto_rtnl_link struct rtnl_link *link_clone = NULL; + + link_clone = (struct rtnl_link *)nl_object_clone( + (struct nl_object *)link); + ck_assert(link_clone); + + _nltst_object_identical(link, link_clone); + } +} +END_TEST + +/*****************************************************************************/ + +START_TEST(test_create_iface) +{ + const int TEST_IDX = _i; + _nl_auto_nl_socket struct nl_sock *sk = _nltst_socket(NETLINK_ROUTE); + _nl_auto_rtnl_link struct rtnl_link *link = NULL; + _nl_auto_rtnl_link struct rtnl_link *link2 = NULL; + _nl_auto_rtnl_link struct rtnl_link *peer = NULL; + _nltst_auto_delete_link const char *IFNAME_DUMMY = NULL; + _nltst_auto_delete_link const char *IFNAME = "ifname"; + int ifindex_dummy; + uint32_t u32; + int r; + + switch (TEST_IDX) { + case 0: + link = _nltst_assert(rtnl_link_bridge_alloc()); + rtnl_link_set_name(link, IFNAME); + break; + case 1: + link = _nltst_assert(rtnl_link_vxlan_alloc()); + rtnl_link_set_name(link, IFNAME); + _nltst_assert_retcode(rtnl_link_vxlan_set_id(link, 128)); + break; + case 2: + link = _nltst_assert(rtnl_link_alloc()); + rtnl_link_set_type(link, "ifb"); + rtnl_link_set_name(link, IFNAME); + break; + case 3: + link = _nltst_assert(rtnl_link_ipgre_alloc()); + rtnl_link_set_name(link, IFNAME); + _nltst_assert_retcode(rtnl_link_ipgre_set_local( + link, _nltst_inet4("192.168.254.12"))); + _nltst_assert_retcode(rtnl_link_ipgre_set_remote( + link, _nltst_inet4("192.168.254.13"))); + _nltst_assert_retcode(rtnl_link_ipgre_set_ttl(link, 64)); + break; + case 4: + link = _nltst_assert(rtnl_link_ip6_tnl_alloc()); + rtnl_link_set_name(link, IFNAME); + _nltst_assert_retcode(rtnl_link_ip6_tnl_set_local( + link, _nltst_inet6p("2607:f0d0:1002:51::4"))); + _nltst_assert_retcode(rtnl_link_ip6_tnl_set_remote( + link, _nltst_inet6p("2607:f0d0:1002:52::5"))); + break; + case 5: + link = _nltst_assert(rtnl_link_ipgretap_alloc()); + rtnl_link_set_name(link, IFNAME); + _nltst_assert_retcode(rtnl_link_ipgre_set_local( + link, _nltst_inet4("10.211.55.10"))); + _nltst_assert_retcode(rtnl_link_ipgre_set_remote( + link, _nltst_inet4("10.133.6.33"))); + _nltst_assert_retcode(rtnl_link_ipgre_set_ttl(link, 64)); + break; + case 6: + link = _nltst_assert(rtnl_link_ipvti_alloc()); + rtnl_link_set_name(link, IFNAME); + _nltst_assert_retcode(rtnl_link_ipvti_set_local( + link, _nltst_inet4("192.168.254.12"))); + _nltst_assert_retcode(rtnl_link_ipvti_set_remote( + link, _nltst_inet4("192.168.254.13"))); + break; + case 7: + link = _nltst_assert(rtnl_link_sit_alloc()); + rtnl_link_set_name(link, IFNAME); + _nltst_assert_retcode(rtnl_link_sit_set_local( + link, _nltst_inet4("192.168.254.12"))); + _nltst_assert_retcode(rtnl_link_sit_set_remote( + link, _nltst_inet4("192.168.254.13"))); + _nltst_assert_retcode(rtnl_link_sit_set_ttl(link, 64)); + break; + case 8: + link = _nltst_assert(rtnl_link_ipip_alloc()); + rtnl_link_set_name(link, IFNAME); + _nltst_assert_retcode(rtnl_link_ipip_set_local( + link, _nltst_inet4("192.168.254.12"))); + _nltst_assert_retcode(rtnl_link_ipip_set_remote( + link, _nltst_inet4("192.168.254.13"))); + _nltst_assert_retcode(rtnl_link_ipip_set_ttl(link, 64)); + break; + case 9: + link = _nltst_assert(rtnl_link_bond_alloc()); + rtnl_link_set_name(link, IFNAME); + break; + case 10: + IFNAME_DUMMY = "ci-dummy"; + _nltst_add_link(sk, IFNAME_DUMMY, "dummy", &ifindex_dummy); + + link = _nltst_assert(rtnl_link_macvtap_alloc()); + rtnl_link_set_link(link, ifindex_dummy); + rtnl_link_set_name(link, IFNAME); + _nltst_assert_retcode(rtnl_link_macvtap_set_mode( + link, rtnl_link_macvtap_str2mode("bridge"))); + break; + case 11: + IFNAME_DUMMY = "ci-dummy"; + _nltst_add_link(sk, IFNAME_DUMMY, "dummy", &ifindex_dummy); + + link = _nltst_assert(rtnl_link_macvlan_alloc()); + rtnl_link_set_link(link, ifindex_dummy); + rtnl_link_set_name(link, IFNAME); + break; + case 12: + IFNAME_DUMMY = "ci-dummy"; + _nltst_add_link(sk, IFNAME_DUMMY, "dummy", &ifindex_dummy); + + link = _nltst_assert(rtnl_link_vlan_alloc()); + rtnl_link_set_link(link, ifindex_dummy); + rtnl_link_set_name(link, IFNAME); + _nltst_assert_retcode(rtnl_link_vlan_set_id(link, 10)); + break; + case 13: + IFNAME_DUMMY = "ci-dummy"; + _nltst_add_link(sk, IFNAME_DUMMY, "dummy", &ifindex_dummy); + + link = _nltst_assert(rtnl_link_macsec_alloc()); + rtnl_link_set_link(link, ifindex_dummy); + rtnl_link_set_name(link, IFNAME); + _nltst_assert_retcode(rtnl_link_macsec_set_port(link, 10)); + _nltst_assert_retcode(rtnl_link_macsec_set_encrypt(link, 1)); + _nltst_assert_retcode( + rtnl_link_macsec_set_replay_protect(link, 1)); + _nltst_assert_retcode(rtnl_link_macsec_set_window(link, 200)); + break; + case 14: + IFNAME_DUMMY = "ci-dummy"; + _nltst_add_link(sk, IFNAME_DUMMY, "dummy", &ifindex_dummy); + + link = _nltst_assert(rtnl_link_ipvlan_alloc()); + rtnl_link_set_link(link, ifindex_dummy); + _nltst_assert_retcode(rtnl_link_ipvlan_set_mode( + link, rtnl_link_ipvlan_str2mode("l2"))); + rtnl_link_set_name(link, IFNAME); + break; + case 15: + link = _nltst_assert(rtnl_link_vrf_alloc()); + rtnl_link_set_name(link, IFNAME); + _nltst_assert_retcode(rtnl_link_vrf_set_tableid(link, 10)); + break; + case 16: { + link = _nltst_assert(rtnl_link_veth_alloc()); + rtnl_link_set_name(link, IFNAME); + peer = _nltst_assert(rtnl_link_veth_get_peer(link)); + rtnl_link_set_name(peer, "ci-veth-peer"); + } break; + default: + ck_assert_msg(0, "unexpected TEST_IDX=%d", _i); + break; + } + + r = rtnl_link_add(sk, link, NLM_F_CREATE); + if (r == -NLE_OPNOTSUPP) { + /* Hm, no kernel module? Skip the test. */ + _nltst_assert_link_not_exists(IFNAME); + IFNAME = NULL; + return; + } + _nltst_assert_retcode(r); + + _nltst_assert_link_exists(IFNAME); + + switch (TEST_IDX) { + case 15: + _nltst_get_link(sk, IFNAME, NULL, &link2); + _nltst_assert_retcode(rtnl_link_vrf_get_tableid(link2, &u32)); + ck_assert_int_eq(u32, 10); + break; + case 16: + _nltst_assert_link_exists("ci-veth-peer"); + if (_nltst_rand_bool()) + IFNAME = "ci-veth-peer"; + break; + } +} +END_TEST + +/*****************************************************************************/ + +Suite *make_nl_netns_suite(void) +{ + Suite *suite = suite_create("netns"); + TCase *tc = tcase_create("Core"); + + tcase_add_checked_fixture(tc, nltst_netns_fixture_setup, + nltst_netns_fixture_teardown); + tcase_add_test(tc, cache_and_clone); + tcase_add_loop_test(tc, test_create_iface, 0, 17); + + suite_add_tcase(suite, tc); + + return suite; +} diff --git a/tests/cksuite-all.h b/tests/cksuite-all.h new file mode 100644 index 0000000..26e9b5c --- /dev/null +++ b/tests/cksuite-all.h @@ -0,0 +1,13 @@ +#ifndef __LIBNL3_TESTS_CHECK_ALL_H__ +#define __LIBNL3_TESTS_CHECK_ALL_H__ + +#include + +#include "nl-test-util.h" + +Suite *make_nl_attr_suite(void); +Suite *make_nl_addr_suite(void); +Suite *make_nl_ematch_tree_clone_suite(void); +Suite *make_nl_netns_suite(void); + +#endif /* __LIBNL3_TESTS_CHECK_ALL_H__ */ diff --git a/tests/nl-test-util.c b/tests/nl-test-util.c new file mode 100644 index 0000000..52188a0 --- /dev/null +++ b/tests/nl-test-util.c @@ -0,0 +1,655 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include "nl-test-util.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "nl-aux-route/nl-route.h" + +/*****************************************************************************/ + +void _nltst_get_urandom(void *ptr, size_t len) +{ + int fd; + ssize_t nread; + + ck_assert_int_gt(len, 0); + ck_assert_ptr_nonnull(ptr); + + fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOCTTY); + _nltst_assert_errno(fd >= 0); + + nread = read(fd, ptr, len); + _nltst_assert_errno(nread == len); + + _nltst_close(fd); +} + +uint32_t _nltst_rand_u32(void) +{ + _nl_thread_local static unsigned short entropy[3]; + _nl_thread_local static bool has_entropy = false; + + if (!has_entropy) { + unsigned long long seed; + uint64_t seed64; + const char *s; + char *s_end; + + memset(entropy, 0, sizeof(entropy)); + s = getenv("NLTST_SEED_RAND"); + if (!s) + seed = 0; + else if (s[0] != '\0') { + errno = 0; + seed = strtoull(s, &s_end, 10); + if (errno != 0 || s_end[0] != '\0') { + ck_assert_msg( + 0, + "invalid NLTST_SEED_RAND=\"%s\". Must be an integer to seed the random numbers", + s); + } + } else + _nltst_get_urandom(&seed, sizeof(seed)); + + seed64 = seed; + printf("runs with NLTST_SEED_RAND=%" PRIu64 "\n", seed64); + + entropy[0] = (seed64 >> 0) ^ (seed64 >> 48); + entropy[1] = (seed64 >> 16) ^ (seed64 >> 0); + entropy[2] = (seed64 >> 32) ^ (seed64 >> 16); + has_entropy = true; + } + + _NL_STATIC_ASSERT(sizeof(long) >= sizeof(uint32_t)); + return jrand48(entropy); +} + +/*****************************************************************************/ + +#define _CANARY 539339 + +struct nltst_netns { + int canary; +}; + +/*****************************************************************************/ + +#define _assert_nltst_netns(nsdata) \ + do { \ + const struct nltst_netns *_nsdata = (nsdata); \ + \ + ck_assert_ptr_nonnull(_nsdata); \ + ck_assert_int_eq(_nsdata->canary, _CANARY); \ + } while (0) + +static struct { + struct nltst_netns *nsdata; +} _netns_fixture_global; + +void nltst_netns_fixture_setup(void) +{ + ck_assert(!_netns_fixture_global.nsdata); + + _netns_fixture_global.nsdata = nltst_netns_enter(); + _assert_nltst_netns(_netns_fixture_global.nsdata); +} + +void nltst_netns_fixture_teardown(void) +{ + _assert_nltst_netns(_netns_fixture_global.nsdata); + _nl_clear_pointer(&_netns_fixture_global.nsdata, nltst_netns_leave); +} + +/*****************************************************************************/ + +static void unshare_user(void) +{ + const uid_t uid = geteuid(); + const gid_t gid = getegid(); + FILE *f; + int r; + + /* Become a root in new user NS. */ + r = unshare(CLONE_NEWUSER); + _nltst_assert_errno(r == 0); + + /* Since Linux 3.19 we have to disable setgroups() in order to map users. + * Just proceed if the file is not there. */ + f = fopen("/proc/self/setgroups", "we"); + if (f) { + r = fprintf(f, "deny"); + _nltst_assert_errno(r > 0); + _nltst_fclose(f); + } + + /* Map current UID to root in NS to be created. */ + f = fopen("/proc/self/uid_map", "we"); + if (!f) { + if (errno == EACCES) { + /* Accessing uid_map might fail due to sandboxing. + * We ignore that error and proceed with the test. It will probably + * still work. */ + return; + } + _nltst_assert_errno(f); + } + r = fprintf(f, "0 %d 1", uid); + _nltst_assert_errno(r > 0); + _nltst_fclose(f); + + /* Map current GID to root in NS to be created. */ + f = fopen("/proc/self/gid_map", "we"); + _nltst_assert_errno(f); + r = fprintf(f, "0 %d 1", gid); + _nltst_assert_errno(r > 0); + _nltst_fclose(f); +} + +struct nltst_netns *nltst_netns_enter(void) +{ + struct nltst_netns *nsdata; + int r; + + nsdata = calloc(1, sizeof(struct nltst_netns)); + ck_assert(nsdata); + + nsdata->canary = _CANARY; + + unshare_user(); + + r = unshare(CLONE_NEWNET | CLONE_NEWNS); + _nltst_assert_errno(r == 0); + + /* We need a read-only /sys so that the platform knows there's no udev. */ + mount(NULL, "/sys", "sysfs", MS_SLAVE, NULL); + r = mount("sys", "/sys", "sysfs", MS_RDONLY, NULL); + _nltst_assert_errno(r == 0); + + return nsdata; +} + +void nltst_netns_leave(struct nltst_netns *nsdata) +{ + ck_assert(nsdata); + ck_assert_int_eq(nsdata->canary, _CANARY); + + /* nltst_netns_leave() was supposed to enter the original namespaces again + * and undo enter. + * + * However, I could get it to work (setns() always fails with EPERM) + * and valgrind on current Ubuntu seems not to support setns() call. + * + * So, do nothing. It's not really a problem, because the next test + * either should unshare yet another namespace, or not care about + * such things. */ + + free(nsdata); +} + +/*****************************************************************************/ + +void _nltst_object_identical(const void *a, const void *b) +{ + struct nl_object *o_a = (void *)a; + struct nl_object *o_b = (void *)b; + + ck_assert(a); + ck_assert(b); + + ck_assert_int_eq(nl_object_identical(o_a, o_b), 1); + ck_assert_int_eq(nl_object_identical(o_b, o_a), 1); + ck_assert_int_eq(nl_object_diff64(o_b, o_a), 0); + ck_assert_int_eq(nl_object_diff64(o_a, o_b), 0); + ck_assert_int_eq(nl_object_diff(o_a, o_b), 0); + ck_assert_int_eq(nl_object_diff(o_b, o_a), 0); +} + +/*****************************************************************************/ + +char *_nltst_object_to_string(struct nl_object *obj) +{ + size_t L = 1024; + size_t l; + char *s; + + if (!obj) + return strdup("(null)"); + + s = malloc(L); + ck_assert_ptr_nonnull(s); + + nl_object_dump_buf(obj, s, L); + l = strlen(s); + ck_assert_int_lt(l, L); + s = realloc(s, l + 1); + ck_assert_ptr_nonnull(s); + return s; +} + +struct cache_get_all_data { + struct nl_object **arr; + size_t len; + size_t idx; +}; + +static void _cache_get_all_fcn(struct nl_object *obj, void *user_data) +{ + struct cache_get_all_data *data = user_data; + size_t i; + + ck_assert(obj); + ck_assert_int_lt(data->idx, data->len); + + for (i = 0; i < data->idx; i++) + ck_assert_ptr_ne(data->arr[i], obj); + + data->arr[data->idx++] = obj; +} + +struct nl_object **_nltst_cache_get_all(struct nl_cache *cache, size_t *out_len) +{ + int nitems; + struct cache_get_all_data data = { + .idx = 0, + .len = 0, + }; + size_t len2 = 0; + size_t i; + size_t j; + + ck_assert(cache); + + nitems = nl_cache_nitems(cache); + ck_assert_int_ge(nitems, 0); + + data.len = nitems; + data.arr = malloc(sizeof(struct nl_object *) * (data.len + 1)); + ck_assert_ptr_nonnull(data.arr); + + nl_cache_foreach(cache, _cache_get_all_fcn, &data); + + ck_assert_int_eq(data.idx, data.len); + + ck_assert_int_le(data.len, SSIZE_MAX); + + data.arr[data.len] = NULL; + if (out_len) + *out_len = data.len; + + /* double check the result. */ + for (struct nl_object *obj = nl_cache_get_first(cache); obj; + obj = nl_cache_get_next(obj)) { + ck_assert_ptr_eq(data.arr[len2], obj); + len2++; + } + ck_assert_ptr_null(data.arr[len2]); + + for (i = 0; i < data.len; i++) { + ck_assert_ptr_nonnull(data.arr[i]); + for (j = i + 1; j < data.len; j++) + ck_assert_ptr_ne(data.arr[i], data.arr[j]); + } + + return data.arr; +} + +struct rtnl_link *_nltst_cache_get_link(struct nl_cache *cache, + const char *ifname) +{ + _nl_auto_free struct nl_object **objs = NULL; + struct rtnl_link *link = NULL; + size_t i; + + ck_assert_ptr_nonnull(cache); + ck_assert_ptr_nonnull(ifname); + + objs = _nltst_cache_get_all(cache, NULL); + for (i = 0; objs[i]; i++) { + if (_nl_streq(rtnl_link_get_name((struct rtnl_link *)objs[i]), + ifname)) { + ck_assert_ptr_null(link); + link = (struct rtnl_link *)objs[i]; + } + } + + if (_nltst_rand_u32_range(5) == 0) { + _nl_auto_rtnl_link struct rtnl_link *link2 = NULL; + + link2 = rtnl_link_get_by_name(cache, ifname); + ck_assert_ptr_eq(link2, link); + } + + return link; +} + +/*****************************************************************************/ + +struct nl_sock *_nltst_socket(int protocol) +{ + struct nl_sock *sk; + int r; + + sk = nl_socket_alloc(); + ck_assert(sk); + + r = nl_connect(sk, protocol); + ck_assert_int_eq(r, 0); + + if (_nltst_rand_u32_range(5) == 0) + nl_cache_free(_nltst_rtnl_link_alloc_cache(sk, AF_UNSPEC, 0)); + + if (_nltst_rand_u32_range(5) == 0) + nl_cache_free(_nltst_rtnl_route_alloc_cache( + sk, _nltst_rand_select(AF_UNSPEC, AF_INET, AF_INET6))); + + return sk; +} + +void _nltst_add_link(struct nl_sock *sk, const char *ifname, const char *kind, + int *out_ifindex) +{ + _nl_auto_nl_socket struct nl_sock *sk_free = NULL; + _nl_auto_rtnl_link struct rtnl_link *link = NULL; + _nl_auto_nl_cache struct nl_cache *cache = NULL; + struct rtnl_link *link2; + int ifindex; + int r; + + ck_assert(ifname); + ck_assert(kind); + + if (_nltst_rand_u32_range(5) == 0) + _nltst_assert_link_not_exists(ifname); + + if (!sk) { + sk = _nltst_socket(NETLINK_ROUTE); + sk_free = sk; + } + + link = rtnl_link_alloc(); + ck_assert(link); + + r = rtnl_link_set_type(link, kind); + ck_assert_int_eq(r, 0); + + rtnl_link_set_name(link, ifname); + + r = rtnl_link_add(sk, link, NLM_F_CREATE); + ck_assert_int_eq(r, 0); + + if (!out_ifindex && _nltst_rand_u32_range(5) != 0) + return; + + cache = _nltst_rtnl_link_alloc_cache(sk, AF_UNSPEC, 0); + + link2 = _nltst_cache_get_link(cache, ifname); + ck_assert_ptr_nonnull(link2); + + ifindex = rtnl_link_get_ifindex(link2); + ck_assert_int_gt(ifindex, 0); + + if (out_ifindex) + *out_ifindex = ifindex; +} + +void _nltst_delete_link(struct nl_sock *sk, const char *ifname) +{ + _nl_auto_nl_socket struct nl_sock *sk_free = NULL; + _nl_auto_rtnl_link struct rtnl_link *link = NULL; + + _nltst_assert_link_exists(ifname); + + if (!sk) { + sk = _nltst_socket(NETLINK_ROUTE); + sk_free = sk; + } + + if (_nltst_rand_u32_range(5) == 0) { + _nl_auto_nl_cache struct nl_cache *cache = NULL; + + cache = _nltst_rtnl_link_alloc_cache(sk, AF_UNSPEC, 0); + ck_assert_ptr_nonnull(_nltst_cache_get_link(cache, ifname)); + } + + link = rtnl_link_alloc(); + ck_assert_ptr_nonnull(link); + + rtnl_link_set_name(link, ifname); + + _nltst_assert_retcode(rtnl_link_delete(sk, link)); + + _nltst_assert_link_not_exists(ifname); +} + +void _nltst_get_link(struct nl_sock *sk, const char *ifname, int *out_ifindex, + struct rtnl_link **out_link) +{ + _nl_auto_nl_cache struct nl_cache *cache = NULL; + struct rtnl_link *link; + + if (_nltst_rand_u32_range(5) == 0) + _nltst_assert_link_exists(ifname); + + cache = _nltst_rtnl_link_alloc_cache(sk, AF_UNSPEC, 0); + + link = _nltst_cache_get_link(cache, ifname); + ck_assert(link); + + if (out_ifindex) + *out_ifindex = rtnl_link_get_ifindex(link); + + if (out_link) { + nl_object_get((struct nl_object *)link); + *out_link = link; + } +} + +struct nl_cache *_nltst_rtnl_link_alloc_cache(struct nl_sock *sk, + int addr_family, unsigned flags) +{ + _nl_auto_nl_socket struct nl_sock *sk_free = NULL; + struct nl_cache *cache; + int r; + + if (!sk) { + sk = _nltst_socket(NETLINK_ROUTE); + sk_free = sk; + } + + if (flags == 0 && _nltst_rand_bool()) + r = rtnl_link_alloc_cache(sk, addr_family, &cache); + else + r = rtnl_link_alloc_cache_flags(sk, addr_family, &cache, flags); + + _nltst_assert_retcode(r); + + if (_nltst_rand_u32_range(5) == 0) + free(_nltst_cache_get_all(cache, NULL)); + + return _nltst_assert(cache); +} + +struct nl_cache *_nltst_rtnl_route_alloc_cache(struct nl_sock *sk, + int addr_family) +{ + struct nl_cache *cache; + + ck_assert_ptr_nonnull(sk); + ck_assert(addr_family == AF_UNSPEC || addr_family == AF_INET || + addr_family == AF_INET6); + + _nltst_assert_retcode( + rtnl_route_alloc_cache(sk, addr_family, 0, &cache)); + + if (_nltst_rand_u32_range(5) == 0) + free(_nltst_cache_get_all(cache, NULL)); + + return _nltst_assert(cache); +} + +/*****************************************************************************/ + +char *_nltst_strtok(const char **p_str) +{ + const char *str; + _nl_auto_free char *dst = NULL; + size_t dst_len = 0; + size_t dst_alloc = 0; + size_t i; + + ck_assert_ptr_nonnull(p_str); + + str = _nltst_str_skip_space(*p_str); + + if (str[0] == '\0') { + *p_str = str; + return NULL; + } + + dst_len = 0; + dst_alloc = 10; + dst = malloc(dst_alloc); + ck_assert_ptr_nonnull(dst); + + i = 0; + while (true) { + char ch1 = '\0'; + char ch2 = '\0'; + + /* We take the first word, up until whitespace. Note that backslash + * escape is honored, so you can backslash escape spaces. The returned + * string will NOT have backslashes removed. */ + + if (str[i] == '\0') { + *p_str = &str[i]; + break; + } + if (_nltst_char_is_space(str[i])) { + *p_str = _nltst_str_skip_space(&str[i + 1]); + break; + } + ch1 = str[i]; + if (str[i] == '\\') { + if (str[i + 1] != '\0') { + ch2 = str[i + 1]; + i += 2; + } else + i += 1; + } else + i += 1; + + if (dst_len + 3 >= dst_alloc) { + dst_alloc *= 2; + dst = realloc(dst, dst_alloc); + ck_assert_ptr_nonnull(dst); + } + dst[dst_len++] = ch1; + if (ch2 != '\0') + dst[dst_len++] = ch2; + } + + ck_assert_int_gt(dst_len, 0); + return strndup(dst, dst_len); +} + +char **_nltst_strtokv(const char *str) +{ + _nl_auto_free char *s = NULL; + _nltst_auto_strfreev char **result = NULL; + size_t r_len = 0; + size_t r_alloc = 0; + + if (!str) + return NULL; + + r_alloc = 4; + result = malloc(sizeof(char *) * r_alloc); + ck_assert_ptr_nonnull(result); + + while ((s = _nltst_strtok(&str))) { + if (r_len + 2 >= r_alloc) { + r_alloc *= 2; + result = realloc(result, sizeof(char *) * r_alloc); + ck_assert_ptr_nonnull(result); + } + result[r_len++] = _nl_steal_pointer(&s); + } + ck_assert_int_lt(r_len, r_alloc); + result[r_len] = NULL; + return _nl_steal_pointer(&result); +} + +/*****************************************************************************/ + +void _nltst_assert_link_exists_full(const char *ifname, bool exists) +{ + _nl_auto_nl_cache struct nl_cache *cache = NULL; + _nl_auto_rtnl_link struct rtnl_link *link_clone = NULL; + struct rtnl_link *link; + char path[100]; + struct stat st; + int rnd; + int r; + + ck_assert_pstr_ne(ifname, NULL); + ck_assert_int_lt(strlen(ifname), IFNAMSIZ); + + strcpy(path, "/sys/class/net/"); + strcat(path, ifname); + ck_assert_int_lt(strlen(path), sizeof(path)); + + r = stat(path, &st); + if (exists) { + if (r != 0) { + const int errsv = (errno); + + ck_assert_msg( + 0, + "link(%s) does not exist (stat(%s) failed with r=%d, errno=%d (%s)", + ifname, path, r, errsv, strerror(errsv)); + } + } else { + if (r != -1 && errno != ENOENT) { + const int errsv = (errno); + + ck_assert_msg( + 0, + "link(%s) should not exist but stat(%s) gave r=%d, errno=%d (%s)", + ifname, path, r, errsv, strerror(errsv)); + } + } + + rnd = _nltst_rand_u32_range(3); + + if (rnd == 0) + return; + + cache = _nltst_rtnl_link_alloc_cache(NULL, AF_UNSPEC, 0); + + link = _nltst_cache_get_link(cache, ifname); + if (exists) + ck_assert_ptr_nonnull(link); + else + ck_assert_ptr_null(link); + + if (!link || rnd == 1) + return; + + link_clone = + (struct rtnl_link *)nl_object_clone((struct nl_object *)link); + ck_assert(link_clone); + + /* FIXME: we would expect that the cloned object is identical. It is not. */ + /* _nltst_object_identical(link, link_clone); */ +} diff --git a/tests/nl-test-util.h b/tests/nl-test-util.h new file mode 100644 index 0000000..ee4bd96 --- /dev/null +++ b/tests/nl-test-util.h @@ -0,0 +1,397 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#ifndef __NL_TEST_UTIL_H__ +#define __NL_TEST_UTIL_H__ + +#include +#include + +#include +#include + +#include "base/nl-base-utils.h" +#include "nl-aux-core/nl-core.h" +#include "nl-aux-route/nl-route.h" + +/*****************************************************************************/ + +static inline void _nltst_strfreev(char **strv) +{ + size_t i; + + if (strv) { + for (i = 0; strv[i]; i++) + free(strv[i]); + free(strv); + } +} + +#define _nltst_auto_strfreev _nl_auto(_nltst_auto_strfreev_fcn) +_NL_AUTO_DEFINE_FCN_TYPED0(char **, _nltst_auto_strfreev_fcn, _nltst_strfreev); + +/*****************************************************************************/ + +#ifndef ck_assert_ptr_nonnull +#define ck_assert_ptr_nonnull(ptr) ck_assert(ptr) +#endif + +#ifndef ck_assert_pstr_ne +#define ck_assert_pstr_ne(a, b) \ + do { \ + const char *_a = (a); \ + const char *_b = (b); \ + \ + ck_assert(!(_a == _b || (_a && _b && strcmp(_a, _b) == 0))); \ + } while (0) +#endif + +#ifndef ck_assert_ptr_null +#define ck_assert_ptr_null(ptr) ck_assert(!(ptr)) +#endif + +/*****************************************************************************/ + +void _nltst_get_urandom(void *ptr, size_t len); + +uint32_t _nltst_rand_u32(void); + +static inline uint32_t _nltst_rand_u32_range(uint32_t n) +{ + uint32_t rem; + uint32_t i; + + if (n == 0) + return _nltst_rand_u32(); + if (n == 1) + return 0; + + rem = UINT32_MAX % n; + for (;;) { + i = _nltst_rand_u32(); + if (i < (UINT32_MAX - rem)) + return i % n; + } +} + +static inline bool _nltst_rand_bool(void) +{ + return _nltst_rand_u32() % 2 == 0; +} + +#define _nltst_rand_select(a, ...) \ + ({ \ + const typeof(a) _lst[] = { (a), ##__VA_ARGS__ }; \ + \ + _lst[_nltst_rand_u32_range(_NL_N_ELEMENTS(_lst))]; \ + }) + +/*****************************************************************************/ + +#define _nltst_assert(expr) \ + ({ \ + typeof(expr) _expr = (expr); \ + \ + if (!_expr) { \ + ck_assert_msg(0, "assert(%s) failed", #expr); \ + } \ + _expr; \ + }) + +#define _nltst_assert_errno(expr) \ + do { \ + if (expr) { \ + } else { \ + const int _errno = (errno); \ + \ + ck_assert_msg(0, "assert(%s) failed (errno=%d, %s)", \ + #expr, _errno, strerror(_errno)); \ + } \ + } while (0) + +#define _nltst_assert_retcode(expr) \ + do { \ + const int _r = (expr); \ + \ + if (_r < 0) { \ + ck_assert_msg( \ + 0, "command(%s) failed with return code %d", \ + #expr, _r); \ + } \ + if (_r > 0) { \ + ck_assert_msg( \ + 0, \ + "command(%s) has unexpected positive return code %d", \ + #expr, _r); \ + } \ + } while (0) + +#define _nltst_close(fd) \ + do { \ + int _r; \ + \ + _r = _nl_close((fd)); \ + _nltst_assert_errno(_r == 0); \ + } while (0) + +#define _nltst_fclose(f) \ + do { \ + int _r; \ + \ + _r = fclose((f)); \ + _nltst_assert_errno(_r == 0); \ + } while (0) + +void _nltst_assert_link_exists_full(const char *ifname, bool exists); + +#define _nltst_assert_link_exists(ifname) \ + _nltst_assert_link_exists_full((ifname), true) + +#define _nltst_assert_link_not_exists(ifname) \ + _nltst_assert_link_exists_full((ifname), false) + +/*****************************************************************************/ + +typedef union { + in_addr_t addr4; + struct in_addr a4; + struct in6_addr a6; +} NLTstIPAddr; + +static inline char *_nltst_inet_ntop(int addr_family, const void *addr, + char buf[static INET_ADDRSTRLEN]) +{ + char *r; + + ck_assert(addr_family == AF_INET || addr_family == AF_INET6); + ck_assert(addr); + + r = (char *)inet_ntop(addr_family, addr, buf, + (addr_family == AF_INET) ? INET_ADDRSTRLEN : + INET6_ADDRSTRLEN); + ck_assert_ptr_eq(r, buf); + ck_assert_int_lt(strlen(r), (addr_family == AF_INET) ? + INET_ADDRSTRLEN : + INET6_ADDRSTRLEN); + return r; +} + +static inline char *_nltst_inet_ntop_dup(int addr_family, const void *addr) +{ + return (char *)_nltst_inet_ntop(addr_family, addr, + malloc((addr_family == AF_INET) ? + INET_ADDRSTRLEN : + INET6_ADDRSTRLEN)); +} + +static inline bool _nltst_inet_pton(int addr_family, const char *str, + int *out_addr_family, void *out_addr) +{ + NLTstIPAddr a; + int r; + + ck_assert(addr_family == AF_UNSPEC || addr_family == AF_INET || + addr_family == AF_INET6); + + /* when requesting @out_addr, then the addr-family must either be + * pre-determined or requested too. */ + ck_assert(!out_addr || out_addr_family || addr_family != AF_UNSPEC); + + if (!str) + return false; + + if (addr_family == AF_UNSPEC) + addr_family = strchr(str, ':') ? AF_INET6 : AF_INET; + + r = inet_pton(addr_family, str, &a); + if (r != 1) + return false; + + if (out_addr) { + memcpy(out_addr, &a, + addr_family == AF_INET ? sizeof(in_addr_t) : + sizeof(struct in6_addr)); + } + if (out_addr_family) + *out_addr_family = addr_family; + + return true; +} + +static inline bool _nltst_inet_valid(int addr_family, const char *addr) +{ + return _nltst_inet_pton(addr_family, addr, NULL, NULL); +} + +static inline in_addr_t _nltst_inet4(const char *addr) +{ + in_addr_t addr_bin = 0; + + _nltst_assert(_nltst_inet_pton(AF_INET, addr, NULL, &addr_bin)); + return addr_bin; +} + +static inline struct in6_addr *_nltst_inet6p(const char *addr) +{ + _nl_thread_local static struct in6_addr addr_bin; + + ck_assert(_nltst_inet_pton(AF_INET6, addr, NULL, &addr_bin)); + return &addr_bin; +} + +static inline struct in6_addr _nltst_inet6(const char *addr) +{ + struct in6_addr addr_bin; + + ck_assert(_nltst_inet_pton(AF_INET6, addr, NULL, &addr_bin)); + return addr_bin; +} + +static inline int _nltst_inet_addr_family(int addr_family, const char *addr) +{ + if (!_nltst_inet_pton(addr_family, addr, &addr_family, NULL)) + return AF_UNSPEC; + return addr_family; +} + +static inline char *_nltst_inet_normalize(int addr_family, const char *addr, + char buf[static INET_ADDRSTRLEN]) +{ + NLTstIPAddr a; + + buf[0] = '\0'; + if (!_nltst_inet_pton(addr_family, addr, &addr_family, &a)) + return NULL; + return _nltst_inet_ntop(addr_family, &a, buf); +} + +/*****************************************************************************/ + +char *_nltst_strtok(const char **p_str); + +char **_nltst_strtokv(const char *str); + +#define _nltst_assert_strv_equal(strv1, strv2) \ + do { \ + typeof(strv1) _strv1 = (strv1); \ + typeof(strv2) _strv2 = (strv2); \ + _nl_unused const void *_strv1_typecheck1 = _strv1; \ + _nl_unused const void *_strv2_typecheck1 = _strv2; \ + _nl_unused const char *_strv1_typecheck2 = \ + _strv1 ? _strv1[0] : NULL; \ + _nl_unused const char *_strv2_typecheck2 = \ + _strv2 ? _strv2[0] : NULL; \ + size_t _i; \ + \ + ck_assert_int_eq(!!_strv1, !!_strv2); \ + if (_strv1) { \ + for (_i = 0; _strv1[_i] || _strv2[_i]; _i++) { \ + ck_assert_str_eq(_strv1[_i], _strv2[_i]); \ + } \ + } \ + } while (0) + +#define _NLTST_CHARSET_SPACE " \n\r\t" + +#define _nltst_char_is(ch, charset) (!!(strchr("" charset "", (ch)))) + +#define _nltst_char_is_space(ch) _nltst_char_is(ch, _NLTST_CHARSET_SPACE) + +#define _nltst_str_skip_predicate(s, ch, predicate) \ + ({ \ + typeof(s) _s1 = (s); \ + _nl_unused const char *_s1_typecheck = (_s1); \ + \ + if (_s1) { \ + while (({ \ + const char ch = _s1[0]; \ + \ + (ch != '\0') && (predicate); \ + })) \ + _s1++; \ + } \ + _s1; \ + }) + +#define _nltst_str_skip_charset(s, charset) \ + _nltst_str_skip_predicate(s, _ch, _nltst_char_is(_ch, "" charset "")) + +#define _nltst_str_skip_space(s) \ + _nltst_str_skip_charset(s, _NLTST_CHARSET_SPACE) + +#define _nltst_str_has_prefix_and_space(s, prefix) \ + ({ \ + typeof(s) _s2 = (s); \ + _nl_unused const char *_s2_typecheck = (_s2); \ + const size_t _l = strlen("" prefix ""); \ + \ + if (_s2) { \ + if ((strncmp(_s2, "" prefix "", _l)) == 0 && \ + _nltst_char_is_space(_s2[_l])) \ + _s2 = _nltst_str_skip_space(&_s2[_l + 1]); \ + else \ + _s2 = NULL; \ + } \ + _s2; \ + }) + +#define _nltst_str_find_first_not_from_charset(s, charset) \ + ({ \ + typeof(s) _s3 = (s); \ + _nl_unused const char *_s3_typecheck = (_s3); \ + size_t _l3; \ + \ + _l3 = strspn(_s3, "" charset ""); \ + \ + &_s3[_l3]; \ + }) + +#define _nltst_str_find_first_from_charset(s, charset) \ + ({ \ + typeof(s) _s3 = (s); \ + _nl_unused const char *_s3_typecheck = (_s3); \ + size_t _l3; \ + \ + _l3 = strcspn(_s3, "" charset ""); \ + \ + &_s3[_l3]; \ + }) + +/*****************************************************************************/ + +void nltst_netns_fixture_setup(void); +void nltst_netns_fixture_teardown(void); + +struct nltst_netns; + +struct nltst_netns *nltst_netns_enter(void); +void nltst_netns_leave(struct nltst_netns *nsdata); + +/*****************************************************************************/ + +void _nltst_object_identical(const void *a, const void *b); + +char *_nltst_object_to_string(struct nl_object *obj); + +struct nl_object **_nltst_cache_get_all(struct nl_cache *cache, + size_t *out_len); + +struct rtnl_link *_nltst_cache_get_link(struct nl_cache *cache, + const char *ifname); + +struct nl_cache *_nltst_rtnl_link_alloc_cache(struct nl_sock *sk, + int addr_family, unsigned flags); + +struct nl_cache *_nltst_rtnl_route_alloc_cache(struct nl_sock *sk, + int addr_family); + +struct nl_sock *_nltst_socket(int protocol); + +void _nltst_add_link(struct nl_sock *sk, const char *ifname, const char *kind, + int *out_ifindex); + +void _nltst_delete_link(struct nl_sock *sk, const char *ifname); + +void _nltst_get_link(struct nl_sock *sk, const char *ifname, int *out_ifindex, + struct rtnl_link **out_link); + +#endif /* __NL_TEST_UTIL_H__ */ diff --git a/tests/test-cache-mngr.c b/tests/test-cache-mngr.c index 8999e58..cc0e15b 100644 --- a/tests/test-cache-mngr.c +++ b/tests/test-cache-mngr.c @@ -1,20 +1,46 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include +#include +#include + +#include + #include #include #include -#include - -#include static int quit = 0; +static int change = 1; +static int print_ts = 0; -static struct nl_dump_params dp = { +static struct nl_dump_params params = { .dp_type = NL_DUMP_LINE, }; +static void print_timestamp(FILE *fp) +{ + struct timeval tv; + char tshort[40]; + struct tm *tm; + struct tm tm_buf; + + gettimeofday(&tv, NULL); + tm = localtime_r(&tv.tv_sec, &tm_buf); + + strftime(tshort, sizeof(tshort), "%Y-%m-%dT%H:%M:%S", tm); + fprintf(fp, "[%s.%06ld] ", tshort, tv.tv_usec); +} + static void change_cb(struct nl_cache *cache, struct nl_object *obj, int action, void *data) { + if (print_ts) + print_timestamp(stdout); + if (action == NL_ACT_NEW) printf("NEW "); else if (action == NL_ACT_DEL) @@ -22,7 +48,10 @@ static void change_cb(struct nl_cache *cache, struct nl_object *obj, else if (action == NL_ACT_CHANGE) printf("CHANGE "); - nl_object_dump(obj, &dp); + nl_object_dump(obj, ¶ms); + fflush(stdout); + + change = 1; } static void sigint(int arg) @@ -30,34 +59,128 @@ static void sigint(int arg) quit = 1; } +static void print_usage(FILE* stream, const char *name) +{ + fprintf(stream, + "Usage: %s [OPTIONS]... ... \n" + "\n" + "OPTIONS\n" + " -f, --format=TYPE Output format { brief | details | stats }\n" + " Default: brief\n" + " -d, --dump Dump cache content after a change.\n" + " -i, --interval=TIME Dump cache content after TIME seconds when there is no\n" + " change; 0 to disable. Default: 1\n" + " -I, --iter Iterate over all address families when updating caches.\n" + " -t, --tshort Print a short timestamp before change messages.\n" + " -h, --help Show this help text.\n" + , name); +} + int main(int argc, char *argv[]) { + bool dump_on_change = false, dump_on_timeout = true, iter = false; struct nl_cache_mngr *mngr; - struct nl_cache *cache; - int err, i; - - dp.dp_fd = stdout; - - signal(SIGINT, sigint); + int timeout = 1000, err; + + for (;;) { + static struct option long_opts[] = { + { "format", required_argument, 0, 'f' }, + { "dump", no_argument, 0, 'd' }, + { "interval", required_argument, 0, 'i' }, + { "iter", no_argument, 0, 'I' }, + { "tshort", no_argument, 0, 't' }, + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } + }; + int c; + + c = getopt_long(argc, argv, "hf:di:It", long_opts, NULL); + if (c == -1) + break; + + switch (c) { + char *endptr; + long interval; + + case 'f': + params.dp_type = nl_cli_parse_dumptype(optarg); + break; + + case 'd': + dump_on_change = true; + break; + + case 'i': + errno = 0; + interval = strtol(optarg, &endptr, 0); + if (interval < 0 || errno || *endptr) { + nl_cli_fatal(EINVAL, "Invalid interval \"%s\".\n", + optarg); + exit(1); + } + if (!interval) { + dump_on_timeout = false; + } else { + timeout = interval * 1000; + } + + break; + + case 'I': + iter = true; + break; + + case 't': + print_ts = true; + break; + + case 'h': + print_usage(stdout, argv[0]); + exit(0); + + case '?': + print_usage(stderr, argv[0]); + exit(1); + } + } err = nl_cache_mngr_alloc(NULL, NETLINK_ROUTE, NL_AUTO_PROVIDE, &mngr); if (err < 0) nl_cli_fatal(err, "Unable to allocate cache manager: %s", nl_geterror(err)); - for (i = 1; i < argc; i++) { - err = nl_cache_mngr_add(mngr, argv[i], &change_cb, NULL, &cache); + while (optind < argc) { + struct nl_cache *cache; + + err = nl_cache_alloc_name(argv[optind], &cache); + if (err < 0) + nl_cli_fatal(err, "Couldn't add cache %s: %s\n", + argv[optind], nl_geterror(err)); + + if (iter) + nl_cache_set_flags(cache, NL_CACHE_AF_ITER); + + err = nl_cache_mngr_add_cache(mngr, cache, &change_cb, NULL); if (err < 0) nl_cli_fatal(err, "Unable to add cache %s: %s", - argv[i], nl_geterror(err)); + argv[optind], nl_geterror(err)); + + optind++; } + params.dp_fd = stdout; + signal(SIGINT, sigint); + while (!quit) { - int err = nl_cache_mngr_poll(mngr, 1000); + err = nl_cache_mngr_poll(mngr, timeout); if (err < 0 && err != -NLE_INTR) nl_cli_fatal(err, "Polling failed: %s", nl_geterror(err)); - nl_cache_mngr_info(mngr, &dp); + if (dump_on_timeout || (dump_on_change && change)) { + nl_cache_mngr_info(mngr, ¶ms); + fflush(stdout); + change = 0; + } } nl_cache_mngr_free(mngr); diff --git a/tests/test-complex-HTB-with-hash-filters.c b/tests/test-complex-HTB-with-hash-filters.c index 48cf5e3..713ed3e 100644 --- a/tests/test-complex-HTB-with-hash-filters.c +++ b/tests/test-complex-HTB-with-hash-filters.c @@ -1,14 +1,16 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ /* - * test/test-complex-HTB-with-hash-filters.c Add HTB qdisc, HTB classes and creates some hash filters - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * * Copyright (c) 2011 Adrian Ban */ +#include "nl-default.h" + +#include + +#include +#include +#include + #include #include #include @@ -17,19 +19,12 @@ #include #include #include -#include - #include -//#include "include/rtnl_u32.h" - -#include -#include -//#include "include/rtnl_u32_addon.h" #define TC_HANDLE(maj, min) (TC_H_MAJ((maj) << 16) | TC_H_MIN(min)) /* some functions are copied from iproute-tc tool */ -int get_u32(__u32 *val, const char *arg, int base) +static int get_u32(__u32 *val, const char *arg, int base) { unsigned long res; char *ptr; @@ -43,7 +38,7 @@ int get_u32(__u32 *val, const char *arg, int base) return 0; } -int get_u32_handle(__u32 *handle, const char *str) +static int get_u32_handle(__u32 *handle, const char *str) { __u32 htid=0, hash=0, nodeid=0; char *tmp = strchr(str, ':'); @@ -78,7 +73,7 @@ int get_u32_handle(__u32 *handle, const char *str) return 0; } -uint32_t get_u32_parse_handle(const char *cHandle) +static uint32_t get_u32_parse_handle(const char *cHandle) { uint32_t handle=0; @@ -94,7 +89,7 @@ uint32_t get_u32_parse_handle(const char *cHandle) return handle; } -int get_tc_classid(__u32 *h, const char *str) +static int get_tc_classid(__u32 *h, const char *str) { __u32 maj, min; char *p; @@ -134,7 +129,7 @@ ok: * Function that adds a new filter and attach it to a hash table * */ -int u32_add_filter_on_ht(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio, +static int u32_add_filter_on_ht(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio, uint32_t keyval, uint32_t keymask, int keyoff, int keyoffmask, uint32_t htid, uint32_t classid ) @@ -186,7 +181,7 @@ int u32_add_filter_on_ht(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint3 * and set next hash table link with hash mask * */ -int u32_add_filter_on_ht_with_hashmask(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio, +static int u32_add_filter_on_ht_with_hashmask(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio, uint32_t keyval, uint32_t keymask, int keyoff, int keyoffmask, uint32_t htid, uint32_t htlink, uint32_t hmask, uint32_t hoffset ) @@ -237,7 +232,7 @@ int u32_add_filter_on_ht_with_hashmask(struct nl_sock *sock, struct rtnl_link *r /* * function that creates a new hash table */ -int u32_add_ht(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio, uint32_t htid, uint32_t divisor) +static int u32_add_ht(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio, uint32_t htid, uint32_t divisor) { int err; @@ -276,7 +271,7 @@ int u32_add_ht(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio, /* * function that adds a new HTB qdisc and set the default class for unclassified traffic */ -int qdisc_add_HTB(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t defaultClass) +static int qdisc_add_HTB(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t defaultClass) { struct rtnl_qdisc *qdisc; @@ -326,7 +321,7 @@ int qdisc_add_HTB(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t def /* * function that adds a new HTB class and set its parameters */ -int class_add_HTB(struct nl_sock *sock, struct rtnl_link *rtnlLink, +static int class_add_HTB(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t parentMaj, uint32_t parentMin, uint32_t childMaj, uint32_t childMin, uint64_t rate, uint64_t ceil, @@ -388,7 +383,7 @@ int class_add_HTB(struct nl_sock *sock, struct rtnl_link *rtnlLink, /* * function that adds a HTB root class and set its parameters */ -int class_add_HTB_root(struct nl_sock *sock, struct rtnl_link *rtnlLink, +static int class_add_HTB_root(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint64_t rate, uint64_t ceil, uint32_t burst, uint32_t cburst ) @@ -443,7 +438,7 @@ int class_add_HTB_root(struct nl_sock *sock, struct rtnl_link *rtnlLink, /* * function that adds a new SFQ qdisc as a leaf for a HTB class */ -int qdisc_add_SFQ_leaf(struct nl_sock *sock, struct rtnl_link *rtnlLink, +static int qdisc_add_SFQ_leaf(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t parentMaj, uint32_t parentMin, int quantum, int limit, int perturb ) @@ -514,6 +509,8 @@ int main() { struct nl_cache *link_cache; + uint32_t i; + if (!(sock = nl_socket_alloc())) { printf("Unable to allocate netlink socket\n"); exit(1); @@ -576,7 +573,6 @@ int main() { * each entry in hash table match a byte from IP address specified later by a hash key */ - uint32_t i; for (i = 1; i <= 0xf; i++) u32_add_ht(sock, link, 1, i, 256); diff --git a/tests/test-create-bond.c b/tests/test-create-bond.c index 11bc5b0..6edb41f 100644 --- a/tests/test-create-bond.c +++ b/tests/test-create-bond.c @@ -1,3 +1,9 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + #include #include #include diff --git a/tests/test-create-bridge.c b/tests/test-create-bridge.c new file mode 100644 index 0000000..758aaa2 --- /dev/null +++ b/tests/test-create-bridge.c @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +#include +#include +#include + +#define TEST_BRIDGE_NAME "testbridge" +#define TEST_INTERFACE_NAME "testtap1" + +static int create_bridge(struct nl_sock *sk, struct nl_cache *link_cache, const char *name) { + struct rtnl_link *link; + int err; + + link = rtnl_link_alloc(); + if ((err = rtnl_link_set_type(link, "bridge")) < 0) { + rtnl_link_put(link); + return err; + } + rtnl_link_set_name(link, name); + + if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { + return err; + } + rtnl_link_put(link); + + return 0; +} + +int main(int argc, char *argv[]) +{ + struct rtnl_link *link; + struct nl_cache *link_cache; + struct nl_sock *sk; + struct rtnl_link *ltap; + int err; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + if ((err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache)) < 0) { + nl_perror(err, "Unable to allocate cache"); + return err; + } + + if ((err = create_bridge(sk, link_cache, TEST_BRIDGE_NAME)) < 0) { + nl_perror(err, "Unable to allocate testbridge"); + return err; + } + + nl_cache_refill(sk, link_cache); + + link = rtnl_link_get_by_name(link_cache, TEST_BRIDGE_NAME); + ltap = rtnl_link_get_by_name(link_cache, TEST_INTERFACE_NAME); + if (!ltap) { + fprintf(stderr, "You should create a tap interface before lunch this test (# tunctl -t %s)\n", TEST_INTERFACE_NAME); + return -1; + } + + if ((err = rtnl_link_enslave(sk, link, ltap)) < 0) { + nl_perror(err, "Unable to enslave interface to his bridge\n"); + return err; + } + + if(rtnl_link_is_bridge(link) == 0) { + fprintf(stderr, "Link is not a bridge\n"); + return -2; + } + + rtnl_link_put(ltap); + nl_cache_refill(sk, link_cache); + ltap = rtnl_link_get_by_name(link_cache, TEST_INTERFACE_NAME); + + if(rtnl_link_get_master(ltap) <= 0) { + fprintf(stderr, "Interface is not attached to a bridge\n"); + return -3; + } + + rtnl_link_put(ltap); + rtnl_link_put(link); + + nl_cache_free(link_cache); + nl_socket_free(sk); + + return 0; +} diff --git a/tests/test-create-geneve.c b/tests/test-create-geneve.c new file mode 100644 index 0000000..1816e5b --- /dev/null +++ b/tests/test-create-geneve.c @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +#include +#include +#include + +#define IPv6 1 + +int main(int argc, char *argv[]) +{ + struct rtnl_link *link; + struct nl_addr *addr; + struct nl_sock *sk; + int err; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + link = rtnl_link_geneve_alloc(); + + rtnl_link_set_name(link, "gnv123"); + + if ((err = rtnl_link_geneve_set_id(link, 123)) < 0) { + nl_perror(err, "Unable to set GENEVE ID"); + return err; + } + +#if IPv6 + if ((err = nl_addr_parse("2001:0db8:0:f101::1/64", AF_INET6, &addr)) < 0) { + nl_perror(err, "Unable to parse IPv6 address"); + return err; + } + if ((err = rtnl_link_geneve_set_label(link, 123)) < 0) { + nl_perror(err, "Unable to set label"); + return err; + } + + if ((err = rtnl_link_geneve_set_udp_zero_csum6_tx(link, 1)) < 0) { + nl_perror(err, "Unable to set skip transmitted UDP checksum"); + return err; + } + + if ((err = rtnl_link_geneve_set_udp_zero_csum6_rx(link, 1)) < 0) { + nl_perror(err, "Unable to set skip received UDP checksum"); + return err; + } +#else + if ((err = nl_addr_parse("10.4.4.4", AF_INET, &addr)) < 0) { + nl_perror(err, "Unable to parse IP address"); + return err; + } +#endif + + if ((err = rtnl_link_geneve_set_remote(link, addr)) < 0) { + nl_perror(err, "Unable to set remote address"); + return err; + } + nl_addr_put(addr); + + if ((err = rtnl_link_geneve_set_ttl(link, 1)) < 0) { + nl_perror(err, "Unable to set TTL"); + return err; + } + + if ((err = rtnl_link_geneve_set_tos(link, 0)) < 0) { + nl_perror(err, "Unable to set ToS"); + return err; + } + + if ((err = rtnl_link_geneve_set_port(link, 5060)) < 0) { + nl_perror(err, "Unable to set port"); + return err; + } + + if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-create-ifb.c b/tests/test-create-ifb.c new file mode 100644 index 0000000..46524fe --- /dev/null +++ b/tests/test-create-ifb.c @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +#include +#include + +int main(int argc, char *argv[]) +{ + struct rtnl_link *link; + struct nl_sock *sk; + int err; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + link = rtnl_link_alloc(); + rtnl_link_set_type(link, "ifb"); + rtnl_link_set_name(link, "ifb1"); + + if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-create-ip6tnl.c b/tests/test-create-ip6tnl.c new file mode 100644 index 0000000..b0c0281 --- /dev/null +++ b/tests/test-create-ip6tnl.c @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +int main(int argc, char *argv[]) +{ + struct nl_cache *link_cache; + struct rtnl_link *link; + struct in6_addr addr; + struct nl_sock *sk; + int err, if_index; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache); + if ( err < 0) { + nl_perror(err, "Unable to allocate cache"); + return err; + } + + if_index = rtnl_link_name2i(link_cache, "ens33"); + if (!if_index) { + fprintf(stderr, "Unable to lookup ens33"); + return -1; + } + + link = rtnl_link_ip6_tnl_alloc(); + if(!link) { + nl_perror(err, "Unable to allocate link"); + return -1; + + } + rtnl_link_set_name(link, "ip6tnl-tun"); + rtnl_link_ip6_tnl_set_link(link, if_index); + + inet_pton(AF_INET6, "2607:f0d0:1002:51::4", &addr); + rtnl_link_ip6_tnl_set_local(link, &addr); + + inet_pton(AF_INET6, "2607:f0d0:1002:52::5", &addr); + rtnl_link_ip6_tnl_set_remote(link, &addr); + + err = rtnl_link_add(sk, link, NLM_F_CREATE); + if (err < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-create-ipgre.c b/tests/test-create-ipgre.c new file mode 100644 index 0000000..31d0eec --- /dev/null +++ b/tests/test-create-ipgre.c @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +int main(int argc, char *argv[]) +{ + struct nl_cache *link_cache; + struct rtnl_link *link; + struct in_addr addr; + struct nl_sock *sk; + int err, if_index; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache); + if ( err < 0) { + nl_perror(err, "Unable to allocate cache"); + return err; + } + + if_index = rtnl_link_name2i(link_cache, "eno16777736"); + if (!if_index) { + fprintf(stderr, "Unable to lookup eno16777736"); + return -1; + } + + link = rtnl_link_ipgre_alloc(); + if(!link) { + nl_perror(err, "Unable to allocate link"); + return -1; + + } + rtnl_link_set_name(link, "ipgre-tun"); + rtnl_link_ipgre_set_link(link, if_index); + + inet_pton(AF_INET, "192.168.254.12", &addr.s_addr); + rtnl_link_ipgre_set_local(link, addr.s_addr); + + inet_pton(AF_INET, "192.168.254.13", &addr.s_addr); + rtnl_link_ipgre_set_remote(link, addr.s_addr); + + rtnl_link_ipgre_set_ttl(link, 64); + err = rtnl_link_add(sk, link, NLM_F_CREATE); + if (err < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-create-ipgretap.c b/tests/test-create-ipgretap.c new file mode 100644 index 0000000..8dceaf1 --- /dev/null +++ b/tests/test-create-ipgretap.c @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +int main(int argc, char *argv[]) +{ + struct nl_cache *link_cache; + struct rtnl_link *link; + struct in_addr addr; + struct nl_sock *sk; + int err, if_index; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache); + if ( err < 0) { + nl_perror(err, "Unable to allocate cache"); + return err; + } + + if_index = rtnl_link_name2i(link_cache, "enp0s5"); + if (!if_index) { + fprintf(stderr, "Unable to lookup enp0s5"); + return -1; + } + + link = rtnl_link_ipgretap_alloc(); + if(!link) { + nl_perror(err, "Unable to allocate link"); + return -1; + + } + rtnl_link_set_name(link, "ipgre-tap"); + rtnl_link_ipgre_set_link(link, if_index); + + inet_pton(AF_INET, "10.211.55.10", &addr.s_addr); + rtnl_link_ipgre_set_local(link, addr.s_addr); + + inet_pton(AF_INET, "10.133.6.33", &addr.s_addr); + rtnl_link_ipgre_set_remote(link, addr.s_addr); + + rtnl_link_ipgre_set_ttl(link, 64); + err = rtnl_link_add(sk, link, NLM_F_CREATE); + if (err < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-create-ipip.c b/tests/test-create-ipip.c new file mode 100644 index 0000000..2ea3bf0 --- /dev/null +++ b/tests/test-create-ipip.c @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +int main(int argc, char *argv[]) +{ + struct nl_cache *link_cache; + struct rtnl_link *link; + struct in_addr addr; + struct nl_sock *sk; + int err, if_index; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache); + if ( err < 0) { + nl_perror(err, "Unable to allocate cache"); + return err; + } + + if_index = rtnl_link_name2i(link_cache, "eno16777736"); + if (!if_index) { + fprintf(stderr, "Unable to lookup eno16777736"); + return -1; + } + + link = rtnl_link_ipip_alloc(); + if(!link) { + nl_perror(err, "Unable to allocate link"); + return -1; + } + + rtnl_link_set_name(link, "ipip-tun"); + rtnl_link_ipip_set_link(link, if_index); + + inet_pton(AF_INET, "192.168.254.12", &addr.s_addr); + rtnl_link_ipip_set_local(link, addr.s_addr); + + inet_pton(AF_INET, "192.168.254.13", &addr.s_addr); + rtnl_link_ipip_set_remote(link, addr.s_addr); + + rtnl_link_ipip_set_ttl(link, 64); + err = rtnl_link_add(sk, link, NLM_F_CREATE); + if (err < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-create-ipvlan.c b/tests/test-create-ipvlan.c new file mode 100644 index 0000000..b0b200c --- /dev/null +++ b/tests/test-create-ipvlan.c @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + struct rtnl_link *link; + struct nl_cache *link_cache; + struct nl_sock *sk; + int err, master_index; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + if ((err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache)) < 0) { + nl_perror(err, "Unable to allocate cache"); + return err; + } + + if (!(master_index = rtnl_link_name2i(link_cache, "eth0"))) { + fprintf(stderr, "Unable to lookup eth0"); + return -1; + } + + if (!(link = rtnl_link_ipvlan_alloc())) { + fprintf(stderr, "Unable to allocate link"); + return -1; + } + + rtnl_link_set_link(link, master_index); + rtnl_link_ipvlan_set_mode(link, rtnl_link_ipvlan_str2mode("l2")); + + if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-create-ipvti.c b/tests/test-create-ipvti.c new file mode 100644 index 0000000..33eb646 --- /dev/null +++ b/tests/test-create-ipvti.c @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +int main(int argc, char *argv[]) +{ + struct nl_cache *link_cache; + struct rtnl_link *link; + struct in_addr addr; + struct nl_sock *sk; + int err, if_index; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache); + if ( err < 0) { + nl_perror(err, "Unable to allocate cache"); + return err; + } + + if_index = rtnl_link_name2i(link_cache, "ens33"); + if (!if_index) { + fprintf(stderr, "Unable to lookup ens33"); + return -1; + } + + link = rtnl_link_ipvti_alloc(); + if(!link) { + nl_perror(err, "Unable to allocate link"); + return -1; + + } + rtnl_link_set_name(link, "ipvti-tun"); + rtnl_link_ipvti_set_link(link, if_index); + + inet_pton(AF_INET, "192.168.254.12", &addr.s_addr); + rtnl_link_ipvti_set_local(link, addr.s_addr); + + inet_pton(AF_INET, "192.168.254.13", &addr.s_addr); + rtnl_link_ipvti_set_remote(link, addr.s_addr); + + err = rtnl_link_add(sk, link, NLM_F_CREATE); + if (err < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-create-macsec.c b/tests/test-create-macsec.c new file mode 100644 index 0000000..b702f7d --- /dev/null +++ b/tests/test-create-macsec.c @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include +#include + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + struct rtnl_link *link; + struct nl_cache *link_cache; + struct nl_sock *sk; + int err, master_index; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + if ((err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache)) < 0) { + nl_perror(err, "Unable to allocate cache"); + return err; + } + + if (!(master_index = rtnl_link_name2i(link_cache, "eth0"))) { + fprintf(stderr, "Unable to lookup eth0"); + return -1; + } + + + link = rtnl_link_macsec_alloc(); + + rtnl_link_set_link(link, master_index); + + rtnl_link_macsec_set_port(link, 10); + rtnl_link_macsec_set_encrypt(link, 1); + rtnl_link_macsec_set_replay_protect(link, 1); + rtnl_link_macsec_set_window(link, 200); + + if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-create-macvlan.c b/tests/test-create-macvlan.c new file mode 100644 index 0000000..665c502 --- /dev/null +++ b/tests/test-create-macvlan.c @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +#include + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + struct rtnl_link *link; + struct nl_cache *link_cache; + struct nl_sock *sk; + struct nl_addr* addr; + int err, master_index; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + if ((err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache)) < 0) { + nl_perror(err, "Unable to allocate cache"); + return err; + } + + if (!(master_index = rtnl_link_name2i(link_cache, "eth0"))) { + fprintf(stderr, "Unable to lookup eth0"); + return -1; + } + + link = rtnl_link_macvlan_alloc(); + + rtnl_link_set_link(link, master_index); + + addr = nl_addr_build(AF_LLC, ether_aton("00:11:22:33:44:55"), ETH_ALEN); + rtnl_link_set_addr(link, addr); + nl_addr_put(addr); + + rtnl_link_macvlan_set_mode(link, rtnl_link_macvlan_str2mode("bridge")); + + if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-create-macvtap.c b/tests/test-create-macvtap.c new file mode 100644 index 0000000..c3e19a7 --- /dev/null +++ b/tests/test-create-macvtap.c @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +#include + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + struct rtnl_link *link; + struct nl_cache *link_cache; + struct nl_sock *sk; + struct nl_addr* addr; + int err, master_index; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + if ((err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache)) < 0) { + nl_perror(err, "Unable to allocate cache"); + return err; + } + + if (!(master_index = rtnl_link_name2i(link_cache, "eth0"))) { + fprintf(stderr, "Unable to lookup eth0"); + return -1; + } + + link = rtnl_link_macvtap_alloc(); + + rtnl_link_set_link(link, master_index); + + addr = nl_addr_build(AF_LLC, ether_aton("00:11:22:33:44:55"), ETH_ALEN); + rtnl_link_set_addr(link, addr); + nl_addr_put(addr); + + rtnl_link_macvtap_set_mode(link, rtnl_link_macvtap_str2mode("bridge")); + + if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-create-sit.c b/tests/test-create-sit.c new file mode 100644 index 0000000..5c7aaeb --- /dev/null +++ b/tests/test-create-sit.c @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +int main(int argc, char *argv[]) +{ + struct nl_cache *link_cache; + struct rtnl_link *link; + struct in_addr addr; + struct nl_sock *sk; + int err, if_index; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache); + if ( err < 0) { + nl_perror(err, "Unable to allocate cache"); + return err; + } + + if_index = rtnl_link_name2i(link_cache, "eno16777736"); + if (!if_index) { + fprintf(stderr, "Unable to lookup eno16777736"); + return -1; + } + + link = rtnl_link_sit_alloc(); + if(!link) { + nl_perror(err, "Unable to allocate link"); + return -1; + + } + rtnl_link_set_name(link, "sit-tun"); + rtnl_link_sit_set_link(link, if_index); + + inet_pton(AF_INET, "192.168.254.12", &addr.s_addr); + rtnl_link_sit_set_local(link, addr.s_addr); + + inet_pton(AF_INET, "192.168.254.13", &addr.s_addr); + rtnl_link_sit_set_remote(link, addr.s_addr); + + rtnl_link_sit_set_ttl(link, 64); + err = rtnl_link_add(sk, link, NLM_F_CREATE); + if (err < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-create-veth.c b/tests/test-create-veth.c new file mode 100644 index 0000000..fda4d2e --- /dev/null +++ b/tests/test-create-veth.c @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + struct rtnl_link *link; + struct nl_sock *sk; + int err; + struct rtnl_link *peer; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + +#if 0 + rtnl_link_veth_add(sk, "veth2", "veth3", getpid()); +#else + link = rtnl_link_veth_alloc(); + if (!link) { + nl_perror(err, "Unable to alloc link"); + return err; + } + + rtnl_link_set_name(link, "veth8"); + peer = rtnl_link_veth_get_peer(link); + rtnl_link_set_name(peer, "veth9"); + + if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + printf("peer is %s\n", rtnl_link_get_name(peer)); + rtnl_link_put(peer); + rtnl_link_put(link); +#endif + nl_close(sk); + + return 0; +} diff --git a/tests/test-create-vlan.c b/tests/test-create-vlan.c index 64e478f..e2cd2b1 100644 --- a/tests/test-create-vlan.c +++ b/tests/test-create-vlan.c @@ -1,3 +1,9 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + #include #include #include diff --git a/tests/test-create-vrf.c b/tests/test-create-vrf.c new file mode 100644 index 0000000..b5f7176 --- /dev/null +++ b/tests/test-create-vrf.c @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + struct nl_cache *link_cache; + struct rtnl_link *link, *link2; + struct nl_sock *sk; + uint32_t tb_id; + int err; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + if (!(link = rtnl_link_vrf_alloc())) { + fprintf(stderr, "Unable to allocate link"); + return -1; + } + + rtnl_link_set_name(link, "vrf-red"); + + if ((err = rtnl_link_vrf_set_tableid(link, 10)) < 0) { + nl_perror(err, "Unable to set VRF table id"); + return err; + } + + if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + if ((err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache)) < 0) { + nl_perror(err, "Unable to allocate cache"); + return err; + } + + if (!(link2 = rtnl_link_get_by_name(link_cache, "vrf-red"))) { + fprintf(stderr, "Unable to lookup vrf-red"); + return -1; + } + + if ((err = rtnl_link_vrf_get_tableid(link2, &tb_id)) < 0) { + nl_perror(err, "Unable to get VRF table id"); + return err; + } + + if (tb_id != 10) { + fprintf(stderr, "Mismatch with VRF table id\n"); + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-create-vxlan.c b/tests/test-create-vxlan.c new file mode 100644 index 0000000..6d2fd94 --- /dev/null +++ b/tests/test-create-vxlan.c @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + struct rtnl_link *link; + struct nl_addr *addr; + struct nl_sock *sk; + int err; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + link = rtnl_link_vxlan_alloc(); + + rtnl_link_set_name(link, "vxlan128"); + + if ((err = rtnl_link_vxlan_set_id(link, 128)) < 0) { + nl_perror(err, "Unable to set VXLAN network identifier"); + return err; + } + + if ((err = nl_addr_parse("239.0.0.1", AF_INET, &addr)) < 0) { + nl_perror(err, "Unable to parse IP address"); + return err; + } + + if ((err = rtnl_link_vxlan_set_group(link, addr)) < 0) { + nl_perror(err, "Unable to set multicast IP address"); + return err; + } + nl_addr_put(addr); + + if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + + return 0; +} diff --git a/tests/test-create-xfrmi.c b/tests/test-create-xfrmi.c new file mode 100644 index 0000000..8fd7c3a --- /dev/null +++ b/tests/test-create-xfrmi.c @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +int main(int argc, char *argv[]) +{ + struct nl_cache *link_cache; + struct rtnl_link *link; + struct nl_sock *sk; + int err, if_index; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache); + if (err < 0) { + nl_perror(err, "Unable to allocate cache"); + return err; + } + + if_index = rtnl_link_name2i(link_cache, "eth0"); + if (!if_index) { + fprintf(stderr, "Unable to lookup eth0"); + return -1; + } + + link = rtnl_link_xfrmi_alloc(); + if (!link) { + nl_perror(err, "Unable to allocate link"); + return -1; + + } + + rtnl_link_set_name(link, "ipsec0"); + rtnl_link_xfrmi_set_link(link, if_index); + rtnl_link_xfrmi_set_if_id(link, 16); + + err = rtnl_link_add(sk, link, NLM_F_CREATE); + if (err < 0) { + nl_perror(err, "Unable to add link"); + return err; + } + + rtnl_link_put(link); + nl_close(sk); + return 0; +} diff --git a/tests/test-delete-link.c b/tests/test-delete-link.c index 9cf1034..58c70f0 100644 --- a/tests/test-delete-link.c +++ b/tests/test-delete-link.c @@ -1,3 +1,9 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + #include #include diff --git a/tests/test-genl.c b/tests/test-genl.c index 74aea10..5e32c6d 100644 --- a/tests/test-genl.c +++ b/tests/test-genl.c @@ -1,6 +1,13 @@ -#include +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + #include +#include + static struct nla_policy attr_policy[TASKSTATS_TYPE_MAX+1] = { [TASKSTATS_TYPE_PID] = { .type = NLA_U32 }, [TASKSTATS_TYPE_TGID] = { .type = NLA_U32 }, @@ -60,8 +67,6 @@ static struct genl_cmd cmds[] = { }, }; -#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0])) - static struct genl_ops ops = { .o_name = TASKSTATS_GENL_NAME, .o_cmds = cmds, @@ -99,7 +104,7 @@ int main(int argc, char *argv[]) if ((err = nla_put_u32(msg, TASKSTATS_CMD_ATTR_PID, 1)) < 0) nl_cli_fatal(err, "Unable to add attribute: %s", nl_geterror(err)); - if ((err = nl_send_auto_complete(sock, msg)) < 0) + if ((err = nl_send_auto(sock, msg)) < 0) nl_cli_fatal(err, "Unable to send message: %s", nl_geterror(err)); nlmsg_free(msg); diff --git a/tests/test-loopback-up-down.c b/tests/test-loopback-up-down.c new file mode 100644 index 0000000..fdb5a98 --- /dev/null +++ b/tests/test-loopback-up-down.c @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + +#include + +int main(void) +{ + struct nl_sock *sk; + struct rtnl_link *link, *change; + struct nl_cache *cache; + int err = 0; + + sk = nl_socket_alloc(); + if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { + nl_perror(err, "Unable to connect socket"); + return err; + } + + if ((err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &cache)) < 0) { + nl_perror(err, "Unable to allocate cache"); + goto out; + } + + if (!(link = rtnl_link_get_by_name(cache, "lo"))) { + fprintf(stderr, "Interface not found\n"); + err = 1; + goto out; + } + + /* exit if the loopback interface is already deactivated */ + err = rtnl_link_get_flags(link); + if (!(err & IFF_UP)) { + err = 0; + goto out; + } + + change = rtnl_link_alloc(); + rtnl_link_unset_flags(change, IFF_UP); + + if ((err = rtnl_link_change(sk, link, change, 0)) < 0) { + nl_perror(err, "Unable to deactivate lo"); + goto out; + } + + rtnl_link_set_flags(change, IFF_UP); + if ((err = rtnl_link_change(sk, link, change, 0)) < 0) { + nl_perror(err, "Unable to activate lo"); + goto out; + } + + err = 0; + +out: + nl_socket_free(sk); + return err; +} diff --git a/tests/test-nf-cache-mngr.c b/tests/test-nf-cache-mngr.c index b4f3022..7dcc9fc 100644 --- a/tests/test-nf-cache-mngr.c +++ b/tests/test-nf-cache-mngr.c @@ -1,3 +1,9 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + +#include + #include static void change_cb(struct nl_cache *cache, struct nl_object *obj, diff --git a/tests/test-socket-creation.c b/tests/test-socket-creation.c index 83f3ad4..00259a1 100644 --- a/tests/test-socket-creation.c +++ b/tests/test-socket-creation.c @@ -1,5 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ + +#include "nl-default.h" + #include -#include int main(int argc, char *argv[]) { diff --git a/tests/test-u32-filter-with-actions.c b/tests/test-u32-filter-with-actions.c new file mode 100644 index 0000000..d676013 --- /dev/null +++ b/tests/test-u32-filter-with-actions.c @@ -0,0 +1,409 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/* + * Copyright (c) 2013 Cong Wang + * + * Stolen from tests/test-complex-HTB-with-hash-filters.c + */ + +#include "nl-default.h" + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TC_HANDLE(maj, min) (TC_H_MAJ((maj) << 16) | TC_H_MIN(min)) + +/* some functions are copied from iproute-tc tool */ +static int get_u32(__u32 *val, const char *arg, int base) +{ + unsigned long res; + char *ptr; + + if (!arg || !*arg) + return -1; + res = strtoul(arg, &ptr, base); + if (!ptr || ptr == arg || *ptr || res > 0xFFFFFFFFUL) + return -1; + *val = res; + return 0; +} + +static int get_u32_handle(__u32 *handle, const char *str) +{ + __u32 htid=0, hash=0, nodeid=0; + char *tmp = strchr(str, ':'); + + if (tmp == NULL) { + if (memcmp("0x", str, 2) == 0) + return get_u32(handle, str, 16); + return -1; + } + htid = strtoul(str, &tmp, 16); + if (tmp == str && *str != ':' && *str != 0) + return -1; + if (htid>=0x1000) + return -1; + if (*tmp) { + str = tmp+1; + hash = strtoul(str, &tmp, 16); + if (tmp == str && *str != ':' && *str != 0) + return -1; + if (hash>=0x100) + return -1; + if (*tmp) { + str = tmp+1; + nodeid = strtoul(str, &tmp, 16); + if (tmp == str && *str != 0) + return -1; + if (nodeid>=0x1000) + return -1; + } + } + *handle = (htid<<20)|(hash<<12)|nodeid; + return 0; +} + +static uint32_t get_u32_parse_handle(const char *cHandle) +{ + uint32_t handle=0; + + if(get_u32_handle(&handle, cHandle)) { + printf ("Illegal \"ht\"\n"); + return -1; + } + + if (handle && TC_U32_NODE(handle)) { + printf("\"link\" must be a hash table.\n"); + return -1; + } + return handle; +} + +/* + * Function that adds a new filter and attach it to a hash table + * and set next hash table link with hash mask + * + */ +static +int u32_add_filter_on_ht_with_hashmask(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio, + uint32_t keyval, uint32_t keymask, int keyoff, int keyoffmask, + uint32_t htid, uint32_t htlink, uint32_t hmask, uint32_t hoffset, struct rtnl_act *act, struct rtnl_act *act2) +{ + struct rtnl_cls *cls; + int err; + + cls=rtnl_cls_alloc(); + if (!(cls)) { + printf("Can not allocate classifier\n"); + nl_socket_free(sock); + exit(1); + } + + rtnl_tc_set_link(TC_CAST(cls), rtnlLink); + + if ((err = rtnl_tc_set_kind(TC_CAST(cls), "u32"))) { + printf("Can not set classifier as u32\n"); + return 1; + } + + rtnl_cls_set_prio(cls, prio); + rtnl_cls_set_protocol(cls, ETH_P_IP); + + rtnl_tc_set_parent(TC_CAST(cls), TC_HANDLE(0xffff, 0)); + + if (htid) + rtnl_u32_set_hashtable(cls, htid); + + rtnl_u32_add_key_uint32(cls, keyval, keymask, keyoff, keyoffmask); + + rtnl_u32_set_hashmask(cls, hmask, hoffset); + + rtnl_u32_set_link(cls, htlink); + + rtnl_u32_add_action(cls, act); + + rtnl_u32_add_action(cls, act2); + + + if ((err = rtnl_cls_add(sock, cls, NLM_F_CREATE))) { + printf("Can not add classifier: %s\n", nl_geterror(err)); + return -1; + } + rtnl_cls_put(cls); + return 0; +} + +/* + * function that creates a new hash table + */ +static +int u32_add_ht(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio, uint32_t htid, uint32_t divisor) +{ + + int err; + struct rtnl_cls *cls; + + cls=rtnl_cls_alloc(); + if (!(cls)) { + printf("Can not allocate classifier\n"); + nl_socket_free(sock); + exit(1); + } + + rtnl_tc_set_link(TC_CAST(cls), rtnlLink); + + if ((err = rtnl_tc_set_kind(TC_CAST(cls), "u32"))) { + printf("Can not set classifier as u32\n"); + return 1; + } + + rtnl_cls_set_prio(cls, prio); + rtnl_cls_set_protocol(cls, ETH_P_IP); + rtnl_tc_set_parent(TC_CAST(cls), TC_HANDLE(0xffff, 0)); + + rtnl_u32_set_handle(cls, htid, 0x0, 0x0); + //printf("htid: 0x%X\n", htid); + rtnl_u32_set_divisor(cls, divisor); + + if ((err = rtnl_cls_add(sock, cls, NLM_F_CREATE))) { + printf("Can not add classifier: %s\n", nl_geterror(err)); + return -1; + } + rtnl_cls_put(cls); + return 0; +} + +/* + * function that adds a new ingress qdisc and set the default class for unclassified traffic + */ +static +int qdisc_add_ingress(struct nl_sock *sock, struct rtnl_link *rtnlLink) +{ + + struct rtnl_qdisc *qdisc; + int err; + + /* Allocation of a qdisc object */ + if (!(qdisc = rtnl_qdisc_alloc())) { + printf("Can not allocate Qdisc\n"); + return -1; + } + + //rtnl_tc_set_ifindex(TC_CAST(qdisc), master_index); + rtnl_tc_set_link(TC_CAST(qdisc), rtnlLink); + rtnl_tc_set_parent(TC_CAST(qdisc), TC_H_ROOT); + + //printf("Delete current qdisc\n"); + rtnl_qdisc_delete(sock, qdisc); + //rtnl_qdisc_put(qdisc); + + rtnl_tc_set_handle(TC_CAST(qdisc), TC_HANDLE(0xffff, 0)); + + if ((err = rtnl_tc_set_kind(TC_CAST(qdisc), "ingress"))) { + printf("Can not allocate ingress\n"); + return -1; + } + + /* Submit request to kernel and wait for response */ + if ((err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE))) { + printf("Can not allocate ingress Qdisc\n"); + return -1; + } + + /* Return the qdisc object to free memory resources */ + rtnl_qdisc_put(qdisc); + + return 0; +} + +int main(void) +{ + struct nl_sock *sock; + struct rtnl_link *link; + uint32_t ht, htlink, htid, direction; + char chashlink[16]=""; + int err; + struct nl_cache *link_cache; + struct rtnl_act *act, *act2; + uint32_t i; + + if (!(sock = nl_socket_alloc())) { + printf("Unable to allocate netlink socket\n"); + exit(1); + } + + if ((err = nl_connect(sock, NETLINK_ROUTE)) < 0 ) { + printf("Nu s-a putut conecta la NETLINK!\n"); + nl_socket_free(sock); + exit(1); + } + + if ((err = rtnl_link_alloc_cache(sock, AF_UNSPEC, &link_cache)) < 0) { + printf("Unable to allocate link cache: %s\n", + nl_geterror(err)); + nl_socket_free(sock); + exit(1); + } + + /* lookup interface index of eth0 */ + if (!(link = rtnl_link_get_by_name(link_cache, "eth0"))) { + /* error */ + printf("Interface not found\n"); + nl_socket_free(sock); + exit(1); + } + + err=qdisc_add_ingress(sock, link); + //printf("Add main hash table\n"); + + /* create u32 first hash filter table + * + */ + /* formula calcul handle: + * uint32_t handle = (htid << 20) | (hash << 12) | nodeid; + */ + + /* + * Upper limit of number of hash tables: 4096 (0xFFF) + * Number of hashes in a table: 256 values (0xFF) + * + */ + + /* using 256 values for hash table + * each entry in hash table match a byte from IP address specified later by a hash key + */ + + for (i = 1; i <= 0xf; i++) + u32_add_ht(sock, link, 1, i, 256); + + /* + * attach a u32 filter to the first hash + * that redirects all traffic and make a hash key + * from the fist byte of the IP address + * + */ + + //divisor=0x0; // unused here + //handle = 0x0; // unused here + //hash = 0x0; // unused here + //htid = 0x0; // unused here + //nodeid = 0x0; // unused here + + // direction = 12 -> source IP + // direction = 16 -> destination IP + direction = 16; + + /* + * which hash table will use + * in our case is hash table no 1 defined previous + * + * There are 2 posibilities to set the the hash table: + * 1. Using function get_u32_handle and sent a string in + * format 10: where 10 is number of the hash table + * 2. Create your own value in format: 0xa00000 + * + */ + strcpy(chashlink, "1:"); + //printf("Hash Link: %s\n", chashlink); + //chashlink=malloc(sizeof(char) * + htlink = 0x0; // is used by get_u32_handle to return the correct value of hash table (link) + + if(get_u32_handle(&htlink, chashlink)) { + printf ("Illegal \"link\""); + nl_socket_free(sock); + exit(1); + } + //printf ("hash link : 0x%X\n", htlink); + //printf ("hash link test : %u\n", (htlink && TC_U32_NODE(htlink))); + + if (htlink && TC_U32_NODE(htlink)) { + printf("\"link\" must be a hash table.\n"); + nl_socket_free(sock); + exit(1); + } + + /* the hash mask will hit the hash table (link) no 1: in our case + */ + + /* set the hash key mask */ + //hashmask = 0xFF000000UL; // the mask that is used to match the hash in specific table, in our case for example 1:a with mean the first byte which is 10 in hash table 1 + + /* Here we add a hash filter which match the first byte (see the hashmask value) + * of the source IP (offset 12 in the packet header) + * You can use also offset 16 to match the destination IP + */ + + /* + * Also we need a filter to match our rule + * This mean that we will put a 0.0.0.0/0 filter in our first rule + * that match the offset 12 (source IP) + * Also you can put offset 16 to match the destination IP + */ + + u32_add_filter_on_ht_with_hashmask(sock, link, 1, + 0x0, 0x0, direction, 0, + 0, htlink, 0xff000000, direction, NULL, NULL); + + /* + * For each first byte that we need to match we will create a new hash table + * For example: you have those clases: 10.0.0.0/24 and 172.16.0.0/23 + * For byte 10 and byte 172 will create a separate hash table that will match the second + * byte from each class. + * + */ + + + /* + * Now we will create other filter under (ATENTION) our first hash table (link) 1: + * Previous rule redirects the trafic according the hash mask to hash table (link) no 1: + * Here we will match the hash tables from 1:0 to 1:ff. Under each hash table we will attach + * other rules that matches next byte from IP source/destination IP and we will repeat the + * previous steps. + * + */ + act = rtnl_act_alloc(); + if (!act) { + printf("rtnl_act_alloc() returns %p\n", act); + return -1; + } + rtnl_tc_set_kind(TC_CAST(act), "skbedit"); + rtnl_skbedit_set_queue_mapping(act, 4); + rtnl_skbedit_set_action(act, TC_ACT_PIPE); + + act2 = rtnl_act_alloc(); + if (!act2) { + printf("rtnl_act_alloc() returns %p\n", act2); + return -1; + } + rtnl_tc_set_kind(TC_CAST(act2), "mirred"); + rtnl_mirred_set_action(act2, TCA_EGRESS_REDIR); + rtnl_mirred_set_policy(act2, TC_ACT_STOLEN); + rtnl_mirred_set_ifindex(act2, rtnl_link_name2i(link_cache, "eth1")); + // /8 check + + // 10.0.0.0/8 + ht=get_u32_parse_handle("1:a:"); + htid = (ht&0xFFFFF000); + htlink=get_u32_parse_handle("2:"); + + u32_add_filter_on_ht_with_hashmask(sock, link, 1, + 0x0a000000, 0xff000000, direction, 0, + htid, htlink, 0x00ff0000, direction, act, act2); + + rtnl_act_put(act); + nl_socket_free(sock); + return 0; +} diff --git a/tests/util.h b/tests/util.h deleted file mode 100644 index c675383..0000000 --- a/tests/util.h +++ /dev/null @@ -1,5 +0,0 @@ -#include - -#define nl_fail_if(condition, error, message) \ - fail_if((condition), "nlerr=%d (%s): %s", \ - (error), nl_geterror(error), (message)) -- 2.7.4